Skip to content

Commit

Permalink
0.6.3
Browse files Browse the repository at this point in the history
Important fixes for cluster and LocalProfile files, can affect map-saves too
Command export can now select objects by class
Added switches --without-references and --without-components to export command (use --without-references for items, unless you want the whole base too)
Command import is now able to import items into cluster files and into the LocalProfile (with caveats, items will lose durability if you exported them from a map)
Command modify is now able to mass-delete objects in maps, cluster and LocalProfile files
All creature commands, the tribe command and db command are now aware of hibernation
Improved detection of all object types, no longer based on their class name
  • Loading branch information
Qowyn committed Sep 18, 2017
1 parent a84838c commit c0fd5b2
Show file tree
Hide file tree
Showing 16 changed files with 832 additions and 250 deletions.
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>qowyn.ark</groupId>
<artifactId>ark-tools</artifactId>
<version>0.6.2</version>
<version>0.6.3</version>
<packaging>jar</packaging>

<name>ark-tools</name>
Expand All @@ -13,14 +13,14 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<launch4j.version>0.6.2.0</launch4j.version>
<launch4j.version>0.6.3.0</launch4j.version>
</properties>

<dependencies>
<dependency>
<groupId>qowyn.ark</groupId>
<artifactId>ark-savegame-toolkit</artifactId>
<version>0.8.0</version>
<version>0.8.1</version>
</dependency>

<dependency>
Expand Down
37 changes: 32 additions & 5 deletions src/main/java/qowyn/ark/tools/CommonFunctions.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,47 @@
import qowyn.ark.GameObject;
import qowyn.ark.GameObjectContainer;
import qowyn.ark.structs.StructLinearColor;
import qowyn.ark.tools.data.TeamType;
import qowyn.ark.types.ObjectReference;

public class CommonFunctions {
public final class CommonFunctions {

public static final JsonFactory JSON_FACTORY = new JsonFactory();

public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(JSON_FACTORY);

public static boolean onlyTamed(GameObject animal, GameObjectContainer saveFile) {
return animal.findPropertyValue("TargetingTeam", Integer.class).orElse(0) >= 50000;
public static boolean isCreature(GameObject object) {
return object.hasAnyProperty("bServerInitializedDino");
}

public static boolean onlyWild(GameObject animal, GameObjectContainer saveFile) {
return animal.findPropertyValue("TargetingTeam", Integer.class).orElse(0) < 50000;
public static boolean isDroppedItem(GameObject object) {
return object.hasAnyProperty("MyItem");
}

public static boolean isInventory(GameObject object) {
return object.hasAnyProperty("bInitializedMe");
}

public static boolean isPlayer(GameObject object) {
return object.hasAnyProperty("LinkedPlayerDataID");
}

public static boolean isStatusComponent(GameObject object) {
return object.hasAnyProperty("bServerFirstInitialized");
}

public static boolean isTamed(GameObject animal) {
TeamType teamType = TeamType.forTeam(animal.findPropertyValue("TargetingTeam", Integer.class).orElse(0));
return teamType.tamed;
}

public static boolean isWeapon(GameObject object) {
return object.hasAnyProperty("AssociatedPrimalItem") || object.hasAnyProperty("MyPawn");
}

public static boolean isWild(GameObject animal) {
TeamType teamType = TeamType.forTeam(animal.findPropertyValue("TargetingTeam", Integer.class).orElse(0));
return !teamType.tamed;
}

public static int getBaseLevel(GameObject animal, GameObjectContainer saveFile) {
Expand Down
58 changes: 36 additions & 22 deletions src/main/java/qowyn/ark/tools/CreatureListCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Expand All @@ -23,6 +23,8 @@
import joptsimple.OptionSpec;
import qowyn.ark.ArkSavegame;
import qowyn.ark.GameObject;
import qowyn.ark.GameObjectContainer;
import qowyn.ark.HibernationEntry;
import qowyn.ark.ReadingOptions;
import qowyn.ark.tools.data.Creature;
import qowyn.ark.tools.data.CustomDataContext;
Expand All @@ -31,6 +33,8 @@ public class CreatureListCommands {

private static ArkSavegame saveFile;

private static GameObjectContainer container;

private static OptionHandler optionHandler;

private static Path outputDirectory;
Expand Down Expand Up @@ -58,29 +62,25 @@ public static void creatures(OptionHandler optionHandler) {

public static void tamed(OptionHandler optionHandler) {
CreatureListCommands.optionHandler = optionHandler;
listImpl(CommonFunctions::onlyTamed);
listImpl(CommonFunctions::isTamed);
}

public static void wild(OptionHandler optionHandler) {
CreatureListCommands.optionHandler = optionHandler;
listImpl(CommonFunctions::onlyWild);
listImpl(CommonFunctions::isWild);
}

private static final List<String> KNOWN_CREATURES = Arrays.asList("Raft_BP_C", "Polar_Bear_C", "Ragnarok_Wyvern_Override_C", "Ragnarok_Wyvern_Override_Ice_C");

protected static boolean neededClasses(GameObject object) {
return object.getClassString().contains("_Character_") || object.getClassString().startsWith("DinoCharacterStatusComponent_") || KNOWN_CREATURES.contains(object.getClassString());
// Load everything that is not an item and either has a parent or components
// Drawback: includes structures and players
return !object.isItem() && (object.getParent() != null || !object.getComponents().isEmpty());
}

protected static boolean onlyTameable(GameObject object) {
return (!object.hasAnyProperty("bForceDisablingTaming") || !object.getPropertyValue("bForceDisablingTaming", Boolean.class)) || object.getClassString().equals("Raft_BP_C");
return !object.findPropertyValue("bForceDisablingTaming", Boolean.class).orElse(false) || object.getClassString().equals("Raft_BP_C");
}

protected static boolean onlyCreatures(GameObject object) {
return object.getClassString().contains("_Character_") || KNOWN_CREATURES.contains(object.getClassString());
}

protected static void listImpl(BiPredicate<GameObject, ArkSavegame> filter) {
protected static void listImpl(Predicate<GameObject> filter) {
try {
untameableSpec = optionHandler.accepts("include-untameable", "Include untameable high-level dinos.");
statisticsSpec = optionHandler.accepts("statistics", "Wrap list of dinos in statistics block.");
Expand All @@ -105,7 +105,7 @@ protected static void listImpl(BiPredicate<GameObject, ArkSavegame> filter) {
Path savePath = Paths.get(params.get(0));
outputDirectory = Paths.get(params.get(1));

ReadingOptions readingOptions = optionHandler.readingOptions().withObjectFilter(CreatureListCommands::neededClasses);
ReadingOptions readingOptions = optionHandler.readingOptions().withObjectFilter(CreatureListCommands::neededClasses).buildComponentTree(true);

Stopwatch stopwatch = new Stopwatch(optionHandler.useStopwatch());
saveFile = new ArkSavegame(savePath, readingOptions);
Expand All @@ -119,11 +119,24 @@ protected static void listImpl(BiPredicate<GameObject, ArkSavegame> filter) {
}
}

public static void writeAnimalLists(BiPredicate<GameObject, ArkSavegame> filter) {
Stream<GameObject> objectStream = saveFile.getObjects().parallelStream().filter(CreatureListCommands::onlyCreatures);
public static void writeAnimalLists(Predicate<GameObject> filter) {
if (!saveFile.getHibernationEntries().isEmpty()) {
List<GameObject> combinedObjects = new ArrayList<>(saveFile.getObjects());

for (HibernationEntry entry: saveFile.getHibernationEntries()) {
ObjectCollector collector = new ObjectCollector(entry, 1);
combinedObjects.addAll(collector.remap(combinedObjects.size()));
}

container = new GameObjectList(combinedObjects);
} else {
container = saveFile;
}

Stream<GameObject> objectStream = container.getObjects().parallelStream().filter(CommonFunctions::isCreature);

if (filter != null) {
objectStream = objectStream.filter(object -> filter.test(object, saveFile));
objectStream = objectStream.filter(filter::test);
}

if (!options.has(untameableSpec)) {
Expand Down Expand Up @@ -240,23 +253,23 @@ public static void writeList(Map.Entry<String, List<GameObject>> entry) {
generator.writeNumberField("count", filteredClasses.size());

IntSummaryStatistics statistics =
filteredClasses.stream().filter(a -> CommonFunctions.onlyWild(a, saveFile)).mapToInt(a -> CommonFunctions.getBaseLevel(a, saveFile)).summaryStatistics();
filteredClasses.stream().filter(CommonFunctions::isWild).mapToInt(a -> CommonFunctions.getBaseLevel(a, saveFile)).summaryStatistics();
if (statistics.getCount() > 0) {
generator.writeNumberField("wildMin", statistics.getMin());
generator.writeNumberField("wildMax", statistics.getMax());
generator.writeNumberField("wildAverage", statistics.getAverage());
}

IntSummaryStatistics tamedBaseStatistics =
filteredClasses.stream().filter(a -> CommonFunctions.onlyTamed(a, saveFile)).mapToInt(a -> CommonFunctions.getBaseLevel(a, saveFile)).summaryStatistics();
filteredClasses.stream().filter(CommonFunctions::isTamed).mapToInt(a -> CommonFunctions.getBaseLevel(a, saveFile)).summaryStatistics();
if (tamedBaseStatistics.getCount() > 0) {
generator.writeNumberField("tamedBaseMin", tamedBaseStatistics.getMin());
generator.writeNumberField("tamedBaseMax", tamedBaseStatistics.getMax());
generator.writeNumberField("tamedBaseAverage", tamedBaseStatistics.getAverage());
}

IntSummaryStatistics tamedFullStatistics =
filteredClasses.stream().filter(a -> CommonFunctions.onlyTamed(a, saveFile)).mapToInt(a -> CommonFunctions.getFullLevel(a, saveFile)).summaryStatistics();
filteredClasses.stream().filter(CommonFunctions::isTamed).mapToInt(a -> CommonFunctions.getFullLevel(a, saveFile)).summaryStatistics();
if (tamedFullStatistics.getCount() > 0) {
generator.writeNumberField("tamedFullMin", tamedFullStatistics.getMin());
generator.writeNumberField("tamedFullMax", tamedFullStatistics.getMax());
Expand All @@ -270,9 +283,10 @@ public static void writeList(Map.Entry<String, List<GameObject>> entry) {

CustomDataContext context = new CustomDataContext();
context.setLatLonCalculator(latLongCalculator);
context.setObjectContainer(saveFile);
context.setObjectContainer(container);
context.setSavegame(saveFile);
for (GameObject creatureObject : filteredClasses) {
Creature creature = new Creature(creatureObject, saveFile);
Creature creature = new Creature(creatureObject, container);
generator.writeStartObject();
creature.writeAllProperties(generator, context, options.has(writeAllFieldsSpec));
if (options.has(inventorySpec)) {
Expand Down
Loading

0 comments on commit c0fd5b2

Please sign in to comment.