diff --git a/pom.xml b/pom.xml index a91c636..2eb87ad 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ qowyn.ark ark-savegame-toolkit - 0.8.0 + 0.8.1 jar ARK Savegame Toolkit diff --git a/src/main/java/qowyn/ark/ArkCloudInventory.java b/src/main/java/qowyn/ark/ArkCloudInventory.java index 8b1d60e..ae5ae4c 100644 --- a/src/main/java/qowyn/ark/ArkCloudInventory.java +++ b/src/main/java/qowyn/ark/ArkCloudInventory.java @@ -7,19 +7,24 @@ import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonNode; import qowyn.ark.properties.Property; +import qowyn.ark.types.ArkName; -public class ArkCloudInventory extends FileFormatBase implements PropertyContainer, GameObjectContainer { +public class ArkCloudInventory extends FileFormatBase implements PropertyContainer, GameObjectContainerMixin { private int inventoryVersion; private final ArrayList objects = new ArrayList<>(); + private final Map, GameObject>> objectMap = new HashMap<>(); + private GameObject inventoryData; public ArkCloudInventory() {} @@ -50,8 +55,10 @@ public void readBinary(ArkArchive archive, ReadingOptions options) { int objectCount = archive.getInt(); + objects.clear(); + objectMap.clear(); for (int i = 0; i < objectCount; i++) { - objects.add(new GameObject(archive)); + addObject(new GameObject(archive), options.getBuildComponentTree()); } for (int i = 0; i < objectCount; i++) { @@ -112,15 +119,17 @@ public void writeBinary(Path filePath, WritingOptions options) throws FileNotFou @Override public void readJson(JsonNode node, ReadingOptions options) { inventoryVersion = node.path("inventoryVersion").asInt(); - objects.clear(); + objects.clear(); + objectMap.clear(); if (node.hasNonNull("inventoryData")) { - setInventoryData(new GameObject(node.get("inventoryData"))); + addObject(new GameObject(node.get("inventoryData")), options.getBuildComponentTree()); + inventoryData = objects.get(0); } if (node.hasNonNull("objects")) { - for (JsonNode profileObject : node.get("objects")) { - objects.add(new GameObject(profileObject)); + for (JsonNode objectNode : node.get("objects")) { + addObject(new GameObject(objectNode), options.getBuildComponentTree()); } } } @@ -162,10 +171,16 @@ public void setInventoryVersion(int inventoryVersion) { this.inventoryVersion = inventoryVersion; } + @Override public ArrayList getObjects() { return objects; } + @Override + public Map, GameObject>> getObjectMap() { + return objectMap; + } + public GameObject getInventoryData() { return inventoryData; } diff --git a/src/main/java/qowyn/ark/ArkContainer.java b/src/main/java/qowyn/ark/ArkContainer.java index ed085f3..46ba40e 100644 --- a/src/main/java/qowyn/ark/ArkContainer.java +++ b/src/main/java/qowyn/ark/ArkContainer.java @@ -7,17 +7,23 @@ import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonNode; import qowyn.ark.arrays.ArkArrayInt8; import qowyn.ark.arrays.ArkArrayUInt8; +import qowyn.ark.types.ArkName; -public class ArkContainer extends FileFormatBase implements GameObjectContainer { +public class ArkContainer extends FileFormatBase implements GameObjectContainerMixin { private final ArrayList objects = new ArrayList<>(); + private final Map, GameObject>> objectMap = new HashMap<>(); + public ArkContainer() {} public ArkContainer(Path filePath) throws IOException { @@ -62,8 +68,10 @@ public ArkContainer(ArkArrayInt8 source) { public void readBinary(ArkArchive archive, ReadingOptions options) { int objectCount = archive.getInt(); + objects.clear(); + objectMap.clear(); for (int i = 0; i < objectCount; i++) { - objects.add(new GameObject(archive)); + addObject(new GameObject(archive), options.getBuildComponentTree()); } for (int i = 0; i < objectCount; i++) { @@ -118,20 +126,17 @@ public void writeBinary(Path filePath, WritingOptions options) throws FileNotFou @Override public void readJson(JsonNode node, ReadingOptions options) { - objects.clear(); + objects.clear(); + objectMap.clear(); if (node.isArray()) { - int id = 0; for (JsonNode jsonObject : node) { - objects.add(new GameObject(jsonObject)); - objects.get(id).setId(id++); // Set id and increase afterwards + addObject(new GameObject(jsonObject), options.getBuildComponentTree()); } } else { if (node.hasNonNull("objects")) { - int id = 0; for (JsonNode jsonObject : node.get("objects")) { - objects.add(new GameObject(jsonObject)); - objects.get(id).setId(id++); // Set id and increase afterwards + addObject(new GameObject(jsonObject), options.getBuildComponentTree()); } } } @@ -148,10 +153,16 @@ public void writeJson(JsonGenerator generator, WritingOptions options) throws IO generator.writeEndArray(); } + @Override public ArrayList getObjects() { return objects; } + @Override + public Map, GameObject>> getObjectMap() { + return objectMap; + } + private ByteBuffer toBuffer() { int size = Integer.BYTES; diff --git a/src/main/java/qowyn/ark/ArkLocalProfile.java b/src/main/java/qowyn/ark/ArkLocalProfile.java index bc472d0..01ed57b 100644 --- a/src/main/java/qowyn/ark/ArkLocalProfile.java +++ b/src/main/java/qowyn/ark/ArkLocalProfile.java @@ -7,14 +7,17 @@ import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonNode; import qowyn.ark.properties.Property; +import qowyn.ark.types.ArkName; -public class ArkLocalProfile extends FileFormatBase implements PropertyContainer, GameObjectContainer { +public class ArkLocalProfile extends FileFormatBase implements PropertyContainer, GameObjectContainerMixin { private static final int UNKNOWN_DATA_2_SIZE = 0xc; @@ -26,6 +29,8 @@ public class ArkLocalProfile extends FileFormatBase implements PropertyContainer private final ArrayList objects = new ArrayList<>(); + private final Map, GameObject>> objectMap = new HashMap<>(); + private GameObject localProfile; public ArkLocalProfile() {} @@ -66,8 +71,10 @@ public void readBinary(ArkArchive archive, ReadingOptions options) { int objectCount = archive.getInt(); + objects.clear(); + objectMap.clear(); for (int i = 0; i < objectCount; i++) { - objects.add(new GameObject(archive)); + addObject(new GameObject(archive), options.getBuildComponentTree()); } for (int i = 0; i < objectCount; i++) { @@ -160,15 +167,17 @@ public void writeBinary(Path filePath, WritingOptions options) throws FileNotFou @Override public void readJson(JsonNode node, ReadingOptions options) { localProfileVersion = node.path("localProfileVersion").asInt(); - objects.clear(); + objects.clear(); + objectMap.clear(); if (node.hasNonNull("localProfile")) { - setLocalProfile(new GameObject(node.get("localProfile"))); + addObject(new GameObject(node.get("localProfile")), options.getBuildComponentTree()); + localProfile = objects.get(0); } if (node.hasNonNull("objects")) { - for (JsonNode profileObject : node.get("objects")) { - objects.add(new GameObject(profileObject)); + for (JsonNode objectNode : node.get("objects")) { + addObject(new GameObject(objectNode), options.getBuildComponentTree()); } } @@ -233,10 +242,16 @@ public void setLocalProfileVersion(int localProfileVersion) { this.localProfileVersion = localProfileVersion; } + @Override public ArrayList getObjects() { return objects; } + @Override + public Map, GameObject>> getObjectMap() { + return objectMap; + } + public GameObject getLocalProfile() { return localProfile; } diff --git a/src/main/java/qowyn/ark/ArkProfile.java b/src/main/java/qowyn/ark/ArkProfile.java index 954767b..a840769 100644 --- a/src/main/java/qowyn/ark/ArkProfile.java +++ b/src/main/java/qowyn/ark/ArkProfile.java @@ -7,19 +7,24 @@ import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonNode; import qowyn.ark.properties.Property; +import qowyn.ark.types.ArkName; -public class ArkProfile extends FileFormatBase implements PropertyContainer, GameObjectContainer { +public class ArkProfile extends FileFormatBase implements PropertyContainer, GameObjectContainerMixin { private int profileVersion; private final ArrayList objects = new ArrayList<>(); + private final Map, GameObject>> objectMap = new HashMap<>(); + private GameObject profile; public ArkProfile() {} @@ -50,8 +55,10 @@ public void readBinary(ArkArchive archive, ReadingOptions options) { int profilesCount = archive.getInt(); + objects.clear(); + objectMap.clear(); for (int i = 0; i < profilesCount; i++) { - objects.add(new GameObject(archive)); + addObject(new GameObject(archive), options.getBuildComponentTree()); } for (int i = 0; i < profilesCount; i++) { @@ -112,15 +119,17 @@ public void writeBinary(Path filePath, WritingOptions options) throws FileNotFou @Override public void readJson(JsonNode node, ReadingOptions options) { profileVersion = node.path("profileVersion").asInt(); - objects.clear(); + objects.clear(); + objectMap.clear(); if (node.hasNonNull("profile")) { - setProfile(new GameObject(node.get("profile"))); + addObject(new GameObject(node.get("profile")), options.getBuildComponentTree()); + profile = objects.get(0); } if (node.hasNonNull("objects")) { - for (JsonNode tribeObject : node.get("objects")) { - objects.add(new GameObject(tribeObject)); + for (JsonNode objectNode : node.get("objects")) { + addObject(new GameObject(objectNode), options.getBuildComponentTree()); } } } @@ -160,10 +169,16 @@ public void setProfileVersion(int profileVersion) { this.profileVersion = profileVersion; } + @Override public ArrayList getObjects() { return objects; } + @Override + public Map, GameObject>> getObjectMap() { + return objectMap; + } + public GameObject getProfile() { return profile; } diff --git a/src/main/java/qowyn/ark/ArkSavegame.java b/src/main/java/qowyn/ark/ArkSavegame.java index 3734ab1..980fa93 100644 --- a/src/main/java/qowyn/ark/ArkSavegame.java +++ b/src/main/java/qowyn/ark/ArkSavegame.java @@ -7,6 +7,7 @@ import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; @@ -19,11 +20,12 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonNode; +import qowyn.ark.types.ArkName; import qowyn.ark.types.EmbeddedData; import qowyn.ark.types.ListAppendingSet; import qowyn.ark.types.ObjectReference; -public class ArkSavegame extends FileFormatBase implements GameObjectContainer { +public class ArkSavegame extends FileFormatBase implements GameObjectContainerMixin { protected short saveVersion; @@ -51,6 +53,8 @@ public class ArkSavegame extends FileFormatBase implements GameObjectContainer { protected final ArrayList objects = new ArrayList<>(); + protected final Map, GameObject>> objectMap = new HashMap<>(); + protected int hibernationV8Unknown1; protected int hibernationV8Unknown2; @@ -120,6 +124,11 @@ public ArrayList getObjects() { return objects; } + @Override + public Map, GameObject>> getObjectMap() { + return objectMap; + } + public boolean hasUnknownNames() { return oldNameList != null; } @@ -128,6 +137,22 @@ public boolean hasUnknownData() { return hasUnknownData; } + public Map> getDataFilesObjectMap() { + return dataFilesObjectMap; + } + + public ArrayList getHibernationClasses() { + return hibernationClasses; + } + + public ArrayList getHibernationIndices() { + return hibernationIndices; + } + + public ArrayList getHibernationEntries() { + return hibernationEntries; + } + @Override public void readBinary(ArkArchive archive, ReadingOptions options) { readBinaryHeader(archive); @@ -265,10 +290,9 @@ protected void readBinaryObjects(ArkArchive archive, ReadingOptions options) { int count = archive.getInt(); objects.clear(); + objectMap.clear(); for (int n = 0; n < count; n++) { - GameObject gameObject = new GameObject(archive); - gameObject.setId(n); - objects.add(gameObject); + addObject(new GameObject(archive), options.getBuildComponentTree()); } } else { archive.unknownData(); @@ -374,7 +398,7 @@ protected void readBinaryHibernation(ArkArchive archive, ReadingOptions options) hibernationEntries.clear(); hibernationEntries.ensureCapacity(hibernatedObjectsCount); for (int index = 0; index < hibernatedObjectsCount; index++) { - hibernationEntries.add(new HibernationEntry(archive, options.getHibernationObjectProperties())); + hibernationEntries.add(new HibernationEntry(archive, options)); } } @@ -714,13 +738,13 @@ protected void readJsonDataFilesObjectMap(JsonNode node, ReadingOptions options) protected void readJsonObjects(JsonNode node, ReadingOptions options) { objects.clear(); + objectMap.clear(); if (options.getGameObjects()) { JsonNode objectsArray = node.path("objects"); if (!objectsArray.isNull()) { objects.ensureCapacity(objectsArray.size()); for (int i = 0; i < objectsArray.size(); i++) { - objects.add(new GameObject(objectsArray.get(i), options.getGameObjectProperties())); - objects.get(i).setId(i); + addObject(new GameObject(objectsArray.get(i), options.getGameObjectProperties()), options.getBuildComponentTree()); } } } @@ -757,7 +781,7 @@ protected void readJsonHibernatedObjects(JsonNode node, ReadingOptions options) JsonNode entriesArray = hibernation.path("entries"); if (!entriesArray.isNull()) { for (JsonNode hibernatedObject: entriesArray) { - hibernationEntries.add(new HibernationEntry(hibernatedObject, options.getHibernationObjectProperties())); + hibernationEntries.add(new HibernationEntry(hibernatedObject, options)); } } } else { diff --git a/src/main/java/qowyn/ark/ArkTribe.java b/src/main/java/qowyn/ark/ArkTribe.java index bbfb458..1906674 100644 --- a/src/main/java/qowyn/ark/ArkTribe.java +++ b/src/main/java/qowyn/ark/ArkTribe.java @@ -7,19 +7,24 @@ import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonNode; import qowyn.ark.properties.Property; +import qowyn.ark.types.ArkName; -public class ArkTribe extends FileFormatBase implements PropertyContainer, GameObjectContainer { +public class ArkTribe extends FileFormatBase implements PropertyContainer, GameObjectContainerMixin { private int tribeVersion; private final ArrayList objects = new ArrayList<>(); + private final Map, GameObject>> objectMap = new HashMap<>(); + private GameObject tribe; public ArkTribe() {} @@ -50,8 +55,10 @@ public void readBinary(ArkArchive archive, ReadingOptions options) { int tribesCount = archive.getInt(); + objects.clear(); + objectMap.clear(); for (int i = 0; i < tribesCount; i++) { - objects.add(new GameObject(archive)); + addObject(new GameObject(archive), options.getBuildComponentTree()); } for (int i = 0; i < tribesCount; i++) { @@ -112,15 +119,17 @@ public void writeBinary(Path filePath, WritingOptions options) throws FileNotFou @Override public void readJson(JsonNode node, ReadingOptions options) { tribeVersion = node.path("tribeVersion").asInt(); - objects.clear(); + objects.clear(); + objectMap.clear(); if (node.hasNonNull("tribe")) { - setTribe(new GameObject(node.get("tribe"))); + addObject(new GameObject(node.get("tribe")), options.getBuildComponentTree()); + tribe = objects.get(0); } if (node.hasNonNull("objects")) { - for (JsonNode tribeObject : node.get("objects")) { - objects.add(new GameObject(tribeObject)); + for (JsonNode objectNode : node.get("objects")) { + addObject(new GameObject(objectNode), options.getBuildComponentTree()); } } } @@ -160,10 +169,16 @@ public void setTribeVersion(int tribeVersion) { this.tribeVersion = tribeVersion; } + @Override public ArrayList getObjects() { return objects; } + @Override + public Map, GameObject>> getObjectMap() { + return objectMap; + } + public GameObject getTribe() { return tribe; } diff --git a/src/main/java/qowyn/ark/GameObject.java b/src/main/java/qowyn/ark/GameObject.java index ab8a763..82cc5e6 100644 --- a/src/main/java/qowyn/ark/GameObject.java +++ b/src/main/java/qowyn/ark/GameObject.java @@ -2,6 +2,7 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.UUID; @@ -25,7 +26,7 @@ public class GameObject implements PropertyContainer, NameContainer { private static final UUID NULL_UUID = UUID.fromString(NULL_UUID_STRING); - private static final Map UUID_CACHE = new ConcurrentHashMap<>(); + private static final Map uuidCache = new ConcurrentHashMap<>(); private int id; @@ -54,6 +55,10 @@ public class GameObject implements PropertyContainer, NameContainer { protected ExtraData extraData; + protected GameObject parent; + + protected Map components = new LinkedHashMap<>(); + public GameObject() {} public GameObject(ArkArchive archive) { @@ -174,7 +179,8 @@ public void writeProperties(ArkArchive archive, int propertiesBlockOffset) { } public void readJson(JsonNode node, boolean loadProperties) { - uuid = UUID.fromString(node.path("uuid").asText(NULL_UUID_STRING)); + + uuid = uuidCache.computeIfAbsent(UUID.fromString(node.path("uuid").asText(NULL_UUID_STRING)), uuid -> uuid); className = ArkName.from(node.path("class").asText()); item = node.path("item").asBoolean(); @@ -314,10 +320,14 @@ public int getPropertiesSize(NameSizeCalculator nameSizer) { } public void readBinary(ArkArchive archive) { - long uuidMostSig = archive.getLong(); - long uuidLeastSig = archive.getLong(); + long highOfHigh = archive.getInt(); + long lowOfHigh = archive.getInt(); + long high = (highOfHigh << 32) + lowOfHigh; + long highOfLow = archive.getInt(); + long lowOfLow = archive.getInt(); + long low = (highOfLow << 32) + lowOfLow; - uuid = UUID_CACHE.computeIfAbsent(new LongLong(uuidMostSig, uuidLeastSig), ll -> new UUID(ll.getHigh(), ll.getLow())); + uuid = uuidCache.computeIfAbsent(new UUID(high, low), uuid -> uuid); className = archive.getName(); @@ -455,4 +465,36 @@ public void collectPropertyNames(NameCollector collector) { } } + public GameObject getParent() { + return parent; + } + + public void setParent(GameObject parent) { + this.parent = parent; + } + + public Map getComponents() { + return components; + } + + public void setComponents(Map components) { + this.components = components; + } + + public void addComponent(GameObject component) { + this.components.put(component.getNames().get(0), component); + } + + public boolean hasParentNames() { + return names.size() > 1; + } + + public List getParentNames() { + return names.subList(1, names.size()); + } + + public static void clearUUIDCache() { + uuidCache.clear(); + } + } diff --git a/src/main/java/qowyn/ark/GameObjectContainer.java b/src/main/java/qowyn/ark/GameObjectContainer.java index 983a42f..a22d54d 100644 --- a/src/main/java/qowyn/ark/GameObjectContainer.java +++ b/src/main/java/qowyn/ark/GameObjectContainer.java @@ -1,5 +1,6 @@ package qowyn.ark; +import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -26,4 +27,6 @@ public default Iterator iterator() { return getObjects().iterator(); } + public static final GameObjectContainer EMPTY_CONTAINER = () -> Collections.emptyList(); + } diff --git a/src/main/java/qowyn/ark/GameObjectContainerMixin.java b/src/main/java/qowyn/ark/GameObjectContainerMixin.java new file mode 100644 index 0000000..b0d7b7b --- /dev/null +++ b/src/main/java/qowyn/ark/GameObjectContainerMixin.java @@ -0,0 +1,42 @@ +package qowyn.ark; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import qowyn.ark.types.ArkName; + +interface GameObjectContainerMixin extends GameObjectContainer { + + public Map, GameObject>> getObjectMap(); + + public default void addObject(GameObject object, boolean processNames) { + List objects = getObjects(); + + if (processNames) { + Map, GameObject> map = getObjectMap().get(object.isFromDataFile() ? object.getDataFileIndex() : null); + + if (map != null) { + if (object.hasParentNames()) { + List targetName = object.getParentNames(); + + GameObject parent = map.get(targetName); + if (parent != null) { + parent.addComponent(object); + object.setParent(parent); + } + } + + map.putIfAbsent(object.getNames(), object); + } else { + map = new HashMap<>(); + map.put(object.getNames(), object); + getObjectMap().put(object.isFromDataFile() ? object.getDataFileIndex() : null, map); + }; + } + + object.setId(objects.size()); + objects.add(object); + } + +} diff --git a/src/main/java/qowyn/ark/HibernationEntry.java b/src/main/java/qowyn/ark/HibernationEntry.java index d29611c..68c38c2 100644 --- a/src/main/java/qowyn/ark/HibernationEntry.java +++ b/src/main/java/qowyn/ark/HibernationEntry.java @@ -2,8 +2,10 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Set; import com.fasterxml.jackson.core.JsonGenerator; @@ -11,7 +13,7 @@ import qowyn.ark.types.ArkName; -public class HibernationEntry { +public class HibernationEntry implements GameObjectContainerMixin { private float x; @@ -27,6 +29,8 @@ public class HibernationEntry { private final ArrayList objects = new ArrayList<>(); + private final Map, GameObject>> objectMap = new HashMap<>(); + private int unkInt1; private int classIndex; @@ -42,22 +46,22 @@ public class HibernationEntry { public HibernationEntry() { } - public HibernationEntry(ArkArchive archive, boolean loadProperties) { - readBinary(archive, loadProperties); + public HibernationEntry(ArkArchive archive, ReadingOptions options) { + readBinary(archive, options); } - public HibernationEntry(JsonNode node, boolean loadProperties) { - readJson(node, loadProperties); + public HibernationEntry(JsonNode node, ReadingOptions options) { + readJson(node, options); } - public void readBinary(ArkArchive archive, boolean loadProperties) { + public void readBinary(ArkArchive archive, ReadingOptions options) { x = archive.getFloat(); y = archive.getFloat(); z = archive.getFloat(); unkByte = archive.getByte(); unkFloat = archive.getFloat(); - if (loadProperties) { + if (options.getHibernationObjectProperties()) { ArkArchive nameArchive = archive.slice(archive.getInt()); readBinaryNameTable(nameArchive); } else { @@ -69,7 +73,7 @@ public void readBinary(ArkArchive archive, boolean loadProperties) { } ArkArchive objectArchive = archive.slice(archive.getInt()); - readBinaryObjects(objectArchive); + readBinaryObjects(objectArchive, options); unkInt1 = archive.getInt(); classIndex = archive.getInt(); @@ -96,13 +100,14 @@ protected void readBinaryNameTable(ArkArchive archive) { } } - protected void readBinaryObjects(ArkArchive archive) { + protected void readBinaryObjects(ArkArchive archive, ReadingOptions options) { int count = archive.getInt(); objects.clear(); objects.ensureCapacity(count); + objectMap.clear(); for (int index = 0; index < count; index++) { - objects.add(new GameObject(archive)); + addObject(new GameObject(archive), options.getBuildComponentTree()); } if (nameTable != null) { @@ -178,7 +183,7 @@ public int getSizeAndCollectNames() { return size + nameTableSize + objectsSize; } - public void readJson(JsonNode node, boolean loadProperties) { + public void readJson(JsonNode node, ReadingOptions options) { x = (float) node.path("x").asDouble(); y = (float) node.path("y").asDouble(); z = (float) node.path("z").asDouble(); @@ -193,9 +198,10 @@ public void readJson(JsonNode node, boolean loadProperties) { } objects.clear(); + objectMap.clear(); if (node.hasNonNull("objects")) { for (JsonNode object: node.path("objects")) { - objects.add(new GameObject(object, loadProperties)); + addObject(new GameObject(object, options.getHibernationObjectProperties()), options.getBuildComponentTree()); } } @@ -290,8 +296,14 @@ public ArrayList getZoneVolumes() { return zoneVolumes; } + @Override public ArrayList getObjects() { return objects; } + @Override + public Map, GameObject>> getObjectMap() { + return objectMap; + } + } diff --git a/src/main/java/qowyn/ark/LongLong.java b/src/main/java/qowyn/ark/LongLong.java deleted file mode 100644 index f4017c5..0000000 --- a/src/main/java/qowyn/ark/LongLong.java +++ /dev/null @@ -1,47 +0,0 @@ -package qowyn.ark; - -class LongLong { - - private final long high; - - private final long low; - - public LongLong(long high, long low) { - this.high = high; - this.low = low; - } - - public long getHigh() { - return high; - } - - public long getLow() { - return low; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (int) (high ^ (high >>> 32)); - result = prime * result + (int) (low ^ (low >>> 32)); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - LongLong other = (LongLong) obj; - if (high != other.high) - return false; - if (low != other.low) - return false; - return true; - } - -} diff --git a/src/main/java/qowyn/ark/ReadingOptions.java b/src/main/java/qowyn/ark/ReadingOptions.java index 04bc3aa..9cdaf82 100644 --- a/src/main/java/qowyn/ark/ReadingOptions.java +++ b/src/main/java/qowyn/ark/ReadingOptions.java @@ -25,6 +25,8 @@ public class ReadingOptions extends BaseOptions { private boolean hibernationObjectProperties = true; + private boolean buildComponentTree = false; + public static ReadingOptions create() { return new ReadingOptions(); } @@ -186,6 +188,15 @@ public ReadingOptions withHibernationObjectProperties(boolean hibernationObjectP return this; } + public boolean getBuildComponentTree() { + return buildComponentTree; + } + + public ReadingOptions buildComponentTree(boolean buildComponentTree) { + this.buildComponentTree = buildComponentTree; + return this; + } + @Override public ReadingOptions parallel(boolean parallel) { super.parallel(parallel); diff --git a/src/main/java/qowyn/ark/arrays/ArkArrayByteHandler.java b/src/main/java/qowyn/ark/arrays/ArkArrayByteHandler.java index b33eb3a..b22d40c 100644 --- a/src/main/java/qowyn/ark/arrays/ArkArrayByteHandler.java +++ b/src/main/java/qowyn/ark/arrays/ArkArrayByteHandler.java @@ -23,7 +23,7 @@ public static ArkArray create(ArkArchive archive, PropertyArray property) { if (property.getDataSize() > size + 4) { return new ArkArrayByteValue(archive, property); } else { - return new ArkArrayInt8(archive, property); + return new ArkArrayUInt8(archive, property); } } @@ -32,7 +32,7 @@ public static ArkArray create(JsonNode node, PropertyArray property) { if (node.size() > 0 && node.get(0).isNull()) { return new ArkArrayByteValue(node, property); } else { - return new ArkArrayInt8(node, property); + return new ArkArrayUInt8(node, property); } } diff --git a/src/main/java/qowyn/ark/arrays/ArkArrayString.java b/src/main/java/qowyn/ark/arrays/ArkArrayString.java index 92d4b87..0ef4816 100644 --- a/src/main/java/qowyn/ark/arrays/ArkArrayString.java +++ b/src/main/java/qowyn/ark/arrays/ArkArrayString.java @@ -29,7 +29,7 @@ public ArkArrayString(ArkArchive archive, PropertyArray property) { } public ArkArrayString(JsonNode node, PropertyArray property) { - node.forEach(n -> this.add(n.asText())); + node.forEach(n -> this.add(n.textValue())); } @Override diff --git a/src/main/java/qowyn/ark/properties/PropertyStr.java b/src/main/java/qowyn/ark/properties/PropertyStr.java index e1631a3..60dd516 100644 --- a/src/main/java/qowyn/ark/properties/PropertyStr.java +++ b/src/main/java/qowyn/ark/properties/PropertyStr.java @@ -28,7 +28,7 @@ public PropertyStr(ArkArchive archive, ArkName name) { public PropertyStr(JsonNode node) { super(node); - value = node.path("value").asText(); + value = node.path("value").textValue(); } @Override diff --git a/src/main/java/qowyn/ark/types/ObjectReference.java b/src/main/java/qowyn/ark/types/ObjectReference.java index 1e8bb1b..dba42e0 100644 --- a/src/main/java/qowyn/ark/types/ObjectReference.java +++ b/src/main/java/qowyn/ark/types/ObjectReference.java @@ -103,7 +103,7 @@ public void readJson(JsonNode node) { objectId = node.asInt(); objectType = TYPE_ID; } else if (node.isTextual()) { - objectString = ArkName.from(node.asText()); + objectString = ArkName.from(node.textValue()); objectType = TYPE_PATH; } else { objectString = ArkName.from(node.path("value").asText()); @@ -176,4 +176,12 @@ public void collectNames(NameCollector collector) { } } + public boolean isId() { + return objectType == TYPE_ID; + } + + public boolean isPath() { + return objectType != TYPE_ID; + } + }