diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index f679b412cc..0a8222f8d7 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -236,7 +236,6 @@ public void initialize() { Both the block registries and the common registries depend on each other, so maintaining this order is crucial for Geyser to load. */ - BlockRegistries.load(); Registries.load(); BlockRegistries.populate(); Registries.populate(); diff --git a/core/src/main/java/org/geysermc/geyser/registry/AbstractMappedDeferredRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/AbstractMappedDeferredRegistry.java new file mode 100644 index 0000000000..2506bb8734 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/AbstractMappedDeferredRegistry.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2024 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.registry; + +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.registry.loader.RegistryLoader; + +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.function.Supplier; + +public abstract class AbstractMappedDeferredRegistry, R extends AbstractMappedRegistry> extends DeferredRegistry { + protected AbstractMappedDeferredRegistry(Function, R> registryLoader, RegistryLoader deferredLoader) { + super(registryLoader, deferredLoader); + } + + protected AbstractMappedDeferredRegistry(Function, R> registryLoader, Supplier> deferredLoader) { + super(registryLoader, deferredLoader); + } + + protected AbstractMappedDeferredRegistry(I input, RegistryInitializer registryInitializer, RegistryLoader deferredLoader) { + super(input, registryInitializer, deferredLoader); + } + + protected AbstractMappedDeferredRegistry(I input, RegistryInitializer registryInitializer, Supplier> deferredLoader) { + super(input, registryInitializer, deferredLoader); + } + + /** + * Returns the value registered by the given key. + * + * @param key the key + * @return the value registered by the given key. + */ + public @Nullable V get(K key) { + return get().get(key); + } + + /** + * Returns and maps the value by the given key if present. + * + * @param key the key + * @param mapper the mapper + * @param the type + * @return the mapped value from the given key if present + */ + public Optional map(K key, Function mapper) { + V value = this.get(key); + if (value == null) { + return Optional.empty(); + } else { + return Optional.ofNullable(mapper.apply(value)); + } + } + + /** + * Returns the value registered by the given key or the default value + * specified if null. + * + * @param key the key + * @param defaultValue the default value + * @return the value registered by the given key or the default value + * specified if null. + */ + public V getOrDefault(K key, V defaultValue) { + return get().getOrDefault(key, defaultValue); + } + + /** + * Registers a new value into this registry with the given key. + * + * @param key the key + * @param value the value + * @return a new value into this registry with the given key. + */ + public V register(K key, V value) { + return get().put(key, value); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java b/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java index b7c5e2d071..521d675423 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java @@ -69,7 +69,7 @@ public class BlockRegistries { /** * A mapped registry containing which holds block IDs to its {@link BlockCollision}. */ - public static final ListRegistry COLLISIONS = ListRegistry.create(Pair.of("org.geysermc.geyser.translator.collision.CollisionRemapper", "mappings/collisions.nbt"), CollisionRegistryLoader::new); + public static final ListDeferredRegistry COLLISIONS = ListDeferredRegistry.create(Pair.of("org.geysermc.geyser.translator.collision.CollisionRemapper", "mappings/collisions.nbt"), CollisionRegistryLoader::new); /** * A registry which stores Java IDs to {@link Block}, containing miscellaneous information about @@ -130,23 +130,6 @@ public class BlockRegistries { */ public static final SimpleMappedRegistry CUSTOM_SKULLS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new)); - public static void load() { - BLOCKS.load(); - BLOCK_STATES.load(); - // collisions are loaded later, because they are initialized later - JAVA_BLOCKS.load(); - JAVA_IDENTIFIER_TO_ID.load(); - WATERLOGGED.load(); - INTERACTIVE.load(); - INTERACTIVE_MAY_BUILD.load(); - CUSTOM_BLOCKS.load(); - CUSTOM_BLOCK_STATE_OVERRIDES.load(); - NON_VANILLA_BLOCK_STATE_OVERRIDES.load(); - CUSTOM_BLOCK_ITEM_OVERRIDES.load(); - EXTENDED_COLLISION_BOXES.load(); - CUSTOM_SKULLS.load(); - } - public static void populate() { Blocks.VAULT.javaId(); // FIXME CustomSkullRegistryPopulator.populate(); @@ -160,5 +143,4 @@ public static void populate() { BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.INIT_BEDROCK); BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.POST_INIT); } - } diff --git a/core/src/main/java/org/geysermc/geyser/registry/DeferredRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/DeferredRegistry.java index ce77261aea..f4273edeaf 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/DeferredRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/registry/DeferredRegistry.java @@ -43,32 +43,36 @@ * * @param the value being held by the registry */ -public final class DeferredRegistry implements IRegistry { - private final Registry backingRegistry; +class DeferredRegistry> implements IRegistry { + private final R backingRegistry; private final Supplier loader; private boolean loaded; - private DeferredRegistry(Function, Registry> registryLoader, RegistryLoader deferredLoader) { + protected DeferredRegistry(Function, R> registryLoader, RegistryLoader deferredLoader) { this.backingRegistry = registryLoader.apply(RegistryLoaders.uninitialized()); this.loader = () -> deferredLoader.load(null); } - private DeferredRegistry(Function, Registry> registryLoader, Supplier> deferredLoader) { + protected DeferredRegistry(Function, R> registryLoader, Supplier> deferredLoader) { this.backingRegistry = registryLoader.apply(RegistryLoaders.uninitialized()); this.loader = () -> deferredLoader.get().load(null); } - private DeferredRegistry(I input, RegistryInitializer registryInitializer, RegistryLoader deferredLoader) { + protected DeferredRegistry(I input, RegistryInitializer registryInitializer, RegistryLoader deferredLoader) { this.backingRegistry = registryInitializer.initialize(input, RegistryLoaders.uninitialized()); this.loader = () -> deferredLoader.load(input); } - private DeferredRegistry(I input, RegistryInitializer registryInitializer, Supplier> deferredLoader) { + protected DeferredRegistry(I input, RegistryInitializer registryInitializer, Supplier> deferredLoader) { this.backingRegistry = registryInitializer.initialize(input, RegistryLoaders.uninitialized()); this.loader = () -> deferredLoader.get().load(input); } + protected R backingRegistry() { + return this.backingRegistry; + } + /** * Gets the underlying value held by this registry. * @@ -119,64 +123,12 @@ public boolean loaded() { return this.loaded; } - /** - * Creates a new deferred registry. - * - * @param registryLoader the registry loader - * @param deferredLoader the deferred loader - * @param the input type - * @param the registry type - * @return the new deferred registry - */ - public static DeferredRegistry create(Function, Registry> registryLoader, RegistryLoader deferredLoader) { - return new DeferredRegistry<>(registryLoader, deferredLoader); - } - - /** - * Creates a new deferred registry. - * - * @param registryLoader the registry loader - * @param deferredLoader the deferred loader - * @param the input type - * @param the registry type - * @return the new deferred registry - */ - public static DeferredRegistry create(Function, Registry> registryLoader, Supplier> deferredLoader) { - return new DeferredRegistry<>(registryLoader, deferredLoader); - } - - /** - * Creates a new deferred registry. - * - * @param registryInitializer the registry initializer - * @param deferredLoader the deferred loader - * @param the input type - * @param the registry type - * @return the new deferred registry - */ - public static DeferredRegistry create(I input, RegistryInitializer registryInitializer, RegistryLoader deferredLoader) { - return new DeferredRegistry<>(input, registryInitializer, deferredLoader); - } - - /** - * Creates a new deferred registry. - * - * @param registryInitializer the registry initializer - * @param deferredLoader the deferred loader - * @param the input type - * @param the registry type - * @return the new deferred registry - */ - public static DeferredRegistry create(I input, RegistryInitializer registryInitializer, Supplier> deferredLoader) { - return new DeferredRegistry<>(input, registryInitializer, deferredLoader); - } - /** * A registry initializer. * * @param the registry type */ - interface RegistryInitializer { + public interface RegistryInitializer> { /** * Initializes the registry. @@ -186,6 +138,6 @@ interface RegistryInitializer { * @param the input type * @return the initialized registry */ - Registry initialize(I input, RegistryLoader registryLoader); + R initialize(I input, RegistryLoader registryLoader); } } diff --git a/core/src/main/java/org/geysermc/geyser/registry/ListDeferredRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/ListDeferredRegistry.java new file mode 100644 index 0000000000..91dc74eb78 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/ListDeferredRegistry.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2024 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.registry; + +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.registry.loader.RegistryLoader; + +import java.util.List; +import java.util.function.Function; +import java.util.function.Supplier; + +public class ListDeferredRegistry extends DeferredRegistry, ListRegistry> { + protected ListDeferredRegistry(Function>, ListRegistry> registryLoader, RegistryLoader> deferredLoader) { + super(registryLoader, deferredLoader); + } + + protected ListDeferredRegistry(Function>, ListRegistry> registryLoader, Supplier>> deferredLoader) { + super(registryLoader, deferredLoader); + } + + protected ListDeferredRegistry(I input, RegistryInitializer, ListRegistry> registryInitializer, RegistryLoader> deferredLoader) { + super(input, registryInitializer, deferredLoader); + } + + protected ListDeferredRegistry(I input, RegistryInitializer, ListRegistry> registryInitializer, Supplier>> deferredLoader) { + super(input, registryInitializer, deferredLoader); + } + /** + * Returns the value registered by the given index. + * + * @param index the index + * @return the value registered by the given index. + */ + @Nullable + public V get(int index) { + return backingRegistry().get(index); + } + + /** + * Returns the value registered by the given index or the default value + * specified if null. + * + * @param index the index + * @param defaultValue the default value + * @return the value registered by the given key or the default value + * specified if null. + */ + public V getOrDefault(int index, V defaultValue) { + return backingRegistry().getOrDefault(index, defaultValue); + } + + /** + * Registers a new value into this registry with the given index. + * + * @param index the index + * @param value the value + * @return a new value into this registry with the given index. + */ + public V register(int index, V value) { + return backingRegistry().register(index, value); + } + + /** + * Registers a new value into this registry with the given index, even if this value would normally be outside + * the range of a list. + * + * @param index the index + * @param value the value + * @param defaultValue the default value to fill empty spaces in the registry with. + * @return a new value into this registry with the given index. + */ + public V registerWithAnyIndex(int index, V value, V defaultValue) { + return backingRegistry().registerWithAnyIndex(index, value, defaultValue); + } + + /** + * Mark this registry as unsuitable for new additions. The backing list will then be optimized for storage. + */ + public void freeze() { + backingRegistry().freeze(); + } + + /** + * Creates a new deferred registry. + * + * @param registryLoader the registry loader + * @param deferredLoader the deferred loader + * @param the input type + * @return the new deferred registry + */ + public static ListDeferredRegistry create(Function>, ListRegistry> registryLoader, RegistryLoader> deferredLoader) { + return new ListDeferredRegistry<>(registryLoader, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param registryLoader the registry loader + * @param deferredLoader the deferred loader + * @param the input type + * @return the new deferred registry + */ + public static ListDeferredRegistry create(Function>, ListRegistry> registryLoader, Supplier>> deferredLoader) { + return new ListDeferredRegistry<>(registryLoader, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param registryInitializer the registry initializer + * @param deferredLoader the deferred loader + * @param the input type + * @return the new deferred registry + */ + public static ListDeferredRegistry create(I input, RegistryInitializer, ListRegistry> registryInitializer, RegistryLoader> deferredLoader) { + return new ListDeferredRegistry<>(input, registryInitializer, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param registryInitializer the registry initializer + * @param deferredLoader the deferred loader + * @param the input type + * @return the new deferred registry + */ + public static ListDeferredRegistry create(I input, RegistryInitializer, ListRegistry> registryInitializer, Supplier>> deferredLoader) { + return new ListDeferredRegistry<>(input, registryInitializer, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param deferredLoader the deferred loader + * @param the input type + * @return the new deferred registry + */ + public static ListDeferredRegistry create(I input, RegistryLoader> deferredLoader) { + return create(input, ListRegistry::create, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param deferredLoader the deferred loader + * @param the input type + * @return the new deferred registry + */ + public static ListDeferredRegistry create(I input, Supplier>> deferredLoader) { + return create(input, ListRegistry::create, deferredLoader); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java index 2070d67aef..d1d3d7af06 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java @@ -140,6 +140,18 @@ public static ListRegistry create(RegistryLoader> registryL return new ListRegistry<>(null, registryLoader); } + /** + * Creates a new integer mapped registry with the given {@link RegistryLoader} and input. + * + * @param registryLoader the registry loader + * @param the input + * @param the type value + * @return a new registry with the given RegistryLoader + */ + public static ListRegistry create(I input, RegistryLoader> registryLoader) { + return new ListRegistry<>(input, registryLoader); + } + /** * Creates a new integer mapped registry with the given {@link RegistryLoader} and input. * diff --git a/core/src/main/java/org/geysermc/geyser/registry/Registries.java b/core/src/main/java/org/geysermc/geyser/registry/Registries.java index b86ea3bbff..0d286d5c34 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/Registries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/Registries.java @@ -37,10 +37,18 @@ import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.recipe.GeyserRecipe; import org.geysermc.geyser.item.type.Item; -import org.geysermc.geyser.registry.loader.*; +import org.geysermc.geyser.registry.loader.BiomeIdentifierRegistryLoader; +import org.geysermc.geyser.registry.loader.BlockEntityRegistryLoader; +import org.geysermc.geyser.registry.loader.ParticleTypesRegistryLoader; +import org.geysermc.geyser.registry.loader.PotionMixRegistryLoader; +import org.geysermc.geyser.registry.loader.ProviderRegistryLoader; +import org.geysermc.geyser.registry.loader.RecipeRegistryLoader; +import org.geysermc.geyser.registry.loader.RegistryLoaders; +import org.geysermc.geyser.registry.loader.SoundEventsRegistryLoader; +import org.geysermc.geyser.registry.loader.SoundRegistryLoader; +import org.geysermc.geyser.registry.loader.SoundTranslatorRegistryLoader; import org.geysermc.geyser.registry.populator.ItemRegistryPopulator; import org.geysermc.geyser.registry.populator.PacketRegistryPopulator; -import org.geysermc.geyser.registry.loader.RecipeRegistryLoader; import org.geysermc.geyser.registry.provider.ProviderSupplier; import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.registry.type.ParticleMapping; @@ -56,7 +64,13 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ParticleType; import org.geysermc.mcprotocollib.protocol.data.game.recipe.RecipeType; -import java.util.*; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.HashSet; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * Holds all the common registries in Geyser. @@ -73,7 +87,7 @@ public final class Registries { /** * A registry holding a NbtMap of the known entity identifiers. */ - public static final SimpleRegistry BEDROCK_ENTITY_IDENTIFIERS = SimpleRegistry.create("bedrock/entity_identifiers.dat", RegistryLoaders.NBT); + public static final SimpleDeferredRegistry BEDROCK_ENTITY_IDENTIFIERS = SimpleDeferredRegistry.create("bedrock/entity_identifiers.dat", RegistryLoaders.NBT); /** * A registry containing all the Bedrock packet translators. @@ -83,17 +97,17 @@ public final class Registries { /** * A registry holding a NbtMap of all the known biomes. */ - public static final SimpleRegistry BIOMES_NBT = SimpleRegistry.create("bedrock/biome_definitions.dat", RegistryLoaders.NBT); + public static final SimpleDeferredRegistry BIOMES_NBT = SimpleDeferredRegistry.create("bedrock/biome_definitions.dat", RegistryLoaders.NBT); /** * A mapped registry which stores Java biome identifiers and their Bedrock biome identifier. */ - public static final SimpleRegistry> BIOME_IDENTIFIERS = SimpleRegistry.create("mappings/biomes.json", BiomeIdentifierRegistryLoader::new); + public static final SimpleDeferredRegistry> BIOME_IDENTIFIERS = SimpleDeferredRegistry.create("mappings/biomes.json", BiomeIdentifierRegistryLoader::new); /** * A mapped registry which stores a block entity identifier to its {@link BlockEntityTranslator}. */ - public static final SimpleMappedRegistry BLOCK_ENTITIES = SimpleMappedRegistry.create("org.geysermc.geyser.translator.level.block.entity.BlockEntity", BlockEntityRegistryLoader::new); + public static final SimpleMappedDeferredRegistry BLOCK_ENTITIES = SimpleMappedDeferredRegistry.create("org.geysermc.geyser.translator.level.block.entity.BlockEntity", BlockEntityRegistryLoader::new); /** * A map containing all entity types and their respective Geyser definitions @@ -135,55 +149,50 @@ public final class Registries { * A mapped registry holding the {@link ParticleType} to a corresponding {@link ParticleMapping}, containing various pieces of * data primarily for how Bedrock should handle the particle. */ - public static final SimpleMappedRegistry PARTICLES = SimpleMappedRegistry.create("mappings/particles.json", ParticleTypesRegistryLoader::new); + public static final SimpleMappedDeferredRegistry PARTICLES = SimpleMappedDeferredRegistry.create("mappings/particles.json", ParticleTypesRegistryLoader::new); /** * A registry holding all the potion mixes. */ - public static final VersionedRegistry> POTION_MIXES = VersionedRegistry.create(PotionMixRegistryLoader::new); + public static final VersionedDeferredRegistry> POTION_MIXES = VersionedDeferredRegistry.create(VersionedRegistry::create, PotionMixRegistryLoader::new); /** * A versioned registry holding all the recipes, with the net ID being the key, and {@link GeyserRecipe} as the value. */ - public static final SimpleMappedRegistry> RECIPES = SimpleMappedRegistry.create("mappings/recipes.nbt", RecipeRegistryLoader::new); + public static final SimpleMappedDeferredRegistry> RECIPES = SimpleMappedDeferredRegistry.create("mappings/recipes.nbt", RecipeRegistryLoader::new); /** * A mapped registry holding {@link ResourcePack}'s with the pack uuid as keys. */ - public static final DeferredRegistry> RESOURCE_PACKS = DeferredRegistry.create(GeyserImpl.getInstance().packDirectory(), SimpleMappedRegistry::create, RegistryLoaders.RESOURCE_PACKS); + public static final SimpleMappedDeferredRegistry RESOURCE_PACKS = SimpleMappedDeferredRegistry.create(GeyserImpl.getInstance().packDirectory(), RegistryLoaders.RESOURCE_PACKS); /** * A mapped registry holding sound identifiers to their corresponding {@link SoundMapping}. */ - public static final SimpleMappedRegistry SOUNDS = SimpleMappedRegistry.create("mappings/sounds.json", SoundRegistryLoader::new); + public static final SimpleMappedDeferredRegistry SOUNDS = SimpleMappedDeferredRegistry.create("mappings/sounds.json", SoundRegistryLoader::new); /** * A mapped registry holding {@link LevelEvent}s to their corresponding {@link LevelEventTranslator}. */ - public static final SimpleMappedRegistry SOUND_LEVEL_EVENTS = SimpleMappedRegistry.create("mappings/effects.json", SoundEventsRegistryLoader::new); + public static final SimpleMappedDeferredRegistry SOUND_LEVEL_EVENTS = SimpleMappedDeferredRegistry.create("mappings/effects.json", SoundEventsRegistryLoader::new); /** * A mapped registry holding {@link SoundTranslator}s to their corresponding {@link SoundInteractionTranslator}. */ - public static final SimpleMappedRegistry> SOUND_TRANSLATORS = SimpleMappedRegistry.create("org.geysermc.geyser.translator.sound.SoundTranslator", SoundTranslatorRegistryLoader::new); + public static final SimpleMappedDeferredRegistry> SOUND_TRANSLATORS = SimpleMappedDeferredRegistry.create("org.geysermc.geyser.translator.sound.SoundTranslator", SoundTranslatorRegistryLoader::new); public static void load() { if (loaded) return; loaded = true; - PROVIDERS.load(); + // the following registries are registries that are more complicated than initializing as an empty collection. + // They generally have in common that they either depend on loading a resource file directly or indirectly + // (by using the Items or Blocks class, which loads all the blocks) + BEDROCK_ENTITY_IDENTIFIERS.load(); - BEDROCK_PACKET_TRANSLATORS.load(); BIOMES_NBT.load(); BIOME_IDENTIFIERS.load(); BLOCK_ENTITIES.load(); - ENTITY_DEFINITIONS.load(); - BEDROCK_ENTITY_PROPERTIES.load(); - JAVA_ENTITY_IDENTIFIERS.load(); - JAVA_PACKET_TRANSLATORS.load(); - JAVA_ITEMS.load(); - JAVA_ITEM_IDENTIFIERS.load(); - ITEMS.load(); PARTICLES.load(); // load potion mixes later RECIPES.load(); diff --git a/core/src/main/java/org/geysermc/geyser/registry/Registry.java b/core/src/main/java/org/geysermc/geyser/registry/Registry.java index 4e83a3c2e2..8a82af0538 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/Registry.java +++ b/core/src/main/java/org/geysermc/geyser/registry/Registry.java @@ -27,7 +27,6 @@ import java.util.function.Consumer; import org.geysermc.geyser.registry.loader.RegistryLoader; -import org.geysermc.geyser.registry.loader.RegistryLoaderHolder; /** * A wrapper around a value which is loaded based on the output from the provided @@ -63,9 +62,7 @@ * * @param the value being held by the registry */ -@SuppressWarnings("rawtypes") public abstract class Registry implements IRegistry { - protected RegistryLoaderHolder loaderHolder; protected M mappings; /** @@ -78,17 +75,7 @@ public abstract class Registry implements IRegistry { * @param the input type */ protected Registry(I input, RegistryLoader registryLoader) { - this.loaderHolder = new RegistryLoaderHolder<>(input, registryLoader); - } - - public void load() { - // don't load twice - if (this.mappings != null) return; - - var holder = this.loaderHolder; - this.loaderHolder = null; - //noinspection unchecked - this.mappings = (M) holder.registryLoader().load(holder.input()); + this.mappings = registryLoader.load(input); } /** diff --git a/core/src/main/java/org/geysermc/geyser/registry/SimpleDeferredRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/SimpleDeferredRegistry.java new file mode 100644 index 0000000000..cdbd985be9 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/SimpleDeferredRegistry.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2024 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.registry; + +import org.geysermc.geyser.registry.loader.RegistryLoader; + +import java.util.function.Function; +import java.util.function.Supplier; + +public class SimpleDeferredRegistry extends DeferredRegistry> { + protected SimpleDeferredRegistry(Function, SimpleRegistry> registryLoader, RegistryLoader deferredLoader) { + super(registryLoader, deferredLoader); + } + + protected SimpleDeferredRegistry(Function, SimpleRegistry> registryLoader, Supplier> deferredLoader) { + super(registryLoader, deferredLoader); + } + + protected SimpleDeferredRegistry(I input, RegistryInitializer> registryInitializer, RegistryLoader deferredLoader) { + super(input, registryInitializer, deferredLoader); + } + + protected SimpleDeferredRegistry(I input, RegistryInitializer> registryInitializer, Supplier> deferredLoader) { + super(input, registryInitializer, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param registryLoader the registry loader + * @param deferredLoader the deferred loader + * @param the input type + * @return the new deferred registry + */ + public static SimpleDeferredRegistry create(Function, SimpleRegistry> registryLoader, RegistryLoader deferredLoader) { + return new SimpleDeferredRegistry<>(registryLoader, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param registryLoader the registry loader + * @param deferredLoader the deferred loader + * @param the input type + * @return the new deferred registry + */ + public static SimpleDeferredRegistry create(Function, SimpleRegistry> registryLoader, Supplier> deferredLoader) { + return new SimpleDeferredRegistry<>(registryLoader, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param registryInitializer the registry initializer + * @param deferredLoader the deferred loader + * @param the input type + * @return the new deferred registry + */ + public static SimpleDeferredRegistry create(I input, RegistryInitializer> registryInitializer, RegistryLoader deferredLoader) { + return new SimpleDeferredRegistry<>(input, registryInitializer, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param registryInitializer the registry initializer + * @param deferredLoader the deferred loader + * @param the input type + * @return the new deferred registry + */ + public static SimpleDeferredRegistry create(I input, RegistryInitializer> registryInitializer, Supplier> deferredLoader) { + return new SimpleDeferredRegistry<>(input, registryInitializer, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param deferredLoader the deferred loader + * @param the input type + * @return the new deferred registry + */ + public static SimpleDeferredRegistry create(I input, RegistryLoader deferredLoader) { + return create(input, SimpleRegistry::create, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param deferredLoader the deferred loader + * @param the input type + * @return the new deferred registry + */ + public static SimpleDeferredRegistry create(I input, Supplier> deferredLoader) { + return create(input, SimpleRegistry::create, deferredLoader); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/SimpleMappedDeferredRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/SimpleMappedDeferredRegistry.java new file mode 100644 index 0000000000..6a837c9e03 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/SimpleMappedDeferredRegistry.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2024 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.registry; + +import org.geysermc.geyser.registry.loader.RegistryLoader; + +import java.util.Map; +import java.util.function.Function; +import java.util.function.Supplier; + +public class SimpleMappedDeferredRegistry extends AbstractMappedDeferredRegistry, SimpleMappedRegistry> { + protected SimpleMappedDeferredRegistry(Function>, SimpleMappedRegistry> registryLoader, RegistryLoader> deferredLoader) { + super(registryLoader, deferredLoader); + } + + protected SimpleMappedDeferredRegistry(Function>, SimpleMappedRegistry> registryLoader, Supplier>> deferredLoader) { + super(registryLoader, deferredLoader); + } + + protected SimpleMappedDeferredRegistry(I input, RegistryInitializer, SimpleMappedRegistry> registryInitializer, RegistryLoader> deferredLoader) { + super(input, registryInitializer, deferredLoader); + } + + protected SimpleMappedDeferredRegistry(I input, RegistryInitializer, SimpleMappedRegistry> registryInitializer, Supplier>> deferredLoader) { + super(input, registryInitializer, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param registryLoader the registry loader + * @param deferredLoader the deferred loader + * @param the input type + * @return the new deferred registry + */ + public static SimpleMappedDeferredRegistry create(Function>, SimpleMappedRegistry> registryLoader, RegistryLoader> deferredLoader) { + return new SimpleMappedDeferredRegistry<>(registryLoader, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param registryLoader the registry loader + * @param deferredLoader the deferred loader + * @param the input type + * @return the new deferred registry + */ + public static SimpleMappedDeferredRegistry create(Function>, SimpleMappedRegistry> registryLoader, Supplier>> deferredLoader) { + return new SimpleMappedDeferredRegistry<>(registryLoader, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param registryInitializer the registry initializer + * @param deferredLoader the deferred loader + * @param the input type + * @return the new deferred registry + */ + public static SimpleMappedDeferredRegistry create(I input, DeferredRegistry.RegistryInitializer, SimpleMappedRegistry> registryInitializer, RegistryLoader> deferredLoader) { + return new SimpleMappedDeferredRegistry<>(input, registryInitializer, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param registryInitializer the registry initializer + * @param deferredLoader the deferred loader + * @param the input type + * @return the new deferred registry + */ + public static SimpleMappedDeferredRegistry create(I input, DeferredRegistry.RegistryInitializer, SimpleMappedRegistry> registryInitializer, Supplier>> deferredLoader) { + return new SimpleMappedDeferredRegistry<>(input, registryInitializer, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param deferredLoader the deferred loader + * @param the input type + * @return the new deferred registry + */ + public static SimpleMappedDeferredRegistry create(I input, RegistryLoader> deferredLoader) { + return create(input, SimpleMappedRegistry::create, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param deferredLoader the deferred loader + * @param the input type + * @return the new deferred registry + */ + public static SimpleMappedDeferredRegistry create(I input, Supplier>> deferredLoader) { + return create(input, SimpleMappedRegistry::create, deferredLoader); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/VersionedDeferredRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/VersionedDeferredRegistry.java new file mode 100644 index 0000000000..6b2f9906bd --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/VersionedDeferredRegistry.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2024 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.registry; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.registry.loader.RegistryLoader; + +import java.util.function.Function; +import java.util.function.Supplier; + +public class VersionedDeferredRegistry extends AbstractMappedDeferredRegistry, VersionedRegistry> { + protected VersionedDeferredRegistry(Function>, VersionedRegistry> registryLoader, RegistryLoader> deferredLoader) { + super(registryLoader, deferredLoader); + } + + protected VersionedDeferredRegistry(Function>, VersionedRegistry> registryLoader, Supplier>> deferredLoader) { + super(registryLoader, deferredLoader); + } + + protected VersionedDeferredRegistry(I input, RegistryInitializer, VersionedRegistry> registryInitializer, RegistryLoader> deferredLoader) { + super(input, registryInitializer, deferredLoader); + } + + protected VersionedDeferredRegistry(I input, RegistryInitializer, VersionedRegistry> registryInitializer, Supplier>> deferredLoader) { + super(input, registryInitializer, deferredLoader); + } + + /** + * Gets the closest value for the specified version. Only + * returns versions higher up than the specified if one + * does not exist for the given one. Useful in the event + * that you want to get a resource which is guaranteed for + * older versions, but not on newer ones. + * + * @param version the version + * @return the closest value for the specified version + * @throws IllegalArgumentException if no values exist at or above the given version + */ + @NonNull + public V forVersion(int version) { + return backingRegistry().forVersion(version); + } + /** + * Creates a new deferred registry. + * + * @param registryLoader the registry loader + * @param deferredLoader the deferred loader + * @param the input type + * @return the new deferred registry + */ + public static VersionedDeferredRegistry create(Function>, VersionedRegistry> registryLoader, RegistryLoader> deferredLoader) { + return new VersionedDeferredRegistry<>(registryLoader, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param registryLoader the registry loader + * @param deferredLoader the deferred loader + * @param the input type + * @return the new deferred registry + */ + public static VersionedDeferredRegistry create(Function>, VersionedRegistry> registryLoader, Supplier>> deferredLoader) { + return new VersionedDeferredRegistry<>(registryLoader, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param registryInitializer the registry initializer + * @param deferredLoader the deferred loader + * @param the input type + * @return the new deferred registry + */ + public static VersionedDeferredRegistry create(I input, RegistryInitializer, VersionedRegistry> registryInitializer, RegistryLoader> deferredLoader) { + return new VersionedDeferredRegistry<>(input, registryInitializer, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param registryInitializer the registry initializer + * @param deferredLoader the deferred loader + * @param the input type + * @return the new deferred registry + */ + public static VersionedDeferredRegistry create(I input, RegistryInitializer, VersionedRegistry> registryInitializer, Supplier>> deferredLoader) { + return new VersionedDeferredRegistry<>(input, registryInitializer, deferredLoader); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/RegistryLoaderHolder.java b/core/src/main/java/org/geysermc/geyser/registry/loader/RegistryLoaderHolder.java deleted file mode 100644 index 751cb4ed4d..0000000000 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/RegistryLoaderHolder.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2024 GeyserMC. http://geysermc.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * @author GeyserMC - * @link https://github.com/GeyserMC/Geyser - */ - -package org.geysermc.geyser.registry.loader; - -/** - * A holder of the constructor parameters to prevent them from automatically loading, - * and instead load them when the load method is called. - */ -public record RegistryLoaderHolder(I input, RegistryLoader registryLoader) { -} diff --git a/core/src/test/java/org/geysermc/geyser/scoreboard/network/util/GeyserMockContext.java b/core/src/test/java/org/geysermc/geyser/scoreboard/network/util/GeyserMockContext.java index 1d262d8b82..2b89867fb3 100644 --- a/core/src/test/java/org/geysermc/geyser/scoreboard/network/util/GeyserMockContext.java +++ b/core/src/test/java/org/geysermc/geyser/scoreboard/network/util/GeyserMockContext.java @@ -61,12 +61,6 @@ public static void mockContext(Consumer geyserContext) { try (var geyserImplMock = mockStatic(GeyserImpl.class)) { geyserImplMock.when(GeyserImpl::getInstance).thenReturn(geyserImpl); - // Since Geyser isn't actually loaded, the Registries#init will not be called. - // This means that we manually load the registries we want to use - Registries.ENTITY_DEFINITIONS.load(); - Registries.JAVA_ENTITY_IDENTIFIERS.load(); - Registries.BEDROCK_ENTITY_PROPERTIES.load(); - geyserContext.accept(context); } }