From 6853eeefcc10f21a750449e3a1835248255a42bf Mon Sep 17 00:00:00 2001 From: Roland Firmont Date: Tue, 19 Sep 2017 11:44:34 +0200 Subject: [PATCH] 0.6.4 Fixed broken players command players command can now detect LocalPlayer.arkprofile Hibernation support for debug commands --- pom.xml | 4 +- .../java/qowyn/ark/tools/DebugCommands.java | 82 ++++++++++++++----- .../qowyn/ark/tools/PlayerListCommands.java | 8 +- 3 files changed, 70 insertions(+), 24 deletions(-) diff --git a/pom.xml b/pom.xml index 444241a..b95f8b9 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ qowyn.ark ark-tools - 0.6.3 + 0.6.4 jar ark-tools @@ -13,7 +13,7 @@ UTF-8 1.8 1.8 - 0.6.3.0 + 0.6.4.0 diff --git a/src/main/java/qowyn/ark/tools/DebugCommands.java b/src/main/java/qowyn/ark/tools/DebugCommands.java index e4a06d7..03a5dc4 100644 --- a/src/main/java/qowyn/ark/tools/DebugCommands.java +++ b/src/main/java/qowyn/ark/tools/DebugCommands.java @@ -8,19 +8,20 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Comparator; -import java.util.HashSet; +import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.concurrent.ConcurrentMap; import java.util.function.Predicate; import java.util.stream.Collectors; +import java.util.stream.Stream; import joptsimple.OptionSet; import joptsimple.OptionSpec; import qowyn.ark.ArkArchive; import qowyn.ark.ArkSavegame; import qowyn.ark.GameObject; +import qowyn.ark.HibernationEntry; import qowyn.ark.NameSizeCalculator; import qowyn.ark.ReadingOptions; import qowyn.ark.types.ArkName; @@ -51,28 +52,45 @@ public static void classes(OptionHandler oh) { Path savePath = Paths.get(params.get(0)); Stopwatch stopwatch = new Stopwatch(oh.useStopwatch()); + boolean withoutDupes = options.has(withoutDupesSpec); // Don't load any properties, we don't need them - ArkSavegame savegame = new ArkSavegame(savePath, ReadingOptions.create().withObjectFilter(o -> false)); + ArkSavegame savegame = new ArkSavegame(savePath, ReadingOptions.create().withObjectFilter(o -> false).buildComponentTree(withoutDupes)); stopwatch.stop("Loading"); List objects; + Map, GameObject>> objectMap; + + if (!savegame.getHibernationEntries().isEmpty()) { + objects = new ArrayList<>(savegame.getObjects()); + if (withoutDupes) { + objectMap = new HashMap<>(); + savegame.getObjectMap().forEach((key, map) -> objectMap.put(key, new HashMap<>(map))); + } else { + objectMap = null; + } - if (options.has(withoutDupesSpec)) { - Set nameSet = new HashSet<>(); - objects = new ArrayList<>(); - - for (GameObject object : savegame.getObjects()) { - if (object.getNames().size() != 1) { - objects.add(object); - } else if (!nameSet.contains(object.getNames().get(0))) { - objects.add(object); - nameSet.add(object.getNames().get(0)); + for (HibernationEntry entry: savegame.getHibernationEntries()) { + ObjectCollector collector = new ObjectCollector(entry, 1); + objects.addAll(collector.remap(objects.size())); + if (withoutDupes) { + for (GameObject object: collector) { + Integer key = object.isFromDataFile() ? object.getDataFileIndex() : null; + objectMap.computeIfAbsent(key, k -> new HashMap<>()).putIfAbsent(object.getNames(), object); + } } } } else { objects = savegame.getObjects(); + objectMap = savegame.getObjectMap(); + } + + if (withoutDupes) { + objects.removeIf(object -> { + Integer key = object.isFromDataFile() ? object.getDataFileIndex() : null; + return objectMap.get(key).get(object.getNames()) != object; + }); } ConcurrentMap> map = objects.parallelStream().collect(Collectors.groupingByConcurrent(GameObject::getClassString)); @@ -151,6 +169,14 @@ public static void dump(OptionHandler oh) { } } + for (HibernationEntry entry: savegame.getHibernationEntries()) { + for (GameObject object: entry) { + if (filter.test(object)) { + object.writeJson(generator, true); + } + } + } + generator.writeEndArray(); }; @@ -185,8 +211,15 @@ public static void sizes(OptionHandler oh) { stopwatch.stop("Loading"); - List pairList = savegame.getObjects().parallelStream() - .map(SizeObjectPair::new) + List hibernationObjects = new ArrayList<>(); + + for (HibernationEntry entry: savegame.getHibernationEntries()) { + hibernationObjects.addAll(entry.getObjects()); + } + + List pairList = Stream.concat( + savegame.getObjects().parallelStream().map(object -> new SizeObjectPair(object, savegame.getSaveVersion() < 6, false)), + hibernationObjects.parallelStream().map(object -> new SizeObjectPair(object, false, true))) .sorted(Comparator.comparingInt(SizeObjectPair::getSize).reversed()) .collect(Collectors.toList()); @@ -197,12 +230,20 @@ public static void sizes(OptionHandler oh) { for (SizeObjectPair pair: pairList) { generator.writeStartObject(); + generator.writeArrayFieldStart("names"); + for (ArkName name: pair.object.getNames()) { + generator.writeString(name.toString()); + } + generator.writeEndArray(); + if (pair.object.isFromDataFile()) { + generator.writeNumberField("dataFileIndex", pair.object.getDataFileIndex()); + } generator.writeStringField("class", pair.object.getClassString()); generator.writeNumberField("size", pair.size); generator.writeEndObject(); } - generator.writeEndObject(); + generator.writeEndArray(); }; if (params.size() > 1) { @@ -219,13 +260,16 @@ public static void sizes(OptionHandler oh) { } private static class SizeObjectPair { - private final static NameSizeCalculator NAME_SIZER = ArkArchive.getNameSizer(true); + private final static NameSizeCalculator ANCIENT_SIZER = ArkArchive.getNameSizer(false); + private final static NameSizeCalculator MODERN_SIZER = ArkArchive.getNameSizer(true); + private final static NameSizeCalculator HIBERNATION_SIZER = ArkArchive.getNameSizer(true, true); private final int size; private final GameObject object; - public SizeObjectPair(GameObject object) { + public SizeObjectPair(GameObject object, boolean ancient, boolean hibernation) { + NameSizeCalculator nameSizer = hibernation ? HIBERNATION_SIZER : ancient ? ANCIENT_SIZER : MODERN_SIZER; this.object = object; - this.size = object.getSize(NAME_SIZER) + object.getPropertiesSize(NAME_SIZER); + this.size = object.getSize(nameSizer) + object.getPropertiesSize(nameSizer); } public int getSize() { diff --git a/src/main/java/qowyn/ark/tools/PlayerListCommands.java b/src/main/java/qowyn/ark/tools/PlayerListCommands.java index 5d0085e..c0a8716 100644 --- a/src/main/java/qowyn/ark/tools/PlayerListCommands.java +++ b/src/main/java/qowyn/ark/tools/PlayerListCommands.java @@ -64,7 +64,7 @@ public class PlayerListCommands { - private static final Pattern PROFILE_PATTERN = Pattern.compile("\\d+\\.arkprofile"); + private static final Pattern PROFILE_PATTERN = Pattern.compile("(\\d+|LocalPlayer)\\.arkprofile"); private static final Pattern TRIBE_PATTERN = Pattern.compile("\\d+\\.arktribe"); @@ -109,8 +109,10 @@ public static void players(OptionHandler optionHandler) { CustomDataContext context = new CustomDataContext(); if (mapNeeded) { - context.setObjectContainer(new ArkSavegame(saveGame, optionHandler.readingOptions())); - context.setLatLonCalculator(LatLonCalculator.forSave(context.getSavegame())); + ArkSavegame mapSave = new ArkSavegame(saveGame, optionHandler.readingOptions().buildComponentTree(true)); + context.setObjectContainer(mapSave); + context.setSavegame(mapSave); + context.setLatLonCalculator(LatLonCalculator.forSave(mapSave)); stopwatch.stop("Loading map data"); }