From 25edf413292840bd0b7e37686a9c4b29130f7cc2 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 15 Jul 2021 18:03:41 -0400 Subject: [PATCH] Some optimizations - Fix recipe registry not using an int key-based map - Versioned registries now use Fastutil more effectively - Replace uses of String#split for block identifier manipulation with #indexOf and #substring - Reuse Patterns in collision loader --- .../connector/registry/Registries.java | 12 +----- .../connector/registry/VersionedRegistry.java | 20 ++++----- .../loader/CollisionRegistryLoader.java | 41 +++++++++++-------- .../populator/BlockRegistryPopulator.java | 3 +- .../populator/ItemRegistryPopulator.java | 4 +- .../connector/registry/type/BlockMapping.java | 3 +- .../geysermc/connector/utils/BlockUtils.java | 19 +++++++++ 7 files changed, 62 insertions(+), 40 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/registry/Registries.java b/connector/src/main/java/org/geysermc/connector/registry/Registries.java index cb23e9976..6a0498a79 100644 --- a/connector/src/main/java/org/geysermc/connector/registry/Registries.java +++ b/connector/src/main/java/org/geysermc/connector/registry/Registries.java @@ -36,20 +36,12 @@ import com.nukkitx.protocol.bedrock.data.inventory.PotionMixData; import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import org.geysermc.connector.network.translators.collision.translators.BlockCollision; import org.geysermc.connector.network.translators.effect.Effect; import org.geysermc.connector.network.translators.sound.SoundHandler; import org.geysermc.connector.network.translators.sound.SoundInteractionHandler; import org.geysermc.connector.network.translators.world.block.entity.BlockEntityTranslator; -import org.geysermc.connector.registry.loader.BlockEntityRegistryLoader; -import org.geysermc.connector.registry.loader.CollisionRegistryLoader; -import org.geysermc.connector.registry.loader.ParticleTypesRegistryLoader; -import org.geysermc.connector.registry.loader.PotionMixRegistryLoader; -import org.geysermc.connector.registry.loader.RegistryLoaders; -import org.geysermc.connector.registry.loader.SoundEffectsRegistryLoader; -import org.geysermc.connector.registry.loader.SoundHandlerRegistryLoader; -import org.geysermc.connector.registry.loader.SoundRegistryLoader; +import org.geysermc.connector.registry.loader.*; import org.geysermc.connector.registry.populator.ItemRegistryPopulator; import org.geysermc.connector.registry.populator.RecipeRegistryPopulator; import org.geysermc.connector.registry.type.ItemMappings; @@ -67,7 +59,7 @@ public class Registries { public static final SimpleMappedRegistry COLLISIONS = SimpleMappedRegistry.create(Pair.of("org.geysermc.connector.network.translators.collision.translators", "mappings/collision.json"), CollisionRegistryLoader::new); - public static final VersionedRegistry>> CRAFTING_DATA = VersionedRegistry.create(RegistryLoaders.empty(Object2ObjectLinkedOpenHashMap::new)); + public static final VersionedRegistry>> CRAFTING_DATA = VersionedRegistry.create(RegistryLoaders.empty(Int2ObjectOpenHashMap::new)); public static final SimpleRegistry ENTITY_IDENTIFIERS = SimpleRegistry.create("bedrock/entity_identifiers.dat", RegistryLoaders.NBT); diff --git a/connector/src/main/java/org/geysermc/connector/registry/VersionedRegistry.java b/connector/src/main/java/org/geysermc/connector/registry/VersionedRegistry.java index d29bcddaa..7bdc372ed 100644 --- a/connector/src/main/java/org/geysermc/connector/registry/VersionedRegistry.java +++ b/connector/src/main/java/org/geysermc/connector/registry/VersionedRegistry.java @@ -25,23 +25,23 @@ package org.geysermc.connector.registry; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import org.geysermc.connector.registry.loader.RegistryLoader; -import java.util.Map; import java.util.function.Supplier; -public class VersionedRegistry extends AbstractMappedRegistry> { - protected VersionedRegistry(I input, RegistryLoader> registryLoader) { +public class VersionedRegistry extends AbstractMappedRegistry> { + protected VersionedRegistry(I input, RegistryLoader> registryLoader) { super(input, registryLoader); } public V forVersion(int version) { V value = null; - for (Map.Entry entry : this.mappings.entrySet()) { - if (version < entry.getKey()) { + for (Int2ObjectMap.Entry entry : this.mappings.int2ObjectEntrySet()) { + if (version < entry.getIntKey()) { continue; } - if (version == entry.getKey()) { + if (version == entry.getIntKey()) { return entry.getValue(); } value = entry.getValue(); @@ -49,19 +49,19 @@ public class VersionedRegistry extends AbstractMappedRegistry VersionedRegistry create(RegistryLoader> registryLoader) { + public static VersionedRegistry create(RegistryLoader> registryLoader) { return new VersionedRegistry<>(null, registryLoader); } - public static VersionedRegistry create(I input, RegistryLoader> registryLoader) { + public static VersionedRegistry create(I input, RegistryLoader> registryLoader) { return new VersionedRegistry<>(input, registryLoader); } - public static VersionedRegistry< V> create(Supplier>> registryLoader) { + public static VersionedRegistry< V> create(Supplier>> registryLoader) { return new VersionedRegistry<>(null, registryLoader.get()); } - public static VersionedRegistry< V> create(I input, Supplier>> registryLoader) { + public static VersionedRegistry< V> create(I input, Supplier>> registryLoader) { return new VersionedRegistry<>(input, registryLoader.get()); } } \ No newline at end of file diff --git a/connector/src/main/java/org/geysermc/connector/registry/loader/CollisionRegistryLoader.java b/connector/src/main/java/org/geysermc/connector/registry/loader/CollisionRegistryLoader.java index a60dfdbca..70ba8b253 100644 --- a/connector/src/main/java/org/geysermc/connector/registry/loader/CollisionRegistryLoader.java +++ b/connector/src/main/java/org/geysermc/connector/registry/loader/CollisionRegistryLoader.java @@ -30,6 +30,7 @@ import com.google.common.collect.BiMap; import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import lombok.AllArgsConstructor; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.translators.collision.BoundingBox; import org.geysermc.connector.network.translators.collision.CollisionRemapper; @@ -43,9 +44,7 @@ import org.reflections.Reflections; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.regex.Pattern; @@ -55,14 +54,13 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader load(Pair input) { Int2ObjectMap collisions = new Int2ObjectOpenHashMap<>(); - List> collisionTypes = new ArrayList<>(); - Map, CollisionRemapper> annotationMap = new HashMap<>(); + Map, CollisionInfo> annotationMap = new HashMap<>(); Reflections ref = GeyserConnector.getInstance().useXmlReflections() ? FileUtils.getReflections(input.key()) : new Reflections(input.key()); for (Class clazz : ref.getTypesAnnotatedWith(CollisionRemapper.class)) { GeyserConnector.getInstance().getLogger().debug("Found annotated collision translator: " + clazz.getCanonicalName()); - collisionTypes.add(clazz); - annotationMap.put(clazz, clazz.getAnnotation(CollisionRemapper.class)); + CollisionRemapper collisionRemapper = clazz.getAnnotation(CollisionRemapper.class); + annotationMap.put(clazz, new CollisionInfo(collisionRemapper, Pattern.compile(collisionRemapper.regex()), Pattern.compile(collisionRemapper.paramRegex()))); } // Load collision mappings file @@ -80,7 +78,7 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader, BlockCollision> instantiatedCollision = new HashMap<>(); for (Map.Entry entry : javaIdBlockMap.entrySet()) { - BlockCollision newCollision = instantiateCollision(entry.getKey(), entry.getValue(), collisionTypes, annotationMap, instantiatedCollision, collisionList); + BlockCollision newCollision = instantiateCollision(entry.getKey(), entry.getValue(), annotationMap, instantiatedCollision, collisionList); if (newCollision != null) { instantiatedCollision.put(newCollision.getClass(), newCollision); } @@ -89,22 +87,21 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader> collisionTypes, Map, CollisionRemapper> annotationMap, Map, BlockCollision> instantiatedCollision, ArrayNode collisionList) { - - String blockName = blockID.split("\\[")[0].replace("minecraft:", ""); + private BlockCollision instantiateCollision(String blockID, int numericBlockID, Map, CollisionInfo> annotationMap, Map, BlockCollision> instantiatedCollision, ArrayNode collisionList) { + String[] blockIdParts = blockID.split("\\["); + String blockName = blockIdParts[0].replace("minecraft:", ""); String params = ""; if (blockID.contains("[")) { - params = "[" + blockID.split("\\[")[1]; + params = "[" + blockIdParts[1]; } int collisionIndex = BlockRegistries.JAVA_BLOCKS.get(numericBlockID).getCollisionIndex(); - for (Class type : collisionTypes) { - CollisionRemapper annotation = annotationMap.get(type); + for (Map.Entry, CollisionInfo> collisionRemappers : annotationMap.entrySet()) { + Class type = collisionRemappers.getKey(); + CollisionInfo collisionInfo = collisionRemappers.getValue(); + CollisionRemapper annotation = collisionInfo.collisionRemapper; - Pattern pattern = Pattern.compile(annotation.regex()); - Pattern paramsPattern = Pattern.compile(annotation.paramRegex()); - - if (pattern.matcher(blockName).find() && paramsPattern.matcher(params).find()) { + if (collisionInfo.pattern.matcher(blockName).find() && collisionInfo.paramsPattern.matcher(params).find()) { try { if (!annotation.usesParams() && instantiatedCollision.containsKey(type)) { return instantiatedCollision.get(type); @@ -168,4 +165,14 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader blockEntry : BlockRegistries.JAVA_IDENTIFIERS.get().entrySet()) { - if (blockEntry.getKey().split("\\[")[0].equals(javaBlockIdentifier)) { + String aBlockIdentifier = BlockUtils.getCleanIdentifier(blockEntry.getKey()); + if (aBlockIdentifier.equals(javaBlockIdentifier)) { int bedrockBlockRuntimeId = blockMappings.getBedrockBlockId(blockEntry.getValue()); NbtMap blockTag = blockMappings.getBedrockBlockStates().get(bedrockBlockRuntimeId); String bedrockName = blockTag.getString("name"); diff --git a/connector/src/main/java/org/geysermc/connector/registry/type/BlockMapping.java b/connector/src/main/java/org/geysermc/connector/registry/type/BlockMapping.java index 99045bb22..1602372b9 100644 --- a/connector/src/main/java/org/geysermc/connector/registry/type/BlockMapping.java +++ b/connector/src/main/java/org/geysermc/connector/registry/type/BlockMapping.java @@ -27,6 +27,7 @@ package org.geysermc.connector.registry.type; import lombok.Builder; import lombok.Value; +import org.geysermc.connector.utils.BlockUtils; import javax.annotation.Nullable; @@ -54,7 +55,7 @@ public class BlockMapping { * @return the identifier without the additional block states */ public String getCleanJavaIdentifier() { - return javaIdentifier.split("\\[")[0]; + return BlockUtils.getCleanIdentifier(javaIdentifier); } /** diff --git a/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java b/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java index ea613ef6b..5532a654d 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java @@ -225,6 +225,25 @@ public class BlockUtils { return blockPos; } + /** + * Taking in a complete Java block state identifier, output just the block ID of this block state without the states. + * Examples: + * minecraft:oak_log[axis=x] -> minecraft:oak_log + * minecraft:stone_brick_wall[east=low,north=tall,south=none,up=true,waterlogged=false,west=tall] -> minecraft:stone_brick_wall + * minecraft:stone -> minecraft:stone + * + * @param fullJavaIdentifier a full Java block identifier, with possible block states. + * @return a clean identifier in the format of minecraft:block + */ + public static String getCleanIdentifier(String fullJavaIdentifier) { + int stateIndex = fullJavaIdentifier.indexOf('['); + if (stateIndex == -1) { + // Identical to its clean variation + return fullJavaIdentifier; + } + return fullJavaIdentifier.substring(0, stateIndex); + } + // Note: these reuse classes, so don't try to store more than once instance or coordinates will get overwritten public static BlockCollision getCollision(int blockId, int x, int y, int z) { BlockCollision collision = Registries.COLLISIONS.get(blockId);