From 2080db21cadfd499c1b3bb6cb410597ae119b89a Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 10 Apr 2021 19:22:41 -0700 Subject: [PATCH] warn about dead registry entries when debug mode is enabled --- .../dfsek/terra/config/pack/ConfigPack.java | 12 +++++ .../dfsek/terra/registry/OpenRegistry.java | 48 ++++++++++++++++--- .../terra/registry/config/FloraRegistry.java | 4 +- platforms/bukkit/build.gradle.kts | 10 ++-- .../terra/bukkit/listeners/TerraListener.java | 4 +- 5 files changed, 65 insertions(+), 13 deletions(-) diff --git a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java index a0f2c8bfe..abfeb2266 100644 --- a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java +++ b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java @@ -139,6 +139,7 @@ public class ConfigPack implements LoaderRegistrar { selfLoader.load(packPostTemplate, new FileInputStream(pack)); biomeProviderBuilder = packPostTemplate.getProviderBuilder(); biomeProviderBuilder.build(0); // Build dummy provider to catch errors at load time. + checkDeadEntries(main); } catch(FileNotFoundException e) { throw new LoadException("No pack.yml file found in " + folder.getAbsolutePath(), e); } @@ -183,6 +184,7 @@ public class ConfigPack implements LoaderRegistrar { selfLoader.load(packPostTemplate, file.getInputStream(pack)); biomeProviderBuilder = packPostTemplate.getProviderBuilder(); biomeProviderBuilder.build(0); // Build dummy provider to catch errors at load time. + checkDeadEntries(main); } catch(IOException e) { throw new LoadException("Unable to load pack.yml from ZIP file", e); } @@ -198,6 +200,16 @@ public class ConfigPack implements LoaderRegistrar { for(C template : configTemplates) registry.add(template.getID(), factory.build(template, main)); } + private void checkDeadEntries(TerraPlugin main) { + biomeRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in biome registry: '" + id + "'")); + paletteRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in palette registry: '" + id + "'")); + floraRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in flora registry: '" + id + "'")); + carverRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in carver registry: '" + id + "'")); + treeRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in tree registry: '" + id + "'")); + oreRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in ore registry: '" + id + "'")); + } + + private void load(long start, TerraPlugin main) throws ConfigException { main.getEventManager().callEvent(new ConfigPackPreLoadEvent(this)); diff --git a/common/src/main/java/com/dfsek/terra/registry/OpenRegistry.java b/common/src/main/java/com/dfsek/terra/registry/OpenRegistry.java index 1cd0b81f2..597b5f607 100644 --- a/common/src/main/java/com/dfsek/terra/registry/OpenRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/OpenRegistry.java @@ -7,18 +7,19 @@ import com.dfsek.terra.registry.exception.DuplicateEntryException; import java.lang.reflect.Type; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiConsumer; import java.util.function.Consumer; +import java.util.stream.Collectors; /** * Registry implementation with read/write access. For internal use only. * @param */ public class OpenRegistry implements Registry { - private final Map objects = new HashMap<>(); + private final Map> objects = new HashMap<>(); @Override public T load(Type type, Object o, ConfigLoader configLoader) throws LoadException { @@ -35,6 +36,10 @@ public class OpenRegistry implements Registry { * @param value Value to add. */ public boolean add(String identifier, T value) { + return add(identifier, new Entry<>(value)); + } + + protected boolean add(String identifier, Entry value) { boolean exists = objects.containsKey(identifier); objects.put(identifier, value); return exists; @@ -60,22 +65,22 @@ public class OpenRegistry implements Registry { @Override public T get(String identifier) { - return objects.get(identifier); + return objects.get(identifier).getValue(); } @Override public void forEach(Consumer consumer) { - objects.forEach((id, obj) -> consumer.accept(obj)); + objects.forEach((id, obj) -> consumer.accept(obj.getRaw())); } @Override public void forEach(BiConsumer consumer) { - objects.forEach(consumer); + objects.forEach((id, entry) -> consumer.accept(id, entry.getRaw())); } @Override public Set entries() { - return new HashSet<>(objects.values()); + return objects.values().stream().map(Entry::getRaw).collect(Collectors.toSet()); } @Override @@ -83,10 +88,41 @@ public class OpenRegistry implements Registry { return objects.keySet(); } + public Map getDeadEntries() { + Map dead = new HashMap<>(); + objects.forEach((id, entry) -> { + if(entry.dead()) dead.put(id, entry.value); // dont increment value here. + }); + return dead; + } + /** * Clears all entries from the registry. */ public void clear() { objects.clear(); } + + + protected static final class Entry { + private final T value; + private final AtomicInteger access = new AtomicInteger(0); + + public Entry(T value) { + this.value = value; + } + + public T getValue() { + access.incrementAndGet(); + return value; + } + + private T getRaw() { + return value; + } + + public boolean dead() { + return access.get() == 0; + } + } } diff --git a/common/src/main/java/com/dfsek/terra/registry/config/FloraRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/FloraRegistry.java index 71fd680cd..878890bff 100644 --- a/common/src/main/java/com/dfsek/terra/registry/config/FloraRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/config/FloraRegistry.java @@ -57,7 +57,9 @@ public class FloraRegistry extends OpenRegistry { private void addItem(String id, Callable flora) { try { - add(id, flora.call()); + Entry entry = new Entry<>(flora.call()); + entry.getValue(); // Mark as not dead. + add(id, entry); } catch(Exception e) { main.logger().warning("Failed to load Flora item: " + id + ": " + e.getMessage()); } diff --git a/platforms/bukkit/build.gradle.kts b/platforms/bukkit/build.gradle.kts index e9dac10e5..3b477791b 100644 --- a/platforms/bukkit/build.gradle.kts +++ b/platforms/bukkit/build.gradle.kts @@ -16,7 +16,7 @@ configureCommon() group = "com.dfsek.terra.bukkit" val mcVersion = "1.16.5" -val testDir = "target/server/" +val testDir = "target/server" val testMem = "3G" val paperURL = "https://papermc.io/api/v1/paper/%version%/latest/download/" @@ -42,14 +42,14 @@ dependencies { "shadedImplementation"("com.google.guava:guava:30.0-jre") } -val aikarsFlags = listOf("-XX:+UseG1GC", "-XX:+ParallelRefProcEnabled", "-XX:MaxGCPauseMillis=200", +val jvmFlags = listOf("-XX:+UseG1GC", "-XX:+ParallelRefProcEnabled", "-XX:MaxGCPauseMillis=200", "-XX:+UnlockExperimentalVMOptions", "-XX:+DisableExplicitGC", "-XX:+AlwaysPreTouch", "-XX:G1NewSizePercent=30", "-XX:G1MaxNewSizePercent=40", "-XX:G1HeapRegionSize=8M", "-XX:G1ReservePercent=20", "-XX:G1HeapWastePercent=5", "-XX:G1MixedGCCountTarget=4", "-XX:InitiatingHeapOccupancyPercent=15", "-XX:G1MixedGCLiveThresholdPercent=90", "-XX:G1RSetUpdatingPauseTimePercent=5", "-XX:SurvivorRatio=32", "-XX:+PerfDisableSharedMem", "-XX:MaxTenuringThreshold=1", "-Dusing.aikars.flags=https://mcflags.emc.gs", - "-Daikars.new.flags=true", "-DIReallyKnowWhatIAmDoingISwear") + "-Daikars.new.flags=true", "-DIReallyKnowWhatIAmDoingISwear", "-javaagent:paperclip.jar") fun downloadPaperclip(url: String, dir: String) { val clip = URL(url.replace("%version%", mcVersion)) @@ -160,7 +160,7 @@ task(name = "runPaper") { } main = "io.papermc.paperclip.Paperclip" - jvmArgs = aikarsFlags + jvmArgs = jvmFlags maxHeapSize = testMem minHeapSize = testMem //args = listOf("nogui") @@ -178,7 +178,7 @@ task(name = "runPurpur") { } main = "io.papermc.paperclip.Paperclip" - jvmArgs = aikarsFlags + jvmArgs = jvmFlags maxHeapSize = testMem minHeapSize = testMem //args = listOf("nogui") diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/TerraListener.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/TerraListener.java index 78615d036..4eb05f91e 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/TerraListener.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/TerraListener.java @@ -22,7 +22,9 @@ public class TerraListener implements EventListener { public void injectTrees(ConfigPackPreLoadEvent event) { for(TreeType value : TreeType.values()) { try { - event.getPack().getTreeRegistry().add(BukkitAdapter.TREE_TRANSFORMER.translate(value), new BukkitTree(value, main)); + String id = BukkitAdapter.TREE_TRANSFORMER.translate(value); + event.getPack().getTreeRegistry().add(id, new BukkitTree(value, main)); + event.getPack().getTreeRegistry().get(id); // Platform trees should never be marked "dead" } catch(DuplicateEntryException ignore) { // If another addon has already registered trees, do nothing. } }