mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
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
This commit is contained in:
parent
ba4e0cf5b9
commit
25edf41329
7 changed files with 62 additions and 40 deletions
|
@ -36,20 +36,12 @@ import com.nukkitx.protocol.bedrock.data.inventory.PotionMixData;
|
||||||
import it.unimi.dsi.fastutil.Pair;
|
import it.unimi.dsi.fastutil.Pair;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
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.collision.translators.BlockCollision;
|
||||||
import org.geysermc.connector.network.translators.effect.Effect;
|
import org.geysermc.connector.network.translators.effect.Effect;
|
||||||
import org.geysermc.connector.network.translators.sound.SoundHandler;
|
import org.geysermc.connector.network.translators.sound.SoundHandler;
|
||||||
import org.geysermc.connector.network.translators.sound.SoundInteractionHandler;
|
import org.geysermc.connector.network.translators.sound.SoundInteractionHandler;
|
||||||
import org.geysermc.connector.network.translators.world.block.entity.BlockEntityTranslator;
|
import org.geysermc.connector.network.translators.world.block.entity.BlockEntityTranslator;
|
||||||
import org.geysermc.connector.registry.loader.BlockEntityRegistryLoader;
|
import org.geysermc.connector.registry.loader.*;
|
||||||
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.populator.ItemRegistryPopulator;
|
import org.geysermc.connector.registry.populator.ItemRegistryPopulator;
|
||||||
import org.geysermc.connector.registry.populator.RecipeRegistryPopulator;
|
import org.geysermc.connector.registry.populator.RecipeRegistryPopulator;
|
||||||
import org.geysermc.connector.registry.type.ItemMappings;
|
import org.geysermc.connector.registry.type.ItemMappings;
|
||||||
|
@ -67,7 +59,7 @@ public class Registries {
|
||||||
|
|
||||||
public static final SimpleMappedRegistry<Integer, BlockCollision> COLLISIONS = SimpleMappedRegistry.create(Pair.of("org.geysermc.connector.network.translators.collision.translators", "mappings/collision.json"), CollisionRegistryLoader::new);
|
public static final SimpleMappedRegistry<Integer, BlockCollision> COLLISIONS = SimpleMappedRegistry.create(Pair.of("org.geysermc.connector.network.translators.collision.translators", "mappings/collision.json"), CollisionRegistryLoader::new);
|
||||||
|
|
||||||
public static final VersionedRegistry<Map<RecipeType, List<CraftingData>>> CRAFTING_DATA = VersionedRegistry.create(RegistryLoaders.empty(Object2ObjectLinkedOpenHashMap::new));
|
public static final VersionedRegistry<Map<RecipeType, List<CraftingData>>> CRAFTING_DATA = VersionedRegistry.create(RegistryLoaders.empty(Int2ObjectOpenHashMap::new));
|
||||||
|
|
||||||
public static final SimpleRegistry<NbtMap> ENTITY_IDENTIFIERS = SimpleRegistry.create("bedrock/entity_identifiers.dat", RegistryLoaders.NBT);
|
public static final SimpleRegistry<NbtMap> ENTITY_IDENTIFIERS = SimpleRegistry.create("bedrock/entity_identifiers.dat", RegistryLoaders.NBT);
|
||||||
|
|
||||||
|
|
|
@ -25,23 +25,23 @@
|
||||||
|
|
||||||
package org.geysermc.connector.registry;
|
package org.geysermc.connector.registry;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
import org.geysermc.connector.registry.loader.RegistryLoader;
|
import org.geysermc.connector.registry.loader.RegistryLoader;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class VersionedRegistry<V> extends AbstractMappedRegistry<Integer, V, Map<Integer, V>> {
|
public class VersionedRegistry<V> extends AbstractMappedRegistry<Integer, V, Int2ObjectMap<V>> {
|
||||||
protected <I> VersionedRegistry(I input, RegistryLoader<I, Map<Integer, V>> registryLoader) {
|
protected <I> VersionedRegistry(I input, RegistryLoader<I, Int2ObjectMap<V>> registryLoader) {
|
||||||
super(input, registryLoader);
|
super(input, registryLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public V forVersion(int version) {
|
public V forVersion(int version) {
|
||||||
V value = null;
|
V value = null;
|
||||||
for (Map.Entry<Integer, V> entry : this.mappings.entrySet()) {
|
for (Int2ObjectMap.Entry<V> entry : this.mappings.int2ObjectEntrySet()) {
|
||||||
if (version < entry.getKey()) {
|
if (version < entry.getIntKey()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (version == entry.getKey()) {
|
if (version == entry.getIntKey()) {
|
||||||
return entry.getValue();
|
return entry.getValue();
|
||||||
}
|
}
|
||||||
value = entry.getValue();
|
value = entry.getValue();
|
||||||
|
@ -49,19 +49,19 @@ public class VersionedRegistry<V> extends AbstractMappedRegistry<Integer, V, Map
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <I, V> VersionedRegistry<V> create(RegistryLoader<I, Map<Integer, V>> registryLoader) {
|
public static <I, V> VersionedRegistry<V> create(RegistryLoader<I, Int2ObjectMap<V>> registryLoader) {
|
||||||
return new VersionedRegistry<>(null, registryLoader);
|
return new VersionedRegistry<>(null, registryLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <I, V> VersionedRegistry<V> create(I input, RegistryLoader<I, Map<Integer, V>> registryLoader) {
|
public static <I, V> VersionedRegistry<V> create(I input, RegistryLoader<I, Int2ObjectMap<V>> registryLoader) {
|
||||||
return new VersionedRegistry<>(input, registryLoader);
|
return new VersionedRegistry<>(input, registryLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <I, V> VersionedRegistry< V> create(Supplier<RegistryLoader<I, Map<Integer, V>>> registryLoader) {
|
public static <I, V> VersionedRegistry< V> create(Supplier<RegistryLoader<I, Int2ObjectMap<V>>> registryLoader) {
|
||||||
return new VersionedRegistry<>(null, registryLoader.get());
|
return new VersionedRegistry<>(null, registryLoader.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <I, V> VersionedRegistry< V> create(I input, Supplier<RegistryLoader<I, Map<Integer, V>>> registryLoader) {
|
public static <I, V> VersionedRegistry< V> create(I input, Supplier<RegistryLoader<I, Int2ObjectMap<V>>> registryLoader) {
|
||||||
return new VersionedRegistry<>(input, registryLoader.get());
|
return new VersionedRegistry<>(input, registryLoader.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -30,6 +30,7 @@ import com.google.common.collect.BiMap;
|
||||||
import it.unimi.dsi.fastutil.Pair;
|
import it.unimi.dsi.fastutil.Pair;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import org.geysermc.connector.GeyserConnector;
|
import org.geysermc.connector.GeyserConnector;
|
||||||
import org.geysermc.connector.network.translators.collision.BoundingBox;
|
import org.geysermc.connector.network.translators.collision.BoundingBox;
|
||||||
import org.geysermc.connector.network.translators.collision.CollisionRemapper;
|
import org.geysermc.connector.network.translators.collision.CollisionRemapper;
|
||||||
|
@ -43,9 +44,7 @@ import org.reflections.Reflections;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@ -55,14 +54,13 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader<String,
|
||||||
public Map<Integer, BlockCollision> load(Pair<String, String> input) {
|
public Map<Integer, BlockCollision> load(Pair<String, String> input) {
|
||||||
Int2ObjectMap<BlockCollision> collisions = new Int2ObjectOpenHashMap<>();
|
Int2ObjectMap<BlockCollision> collisions = new Int2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
List<Class<?>> collisionTypes = new ArrayList<>();
|
Map<Class<?>, CollisionInfo> annotationMap = new HashMap<>();
|
||||||
Map<Class<?>, CollisionRemapper> annotationMap = new HashMap<>();
|
|
||||||
Reflections ref = GeyserConnector.getInstance().useXmlReflections() ? FileUtils.getReflections(input.key()) : new Reflections(input.key());
|
Reflections ref = GeyserConnector.getInstance().useXmlReflections() ? FileUtils.getReflections(input.key()) : new Reflections(input.key());
|
||||||
for (Class<?> clazz : ref.getTypesAnnotatedWith(CollisionRemapper.class)) {
|
for (Class<?> clazz : ref.getTypesAnnotatedWith(CollisionRemapper.class)) {
|
||||||
GeyserConnector.getInstance().getLogger().debug("Found annotated collision translator: " + clazz.getCanonicalName());
|
GeyserConnector.getInstance().getLogger().debug("Found annotated collision translator: " + clazz.getCanonicalName());
|
||||||
|
|
||||||
collisionTypes.add(clazz);
|
CollisionRemapper collisionRemapper = clazz.getAnnotation(CollisionRemapper.class);
|
||||||
annotationMap.put(clazz, clazz.getAnnotation(CollisionRemapper.class));
|
annotationMap.put(clazz, new CollisionInfo(collisionRemapper, Pattern.compile(collisionRemapper.regex()), Pattern.compile(collisionRemapper.paramRegex())));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load collision mappings file
|
// Load collision mappings file
|
||||||
|
@ -80,7 +78,7 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader<String,
|
||||||
// Map of classes that don't change based on parameters that have already been created
|
// Map of classes that don't change based on parameters that have already been created
|
||||||
Map<Class<?>, BlockCollision> instantiatedCollision = new HashMap<>();
|
Map<Class<?>, BlockCollision> instantiatedCollision = new HashMap<>();
|
||||||
for (Map.Entry<String, Integer> entry : javaIdBlockMap.entrySet()) {
|
for (Map.Entry<String, Integer> 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) {
|
if (newCollision != null) {
|
||||||
instantiatedCollision.put(newCollision.getClass(), newCollision);
|
instantiatedCollision.put(newCollision.getClass(), newCollision);
|
||||||
}
|
}
|
||||||
|
@ -89,22 +87,21 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader<String,
|
||||||
return collisions;
|
return collisions;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BlockCollision instantiateCollision(String blockID, int numericBlockID, List<Class<?>> collisionTypes, Map<Class<?>, CollisionRemapper> annotationMap, Map<Class<?>, BlockCollision> instantiatedCollision, ArrayNode collisionList) {
|
private BlockCollision instantiateCollision(String blockID, int numericBlockID, Map<Class<?>, CollisionInfo> annotationMap, Map<Class<?>, BlockCollision> instantiatedCollision, ArrayNode collisionList) {
|
||||||
|
String[] blockIdParts = blockID.split("\\[");
|
||||||
String blockName = blockID.split("\\[")[0].replace("minecraft:", "");
|
String blockName = blockIdParts[0].replace("minecraft:", "");
|
||||||
String params = "";
|
String params = "";
|
||||||
if (blockID.contains("[")) {
|
if (blockID.contains("[")) {
|
||||||
params = "[" + blockID.split("\\[")[1];
|
params = "[" + blockIdParts[1];
|
||||||
}
|
}
|
||||||
int collisionIndex = BlockRegistries.JAVA_BLOCKS.get(numericBlockID).getCollisionIndex();
|
int collisionIndex = BlockRegistries.JAVA_BLOCKS.get(numericBlockID).getCollisionIndex();
|
||||||
|
|
||||||
for (Class<?> type : collisionTypes) {
|
for (Map.Entry<Class<?>, CollisionInfo> collisionRemappers : annotationMap.entrySet()) {
|
||||||
CollisionRemapper annotation = annotationMap.get(type);
|
Class<?> type = collisionRemappers.getKey();
|
||||||
|
CollisionInfo collisionInfo = collisionRemappers.getValue();
|
||||||
|
CollisionRemapper annotation = collisionInfo.collisionRemapper;
|
||||||
|
|
||||||
Pattern pattern = Pattern.compile(annotation.regex());
|
if (collisionInfo.pattern.matcher(blockName).find() && collisionInfo.paramsPattern.matcher(params).find()) {
|
||||||
Pattern paramsPattern = Pattern.compile(annotation.paramRegex());
|
|
||||||
|
|
||||||
if (pattern.matcher(blockName).find() && paramsPattern.matcher(params).find()) {
|
|
||||||
try {
|
try {
|
||||||
if (!annotation.usesParams() && instantiatedCollision.containsKey(type)) {
|
if (!annotation.usesParams() && instantiatedCollision.containsKey(type)) {
|
||||||
return instantiatedCollision.get(type);
|
return instantiatedCollision.get(type);
|
||||||
|
@ -168,4 +165,14 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader<String,
|
||||||
|
|
||||||
return collision;
|
return collision;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to prevent patterns from being compiled more than needed
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class CollisionInfo {
|
||||||
|
private final CollisionRemapper collisionRemapper;
|
||||||
|
private final Pattern pattern;
|
||||||
|
private final Pattern paramsPattern;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -42,6 +42,7 @@ import org.geysermc.connector.network.translators.world.chunk.ChunkSection;
|
||||||
import org.geysermc.connector.registry.BlockRegistries;
|
import org.geysermc.connector.registry.BlockRegistries;
|
||||||
import org.geysermc.connector.registry.type.BlockMapping;
|
import org.geysermc.connector.registry.type.BlockMapping;
|
||||||
import org.geysermc.connector.registry.type.BlockMappings;
|
import org.geysermc.connector.registry.type.BlockMappings;
|
||||||
|
import org.geysermc.connector.utils.BlockUtils;
|
||||||
import org.geysermc.connector.utils.FileUtils;
|
import org.geysermc.connector.utils.FileUtils;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
|
@ -165,7 +166,7 @@ public class BlockRegistryPopulator {
|
||||||
bedrockToJavaBlockMap.putIfAbsent(bedrockRuntimeId, javaRuntimeId);
|
bedrockToJavaBlockMap.putIfAbsent(bedrockRuntimeId, javaRuntimeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
String cleanJavaIdentifier = entry.getKey().split("\\[")[0];
|
String cleanJavaIdentifier = BlockUtils.getCleanIdentifier(entry.getKey());
|
||||||
|
|
||||||
// Get the tag needed for non-empty flower pots
|
// Get the tag needed for non-empty flower pots
|
||||||
if (entry.getValue().get("pottable") != null) {
|
if (entry.getValue().get("pottable") != null) {
|
||||||
|
|
|
@ -49,6 +49,7 @@ import org.geysermc.connector.network.translators.item.StoredItemMappings;
|
||||||
import org.geysermc.connector.registry.BlockRegistries;
|
import org.geysermc.connector.registry.BlockRegistries;
|
||||||
import org.geysermc.connector.registry.Registries;
|
import org.geysermc.connector.registry.Registries;
|
||||||
import org.geysermc.connector.registry.type.*;
|
import org.geysermc.connector.registry.type.*;
|
||||||
|
import org.geysermc.connector.utils.BlockUtils;
|
||||||
import org.geysermc.connector.utils.FileUtils;
|
import org.geysermc.connector.utils.FileUtils;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
@ -282,7 +283,8 @@ public class ItemRegistryPopulator {
|
||||||
String correctBedrockIdentifier = blockMappings.getBedrockBlockStates().get(aValidBedrockBlockId).getString("name");
|
String correctBedrockIdentifier = blockMappings.getBedrockBlockStates().get(aValidBedrockBlockId).getString("name");
|
||||||
boolean firstPass = true;
|
boolean firstPass = true;
|
||||||
for (Map.Entry<String, Integer> blockEntry : BlockRegistries.JAVA_IDENTIFIERS.get().entrySet()) {
|
for (Map.Entry<String, Integer> 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());
|
int bedrockBlockRuntimeId = blockMappings.getBedrockBlockId(blockEntry.getValue());
|
||||||
NbtMap blockTag = blockMappings.getBedrockBlockStates().get(bedrockBlockRuntimeId);
|
NbtMap blockTag = blockMappings.getBedrockBlockStates().get(bedrockBlockRuntimeId);
|
||||||
String bedrockName = blockTag.getString("name");
|
String bedrockName = blockTag.getString("name");
|
||||||
|
|
|
@ -27,6 +27,7 @@ package org.geysermc.connector.registry.type;
|
||||||
|
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
|
import org.geysermc.connector.utils.BlockUtils;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
@ -54,7 +55,7 @@ public class BlockMapping {
|
||||||
* @return the identifier without the additional block states
|
* @return the identifier without the additional block states
|
||||||
*/
|
*/
|
||||||
public String getCleanJavaIdentifier() {
|
public String getCleanJavaIdentifier() {
|
||||||
return javaIdentifier.split("\\[")[0];
|
return BlockUtils.getCleanIdentifier(javaIdentifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -225,6 +225,25 @@ public class BlockUtils {
|
||||||
return blockPos;
|
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
|
// 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) {
|
public static BlockCollision getCollision(int blockId, int x, int y, int z) {
|
||||||
BlockCollision collision = Registries.COLLISIONS.get(blockId);
|
BlockCollision collision = Registries.COLLISIONS.get(blockId);
|
||||||
|
|
Loading…
Reference in a new issue