public void writeProperties(DataOutput buffer, List<L2Property> list, UnrealPackageReadOnly up)
      throws UnrealException {
    try {
      for (L2Property property : list) {
        Property template = property.getTemplate();

        for (int i = 0; i < property.getSize(); i++) {
          Object obj = property.getAt(i);
          if (obj == null) continue;

          ByteArrayOutputStream baos = new ByteArrayOutputStream();
          DataOutput objBuffer = new DataOutputStream(baos, buffer.getCharset());
          AtomicBoolean array = new AtomicBoolean(i > 0);
          AtomicReference<String> structName = new AtomicReference<>();
          AtomicReference<Type> type =
              new AtomicReference<>(
                  Type.valueOf(
                      template.getClass().getSimpleName().replace("Property", "").toUpperCase()));
          write(objBuffer, template, obj, array, structName, type, up);
          byte[] bytes = baos.toByteArray();

          int size = getPropertySize(bytes.length);
          int ord = type.get().ordinal();
          if (ord == 8) // FIXME
          ord = 5;
          int info = (array.get() ? 1 << 7 : 0) | (size << 4) | ord;

          buffer.writeCompactInt(up.nameReference(template.getEntry().getObjectName().getName()));
          buffer.writeByte(info);

          if (type.get() == Type.STRUCT) buffer.writeCompactInt(up.nameReference(structName.get()));
          switch (size) {
            case 5:
              buffer.writeByte(bytes.length);
              break;
            case 6:
              buffer.writeShort(bytes.length);
              break;
            case 7:
              buffer.writeInt(bytes.length);
              break;
          }
          if (i > 0) buffer.writeByte(i);
          buffer.write(bytes);
        }
      }
      buffer.writeCompactInt(up.nameReference("None"));
    } catch (IOException e) {
      throw new UnrealException(e);
    }
  }