diff --git a/src/main/java/net/minestom/server/entity/damage/DamageType.java b/src/main/java/net/minestom/server/entity/damage/DamageType.java index e0c2942e9..9729c4524 100644 --- a/src/main/java/net/minestom/server/entity/damage/DamageType.java +++ b/src/main/java/net/minestom/server/entity/damage/DamageType.java @@ -1,7 +1,6 @@ package net.minestom.server.entity.damage; import net.minestom.server.registry.DynamicRegistry; -import net.minestom.server.registry.DynamicRegistryImpl; import net.minestom.server.registry.ProtocolObject; import net.minestom.server.registry.Registry; import net.minestom.server.utils.NamespaceID; @@ -35,7 +34,7 @@ public sealed interface DamageType extends ProtocolObject, DamageTypes permits D */ @ApiStatus.Internal static @NotNull DynamicRegistry createDefaultRegistry() { - return new DynamicRegistryImpl<>( + return DynamicRegistry.create( "minecraft:damage_type", DamageTypeImpl.REGISTRY_NBT_TYPE, Registry.Resource.DAMAGE_TYPES, (namespace, props) -> new DamageTypeImpl(Registry.damageType(namespace, props)) ); diff --git a/src/main/java/net/minestom/server/entity/metadata/animal/tameable/WolfMeta.java b/src/main/java/net/minestom/server/entity/metadata/animal/tameable/WolfMeta.java index 10220cc83..a9bc83495 100644 --- a/src/main/java/net/minestom/server/entity/metadata/animal/tameable/WolfMeta.java +++ b/src/main/java/net/minestom/server/entity/metadata/animal/tameable/WolfMeta.java @@ -6,7 +6,10 @@ import net.kyori.adventure.nbt.StringBinaryTag; import net.minestom.server.entity.Entity; import net.minestom.server.entity.Metadata; import net.minestom.server.network.NetworkBuffer; -import net.minestom.server.registry.*; +import net.minestom.server.registry.DynamicRegistry; +import net.minestom.server.registry.ProtocolObject; +import net.minestom.server.registry.Registries; +import net.minestom.server.registry.Registry; import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.nbt.BinaryTagSerializer; import net.minestom.server.utils.validate.Check; @@ -87,7 +90,7 @@ public class WolfMeta extends TameableAnimalMeta { */ @ApiStatus.Internal static @NotNull DynamicRegistry createDefaultRegistry() { - return new DynamicRegistryImpl<>( + return DynamicRegistry.create( "minecraft:wolf_variant", VariantImpl.REGISTRY_NBT_TYPE, Registry.Resource.WOLF_VARIANTS, (namespace, props) -> new WolfMeta.VariantImpl(Registry.wolfVariant(namespace, props)) ); diff --git a/src/main/java/net/minestom/server/instance/block/banner/BannerPattern.java b/src/main/java/net/minestom/server/instance/block/banner/BannerPattern.java index 3e05f7082..dd9383d6c 100644 --- a/src/main/java/net/minestom/server/instance/block/banner/BannerPattern.java +++ b/src/main/java/net/minestom/server/instance/block/banner/BannerPattern.java @@ -1,7 +1,10 @@ package net.minestom.server.instance.block.banner; import net.minestom.server.network.NetworkBuffer; -import net.minestom.server.registry.*; +import net.minestom.server.registry.DynamicRegistry; +import net.minestom.server.registry.ProtocolObject; +import net.minestom.server.registry.Registries; +import net.minestom.server.registry.Registry; import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.nbt.BinaryTagSerializer; import org.jetbrains.annotations.ApiStatus; @@ -36,7 +39,7 @@ public sealed interface BannerPattern extends ProtocolObject, BannerPatterns per */ @ApiStatus.Internal static @NotNull DynamicRegistry createDefaultRegistry() { - return new DynamicRegistryImpl<>( + return DynamicRegistry.create( "minecraft:banner_pattern", BannerPatternImpl.REGISTRY_NBT_TYPE, Registry.Resource.BANNER_PATTERNS, (namespace, props) -> new BannerPatternImpl(Registry.bannerPattern(namespace, props)) ); diff --git a/src/main/java/net/minestom/server/item/armor/TrimMaterial.java b/src/main/java/net/minestom/server/item/armor/TrimMaterial.java index 5ee555ebd..ed6c2800e 100644 --- a/src/main/java/net/minestom/server/item/armor/TrimMaterial.java +++ b/src/main/java/net/minestom/server/item/armor/TrimMaterial.java @@ -3,7 +3,10 @@ package net.minestom.server.item.armor; import net.kyori.adventure.text.Component; import net.minestom.server.item.Material; import net.minestom.server.network.NetworkBuffer; -import net.minestom.server.registry.*; +import net.minestom.server.registry.DynamicRegistry; +import net.minestom.server.registry.ProtocolObject; +import net.minestom.server.registry.Registries; +import net.minestom.server.registry.Registry; import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.nbt.BinaryTagSerializer; import org.jetbrains.annotations.ApiStatus; @@ -47,7 +50,7 @@ public sealed interface TrimMaterial extends ProtocolObject permits TrimMaterial */ @ApiStatus.Internal static @NotNull DynamicRegistry createDefaultRegistry() { - return new DynamicRegistryImpl<>( + return DynamicRegistry.create( "minecraft:trim_material", TrimMaterialImpl.REGISTRY_NBT_TYPE, Registry.Resource.TRIM_MATERIALS, (namespace, props) -> new TrimMaterialImpl(Registry.trimMaterial(namespace, props)) ); diff --git a/src/main/java/net/minestom/server/item/armor/TrimPattern.java b/src/main/java/net/minestom/server/item/armor/TrimPattern.java index bef27809c..ef33c06ad 100644 --- a/src/main/java/net/minestom/server/item/armor/TrimPattern.java +++ b/src/main/java/net/minestom/server/item/armor/TrimPattern.java @@ -3,7 +3,10 @@ package net.minestom.server.item.armor; import net.kyori.adventure.text.Component; import net.minestom.server.item.Material; import net.minestom.server.network.NetworkBuffer; -import net.minestom.server.registry.*; +import net.minestom.server.registry.DynamicRegistry; +import net.minestom.server.registry.ProtocolObject; +import net.minestom.server.registry.Registries; +import net.minestom.server.registry.Registry; import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.nbt.BinaryTagSerializer; import org.jetbrains.annotations.ApiStatus; @@ -40,7 +43,7 @@ public sealed interface TrimPattern extends ProtocolObject permits TrimPatternIm */ @ApiStatus.Internal static @NotNull DynamicRegistry createDefaultRegistry() { - return new DynamicRegistryImpl<>( + return DynamicRegistry.create( "minecraft:trim_pattern", TrimPatternImpl.REGISTRY_NBT_TYPE, Registry.Resource.TRIM_PATTERNS, (namespace, props) -> new TrimPatternImpl(Registry.trimPattern(namespace, props)) ); diff --git a/src/main/java/net/minestom/server/message/ChatType.java b/src/main/java/net/minestom/server/message/ChatType.java index 3a99dba4f..cdd20934a 100644 --- a/src/main/java/net/minestom/server/message/ChatType.java +++ b/src/main/java/net/minestom/server/message/ChatType.java @@ -1,7 +1,6 @@ package net.minestom.server.message; import net.minestom.server.registry.DynamicRegistry; -import net.minestom.server.registry.DynamicRegistryImpl; import net.minestom.server.registry.ProtocolObject; import net.minestom.server.registry.Registry; import net.minestom.server.utils.NamespaceID; @@ -34,7 +33,7 @@ public sealed interface ChatType extends ProtocolObject, ChatTypes permits ChatT */ @ApiStatus.Internal static @NotNull DynamicRegistry createDefaultRegistry() { - return new DynamicRegistryImpl<>( + return DynamicRegistry.create( "minecraft:chat_type", ChatTypeImpl.REGISTRY_NBT_TYPE, Registry.Resource.CHAT_TYPES, (namespace, props) -> new ChatTypeImpl(Registry.chatType(namespace, props)) ); diff --git a/src/main/java/net/minestom/server/network/packet/client/configuration/ClientSelectKnownPacksPacket.java b/src/main/java/net/minestom/server/network/packet/client/configuration/ClientSelectKnownPacksPacket.java index 2e263ea84..6be68623a 100644 --- a/src/main/java/net/minestom/server/network/packet/client/configuration/ClientSelectKnownPacksPacket.java +++ b/src/main/java/net/minestom/server/network/packet/client/configuration/ClientSelectKnownPacksPacket.java @@ -15,6 +15,7 @@ public record ClientSelectKnownPacksPacket( public ClientSelectKnownPacksPacket { Check.argCondition(entries.size() > MAX_ENTRIES, "Too many known packs: {0} > {1}", entries.size(), MAX_ENTRIES); + entries = List.copyOf(entries); } public ClientSelectKnownPacksPacket(@NotNull NetworkBuffer reader) { diff --git a/src/main/java/net/minestom/server/network/packet/server/configuration/SelectKnownPacksPacket.java b/src/main/java/net/minestom/server/network/packet/server/configuration/SelectKnownPacksPacket.java index ad42a92d9..4f07a5f32 100644 --- a/src/main/java/net/minestom/server/network/packet/server/configuration/SelectKnownPacksPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/configuration/SelectKnownPacksPacket.java @@ -18,6 +18,7 @@ public record SelectKnownPacksPacket( public SelectKnownPacksPacket { Check.argCondition(entries.size() > MAX_ENTRIES, "Too many known packs: {0} > {1}", entries.size(), MAX_ENTRIES); + entries = List.copyOf(entries); } public SelectKnownPacksPacket(@NotNull NetworkBuffer reader) { diff --git a/src/main/java/net/minestom/server/registry/DynamicRegistry.java b/src/main/java/net/minestom/server/registry/DynamicRegistry.java index 1eea50b7e..67ef51beb 100644 --- a/src/main/java/net/minestom/server/registry/DynamicRegistry.java +++ b/src/main/java/net/minestom/server/registry/DynamicRegistry.java @@ -4,11 +4,13 @@ import net.kyori.adventure.key.Keyed; import net.minestom.server.entity.Player; import net.minestom.server.network.packet.server.SendablePacket; import net.minestom.server.utils.NamespaceID; +import net.minestom.server.utils.nbt.BinaryTagSerializer; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Comparator; import java.util.List; public sealed interface DynamicRegistry permits DynamicRegistryImpl { @@ -43,6 +45,27 @@ public sealed interface DynamicRegistry permits Dynami } } + @ApiStatus.Internal + static @NotNull DynamicRegistry create( + @NotNull String id, @NotNull BinaryTagSerializer nbtType) { + return new DynamicRegistryImpl<>(id, nbtType); + } + + @ApiStatus.Internal + static @NotNull DynamicRegistry create( + @NotNull String id, @NotNull BinaryTagSerializer nbtType, + @NotNull Registry.Resource resource, @NotNull Registry.Container.Loader loader) { + return new DynamicRegistryImpl<>(id, nbtType, resource, loader); + } + + @ApiStatus.Internal + static @NotNull DynamicRegistry create( + @NotNull String id, @NotNull BinaryTagSerializer nbtType, + @NotNull Registry.Resource resource, @NotNull Registry.Container.Loader loader, + @Nullable Comparator idComparator) { + return new DynamicRegistryImpl<>(id, nbtType, resource, loader, idComparator); + } + @Nullable T get(int id); @Nullable T get(@NotNull NamespaceID namespace); default @Nullable T get(@NotNull Key key) { diff --git a/src/main/java/net/minestom/server/registry/DynamicRegistryImpl.java b/src/main/java/net/minestom/server/registry/DynamicRegistryImpl.java index 8ca97379a..29f845b4c 100644 --- a/src/main/java/net/minestom/server/registry/DynamicRegistryImpl.java +++ b/src/main/java/net/minestom/server/registry/DynamicRegistryImpl.java @@ -17,7 +17,7 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.locks.ReentrantLock; @ApiStatus.Internal -public final class DynamicRegistryImpl implements DynamicRegistry { +final class DynamicRegistryImpl implements DynamicRegistry { private static final UnsupportedOperationException UNSAFE_REMOVE_EXCEPTION = new UnsupportedOperationException("Unsafe remove is disabled. Enable by setting the system property 'minestom.registry.unsafe-remove' to 'true'"); record KeyImpl(NamespaceID namespace) implements Key { @@ -44,23 +44,23 @@ public final class DynamicRegistryImpl implements Dyna private final CachedPacket vanillaRegistryDataPacket = new CachedPacket(() -> createRegistryDataPacket(true)); private final ReentrantLock lock = new ReentrantLock(); // Protects writes - private final List entryById = new CopyOnWriteArrayList<>(); // We use a CopyOnWriteArrayList even with the lock above because it handles concurrent iteration + private final List entryById = new CopyOnWriteArrayList<>(); private final Map entryByName = new ConcurrentHashMap<>(); private final List idByName = new CopyOnWriteArrayList<>(); private final String id; private final BinaryTagSerializer nbtType; - public DynamicRegistryImpl(@NotNull String id, BinaryTagSerializer nbtType) { + DynamicRegistryImpl(@NotNull String id, BinaryTagSerializer nbtType) { this.id = id; this.nbtType = nbtType; } - public DynamicRegistryImpl(@NotNull String id, BinaryTagSerializer nbtType, @NotNull Registry.Resource resource, @NotNull Registry.Container.Loader loader) { + DynamicRegistryImpl(@NotNull String id, BinaryTagSerializer nbtType, @NotNull Registry.Resource resource, @NotNull Registry.Container.Loader loader) { this(id, nbtType, resource, loader, null); } - public DynamicRegistryImpl(@NotNull String id, BinaryTagSerializer nbtType, @NotNull Registry.Resource resource, @NotNull Registry.Container.Loader loader, @Nullable Comparator idComparator) { + DynamicRegistryImpl(@NotNull String id, BinaryTagSerializer nbtType, @NotNull Registry.Resource resource, @NotNull Registry.Container.Loader loader, @Nullable Comparator idComparator) { this(id, nbtType); loadStaticRegistry(resource, loader, idComparator); } diff --git a/src/main/java/net/minestom/server/world/DimensionType.java b/src/main/java/net/minestom/server/world/DimensionType.java index 70cbe49bd..65c9ec6df 100644 --- a/src/main/java/net/minestom/server/world/DimensionType.java +++ b/src/main/java/net/minestom/server/world/DimensionType.java @@ -1,7 +1,6 @@ package net.minestom.server.world; import net.minestom.server.registry.DynamicRegistry; -import net.minestom.server.registry.DynamicRegistryImpl; import net.minestom.server.registry.ProtocolObject; import net.minestom.server.registry.Registry; import net.minestom.server.utils.NamespaceID; @@ -33,7 +32,7 @@ public sealed interface DimensionType extends ProtocolObject, DimensionTypes per */ @ApiStatus.Internal static @NotNull DynamicRegistry createDefaultRegistry() { - return new DynamicRegistryImpl<>( + return DynamicRegistry.create( "minecraft:dimension_type", DimensionTypeImpl.REGISTRY_NBT_TYPE, Registry.Resource.DIMENSION_TYPES, (namespace, props) -> new DimensionTypeImpl(Registry.dimensionType(namespace, props)) ); diff --git a/src/main/java/net/minestom/server/world/biome/Biome.java b/src/main/java/net/minestom/server/world/biome/Biome.java index 86f47377d..50b6bb387 100644 --- a/src/main/java/net/minestom/server/world/biome/Biome.java +++ b/src/main/java/net/minestom/server/world/biome/Biome.java @@ -2,7 +2,6 @@ package net.minestom.server.world.biome; import net.minestom.server.coordinate.Point; import net.minestom.server.registry.DynamicRegistry; -import net.minestom.server.registry.DynamicRegistryImpl; import net.minestom.server.registry.ProtocolObject; import net.minestom.server.registry.Registry; import net.minestom.server.utils.NamespaceID; @@ -28,7 +27,7 @@ public sealed interface Biome extends Biomes, ProtocolObject permits BiomeImpl { */ @ApiStatus.Internal static @NotNull DynamicRegistry createDefaultRegistry() { - return new DynamicRegistryImpl<>( + return DynamicRegistry.create( "minecraft:worldgen/biome", BiomeImpl.REGISTRY_NBT_TYPE, Registry.Resource.BIOMES, (namespace, props) -> new BiomeImpl(Registry.biome(namespace, props)), // We force plains to be first because it allows convenient palette initialization.