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); } }
public void writeStructBin( DataOutput objBuffer, List<L2Property> struct, String structName, UnrealPackageReadOnly up) throws UnrealException { try { switch (structName) { case "Core.Object.Color": for (int i = 0; i < 4; i++) objBuffer.writeByte((Integer) struct.get(i).getAt(0)); break; case "Core.Object.Vector": for (int i = 0; i < 3; i++) objBuffer.writeFloat((Float) struct.get(i).getAt(0)); break; case "Core.Object.Rotator": for (int i = 0; i < 3; i++) objBuffer.writeInt((Integer) struct.get(i).getAt(0)); break; case "Fire.FireTexture.Spark": for (int i = 0; i < 8; i++) objBuffer.writeByte((Integer) struct.get(i).getAt(0)); break; default: throw new UnsupportedOperationException("not implemented"); // TODO } } catch (IOException e) { throw new UnrealException(e); } }
private void write( DataOutput objBuffer, Property template, Object obj, AtomicBoolean array, AtomicReference<String> structName, AtomicReference<Type> type, UnrealPackageReadOnly up) throws IOException { if (template instanceof ByteProperty) { System.out.println(template.getEntry().getObjectInnerFullName() + " [BYTE]"); objBuffer.writeByte((Integer) obj); } else if (template instanceof IntProperty) { System.out.println(template.getEntry().getObjectInnerFullName() + " [INT]"); objBuffer.writeInt((Integer) obj); } else if (template instanceof BoolProperty) { System.out.println(template.getEntry().getObjectInnerFullName() + " [BOOL]"); array.set((Boolean) obj); } else if (template instanceof FloatProperty) { System.out.println(template.getEntry().getObjectInnerFullName() + " [FLOAT]"); objBuffer.writeFloat((Float) obj); } else if (template instanceof ObjectProperty) { System.out.println(template.getEntry().getObjectInnerFullName() + " [OBJ]"); objBuffer.writeCompactInt((Integer) obj); } else if (template instanceof NameProperty) { System.out.println(template.getEntry().getObjectInnerFullName() + " [NAME]"); objBuffer.writeCompactInt((Integer) obj); } else if (template instanceof ArrayProperty) { System.out.println(template.getEntry().getObjectInnerFullName() + " [ARRAY]"); ArrayProperty arrayProperty = (ArrayProperty) template; List<Object> arrayList = (List<Object>) obj; objBuffer.writeCompactInt(arrayList.size()); UnrealPackageReadOnly.ExportEntry arrayInner = (UnrealPackageReadOnly.ExportEntry) arrayProperty.getInner(); String a = arrayInner.getObjectClass().getObjectName().getName(); try { Class<? extends Property> pc = Class.forName("acmi.l2.clientmod.unreal." + a).asSubclass(Property.class); Property f = pc.getConstructor( ByteBuffer.class, UnrealPackageReadOnly.ExportEntry.class, PropertiesUtil.class) .newInstance( ByteBuffer.wrap(arrayInner.getObjectRawDataExternally()) .order(ByteOrder.LITTLE_ENDIAN), arrayInner, this); for (Object arrayObj : arrayList) { write( objBuffer, f, arrayObj, new AtomicBoolean(), new AtomicReference<>(), new AtomicReference<>(), up); } } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } } else if (template instanceof StructProperty) { System.out.println(template.getEntry().getObjectInnerFullName() + " [STRUCT]"); StructProperty structProperty = (StructProperty) template; structName.set(structProperty.getStructType().getObjectName().getName()); writeStruct(objBuffer, structName.get(), up, (List<L2Property>) obj); // if (false) { //Not used in L2? // switch (structName.get()) { // case "Vector": // type.set(Type.VECTOR); // break; // case "Rotator": // type.set(Type.ROTATOR); // break; // } // } } else if (template instanceof StrProperty) { System.out.println(template.getEntry().getObjectInnerFullName() + " [STR]"); objBuffer.writeLine((String) obj); } else { throw new UnsupportedOperationException( template.getClass().getSimpleName() + " serialization not implemented"); } }