feat: add DynamicRegistry.Key and reference it instead of the underlying type. add wolf variant meta field

This commit is contained in:
mworzala 2024-05-18 07:17:39 -04:00 committed by Matt Worzala
parent aa697a4f94
commit 7f88699836
53 changed files with 525 additions and 409 deletions

View File

@ -74,8 +74,10 @@ public class CodeGenerator {
LOGGER.error("Failed to find resource file for " + typeName); LOGGER.error("Failed to find resource file for " + typeName);
return; return;
} }
ClassName typeClass = ClassName.get(packageName, typeName);
ClassName namespaceIdClass = ClassName.get("net.minestom.server.utils", "NamespaceID"); ClassName typeClass = ClassName.bestGuess(packageName + "." + typeName); // Use bestGuess to handle nested class
ClassName registryKeyClass = ClassName.get("net.minestom.server.registry", "DynamicRegistry", "Key");
ParameterizedTypeName typedRegistryKeyClass = ParameterizedTypeName.get(registryKeyClass, typeClass);
JsonObject json; JsonObject json;
json = GSON.fromJson(new InputStreamReader(resourceFile), JsonObject.class); json = GSON.fromJson(new InputStreamReader(resourceFile), JsonObject.class);
@ -93,12 +95,12 @@ public class CodeGenerator {
.replace(".", "_") .replace(".", "_")
.toUpperCase(Locale.ROOT); .toUpperCase(Locale.ROOT);
blockConstantsClass.addField( blockConstantsClass.addField(
FieldSpec.builder(namespaceIdClass, constantName) FieldSpec.builder(typedRegistryKeyClass, constantName)
.addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
.initializer( .initializer(
// TypeClass.STONE = NamespaceID.from("minecraft:stone") // TypeClass.STONE = NamespaceID.from("minecraft:stone")
"$T.from($S)", "$T.of($S)",
namespaceIdClass, registryKeyClass,
namespace namespace
) )
.build() .build()

View File

@ -45,7 +45,7 @@ public class Generators {
generator.generateKeys(resource("trim_materials.json"), "net.minestom.server.item.armor", "TrimMaterial", "TrimMaterials"); generator.generateKeys(resource("trim_materials.json"), "net.minestom.server.item.armor", "TrimMaterial", "TrimMaterials");
generator.generateKeys(resource("trim_patterns.json"), "net.minestom.server.item.armor", "TrimPattern", "TrimPatterns"); generator.generateKeys(resource("trim_patterns.json"), "net.minestom.server.item.armor", "TrimPattern", "TrimPatterns");
generator.generateKeys(resource("banner_patterns.json"), "net.minestom.server.instance.block.banner", "BannerPattern", "BannerPatterns"); generator.generateKeys(resource("banner_patterns.json"), "net.minestom.server.instance.block.banner", "BannerPattern", "BannerPatterns");
generator.generateKeys(resource("wolf_variants.json"), "net.minestom.server.entity.metadata.animal.tameable", "Wolf$Variant", "WolfVariants"); generator.generateKeys(resource("wolf_variants.json"), "net.minestom.server.entity.metadata.animal.tameable", "WolfMeta.Variant", "WolfVariants");
// Generate fluids // Generate fluids
new FluidGenerator(resource("fluids.json"), outputFolder).generate(); new FluidGenerator(resource("fluids.json"), outputFolder).generate();

View File

@ -1,99 +1,99 @@
package net.minestom.server.entity.damage; package net.minestom.server.entity.damage;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.registry.DynamicRegistry;
/** /**
* Code autogenerated, do not edit! * Code autogenerated, do not edit!
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
interface DamageTypes { interface DamageTypes {
NamespaceID WITHER = NamespaceID.from("minecraft:wither"); DynamicRegistry.Key<DamageType> WITHER = DynamicRegistry.Key.of("minecraft:wither");
NamespaceID SONIC_BOOM = NamespaceID.from("minecraft:sonic_boom"); DynamicRegistry.Key<DamageType> SONIC_BOOM = DynamicRegistry.Key.of("minecraft:sonic_boom");
NamespaceID WITHER_SKULL = NamespaceID.from("minecraft:wither_skull"); DynamicRegistry.Key<DamageType> WITHER_SKULL = DynamicRegistry.Key.of("minecraft:wither_skull");
NamespaceID DRY_OUT = NamespaceID.from("minecraft:dry_out"); DynamicRegistry.Key<DamageType> DRY_OUT = DynamicRegistry.Key.of("minecraft:dry_out");
NamespaceID TRIDENT = NamespaceID.from("minecraft:trident"); DynamicRegistry.Key<DamageType> TRIDENT = DynamicRegistry.Key.of("minecraft:trident");
NamespaceID ON_FIRE = NamespaceID.from("minecraft:on_fire"); DynamicRegistry.Key<DamageType> ON_FIRE = DynamicRegistry.Key.of("minecraft:on_fire");
NamespaceID FALL = NamespaceID.from("minecraft:fall"); DynamicRegistry.Key<DamageType> FALL = DynamicRegistry.Key.of("minecraft:fall");
NamespaceID MOB_ATTACK = NamespaceID.from("minecraft:mob_attack"); DynamicRegistry.Key<DamageType> MOB_ATTACK = DynamicRegistry.Key.of("minecraft:mob_attack");
NamespaceID MOB_PROJECTILE = NamespaceID.from("minecraft:mob_projectile"); DynamicRegistry.Key<DamageType> MOB_PROJECTILE = DynamicRegistry.Key.of("minecraft:mob_projectile");
NamespaceID THROWN = NamespaceID.from("minecraft:thrown"); DynamicRegistry.Key<DamageType> THROWN = DynamicRegistry.Key.of("minecraft:thrown");
NamespaceID FALLING_STALACTITE = NamespaceID.from("minecraft:falling_stalactite"); DynamicRegistry.Key<DamageType> FALLING_STALACTITE = DynamicRegistry.Key.of("minecraft:falling_stalactite");
NamespaceID FIREBALL = NamespaceID.from("minecraft:fireball"); DynamicRegistry.Key<DamageType> FIREBALL = DynamicRegistry.Key.of("minecraft:fireball");
NamespaceID FALLING_BLOCK = NamespaceID.from("minecraft:falling_block"); DynamicRegistry.Key<DamageType> FALLING_BLOCK = DynamicRegistry.Key.of("minecraft:falling_block");
NamespaceID PLAYER_EXPLOSION = NamespaceID.from("minecraft:player_explosion"); DynamicRegistry.Key<DamageType> PLAYER_EXPLOSION = DynamicRegistry.Key.of("minecraft:player_explosion");
NamespaceID SPIT = NamespaceID.from("minecraft:spit"); DynamicRegistry.Key<DamageType> SPIT = DynamicRegistry.Key.of("minecraft:spit");
NamespaceID STING = NamespaceID.from("minecraft:sting"); DynamicRegistry.Key<DamageType> STING = DynamicRegistry.Key.of("minecraft:sting");
NamespaceID UNATTRIBUTED_FIREBALL = NamespaceID.from("minecraft:unattributed_fireball"); DynamicRegistry.Key<DamageType> UNATTRIBUTED_FIREBALL = DynamicRegistry.Key.of("minecraft:unattributed_fireball");
NamespaceID IN_WALL = NamespaceID.from("minecraft:in_wall"); DynamicRegistry.Key<DamageType> IN_WALL = DynamicRegistry.Key.of("minecraft:in_wall");
NamespaceID IN_FIRE = NamespaceID.from("minecraft:in_fire"); DynamicRegistry.Key<DamageType> IN_FIRE = DynamicRegistry.Key.of("minecraft:in_fire");
NamespaceID ARROW = NamespaceID.from("minecraft:arrow"); DynamicRegistry.Key<DamageType> ARROW = DynamicRegistry.Key.of("minecraft:arrow");
NamespaceID HOT_FLOOR = NamespaceID.from("minecraft:hot_floor"); DynamicRegistry.Key<DamageType> HOT_FLOOR = DynamicRegistry.Key.of("minecraft:hot_floor");
NamespaceID DROWN = NamespaceID.from("minecraft:drown"); DynamicRegistry.Key<DamageType> DROWN = DynamicRegistry.Key.of("minecraft:drown");
NamespaceID STARVE = NamespaceID.from("minecraft:starve"); DynamicRegistry.Key<DamageType> STARVE = DynamicRegistry.Key.of("minecraft:starve");
NamespaceID GENERIC_KILL = NamespaceID.from("minecraft:generic_kill"); DynamicRegistry.Key<DamageType> GENERIC_KILL = DynamicRegistry.Key.of("minecraft:generic_kill");
NamespaceID DRAGON_BREATH = NamespaceID.from("minecraft:dragon_breath"); DynamicRegistry.Key<DamageType> DRAGON_BREATH = DynamicRegistry.Key.of("minecraft:dragon_breath");
NamespaceID MOB_ATTACK_NO_AGGRO = NamespaceID.from("minecraft:mob_attack_no_aggro"); DynamicRegistry.Key<DamageType> MOB_ATTACK_NO_AGGRO = DynamicRegistry.Key.of("minecraft:mob_attack_no_aggro");
NamespaceID LAVA = NamespaceID.from("minecraft:lava"); DynamicRegistry.Key<DamageType> LAVA = DynamicRegistry.Key.of("minecraft:lava");
NamespaceID OUTSIDE_BORDER = NamespaceID.from("minecraft:outside_border"); DynamicRegistry.Key<DamageType> OUTSIDE_BORDER = DynamicRegistry.Key.of("minecraft:outside_border");
NamespaceID FLY_INTO_WALL = NamespaceID.from("minecraft:fly_into_wall"); DynamicRegistry.Key<DamageType> FLY_INTO_WALL = DynamicRegistry.Key.of("minecraft:fly_into_wall");
NamespaceID LIGHTNING_BOLT = NamespaceID.from("minecraft:lightning_bolt"); DynamicRegistry.Key<DamageType> LIGHTNING_BOLT = DynamicRegistry.Key.of("minecraft:lightning_bolt");
NamespaceID PLAYER_ATTACK = NamespaceID.from("minecraft:player_attack"); DynamicRegistry.Key<DamageType> PLAYER_ATTACK = DynamicRegistry.Key.of("minecraft:player_attack");
NamespaceID FREEZE = NamespaceID.from("minecraft:freeze"); DynamicRegistry.Key<DamageType> FREEZE = DynamicRegistry.Key.of("minecraft:freeze");
NamespaceID FALLING_ANVIL = NamespaceID.from("minecraft:falling_anvil"); DynamicRegistry.Key<DamageType> FALLING_ANVIL = DynamicRegistry.Key.of("minecraft:falling_anvil");
NamespaceID OUT_OF_WORLD = NamespaceID.from("minecraft:out_of_world"); DynamicRegistry.Key<DamageType> OUT_OF_WORLD = DynamicRegistry.Key.of("minecraft:out_of_world");
NamespaceID MAGIC = NamespaceID.from("minecraft:magic"); DynamicRegistry.Key<DamageType> MAGIC = DynamicRegistry.Key.of("minecraft:magic");
NamespaceID SWEET_BERRY_BUSH = NamespaceID.from("minecraft:sweet_berry_bush"); DynamicRegistry.Key<DamageType> SWEET_BERRY_BUSH = DynamicRegistry.Key.of("minecraft:sweet_berry_bush");
NamespaceID FIREWORKS = NamespaceID.from("minecraft:fireworks"); DynamicRegistry.Key<DamageType> FIREWORKS = DynamicRegistry.Key.of("minecraft:fireworks");
NamespaceID EXPLOSION = NamespaceID.from("minecraft:explosion"); DynamicRegistry.Key<DamageType> EXPLOSION = DynamicRegistry.Key.of("minecraft:explosion");
NamespaceID BAD_RESPAWN_POINT = NamespaceID.from("minecraft:bad_respawn_point"); DynamicRegistry.Key<DamageType> BAD_RESPAWN_POINT = DynamicRegistry.Key.of("minecraft:bad_respawn_point");
NamespaceID STALAGMITE = NamespaceID.from("minecraft:stalagmite"); DynamicRegistry.Key<DamageType> STALAGMITE = DynamicRegistry.Key.of("minecraft:stalagmite");
NamespaceID THORNS = NamespaceID.from("minecraft:thorns"); DynamicRegistry.Key<DamageType> THORNS = DynamicRegistry.Key.of("minecraft:thorns");
NamespaceID INDIRECT_MAGIC = NamespaceID.from("minecraft:indirect_magic"); DynamicRegistry.Key<DamageType> INDIRECT_MAGIC = DynamicRegistry.Key.of("minecraft:indirect_magic");
NamespaceID CRAMMING = NamespaceID.from("minecraft:cramming"); DynamicRegistry.Key<DamageType> CRAMMING = DynamicRegistry.Key.of("minecraft:cramming");
NamespaceID CACTUS = NamespaceID.from("minecraft:cactus"); DynamicRegistry.Key<DamageType> CACTUS = DynamicRegistry.Key.of("minecraft:cactus");
NamespaceID GENERIC = NamespaceID.from("minecraft:generic"); DynamicRegistry.Key<DamageType> GENERIC = DynamicRegistry.Key.of("minecraft:generic");
} }

View File

@ -1,27 +1,27 @@
package net.minestom.server.entity.metadata.animal.tameable; package net.minestom.server.entity.metadata.animal.tameable;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.registry.DynamicRegistry;
/** /**
* Code autogenerated, do not edit! * Code autogenerated, do not edit!
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
interface WolfVariants { interface WolfVariants {
NamespaceID BLACK = NamespaceID.from("minecraft:black"); DynamicRegistry.Key<WolfMeta.Variant> BLACK = DynamicRegistry.Key.of("minecraft:black");
NamespaceID CHESTNUT = NamespaceID.from("minecraft:chestnut"); DynamicRegistry.Key<WolfMeta.Variant> CHESTNUT = DynamicRegistry.Key.of("minecraft:chestnut");
NamespaceID SNOWY = NamespaceID.from("minecraft:snowy"); DynamicRegistry.Key<WolfMeta.Variant> SNOWY = DynamicRegistry.Key.of("minecraft:snowy");
NamespaceID STRIPED = NamespaceID.from("minecraft:striped"); DynamicRegistry.Key<WolfMeta.Variant> STRIPED = DynamicRegistry.Key.of("minecraft:striped");
NamespaceID ASHEN = NamespaceID.from("minecraft:ashen"); DynamicRegistry.Key<WolfMeta.Variant> ASHEN = DynamicRegistry.Key.of("minecraft:ashen");
NamespaceID SPOTTED = NamespaceID.from("minecraft:spotted"); DynamicRegistry.Key<WolfMeta.Variant> SPOTTED = DynamicRegistry.Key.of("minecraft:spotted");
NamespaceID RUSTY = NamespaceID.from("minecraft:rusty"); DynamicRegistry.Key<WolfMeta.Variant> RUSTY = DynamicRegistry.Key.of("minecraft:rusty");
NamespaceID WOODS = NamespaceID.from("minecraft:woods"); DynamicRegistry.Key<WolfMeta.Variant> WOODS = DynamicRegistry.Key.of("minecraft:woods");
NamespaceID PALE = NamespaceID.from("minecraft:pale"); DynamicRegistry.Key<WolfMeta.Variant> PALE = DynamicRegistry.Key.of("minecraft:pale");
} }

View File

@ -1,91 +1,91 @@
package net.minestom.server.instance.block.banner; package net.minestom.server.instance.block.banner;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.registry.DynamicRegistry;
/** /**
* Code autogenerated, do not edit! * Code autogenerated, do not edit!
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
interface BannerPatterns { interface BannerPatterns {
NamespaceID BORDER = NamespaceID.from("minecraft:border"); DynamicRegistry.Key<BannerPattern> BORDER = DynamicRegistry.Key.of("minecraft:border");
NamespaceID SQUARE_BOTTOM_RIGHT = NamespaceID.from("minecraft:square_bottom_right"); DynamicRegistry.Key<BannerPattern> SQUARE_BOTTOM_RIGHT = DynamicRegistry.Key.of("minecraft:square_bottom_right");
NamespaceID STRIPE_RIGHT = NamespaceID.from("minecraft:stripe_right"); DynamicRegistry.Key<BannerPattern> STRIPE_RIGHT = DynamicRegistry.Key.of("minecraft:stripe_right");
NamespaceID RHOMBUS = NamespaceID.from("minecraft:rhombus"); DynamicRegistry.Key<BannerPattern> RHOMBUS = DynamicRegistry.Key.of("minecraft:rhombus");
NamespaceID TRIANGLES_TOP = NamespaceID.from("minecraft:triangles_top"); DynamicRegistry.Key<BannerPattern> TRIANGLES_TOP = DynamicRegistry.Key.of("minecraft:triangles_top");
NamespaceID GRADIENT = NamespaceID.from("minecraft:gradient"); DynamicRegistry.Key<BannerPattern> GRADIENT = DynamicRegistry.Key.of("minecraft:gradient");
NamespaceID GLOBE = NamespaceID.from("minecraft:globe"); DynamicRegistry.Key<BannerPattern> GLOBE = DynamicRegistry.Key.of("minecraft:globe");
NamespaceID MOJANG = NamespaceID.from("minecraft:mojang"); DynamicRegistry.Key<BannerPattern> MOJANG = DynamicRegistry.Key.of("minecraft:mojang");
NamespaceID STRIPE_BOTTOM = NamespaceID.from("minecraft:stripe_bottom"); DynamicRegistry.Key<BannerPattern> STRIPE_BOTTOM = DynamicRegistry.Key.of("minecraft:stripe_bottom");
NamespaceID STRIPE_MIDDLE = NamespaceID.from("minecraft:stripe_middle"); DynamicRegistry.Key<BannerPattern> STRIPE_MIDDLE = DynamicRegistry.Key.of("minecraft:stripe_middle");
NamespaceID FLOWER = NamespaceID.from("minecraft:flower"); DynamicRegistry.Key<BannerPattern> FLOWER = DynamicRegistry.Key.of("minecraft:flower");
NamespaceID DIAGONAL_UP_RIGHT = NamespaceID.from("minecraft:diagonal_up_right"); DynamicRegistry.Key<BannerPattern> DIAGONAL_UP_RIGHT = DynamicRegistry.Key.of("minecraft:diagonal_up_right");
NamespaceID CIRCLE = NamespaceID.from("minecraft:circle"); DynamicRegistry.Key<BannerPattern> CIRCLE = DynamicRegistry.Key.of("minecraft:circle");
NamespaceID HALF_HORIZONTAL = NamespaceID.from("minecraft:half_horizontal"); DynamicRegistry.Key<BannerPattern> HALF_HORIZONTAL = DynamicRegistry.Key.of("minecraft:half_horizontal");
NamespaceID BRICKS = NamespaceID.from("minecraft:bricks"); DynamicRegistry.Key<BannerPattern> BRICKS = DynamicRegistry.Key.of("minecraft:bricks");
NamespaceID TRIANGLE_BOTTOM = NamespaceID.from("minecraft:triangle_bottom"); DynamicRegistry.Key<BannerPattern> TRIANGLE_BOTTOM = DynamicRegistry.Key.of("minecraft:triangle_bottom");
NamespaceID CURLY_BORDER = NamespaceID.from("minecraft:curly_border"); DynamicRegistry.Key<BannerPattern> CURLY_BORDER = DynamicRegistry.Key.of("minecraft:curly_border");
NamespaceID BASE = NamespaceID.from("minecraft:base"); DynamicRegistry.Key<BannerPattern> BASE = DynamicRegistry.Key.of("minecraft:base");
NamespaceID PIGLIN = NamespaceID.from("minecraft:piglin"); DynamicRegistry.Key<BannerPattern> PIGLIN = DynamicRegistry.Key.of("minecraft:piglin");
NamespaceID STRIPE_CENTER = NamespaceID.from("minecraft:stripe_center"); DynamicRegistry.Key<BannerPattern> STRIPE_CENTER = DynamicRegistry.Key.of("minecraft:stripe_center");
NamespaceID SQUARE_BOTTOM_LEFT = NamespaceID.from("minecraft:square_bottom_left"); DynamicRegistry.Key<BannerPattern> SQUARE_BOTTOM_LEFT = DynamicRegistry.Key.of("minecraft:square_bottom_left");
NamespaceID SQUARE_TOP_RIGHT = NamespaceID.from("minecraft:square_top_right"); DynamicRegistry.Key<BannerPattern> SQUARE_TOP_RIGHT = DynamicRegistry.Key.of("minecraft:square_top_right");
NamespaceID STRIPE_DOWNRIGHT = NamespaceID.from("minecraft:stripe_downright"); DynamicRegistry.Key<BannerPattern> STRIPE_DOWNRIGHT = DynamicRegistry.Key.of("minecraft:stripe_downright");
NamespaceID GRADIENT_UP = NamespaceID.from("minecraft:gradient_up"); DynamicRegistry.Key<BannerPattern> GRADIENT_UP = DynamicRegistry.Key.of("minecraft:gradient_up");
NamespaceID DIAGONAL_RIGHT = NamespaceID.from("minecraft:diagonal_right"); DynamicRegistry.Key<BannerPattern> DIAGONAL_RIGHT = DynamicRegistry.Key.of("minecraft:diagonal_right");
NamespaceID HALF_VERTICAL_RIGHT = NamespaceID.from("minecraft:half_vertical_right"); DynamicRegistry.Key<BannerPattern> HALF_VERTICAL_RIGHT = DynamicRegistry.Key.of("minecraft:half_vertical_right");
NamespaceID SMALL_STRIPES = NamespaceID.from("minecraft:small_stripes"); DynamicRegistry.Key<BannerPattern> SMALL_STRIPES = DynamicRegistry.Key.of("minecraft:small_stripes");
NamespaceID CROSS = NamespaceID.from("minecraft:cross"); DynamicRegistry.Key<BannerPattern> CROSS = DynamicRegistry.Key.of("minecraft:cross");
NamespaceID DIAGONAL_LEFT = NamespaceID.from("minecraft:diagonal_left"); DynamicRegistry.Key<BannerPattern> DIAGONAL_LEFT = DynamicRegistry.Key.of("minecraft:diagonal_left");
NamespaceID SKULL = NamespaceID.from("minecraft:skull"); DynamicRegistry.Key<BannerPattern> SKULL = DynamicRegistry.Key.of("minecraft:skull");
NamespaceID STRIPE_DOWNLEFT = NamespaceID.from("minecraft:stripe_downleft"); DynamicRegistry.Key<BannerPattern> STRIPE_DOWNLEFT = DynamicRegistry.Key.of("minecraft:stripe_downleft");
NamespaceID DIAGONAL_UP_LEFT = NamespaceID.from("minecraft:diagonal_up_left"); DynamicRegistry.Key<BannerPattern> DIAGONAL_UP_LEFT = DynamicRegistry.Key.of("minecraft:diagonal_up_left");
NamespaceID HALF_VERTICAL = NamespaceID.from("minecraft:half_vertical"); DynamicRegistry.Key<BannerPattern> HALF_VERTICAL = DynamicRegistry.Key.of("minecraft:half_vertical");
NamespaceID TRIANGLE_TOP = NamespaceID.from("minecraft:triangle_top"); DynamicRegistry.Key<BannerPattern> TRIANGLE_TOP = DynamicRegistry.Key.of("minecraft:triangle_top");
NamespaceID HALF_HORIZONTAL_BOTTOM = NamespaceID.from("minecraft:half_horizontal_bottom"); DynamicRegistry.Key<BannerPattern> HALF_HORIZONTAL_BOTTOM = DynamicRegistry.Key.of("minecraft:half_horizontal_bottom");
NamespaceID SQUARE_TOP_LEFT = NamespaceID.from("minecraft:square_top_left"); DynamicRegistry.Key<BannerPattern> SQUARE_TOP_LEFT = DynamicRegistry.Key.of("minecraft:square_top_left");
NamespaceID STRIPE_TOP = NamespaceID.from("minecraft:stripe_top"); DynamicRegistry.Key<BannerPattern> STRIPE_TOP = DynamicRegistry.Key.of("minecraft:stripe_top");
NamespaceID CREEPER = NamespaceID.from("minecraft:creeper"); DynamicRegistry.Key<BannerPattern> CREEPER = DynamicRegistry.Key.of("minecraft:creeper");
NamespaceID STRIPE_LEFT = NamespaceID.from("minecraft:stripe_left"); DynamicRegistry.Key<BannerPattern> STRIPE_LEFT = DynamicRegistry.Key.of("minecraft:stripe_left");
NamespaceID TRIANGLES_BOTTOM = NamespaceID.from("minecraft:triangles_bottom"); DynamicRegistry.Key<BannerPattern> TRIANGLES_BOTTOM = DynamicRegistry.Key.of("minecraft:triangles_bottom");
NamespaceID STRAIGHT_CROSS = NamespaceID.from("minecraft:straight_cross"); DynamicRegistry.Key<BannerPattern> STRAIGHT_CROSS = DynamicRegistry.Key.of("minecraft:straight_cross");
} }

View File

@ -1,29 +1,29 @@
package net.minestom.server.item.armor; package net.minestom.server.item.armor;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.registry.DynamicRegistry;
/** /**
* Code autogenerated, do not edit! * Code autogenerated, do not edit!
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
interface TrimMaterials { interface TrimMaterials {
NamespaceID LAPIS = NamespaceID.from("minecraft:lapis"); DynamicRegistry.Key<TrimMaterial> LAPIS = DynamicRegistry.Key.of("minecraft:lapis");
NamespaceID IRON = NamespaceID.from("minecraft:iron"); DynamicRegistry.Key<TrimMaterial> IRON = DynamicRegistry.Key.of("minecraft:iron");
NamespaceID DIAMOND = NamespaceID.from("minecraft:diamond"); DynamicRegistry.Key<TrimMaterial> DIAMOND = DynamicRegistry.Key.of("minecraft:diamond");
NamespaceID AMETHYST = NamespaceID.from("minecraft:amethyst"); DynamicRegistry.Key<TrimMaterial> AMETHYST = DynamicRegistry.Key.of("minecraft:amethyst");
NamespaceID COPPER = NamespaceID.from("minecraft:copper"); DynamicRegistry.Key<TrimMaterial> COPPER = DynamicRegistry.Key.of("minecraft:copper");
NamespaceID QUARTZ = NamespaceID.from("minecraft:quartz"); DynamicRegistry.Key<TrimMaterial> QUARTZ = DynamicRegistry.Key.of("minecraft:quartz");
NamespaceID EMERALD = NamespaceID.from("minecraft:emerald"); DynamicRegistry.Key<TrimMaterial> EMERALD = DynamicRegistry.Key.of("minecraft:emerald");
NamespaceID REDSTONE = NamespaceID.from("minecraft:redstone"); DynamicRegistry.Key<TrimMaterial> REDSTONE = DynamicRegistry.Key.of("minecraft:redstone");
NamespaceID GOLD = NamespaceID.from("minecraft:gold"); DynamicRegistry.Key<TrimMaterial> GOLD = DynamicRegistry.Key.of("minecraft:gold");
NamespaceID NETHERITE = NamespaceID.from("minecraft:netherite"); DynamicRegistry.Key<TrimMaterial> NETHERITE = DynamicRegistry.Key.of("minecraft:netherite");
} }

View File

@ -1,41 +1,41 @@
package net.minestom.server.item.armor; package net.minestom.server.item.armor;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.registry.DynamicRegistry;
/** /**
* Code autogenerated, do not edit! * Code autogenerated, do not edit!
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
interface TrimPatterns { interface TrimPatterns {
NamespaceID TIDE = NamespaceID.from("minecraft:tide"); DynamicRegistry.Key<TrimPattern> TIDE = DynamicRegistry.Key.of("minecraft:tide");
NamespaceID RIB = NamespaceID.from("minecraft:rib"); DynamicRegistry.Key<TrimPattern> RIB = DynamicRegistry.Key.of("minecraft:rib");
NamespaceID HOST = NamespaceID.from("minecraft:host"); DynamicRegistry.Key<TrimPattern> HOST = DynamicRegistry.Key.of("minecraft:host");
NamespaceID SILENCE = NamespaceID.from("minecraft:silence"); DynamicRegistry.Key<TrimPattern> SILENCE = DynamicRegistry.Key.of("minecraft:silence");
NamespaceID WILD = NamespaceID.from("minecraft:wild"); DynamicRegistry.Key<TrimPattern> WILD = DynamicRegistry.Key.of("minecraft:wild");
NamespaceID WAYFINDER = NamespaceID.from("minecraft:wayfinder"); DynamicRegistry.Key<TrimPattern> WAYFINDER = DynamicRegistry.Key.of("minecraft:wayfinder");
NamespaceID DUNE = NamespaceID.from("minecraft:dune"); DynamicRegistry.Key<TrimPattern> DUNE = DynamicRegistry.Key.of("minecraft:dune");
NamespaceID RAISER = NamespaceID.from("minecraft:raiser"); DynamicRegistry.Key<TrimPattern> RAISER = DynamicRegistry.Key.of("minecraft:raiser");
NamespaceID SNOUT = NamespaceID.from("minecraft:snout"); DynamicRegistry.Key<TrimPattern> SNOUT = DynamicRegistry.Key.of("minecraft:snout");
NamespaceID VEX = NamespaceID.from("minecraft:vex"); DynamicRegistry.Key<TrimPattern> VEX = DynamicRegistry.Key.of("minecraft:vex");
NamespaceID SPIRE = NamespaceID.from("minecraft:spire"); DynamicRegistry.Key<TrimPattern> SPIRE = DynamicRegistry.Key.of("minecraft:spire");
NamespaceID SENTRY = NamespaceID.from("minecraft:sentry"); DynamicRegistry.Key<TrimPattern> SENTRY = DynamicRegistry.Key.of("minecraft:sentry");
NamespaceID EYE = NamespaceID.from("minecraft:eye"); DynamicRegistry.Key<TrimPattern> EYE = DynamicRegistry.Key.of("minecraft:eye");
NamespaceID WARD = NamespaceID.from("minecraft:ward"); DynamicRegistry.Key<TrimPattern> WARD = DynamicRegistry.Key.of("minecraft:ward");
NamespaceID COAST = NamespaceID.from("minecraft:coast"); DynamicRegistry.Key<TrimPattern> COAST = DynamicRegistry.Key.of("minecraft:coast");
NamespaceID SHAPER = NamespaceID.from("minecraft:shaper"); DynamicRegistry.Key<TrimPattern> SHAPER = DynamicRegistry.Key.of("minecraft:shaper");
} }

View File

@ -1,23 +1,23 @@
package net.minestom.server.message; package net.minestom.server.message;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.registry.DynamicRegistry;
/** /**
* Code autogenerated, do not edit! * Code autogenerated, do not edit!
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
interface ChatTypes { interface ChatTypes {
NamespaceID EMOTE_COMMAND = NamespaceID.from("minecraft:emote_command"); DynamicRegistry.Key<ChatType> EMOTE_COMMAND = DynamicRegistry.Key.of("minecraft:emote_command");
NamespaceID TEAM_MSG_COMMAND_INCOMING = NamespaceID.from("minecraft:team_msg_command_incoming"); DynamicRegistry.Key<ChatType> TEAM_MSG_COMMAND_INCOMING = DynamicRegistry.Key.of("minecraft:team_msg_command_incoming");
NamespaceID TEAM_MSG_COMMAND_OUTGOING = NamespaceID.from("minecraft:team_msg_command_outgoing"); DynamicRegistry.Key<ChatType> TEAM_MSG_COMMAND_OUTGOING = DynamicRegistry.Key.of("minecraft:team_msg_command_outgoing");
NamespaceID CHAT = NamespaceID.from("minecraft:chat"); DynamicRegistry.Key<ChatType> CHAT = DynamicRegistry.Key.of("minecraft:chat");
NamespaceID MSG_COMMAND_INCOMING = NamespaceID.from("minecraft:msg_command_incoming"); DynamicRegistry.Key<ChatType> MSG_COMMAND_INCOMING = DynamicRegistry.Key.of("minecraft:msg_command_incoming");
NamespaceID MSG_COMMAND_OUTGOING = NamespaceID.from("minecraft:msg_command_outgoing"); DynamicRegistry.Key<ChatType> MSG_COMMAND_OUTGOING = DynamicRegistry.Key.of("minecraft:msg_command_outgoing");
NamespaceID SAY_COMMAND = NamespaceID.from("minecraft:say_command"); DynamicRegistry.Key<ChatType> SAY_COMMAND = DynamicRegistry.Key.of("minecraft:say_command");
} }

View File

@ -1,17 +1,17 @@
package net.minestom.server.world; package net.minestom.server.world;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.registry.DynamicRegistry;
/** /**
* Code autogenerated, do not edit! * Code autogenerated, do not edit!
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
interface DimensionTypes { interface DimensionTypes {
NamespaceID THE_END = NamespaceID.from("minecraft:the_end"); DynamicRegistry.Key<DimensionType> THE_END = DynamicRegistry.Key.of("minecraft:the_end");
NamespaceID OVERWORLD_CAVES = NamespaceID.from("minecraft:overworld_caves"); DynamicRegistry.Key<DimensionType> OVERWORLD_CAVES = DynamicRegistry.Key.of("minecraft:overworld_caves");
NamespaceID THE_NETHER = NamespaceID.from("minecraft:the_nether"); DynamicRegistry.Key<DimensionType> THE_NETHER = DynamicRegistry.Key.of("minecraft:the_nether");
NamespaceID OVERWORLD = NamespaceID.from("minecraft:overworld"); DynamicRegistry.Key<DimensionType> OVERWORLD = DynamicRegistry.Key.of("minecraft:overworld");
} }

View File

@ -1,137 +1,137 @@
package net.minestom.server.world.biome; package net.minestom.server.world.biome;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.registry.DynamicRegistry;
/** /**
* Code autogenerated, do not edit! * Code autogenerated, do not edit!
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
interface Biomes { interface Biomes {
NamespaceID SNOWY_SLOPES = NamespaceID.from("minecraft:snowy_slopes"); DynamicRegistry.Key<Biome> SNOWY_SLOPES = DynamicRegistry.Key.of("minecraft:snowy_slopes");
NamespaceID OLD_GROWTH_PINE_TAIGA = NamespaceID.from("minecraft:old_growth_pine_taiga"); DynamicRegistry.Key<Biome> OLD_GROWTH_PINE_TAIGA = DynamicRegistry.Key.of("minecraft:old_growth_pine_taiga");
NamespaceID MUSHROOM_FIELDS = NamespaceID.from("minecraft:mushroom_fields"); DynamicRegistry.Key<Biome> MUSHROOM_FIELDS = DynamicRegistry.Key.of("minecraft:mushroom_fields");
NamespaceID TAIGA = NamespaceID.from("minecraft:taiga"); DynamicRegistry.Key<Biome> TAIGA = DynamicRegistry.Key.of("minecraft:taiga");
NamespaceID DEEP_OCEAN = NamespaceID.from("minecraft:deep_ocean"); DynamicRegistry.Key<Biome> DEEP_OCEAN = DynamicRegistry.Key.of("minecraft:deep_ocean");
NamespaceID ERODED_BADLANDS = NamespaceID.from("minecraft:eroded_badlands"); DynamicRegistry.Key<Biome> ERODED_BADLANDS = DynamicRegistry.Key.of("minecraft:eroded_badlands");
NamespaceID FROZEN_RIVER = NamespaceID.from("minecraft:frozen_river"); DynamicRegistry.Key<Biome> FROZEN_RIVER = DynamicRegistry.Key.of("minecraft:frozen_river");
NamespaceID END_HIGHLANDS = NamespaceID.from("minecraft:end_highlands"); DynamicRegistry.Key<Biome> END_HIGHLANDS = DynamicRegistry.Key.of("minecraft:end_highlands");
NamespaceID CHERRY_GROVE = NamespaceID.from("minecraft:cherry_grove"); DynamicRegistry.Key<Biome> CHERRY_GROVE = DynamicRegistry.Key.of("minecraft:cherry_grove");
NamespaceID SUNFLOWER_PLAINS = NamespaceID.from("minecraft:sunflower_plains"); DynamicRegistry.Key<Biome> SUNFLOWER_PLAINS = DynamicRegistry.Key.of("minecraft:sunflower_plains");
NamespaceID BIRCH_FOREST = NamespaceID.from("minecraft:birch_forest"); DynamicRegistry.Key<Biome> BIRCH_FOREST = DynamicRegistry.Key.of("minecraft:birch_forest");
NamespaceID WINDSWEPT_HILLS = NamespaceID.from("minecraft:windswept_hills"); DynamicRegistry.Key<Biome> WINDSWEPT_HILLS = DynamicRegistry.Key.of("minecraft:windswept_hills");
NamespaceID BAMBOO_JUNGLE = NamespaceID.from("minecraft:bamboo_jungle"); DynamicRegistry.Key<Biome> BAMBOO_JUNGLE = DynamicRegistry.Key.of("minecraft:bamboo_jungle");
NamespaceID WOODED_BADLANDS = NamespaceID.from("minecraft:wooded_badlands"); DynamicRegistry.Key<Biome> WOODED_BADLANDS = DynamicRegistry.Key.of("minecraft:wooded_badlands");
NamespaceID BADLANDS = NamespaceID.from("minecraft:badlands"); DynamicRegistry.Key<Biome> BADLANDS = DynamicRegistry.Key.of("minecraft:badlands");
NamespaceID SAVANNA_PLATEAU = NamespaceID.from("minecraft:savanna_plateau"); DynamicRegistry.Key<Biome> SAVANNA_PLATEAU = DynamicRegistry.Key.of("minecraft:savanna_plateau");
NamespaceID BEACH = NamespaceID.from("minecraft:beach"); DynamicRegistry.Key<Biome> BEACH = DynamicRegistry.Key.of("minecraft:beach");
NamespaceID DARK_FOREST = NamespaceID.from("minecraft:dark_forest"); DynamicRegistry.Key<Biome> DARK_FOREST = DynamicRegistry.Key.of("minecraft:dark_forest");
NamespaceID STONY_PEAKS = NamespaceID.from("minecraft:stony_peaks"); DynamicRegistry.Key<Biome> STONY_PEAKS = DynamicRegistry.Key.of("minecraft:stony_peaks");
NamespaceID MANGROVE_SWAMP = NamespaceID.from("minecraft:mangrove_swamp"); DynamicRegistry.Key<Biome> MANGROVE_SWAMP = DynamicRegistry.Key.of("minecraft:mangrove_swamp");
NamespaceID SPARSE_JUNGLE = NamespaceID.from("minecraft:sparse_jungle"); DynamicRegistry.Key<Biome> SPARSE_JUNGLE = DynamicRegistry.Key.of("minecraft:sparse_jungle");
NamespaceID LUKEWARM_OCEAN = NamespaceID.from("minecraft:lukewarm_ocean"); DynamicRegistry.Key<Biome> LUKEWARM_OCEAN = DynamicRegistry.Key.of("minecraft:lukewarm_ocean");
NamespaceID RIVER = NamespaceID.from("minecraft:river"); DynamicRegistry.Key<Biome> RIVER = DynamicRegistry.Key.of("minecraft:river");
NamespaceID STONY_SHORE = NamespaceID.from("minecraft:stony_shore"); DynamicRegistry.Key<Biome> STONY_SHORE = DynamicRegistry.Key.of("minecraft:stony_shore");
NamespaceID WARPED_FOREST = NamespaceID.from("minecraft:warped_forest"); DynamicRegistry.Key<Biome> WARPED_FOREST = DynamicRegistry.Key.of("minecraft:warped_forest");
NamespaceID SNOWY_PLAINS = NamespaceID.from("minecraft:snowy_plains"); DynamicRegistry.Key<Biome> SNOWY_PLAINS = DynamicRegistry.Key.of("minecraft:snowy_plains");
NamespaceID DRIPSTONE_CAVES = NamespaceID.from("minecraft:dripstone_caves"); DynamicRegistry.Key<Biome> DRIPSTONE_CAVES = DynamicRegistry.Key.of("minecraft:dripstone_caves");
NamespaceID SNOWY_TAIGA = NamespaceID.from("minecraft:snowy_taiga"); DynamicRegistry.Key<Biome> SNOWY_TAIGA = DynamicRegistry.Key.of("minecraft:snowy_taiga");
NamespaceID GROVE = NamespaceID.from("minecraft:grove"); DynamicRegistry.Key<Biome> GROVE = DynamicRegistry.Key.of("minecraft:grove");
NamespaceID SWAMP = NamespaceID.from("minecraft:swamp"); DynamicRegistry.Key<Biome> SWAMP = DynamicRegistry.Key.of("minecraft:swamp");
NamespaceID JAGGED_PEAKS = NamespaceID.from("minecraft:jagged_peaks"); DynamicRegistry.Key<Biome> JAGGED_PEAKS = DynamicRegistry.Key.of("minecraft:jagged_peaks");
NamespaceID COLD_OCEAN = NamespaceID.from("minecraft:cold_ocean"); DynamicRegistry.Key<Biome> COLD_OCEAN = DynamicRegistry.Key.of("minecraft:cold_ocean");
NamespaceID FOREST = NamespaceID.from("minecraft:forest"); DynamicRegistry.Key<Biome> FOREST = DynamicRegistry.Key.of("minecraft:forest");
NamespaceID LUSH_CAVES = NamespaceID.from("minecraft:lush_caves"); DynamicRegistry.Key<Biome> LUSH_CAVES = DynamicRegistry.Key.of("minecraft:lush_caves");
NamespaceID BASALT_DELTAS = NamespaceID.from("minecraft:basalt_deltas"); DynamicRegistry.Key<Biome> BASALT_DELTAS = DynamicRegistry.Key.of("minecraft:basalt_deltas");
NamespaceID DEEP_COLD_OCEAN = NamespaceID.from("minecraft:deep_cold_ocean"); DynamicRegistry.Key<Biome> DEEP_COLD_OCEAN = DynamicRegistry.Key.of("minecraft:deep_cold_ocean");
NamespaceID ICE_SPIKES = NamespaceID.from("minecraft:ice_spikes"); DynamicRegistry.Key<Biome> ICE_SPIKES = DynamicRegistry.Key.of("minecraft:ice_spikes");
NamespaceID END_MIDLANDS = NamespaceID.from("minecraft:end_midlands"); DynamicRegistry.Key<Biome> END_MIDLANDS = DynamicRegistry.Key.of("minecraft:end_midlands");
NamespaceID FROZEN_OCEAN = NamespaceID.from("minecraft:frozen_ocean"); DynamicRegistry.Key<Biome> FROZEN_OCEAN = DynamicRegistry.Key.of("minecraft:frozen_ocean");
NamespaceID DESERT = NamespaceID.from("minecraft:desert"); DynamicRegistry.Key<Biome> DESERT = DynamicRegistry.Key.of("minecraft:desert");
NamespaceID DEEP_FROZEN_OCEAN = NamespaceID.from("minecraft:deep_frozen_ocean"); DynamicRegistry.Key<Biome> DEEP_FROZEN_OCEAN = DynamicRegistry.Key.of("minecraft:deep_frozen_ocean");
NamespaceID WINDSWEPT_FOREST = NamespaceID.from("minecraft:windswept_forest"); DynamicRegistry.Key<Biome> WINDSWEPT_FOREST = DynamicRegistry.Key.of("minecraft:windswept_forest");
NamespaceID JUNGLE = NamespaceID.from("minecraft:jungle"); DynamicRegistry.Key<Biome> JUNGLE = DynamicRegistry.Key.of("minecraft:jungle");
NamespaceID OCEAN = NamespaceID.from("minecraft:ocean"); DynamicRegistry.Key<Biome> OCEAN = DynamicRegistry.Key.of("minecraft:ocean");
NamespaceID OLD_GROWTH_SPRUCE_TAIGA = NamespaceID.from("minecraft:old_growth_spruce_taiga"); DynamicRegistry.Key<Biome> OLD_GROWTH_SPRUCE_TAIGA = DynamicRegistry.Key.of("minecraft:old_growth_spruce_taiga");
NamespaceID SNOWY_BEACH = NamespaceID.from("minecraft:snowy_beach"); DynamicRegistry.Key<Biome> SNOWY_BEACH = DynamicRegistry.Key.of("minecraft:snowy_beach");
NamespaceID WINDSWEPT_SAVANNA = NamespaceID.from("minecraft:windswept_savanna"); DynamicRegistry.Key<Biome> WINDSWEPT_SAVANNA = DynamicRegistry.Key.of("minecraft:windswept_savanna");
NamespaceID END_BARRENS = NamespaceID.from("minecraft:end_barrens"); DynamicRegistry.Key<Biome> END_BARRENS = DynamicRegistry.Key.of("minecraft:end_barrens");
NamespaceID WARM_OCEAN = NamespaceID.from("minecraft:warm_ocean"); DynamicRegistry.Key<Biome> WARM_OCEAN = DynamicRegistry.Key.of("minecraft:warm_ocean");
NamespaceID DEEP_LUKEWARM_OCEAN = NamespaceID.from("minecraft:deep_lukewarm_ocean"); DynamicRegistry.Key<Biome> DEEP_LUKEWARM_OCEAN = DynamicRegistry.Key.of("minecraft:deep_lukewarm_ocean");
NamespaceID FLOWER_FOREST = NamespaceID.from("minecraft:flower_forest"); DynamicRegistry.Key<Biome> FLOWER_FOREST = DynamicRegistry.Key.of("minecraft:flower_forest");
NamespaceID SOUL_SAND_VALLEY = NamespaceID.from("minecraft:soul_sand_valley"); DynamicRegistry.Key<Biome> SOUL_SAND_VALLEY = DynamicRegistry.Key.of("minecraft:soul_sand_valley");
NamespaceID NETHER_WASTES = NamespaceID.from("minecraft:nether_wastes"); DynamicRegistry.Key<Biome> NETHER_WASTES = DynamicRegistry.Key.of("minecraft:nether_wastes");
NamespaceID FROZEN_PEAKS = NamespaceID.from("minecraft:frozen_peaks"); DynamicRegistry.Key<Biome> FROZEN_PEAKS = DynamicRegistry.Key.of("minecraft:frozen_peaks");
NamespaceID THE_END = NamespaceID.from("minecraft:the_end"); DynamicRegistry.Key<Biome> THE_END = DynamicRegistry.Key.of("minecraft:the_end");
NamespaceID SMALL_END_ISLANDS = NamespaceID.from("minecraft:small_end_islands"); DynamicRegistry.Key<Biome> SMALL_END_ISLANDS = DynamicRegistry.Key.of("minecraft:small_end_islands");
NamespaceID OLD_GROWTH_BIRCH_FOREST = NamespaceID.from("minecraft:old_growth_birch_forest"); DynamicRegistry.Key<Biome> OLD_GROWTH_BIRCH_FOREST = DynamicRegistry.Key.of("minecraft:old_growth_birch_forest");
NamespaceID CRIMSON_FOREST = NamespaceID.from("minecraft:crimson_forest"); DynamicRegistry.Key<Biome> CRIMSON_FOREST = DynamicRegistry.Key.of("minecraft:crimson_forest");
NamespaceID THE_VOID = NamespaceID.from("minecraft:the_void"); DynamicRegistry.Key<Biome> THE_VOID = DynamicRegistry.Key.of("minecraft:the_void");
NamespaceID DEEP_DARK = NamespaceID.from("minecraft:deep_dark"); DynamicRegistry.Key<Biome> DEEP_DARK = DynamicRegistry.Key.of("minecraft:deep_dark");
NamespaceID MEADOW = NamespaceID.from("minecraft:meadow"); DynamicRegistry.Key<Biome> MEADOW = DynamicRegistry.Key.of("minecraft:meadow");
NamespaceID WINDSWEPT_GRAVELLY_HILLS = NamespaceID.from("minecraft:windswept_gravelly_hills"); DynamicRegistry.Key<Biome> WINDSWEPT_GRAVELLY_HILLS = DynamicRegistry.Key.of("minecraft:windswept_gravelly_hills");
NamespaceID SAVANNA = NamespaceID.from("minecraft:savanna"); DynamicRegistry.Key<Biome> SAVANNA = DynamicRegistry.Key.of("minecraft:savanna");
NamespaceID PLAINS = NamespaceID.from("minecraft:plains"); DynamicRegistry.Key<Biome> PLAINS = DynamicRegistry.Key.of("minecraft:plains");
} }

View File

@ -25,6 +25,7 @@ import net.minestom.server.network.packet.server.play.EntityAnimationPacket;
import net.minestom.server.network.packet.server.play.EntityAttributesPacket; import net.minestom.server.network.packet.server.play.EntityAttributesPacket;
import net.minestom.server.network.packet.server.play.SoundEffectPacket; import net.minestom.server.network.packet.server.play.SoundEffectPacket;
import net.minestom.server.network.player.PlayerConnection; import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.scoreboard.Team; import net.minestom.server.scoreboard.Team;
import net.minestom.server.sound.SoundEvent; import net.minestom.server.sound.SoundEvent;
import net.minestom.server.utils.block.BlockIterator; import net.minestom.server.utils.block.BlockIterator;
@ -311,7 +312,7 @@ public class LivingEntity extends Entity implements EquipmentHandler {
} }
} }
public boolean damage(@NotNull DamageType type, float amount) { public boolean damage(@NotNull DynamicRegistry.Key<DamageType> type, float amount) {
return damage(new Damage(type, null, null, null, amount)); return damage(new Damage(type, null, null, null, amount));
} }
@ -382,7 +383,7 @@ public class LivingEntity extends Entity implements EquipmentHandler {
* @param type the type of damage * @param type the type of damage
* @return true if this entity is immune to the given type of damage * @return true if this entity is immune to the given type of damage
*/ */
public boolean isImmune(@NotNull DamageType type) { public boolean isImmune(@NotNull DynamicRegistry.Key<DamageType> type) {
return false; return false;
} }

View File

@ -7,11 +7,13 @@ import net.minestom.server.entity.metadata.animal.ArmadilloMeta;
import net.minestom.server.entity.metadata.animal.FrogMeta; import net.minestom.server.entity.metadata.animal.FrogMeta;
import net.minestom.server.entity.metadata.animal.SnifferMeta; import net.minestom.server.entity.metadata.animal.SnifferMeta;
import net.minestom.server.entity.metadata.animal.tameable.CatMeta; import net.minestom.server.entity.metadata.animal.tameable.CatMeta;
import net.minestom.server.entity.metadata.animal.tameable.WolfMeta;
import net.minestom.server.entity.metadata.other.PaintingMeta; import net.minestom.server.entity.metadata.other.PaintingMeta;
import net.minestom.server.item.ItemStack; import net.minestom.server.item.ItemStack;
import net.minestom.server.network.NetworkBuffer; import net.minestom.server.network.NetworkBuffer;
import net.minestom.server.network.packet.server.play.EntityMetaDataPacket; import net.minestom.server.network.packet.server.play.EntityMetaDataPacket;
import net.minestom.server.particle.Particle; import net.minestom.server.particle.Particle;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.utils.Direction; import net.minestom.server.utils.Direction;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -149,6 +151,10 @@ public final class Metadata {
return new MetadataImpl.EntryImpl<>(TYPE_CAT_VARIANT, value, NetworkBuffer.CAT_VARIANT); return new MetadataImpl.EntryImpl<>(TYPE_CAT_VARIANT, value, NetworkBuffer.CAT_VARIANT);
} }
public static Entry<DynamicRegistry.Key<WolfMeta.Variant>> WolfVariant(@NotNull DynamicRegistry.Key<WolfMeta.Variant> value) {
return new MetadataImpl.EntryImpl<>(TYPE_WOLF_VARIANT, value, WolfMeta.Variant.NETWORK_TYPE);
}
// WOLF VARIANT // WOLF VARIANT
public static Entry<FrogMeta.Variant> FrogVariant(@NotNull FrogMeta.Variant value) { public static Entry<FrogMeta.Variant> FrogVariant(@NotNull FrogMeta.Variant value) {

View File

@ -7,6 +7,7 @@ import net.minestom.server.entity.metadata.animal.ArmadilloMeta;
import net.minestom.server.entity.metadata.animal.FrogMeta; import net.minestom.server.entity.metadata.animal.FrogMeta;
import net.minestom.server.entity.metadata.animal.SnifferMeta; import net.minestom.server.entity.metadata.animal.SnifferMeta;
import net.minestom.server.entity.metadata.animal.tameable.CatMeta; import net.minestom.server.entity.metadata.animal.tameable.CatMeta;
import net.minestom.server.entity.metadata.animal.tameable.WolfMeta;
import net.minestom.server.entity.metadata.other.PaintingMeta; import net.minestom.server.entity.metadata.other.PaintingMeta;
import net.minestom.server.instance.block.Block; import net.minestom.server.instance.block.Block;
import net.minestom.server.item.ItemStack; import net.minestom.server.item.ItemStack;
@ -49,7 +50,7 @@ final class MetadataImpl {
EMPTY_VALUES.set(TYPE_OPT_VARINT, OptVarInt(null)); EMPTY_VALUES.set(TYPE_OPT_VARINT, OptVarInt(null));
EMPTY_VALUES.set(TYPE_POSE, Pose(Entity.Pose.STANDING)); EMPTY_VALUES.set(TYPE_POSE, Pose(Entity.Pose.STANDING));
EMPTY_VALUES.set(TYPE_CAT_VARIANT, CatVariant(CatMeta.Variant.TABBY)); EMPTY_VALUES.set(TYPE_CAT_VARIANT, CatVariant(CatMeta.Variant.TABBY));
// WolfVariant EMPTY_VALUES.set(TYPE_WOLF_VARIANT, WolfVariant(WolfMeta.Variant.PALE));
EMPTY_VALUES.set(TYPE_FROG_VARIANT, FrogVariant(FrogMeta.Variant.TEMPERATE)); EMPTY_VALUES.set(TYPE_FROG_VARIANT, FrogVariant(FrogMeta.Variant.TEMPERATE));
// OptGlobalPos // OptGlobalPos
EMPTY_VALUES.set(TYPE_PAINTING_VARIANT, PaintingVariant(PaintingMeta.Variant.KEBAB)); EMPTY_VALUES.set(TYPE_PAINTING_VARIANT, PaintingVariant(PaintingMeta.Variant.KEBAB));

View File

@ -506,7 +506,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
// Set death location // Set death location
if (getInstance() != null) if (getInstance() != null)
setDeathLocation(getInstance().getDimensionType(), getPosition()); setDeathLocation(getInstance().getDimensionName(), getPosition());
} }
super.kill(); super.kill();
} }
@ -1035,9 +1035,9 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
} }
@Override @Override
public boolean isImmune(@NotNull DamageType type) { public boolean isImmune(@NotNull DynamicRegistry.Key<DamageType> type) {
if (!getGameMode().canTakeDamage()) { if (!getGameMode().canTakeDamage()) {
return !DamageType.OUT_OF_WORLD.equals(type.namespace()); return !DamageType.OUT_OF_WORLD.equals(type);
} }
return super.isImmune(type); return super.isImmune(type);
} }
@ -1222,8 +1222,12 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
teleport(getPosition()); teleport(getPosition());
} }
public void setDeathLocation(@NotNull DimensionType type, @NotNull Pos position) { public void setDeathLocation(@NotNull Pos position) {
this.deathLocation = new WorldPos(type.name(), position); setDeathLocation(getInstance().getDimensionName(), position);
}
public void setDeathLocation(@NotNull String dimension, @NotNull Pos position) {
this.deathLocation = new WorldPos(dimension, position);
} }
public @Nullable WorldPos getDeathLocation() { public @Nullable WorldPos getDeathLocation() {
@ -1646,10 +1650,10 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
* *
* @param dimensionType the new player dimension * @param dimensionType the new player dimension
*/ */
protected void sendDimension(@NotNull DimensionType dimensionType, @NotNull String dimensionName) { protected void sendDimension(@NotNull DynamicRegistry.Key<DimensionType> dimensionType, @NotNull String dimensionName) {
Check.argCondition(instance.getDimensionName().equals(dimensionName), Check.argCondition(instance.getDimensionName().equals(dimensionName),
"The dimension needs to be different than the current one!"); "The dimension needs to be different than the current one!");
this.dimensionTypeId = DIMENSION_TYPE_REGISTRY.getId(dimensionType.namespace()); this.dimensionTypeId = DIMENSION_TYPE_REGISTRY.getId(dimensionType);
sendPacket(new RespawnPacket(dimensionTypeId, dimensionName, sendPacket(new RespawnPacket(dimensionTypeId, dimensionName,
0, gameMode, gameMode, false, levelFlat, 0, gameMode, gameMode, false, levelFlat,
deathLocation, portalCooldown, RespawnPacket.COPY_ALL)); deathLocation, portalCooldown, RespawnPacket.COPY_ALL));

View File

@ -1,13 +1,16 @@
package net.minestom.server.entity.damage; package net.minestom.server.entity.damage;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.minestom.server.MinecraftServer;
import net.minestom.server.coordinate.Point; import net.minestom.server.coordinate.Point;
import net.minestom.server.entity.Entity; import net.minestom.server.entity.Entity;
import net.minestom.server.entity.LivingEntity; import net.minestom.server.entity.LivingEntity;
import net.minestom.server.entity.Player; import net.minestom.server.entity.Player;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.sound.SoundEvent; import net.minestom.server.sound.SoundEvent;
import net.minestom.server.tag.TagHandler; import net.minestom.server.tag.TagHandler;
import net.minestom.server.tag.Taggable; import net.minestom.server.tag.Taggable;
import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -18,7 +21,9 @@ import org.jetbrains.annotations.Nullable;
* This class can be extended if you need to include custom fields and/or methods. * This class can be extended if you need to include custom fields and/or methods.
*/ */
public class Damage implements Taggable { public class Damage implements Taggable {
private static final DynamicRegistry<DamageType> DAMAGE_TYPE_REGISTRY = MinecraftServer.getDamageTypeRegistry();
private final DynamicRegistry.Key<DamageType> typeKey;
private final DamageType type; private final DamageType type;
private final Entity source; private final Entity source;
private final Entity attacker; private final Entity attacker;
@ -33,8 +38,10 @@ public class Damage implements Taggable {
* @param type the type of this damage * @param type the type of this damage
* @param amount amount of damage * @param amount amount of damage
*/ */
public Damage(@NotNull DamageType type, @Nullable Entity source, @Nullable Entity attacker, @Nullable Point sourcePosition, float amount) { public Damage(@NotNull DynamicRegistry.Key<DamageType> type, @Nullable Entity source, @Nullable Entity attacker, @Nullable Point sourcePosition, float amount) {
this.type = type; this.typeKey = type;
this.type = DAMAGE_TYPE_REGISTRY.get(type);
Check.argCondition(this.type == null, "Damage type is not registered: {0}", type);
this.source = source; this.source = source;
this.attacker = attacker; this.attacker = attacker;
this.sourcePosition = sourcePosition; this.sourcePosition = sourcePosition;
@ -48,8 +55,8 @@ public class Damage implements Taggable {
* *
* @return the damage type * @return the damage type
*/ */
public @NotNull DamageType getType() { public @NotNull DynamicRegistry.Key<DamageType> getType() {
return type; return typeKey;
} }
/** /**
@ -128,7 +135,7 @@ public class Damage implements Taggable {
return new EntityDamage(entity, amount); return new EntityDamage(entity, amount);
} }
public static @NotNull PositionalDamage fromPosition(@NotNull DamageType type, @NotNull Point sourcePosition, float amount) { public static @NotNull PositionalDamage fromPosition(@NotNull DynamicRegistry.Key<DamageType> type, @NotNull Point sourcePosition, float amount) {
return new PositionalDamage(type, sourcePosition, amount); return new PositionalDamage(type, sourcePosition, amount);
} }

View File

@ -5,13 +5,11 @@ import net.minestom.server.registry.DynamicRegistryImpl;
import net.minestom.server.registry.ProtocolObject; import net.minestom.server.registry.ProtocolObject;
import net.minestom.server.registry.Registry; import net.minestom.server.registry.Registry;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.NamespaceID;
import net.minestom.server.utils.nbt.BinaryTagSerializer;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public sealed interface DamageType extends ProtocolObject, DamageTypes permits DamageTypeImpl { public sealed interface DamageType extends ProtocolObject, DamageTypes permits DamageTypeImpl {
@NotNull BinaryTagSerializer<DamageType> NBT_TYPE = DamageTypeImpl.NBT_TYPE;
static @NotNull DamageType create( static @NotNull DamageType create(
@NotNull NamespaceID namespace, @NotNull NamespaceID namespace,
@ -38,7 +36,7 @@ public sealed interface DamageType extends ProtocolObject, DamageTypes permits D
@ApiStatus.Internal @ApiStatus.Internal
static @NotNull DynamicRegistry<DamageType> createDefaultRegistry() { static @NotNull DynamicRegistry<DamageType> createDefaultRegistry() {
return new DynamicRegistryImpl<>( return new DynamicRegistryImpl<>(
"minecraft:damage_type", NBT_TYPE, Registry.Resource.DAMAGE_TYPES, "minecraft:damage_type", DamageTypeImpl.REGISTRY_NBT_TYPE, Registry.Resource.DAMAGE_TYPES,
(namespace, props) -> new DamageTypeImpl(Registry.damageType(namespace, props)) (namespace, props) -> new DamageTypeImpl(Registry.damageType(namespace, props))
); );
} }

View File

@ -16,7 +16,7 @@ record DamageTypeImpl(
@Nullable Registry.DamageTypeEntry registry @Nullable Registry.DamageTypeEntry registry
) implements DamageType { ) implements DamageType {
static final BinaryTagSerializer<DamageType> NBT_TYPE = BinaryTagSerializer.COMPOUND.map( static final BinaryTagSerializer<DamageType> REGISTRY_NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
tag -> { tag -> {
throw new UnsupportedOperationException("DamageType is read-only"); throw new UnsupportedOperationException("DamageType is read-only");
}, },

View File

@ -1,21 +1,15 @@
package net.minestom.server.entity.damage; package net.minestom.server.entity.damage;
import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.Entity; import net.minestom.server.entity.Entity;
import net.minestom.server.registry.DynamicRegistry;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Objects;
/** /**
* Represents damage inflicted by an {@link Entity}. * Represents damage inflicted by an {@link Entity}.
*/ */
public class EntityDamage extends Damage { public class EntityDamage extends Damage {
private static final DynamicRegistry<DamageType> DAMAGE_TYPES = MinecraftServer.getDamageTypeRegistry();
public EntityDamage(@NotNull Entity source, float amount) { public EntityDamage(@NotNull Entity source, float amount) {
super(Objects.requireNonNull(DAMAGE_TYPES.get(DamageType.MOB_ATTACK)), super(DamageType.MOB_ATTACK, source, source, null, amount);
source, source, null, amount);
} }
/** /**

View File

@ -1,21 +1,16 @@
package net.minestom.server.entity.damage; package net.minestom.server.entity.damage;
import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.Entity; import net.minestom.server.entity.Entity;
import net.minestom.server.registry.DynamicRegistry;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.Objects;
/** /**
* Represents damage inflicted by an entity, via a projectile. * Represents damage inflicted by an entity, via a projectile.
*/ */
public class EntityProjectileDamage extends Damage { public class EntityProjectileDamage extends Damage {
private static final DynamicRegistry<DamageType> DAMAGE_TYPES = MinecraftServer.getDamageTypeRegistry();
public EntityProjectileDamage(@Nullable Entity shooter, @NotNull Entity projectile, float amount) { public EntityProjectileDamage(@Nullable Entity shooter, @NotNull Entity projectile, float amount) {
super(Objects.requireNonNull(DAMAGE_TYPES.get(DamageType.MOB_PROJECTILE)), projectile, shooter, null, amount); super(DamageType.MOB_PROJECTILE, projectile, shooter, null, amount);
} }
/** /**

View File

@ -1,6 +1,7 @@
package net.minestom.server.entity.damage; package net.minestom.server.entity.damage;
import net.minestom.server.coordinate.Point; import net.minestom.server.coordinate.Point;
import net.minestom.server.registry.DynamicRegistry;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
/** /**
@ -8,12 +9,8 @@ import org.jetbrains.annotations.NotNull;
*/ */
public class PositionalDamage extends Damage { public class PositionalDamage extends Damage {
public PositionalDamage(@NotNull DamageType type, @NotNull Point sourcePosition, float amount) { public PositionalDamage(@NotNull DynamicRegistry.Key<DamageType> type, @NotNull Point sourcePosition, float amount) {
super(type, null, null, sourcePosition, amount); super(type, null, null, sourcePosition, amount);
} }
@Override
public @NotNull Point getSourcePosition() {
return super.getSourcePosition();
}
} }

View File

@ -5,10 +5,8 @@ import net.kyori.adventure.nbt.CompoundBinaryTag;
import net.kyori.adventure.nbt.StringBinaryTag; import net.kyori.adventure.nbt.StringBinaryTag;
import net.minestom.server.entity.Entity; import net.minestom.server.entity.Entity;
import net.minestom.server.entity.Metadata; import net.minestom.server.entity.Metadata;
import net.minestom.server.registry.DynamicRegistry; import net.minestom.server.network.NetworkBuffer;
import net.minestom.server.registry.DynamicRegistryImpl; import net.minestom.server.registry.*;
import net.minestom.server.registry.ProtocolObject;
import net.minestom.server.registry.Registry;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.NamespaceID;
import net.minestom.server.utils.nbt.BinaryTagSerializer; import net.minestom.server.utils.nbt.BinaryTagSerializer;
import net.minestom.server.utils.validate.Check; import net.minestom.server.utils.validate.Check;
@ -20,7 +18,7 @@ import java.util.List;
public class WolfMeta extends TameableAnimalMeta { public class WolfMeta extends TameableAnimalMeta {
public static final byte OFFSET = TameableAnimalMeta.MAX_OFFSET; public static final byte OFFSET = TameableAnimalMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 3; public static final byte MAX_OFFSET = OFFSET + 4;
public WolfMeta(@NotNull Entity entity, @NotNull Metadata metadata) { public WolfMeta(@NotNull Entity entity, @NotNull Metadata metadata) {
super(entity, metadata); super(entity, metadata);
@ -52,8 +50,17 @@ public class WolfMeta extends TameableAnimalMeta {
super.metadata.setIndex(OFFSET + 2, Metadata.VarInt(value)); super.metadata.setIndex(OFFSET + 2, Metadata.VarInt(value));
} }
public @NotNull DynamicRegistry.Key<Variant> getVariant() {
return super.metadata.getIndex(OFFSET + 3, Variant.PALE);
}
public void setVariant(@NotNull DynamicRegistry.Key<Variant> value) {
super.metadata.setIndex(OFFSET + 3, Metadata.WolfVariant(value));
}
public sealed interface Variant extends ProtocolObject, WolfVariants permits VariantImpl { public sealed interface Variant extends ProtocolObject, WolfVariants permits VariantImpl {
@NotNull BinaryTagSerializer<Variant> NBT_TYPE = VariantImpl.NBT_TYPE; @NotNull NetworkBuffer.Type<DynamicRegistry.Key<Variant>> NETWORK_TYPE = NetworkBuffer.registryKey(Registries::wolfVariant);
@NotNull BinaryTagSerializer<DynamicRegistry.Key<Variant>> NBT_TYPE = BinaryTagSerializer.registryKey(Registries::wolfVariant);
static @NotNull Variant create( static @NotNull Variant create(
@NotNull NamespaceID namespace, @NotNull NamespaceID namespace,
@ -81,7 +88,7 @@ public class WolfMeta extends TameableAnimalMeta {
@ApiStatus.Internal @ApiStatus.Internal
static @NotNull DynamicRegistry<Variant> createDefaultRegistry() { static @NotNull DynamicRegistry<Variant> createDefaultRegistry() {
return new DynamicRegistryImpl<>( return new DynamicRegistryImpl<>(
"minecraft:wolf_variant", NBT_TYPE, Registry.Resource.WOLF_VARIANTS, "minecraft:wolf_variant", VariantImpl.REGISTRY_NBT_TYPE, Registry.Resource.WOLF_VARIANTS,
(namespace, props) -> new WolfMeta.VariantImpl(Registry.wolfVariant(namespace, props)) (namespace, props) -> new WolfMeta.VariantImpl(Registry.wolfVariant(namespace, props))
); );
} }
@ -149,7 +156,7 @@ public class WolfMeta extends TameableAnimalMeta {
) implements Variant { ) implements Variant {
private static final BinaryTagSerializer<List<String>> BIOMES_NBT_TYPE = BinaryTagSerializer.STRING.list(); private static final BinaryTagSerializer<List<String>> BIOMES_NBT_TYPE = BinaryTagSerializer.STRING.list();
static final BinaryTagSerializer<Variant> NBT_TYPE = BinaryTagSerializer.COMPOUND.map( static final BinaryTagSerializer<Variant> REGISTRY_NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
tag -> { tag -> {
throw new UnsupportedOperationException("WolfVariant is read-only"); throw new UnsupportedOperationException("WolfVariant is read-only");
}, },

View File

@ -18,6 +18,7 @@ import net.minestom.server.tag.TagHandler;
import net.minestom.server.tag.Taggable; import net.minestom.server.tag.Taggable;
import net.minestom.server.utils.chunk.ChunkSupplier; import net.minestom.server.utils.chunk.ChunkSupplier;
import net.minestom.server.utils.chunk.ChunkUtils; import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.world.DimensionType;
import net.minestom.server.world.biome.Biome; import net.minestom.server.world.biome.Biome;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -70,8 +71,9 @@ public abstract class Chunk implements Block.Getter, Block.Setter, Biome.Getter,
this.chunkX = chunkX; this.chunkX = chunkX;
this.chunkZ = chunkZ; this.chunkZ = chunkZ;
this.shouldGenerate = shouldGenerate; this.shouldGenerate = shouldGenerate;
this.minSection = instance.getDimensionType().minY() / CHUNK_SECTION_SIZE; final DimensionType instanceDim = instance.getCachedDimensionType();
this.maxSection = (instance.getDimensionType().minY() + instance.getDimensionType().height()) / CHUNK_SECTION_SIZE; this.minSection = instanceDim.minY() / CHUNK_SECTION_SIZE;
this.maxSection = (instanceDim.minY() + instanceDim.height()) / CHUNK_SECTION_SIZE;
final List<SharedInstance> shared = instance instanceof InstanceContainer instanceContainer ? final List<SharedInstance> shared = instance instanceof InstanceContainer instanceContainer ?
instanceContainer.getSharedInstances() : List.of(); instanceContainer.getSharedInstances() : List.of();
this.viewable = instance.getEntityTracker().viewable(shared, chunkX, chunkZ); this.viewable = instance.getEntityTracker().viewable(shared, chunkX, chunkZ);

View File

@ -27,6 +27,8 @@ import net.minestom.server.snapshot.SnapshotImpl;
import net.minestom.server.snapshot.SnapshotUpdater; import net.minestom.server.snapshot.SnapshotUpdater;
import net.minestom.server.utils.ArrayUtils; import net.minestom.server.utils.ArrayUtils;
import net.minestom.server.utils.chunk.ChunkUtils; import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.utils.validate.Check;
import net.minestom.server.world.DimensionType;
import net.minestom.server.world.biome.Biome; import net.minestom.server.world.biome.Biome;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -71,9 +73,10 @@ public class DynamicChunk extends Chunk {
public void setBlock(int x, int y, int z, @NotNull Block block, public void setBlock(int x, int y, int z, @NotNull Block block,
@Nullable BlockHandler.Placement placement, @Nullable BlockHandler.Placement placement,
@Nullable BlockHandler.Destroy destroy) { @Nullable BlockHandler.Destroy destroy) {
if(y >= instance.getDimensionType().maxY() || y < instance.getDimensionType().minY()) { final DimensionType instanceDim = instance.getCachedDimensionType();
if (y >= instanceDim.maxY() || y < instanceDim.minY()) {
LOGGER.warn("tried to set a block outside the world bounds, should be within [{}, {}): {}", LOGGER.warn("tried to set a block outside the world bounds, should be within [{}, {}): {}",
instance.getDimensionType().minY(), instance.getDimensionType().maxY(), y); instanceDim.minY(), instanceDim.maxY(), y);
return; return;
} }
assertLock(); assertLock();
@ -136,7 +139,7 @@ public class DynamicChunk extends Chunk {
} }
@Override @Override
public void setBiome(int x, int y, int z, @NotNull Biome biome) { public void setBiome(int x, int y, int z, @NotNull DynamicRegistry.Key<Biome> biome) {
assertLock(); assertLock();
this.chunkCache.invalidate(); this.chunkCache.invalidate();
Section section = getSectionAt(y); Section section = getSectionAt(y);
@ -216,17 +219,14 @@ public class DynamicChunk extends Chunk {
} }
@Override @Override
public @NotNull Biome getBiome(int x, int y, int z) { public @NotNull DynamicRegistry.Key<Biome> getBiome(int x, int y, int z) {
assertLock(); assertLock();
final Section section = getSectionAt(y); final Section section = getSectionAt(y);
final int id = section.biomePalette() final int id = section.biomePalette()
.get(toSectionRelativeCoordinate(x) / 4, toSectionRelativeCoordinate(y) / 4, toSectionRelativeCoordinate(z) / 4); .get(toSectionRelativeCoordinate(x) / 4, toSectionRelativeCoordinate(y) / 4, toSectionRelativeCoordinate(z) / 4);
Biome biome = BIOME_REGISTRY.get(id); DynamicRegistry.Key<Biome> biome = BIOME_REGISTRY.getKey(id);
if (biome == null) { Check.notNull(biome, "Biome with id {0} is not registered", id);
throw new IllegalStateException("Biome with id " + id + " is not registered");
}
return biome; return biome;
} }

View File

@ -10,6 +10,7 @@ import net.minestom.server.instance.generator.GenerationUnit;
import net.minestom.server.instance.generator.UnitModifier; import net.minestom.server.instance.generator.UnitModifier;
import net.minestom.server.instance.palette.Palette; import net.minestom.server.instance.palette.Palette;
import net.minestom.server.registry.DynamicRegistry; import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.utils.validate.Check;
import net.minestom.server.world.biome.Biome; import net.minestom.server.world.biome.Biome;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -223,10 +224,10 @@ final class GeneratorImpl {
} }
@Override @Override
public void setBiome(int x, int y, int z, @NotNull Biome biome) { public void setBiome(int x, int y, int z, @NotNull DynamicRegistry.Key<Biome> biome) {
if (fork) throw new IllegalStateException("Cannot modify biomes of a fork"); if (fork) throw new IllegalStateException("Cannot modify biomes of a fork");
var id = BIOME_MANAGER.getId(biome.namespace()); var id = BIOME_MANAGER.getId(biome);
if (id == -1) throw new IllegalStateException("Biome has not been registered: " + biome.namespace()); Check.argCondition(id == -1, "Biome has not been registered: {0}", biome);
this.biomePalette.set( this.biomePalette.set(
toSectionRelativeCoordinate(x) / 4, toSectionRelativeCoordinate(x) / 4,
@ -273,10 +274,10 @@ final class GeneratorImpl {
} }
@Override @Override
public void fillBiome(@NotNull Biome biome) { public void fillBiome(@NotNull DynamicRegistry.Key<Biome> biome) {
if (fork) throw new IllegalStateException("Cannot modify biomes of a fork"); if (fork) throw new IllegalStateException("Cannot modify biomes of a fork");
var id = BIOME_MANAGER.getId(biome.namespace()); var id = BIOME_MANAGER.getId(biome);
if (id == -1) throw new IllegalStateException("Biome has not been registered: " + biome.namespace()); Check.argCondition(id == -1, "Biome has not been registered: {0}", biome);
this.biomePalette.fill(id); this.biomePalette.fill(id);
} }
@ -310,7 +311,7 @@ final class GeneratorImpl {
} }
@Override @Override
public void setBiome(int x, int y, int z, @NotNull Biome biome) { public void setBiome(int x, int y, int z, @NotNull DynamicRegistry.Key<Biome> biome) {
checkBorder(x, y, z); checkBorder(x, y, z);
final GenerationUnit section = findAbsoluteSection(x, y, z); final GenerationUnit section = findAbsoluteSection(x, y, z);
y -= start.y(); y -= start.y();
@ -362,7 +363,7 @@ final class GeneratorImpl {
} }
@Override @Override
public void fillBiome(@NotNull Biome biome) { public void fillBiome(@NotNull DynamicRegistry.Key<Biome> biome) {
for (GenerationUnit section : sections) { for (GenerationUnit section : sections) {
section.modifier().fillBiome(biome); section.modifier().fillBiome(biome);
} }

View File

@ -72,8 +72,8 @@ public abstract class Instance implements Block.Getter, Block.Setter,
private boolean registered; private boolean registered;
private final int dimensionTypeId; private final DynamicRegistry.Key<DimensionType> dimensionType;
private final DimensionType cachedDimensionType; private final DimensionType cachedDimensionType; // Cached to prevent self-destruction if the registry is changed, and to avoid the lookups.
private final String dimensionName; private final String dimensionName;
private final WorldBorder worldBorder; private final WorldBorder worldBorder;
@ -123,7 +123,7 @@ public abstract class Instance implements Block.Getter, Block.Setter,
* @param uniqueId the {@link UUID} of the instance * @param uniqueId the {@link UUID} of the instance
* @param dimensionType the {@link DimensionType} of the instance * @param dimensionType the {@link DimensionType} of the instance
*/ */
public Instance(@NotNull UUID uniqueId, @NotNull DimensionType dimensionType) { public Instance(@NotNull UUID uniqueId, @NotNull DynamicRegistry.Key<DimensionType> dimensionType) {
this(uniqueId, dimensionType, dimensionType.namespace()); this(uniqueId, dimensionType, dimensionType.namespace());
} }
@ -133,11 +133,11 @@ public abstract class Instance implements Block.Getter, Block.Setter,
* @param uniqueId the {@link UUID} of the instance * @param uniqueId the {@link UUID} of the instance
* @param dimensionType the {@link DimensionType} of the instance * @param dimensionType the {@link DimensionType} of the instance
*/ */
public Instance(@NotNull UUID uniqueId, @NotNull DimensionType dimensionType, @NotNull NamespaceID dimensionName) { public Instance(@NotNull UUID uniqueId, @NotNull DynamicRegistry.Key<DimensionType> dimensionType, @NotNull NamespaceID dimensionName) {
this.uniqueId = uniqueId; this.uniqueId = uniqueId;
this.dimensionTypeId = DIMENSION_REGISTRY.getId(dimensionType.namespace()); this.dimensionType = dimensionType;
Check.argCondition(this.dimensionTypeId == -1, "The dimension " + dimensionType.name() + " is not registered! Please add it to the registry (`MinecraftServer.getDimensionTypeRegistry().registry(dimensionType)`)."); this.cachedDimensionType = DIMENSION_REGISTRY.get(dimensionType);
this.cachedDimensionType = dimensionType; Check.argCondition(cachedDimensionType == null, "The dimension " + dimensionType + " is not registered! Please add it to the registry (`MinecraftServer.getDimensionTypeRegistry().registry(dimensionType)`).");
this.dimensionName = dimensionName.asString(); this.dimensionName = dimensionName.asString();
this.worldBorder = new WorldBorder(this); this.worldBorder = new WorldBorder(this);
@ -399,7 +399,12 @@ public abstract class Instance implements Block.Getter, Block.Setter,
* *
* @return the dimension of the instance * @return the dimension of the instance
*/ */
public DimensionType getDimensionType() { public DynamicRegistry.Key<DimensionType> getDimensionType() {
return dimensionType;
}
@ApiStatus.Internal
public @NotNull DimensionType getCachedDimensionType() {
return cachedDimensionType; return cachedDimensionType;
} }

View File

@ -23,6 +23,7 @@ import net.minestom.server.network.packet.server.play.BlockChangePacket;
import net.minestom.server.network.packet.server.play.BlockEntityDataPacket; import net.minestom.server.network.packet.server.play.BlockEntityDataPacket;
import net.minestom.server.network.packet.server.play.EffectPacket; import net.minestom.server.network.packet.server.play.EffectPacket;
import net.minestom.server.network.packet.server.play.UnloadChunkPacket; import net.minestom.server.network.packet.server.play.UnloadChunkPacket;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.NamespaceID;
import net.minestom.server.utils.PacketUtils; import net.minestom.server.utils.PacketUtils;
import net.minestom.server.utils.async.AsyncUtils; import net.minestom.server.utils.async.AsyncUtils;
@ -87,19 +88,19 @@ public class InstanceContainer extends Instance {
protected InstanceContainer srcInstance; // only present if this instance has been created using a copy protected InstanceContainer srcInstance; // only present if this instance has been created using a copy
private long lastBlockChangeTime; // Time at which the last block change happened (#setBlock) private long lastBlockChangeTime; // Time at which the last block change happened (#setBlock)
public InstanceContainer(@NotNull UUID uniqueId, @NotNull DimensionType dimensionType) { public InstanceContainer(@NotNull UUID uniqueId, @NotNull DynamicRegistry.Key<DimensionType> dimensionType) {
this(uniqueId, dimensionType, null, dimensionType.namespace()); this(uniqueId, dimensionType, null, dimensionType.namespace());
} }
public InstanceContainer(@NotNull UUID uniqueId, @NotNull DimensionType dimensionType, @NotNull NamespaceID dimensionName) { public InstanceContainer(@NotNull UUID uniqueId, @NotNull DynamicRegistry.Key<DimensionType> dimensionType, @NotNull NamespaceID dimensionName) {
this(uniqueId, dimensionType, null, dimensionName); this(uniqueId, dimensionType, null, dimensionName);
} }
public InstanceContainer(@NotNull UUID uniqueId, @NotNull DimensionType dimensionType, @Nullable IChunkLoader loader) { public InstanceContainer(@NotNull UUID uniqueId, @NotNull DynamicRegistry.Key<DimensionType> dimensionType, @Nullable IChunkLoader loader) {
this(uniqueId, dimensionType, loader, dimensionType.namespace()); this(uniqueId, dimensionType, loader, dimensionType.namespace());
} }
public InstanceContainer(@NotNull UUID uniqueId, @NotNull DimensionType dimensionType, @Nullable IChunkLoader loader, @NotNull NamespaceID dimensionName) { public InstanceContainer(@NotNull UUID uniqueId, @NotNull DynamicRegistry.Key<DimensionType> dimensionType, @Nullable IChunkLoader loader, @NotNull NamespaceID dimensionName) {
super(uniqueId, dimensionType, dimensionName); super(uniqueId, dimensionType, dimensionName);
setChunkSupplier(DynamicChunk::new); setChunkSupplier(DynamicChunk::new);
setChunkLoader(Objects.requireNonNullElse(loader, DEFAULT_LOADER)); setChunkLoader(Objects.requireNonNullElse(loader, DEFAULT_LOADER));
@ -132,8 +133,9 @@ public class InstanceContainer extends Instance {
@Nullable BlockHandler.Placement placement, @Nullable BlockHandler.Destroy destroy, @Nullable BlockHandler.Placement placement, @Nullable BlockHandler.Destroy destroy,
boolean doBlockUpdates, int updateDistance) { boolean doBlockUpdates, int updateDistance) {
if (chunk.isReadOnly()) return; if (chunk.isReadOnly()) return;
if (y >= getDimensionType().maxY() || y < getDimensionType().minY()) { final DimensionType dim = getCachedDimensionType();
LOGGER.warn("tried to set a block outside the world bounds, should be within [{}, {}): {}", getDimensionType().minY(), getDimensionType().maxY(), y); if (y >= dim.maxY() || y < dim.minY()) {
LOGGER.warn("tried to set a block outside the world bounds, should be within [{}, {}): {}", dim.minY(), dim.maxY(), y);
return; return;
} }
@ -438,7 +440,7 @@ public class InstanceContainer extends Instance {
@Override @Override
public boolean isInVoid(@NotNull Point point) { public boolean isInVoid(@NotNull Point point) {
// TODO: more customizable // TODO: more customizable
return point.y() < getDimensionType().minY() - 64; return point.y() < getCachedDimensionType().minY() - 64;
} }
/** /**
@ -627,7 +629,7 @@ public class InstanceContainer extends Instance {
final int neighborX = blockPosition.blockX() + direction.normalX(); final int neighborX = blockPosition.blockX() + direction.normalX();
final int neighborY = blockPosition.blockY() + direction.normalY(); final int neighborY = blockPosition.blockY() + direction.normalY();
final int neighborZ = blockPosition.blockZ() + direction.normalZ(); final int neighborZ = blockPosition.blockZ() + direction.normalZ();
if (neighborY < getDimensionType().minY() || neighborY > getDimensionType().height()) if (neighborY < getCachedDimensionType().minY() || neighborY > getCachedDimensionType().height())
continue; continue;
final Block neighborBlock = cache.getBlock(neighborX, neighborY, neighborZ, Condition.TYPE); final Block neighborBlock = cache.getBlock(neighborX, neighborY, neighborZ, Condition.TYPE);
if (neighborBlock == null) if (neighborBlock == null)

View File

@ -4,13 +4,17 @@ import net.minestom.server.MinecraftServer;
import net.minestom.server.event.EventDispatcher; import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.instance.InstanceRegisterEvent; import net.minestom.server.event.instance.InstanceRegisterEvent;
import net.minestom.server.event.instance.InstanceUnregisterEvent; import net.minestom.server.event.instance.InstanceUnregisterEvent;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.utils.validate.Check; import net.minestom.server.utils.validate.Check;
import net.minestom.server.world.DimensionType; import net.minestom.server.world.DimensionType;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.*; import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.CopyOnWriteArraySet;
/** /**
@ -42,20 +46,19 @@ public final class InstanceManager {
* @return the created {@link InstanceContainer} * @return the created {@link InstanceContainer}
*/ */
@ApiStatus.Experimental @ApiStatus.Experimental
public @NotNull InstanceContainer createInstanceContainer(@NotNull DimensionType dimensionType, @Nullable IChunkLoader loader) { public @NotNull InstanceContainer createInstanceContainer(@NotNull DynamicRegistry.Key<DimensionType> dimensionType, @Nullable IChunkLoader loader) {
final InstanceContainer instanceContainer = new InstanceContainer(UUID.randomUUID(), dimensionType, loader); final InstanceContainer instanceContainer = new InstanceContainer(UUID.randomUUID(), dimensionType, loader);
registerInstance(instanceContainer); registerInstance(instanceContainer);
return instanceContainer; return instanceContainer;
} }
public @NotNull InstanceContainer createInstanceContainer(@NotNull DimensionType dimensionType) { public @NotNull InstanceContainer createInstanceContainer(@NotNull DynamicRegistry.Key<DimensionType> dimensionType) {
return createInstanceContainer(dimensionType, null); return createInstanceContainer(dimensionType, null);
} }
@ApiStatus.Experimental @ApiStatus.Experimental
public @NotNull InstanceContainer createInstanceContainer(@Nullable IChunkLoader loader) { public @NotNull InstanceContainer createInstanceContainer(@Nullable IChunkLoader loader) {
DimensionType defaultDimension = Objects.requireNonNull(MinecraftServer.getDimensionTypeRegistry().get(DimensionType.OVERWORLD)); return createInstanceContainer(DimensionType.OVERWORLD, loader);
return createInstanceContainer(defaultDimension, loader);
} }
/** /**
@ -64,8 +67,7 @@ public final class InstanceManager {
* @return the created {@link InstanceContainer} * @return the created {@link InstanceContainer}
*/ */
public @NotNull InstanceContainer createInstanceContainer() { public @NotNull InstanceContainer createInstanceContainer() {
DimensionType defaultDimension = Objects.requireNonNull(MinecraftServer.getDimensionTypeRegistry().get(DimensionType.OVERWORLD)); return createInstanceContainer(DimensionType.OVERWORLD, null);
return createInstanceContainer(defaultDimension, null);
} }
/** /**

View File

@ -210,7 +210,7 @@ public class LightingChunk extends DynamicChunk {
if (this.occlusionMap != null) return this.occlusionMap; if (this.occlusionMap != null) return this.occlusionMap;
var occlusionMap = new int[CHUNK_SIZE_X * CHUNK_SIZE_Z]; var occlusionMap = new int[CHUNK_SIZE_X * CHUNK_SIZE_Z];
int minY = instance.getDimensionType().minY(); int minY = instance.getCachedDimensionType().minY();
highestBlock = minY - 1; highestBlock = minY - 1;
synchronized (this) { synchronized (this) {
@ -249,9 +249,8 @@ public class LightingChunk extends DynamicChunk {
List<byte[]> skyLights = new ArrayList<>(); List<byte[]> skyLights = new ArrayList<>();
List<byte[]> blockLights = new ArrayList<>(); List<byte[]> blockLights = new ArrayList<>();
int chunkMin = instance.getDimensionType().minY(); int chunkMin = instance.getCachedDimensionType().minY();
int highestNeighborBlock = instance.getCachedDimensionType().minY();
int highestNeighborBlock = instance.getDimensionType().minY();
for (int i = -1; i <= 1; i++) { for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) { for (int j = -1; j <= 1; j++) {
Chunk neighborChunk = instance.getChunk(chunkX + i, chunkZ + j); Chunk neighborChunk = instance.getChunk(chunkX + i, chunkZ + j);
@ -286,7 +285,7 @@ public class LightingChunk extends DynamicChunk {
final int sectionMinY = index * 16 + chunkMin; final int sectionMinY = index * 16 + chunkMin;
index++; index++;
if ((wasUpdatedSky) && this.instance.getDimensionType().hasSkylight() && sectionMinY <= (highestNeighborBlock + 16)) { if ((wasUpdatedSky) && this.instance.getCachedDimensionType().hasSkylight() && sectionMinY <= (highestNeighborBlock + 16)) {
final byte[] skyLight = section.skyLight().array(); final byte[] skyLight = section.skyLight().array();
if (skyLight.length != 0 && skyLight != emptyContent) { if (skyLight.length != 0 && skyLight != emptyContent) {
@ -433,7 +432,7 @@ public class LightingChunk extends DynamicChunk {
Set<Point> collected = new HashSet<>(); Set<Point> collected = new HashSet<>();
collected.add(point); collected.add(point);
int highestRegionPoint = instance.getDimensionType().minY() - 1; int highestRegionPoint = instance.getCachedDimensionType().minY() - 1;
for (int x = point.blockX() - 1; x <= point.blockX() + 1; x++) { for (int x = point.blockX() - 1; x <= point.blockX() + 1; x++) {
for (int z = point.blockZ() - 1; z <= point.blockZ() + 1; z++) { for (int z = point.blockZ() - 1; z <= point.blockZ() + 1; z++) {
@ -455,7 +454,7 @@ public class LightingChunk extends DynamicChunk {
for (int y = point.blockY() - 1; y <= point.blockY() + 1; y++) { for (int y = point.blockY() - 1; y <= point.blockY() + 1; y++) {
Point sectionPosition = new Vec(x, y, z); Point sectionPosition = new Vec(x, y, z);
int sectionHeight = instance.getDimensionType().minY() + 16 * y; int sectionHeight = instance.getCachedDimensionType().minY() + 16 * y;
if ((sectionHeight + 16) > highestRegionPoint && type == LightType.SKY) continue; if ((sectionHeight + 16) > highestRegionPoint && type == LightType.SKY) continue;
if (sectionPosition.blockY() < chunkCheck.getMaxSection() && sectionPosition.blockY() >= chunkCheck.getMinSection()) { if (sectionPosition.blockY() < chunkCheck.getMaxSection() && sectionPosition.blockY() >= chunkCheck.getMinSection()) {

View File

@ -415,8 +415,8 @@ public class AnvilLoader implements IChunkLoader {
// Add biome (biome are stored for 4x4x4 volumes, avoid unnecessary work) // Add biome (biome are stored for 4x4x4 volumes, avoid unnecessary work)
if (x % 4 == 0 && sectionLocalY % 4 == 0 && z % 4 == 0) { if (x % 4 == 0 && sectionLocalY % 4 == 0 && z % 4 == 0) {
int biomeIndex = (x / 4) + (sectionLocalY / 4) * 4 * 4 + (z / 4) * 4; int biomeIndex = (x / 4) + (sectionLocalY / 4) * 4 * 4 + (z / 4) * 4;
final Biome biome = chunk.getBiome(x, y, z); final DynamicRegistry.Key<Biome> biomeKey = chunk.getBiome(x, y, z);
final BinaryTag biomeName = StringBinaryTag.stringBinaryTag(biome.name()); final BinaryTag biomeName = StringBinaryTag.stringBinaryTag(biomeKey.name());
int biomePaletteIndex = biomePalette.indexOf(biomeName); int biomePaletteIndex = biomePalette.indexOf(biomeName);
if (biomePaletteIndex == -1) { if (biomePaletteIndex == -1) {

View File

@ -5,14 +5,12 @@ import net.minestom.server.registry.DynamicRegistryImpl;
import net.minestom.server.registry.ProtocolObject; import net.minestom.server.registry.ProtocolObject;
import net.minestom.server.registry.Registry; import net.minestom.server.registry.Registry;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.NamespaceID;
import net.minestom.server.utils.nbt.BinaryTagSerializer;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public sealed interface BannerPattern extends ProtocolObject, BannerPatterns permits BannerPatternImpl { public sealed interface BannerPattern extends ProtocolObject, BannerPatterns permits BannerPatternImpl {
@NotNull BinaryTagSerializer<BannerPattern> NBT_TYPE = BannerPatternImpl.NBT_TYPE;
static @NotNull BannerPattern create( static @NotNull BannerPattern create(
@NotNull NamespaceID namespace, @NotNull NamespaceID namespace,
@ -38,7 +36,7 @@ public sealed interface BannerPattern extends ProtocolObject, BannerPatterns per
@ApiStatus.Internal @ApiStatus.Internal
static @NotNull DynamicRegistry<BannerPattern> createDefaultRegistry() { static @NotNull DynamicRegistry<BannerPattern> createDefaultRegistry() {
return new DynamicRegistryImpl<>( return new DynamicRegistryImpl<>(
"minecraft:banner_pattern", NBT_TYPE, Registry.Resource.BANNER_PATTERNS, "minecraft:banner_pattern", BannerPatternImpl.REGISTRY_NBT_TYPE, Registry.Resource.BANNER_PATTERNS,
(namespace, props) -> new BannerPatternImpl(Registry.bannerPattern(namespace, props)) (namespace, props) -> new BannerPatternImpl(Registry.bannerPattern(namespace, props))
); );
} }

View File

@ -15,7 +15,7 @@ record BannerPatternImpl(
@Nullable Registry.BannerPatternEntry registry @Nullable Registry.BannerPatternEntry registry
) implements BannerPattern { ) implements BannerPattern {
static final BinaryTagSerializer<BannerPattern> NBT_TYPE = BinaryTagSerializer.COMPOUND.map( static final BinaryTagSerializer<BannerPattern> REGISTRY_NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
tag -> { tag -> {
throw new UnsupportedOperationException("BannerPattern is read-only"); throw new UnsupportedOperationException("BannerPattern is read-only");
}, },

View File

@ -2,6 +2,7 @@ package net.minestom.server.instance.generator;
import net.minestom.server.coordinate.Point; import net.minestom.server.coordinate.Point;
import net.minestom.server.instance.block.Block; import net.minestom.server.instance.block.Block;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.world.biome.Biome; import net.minestom.server.world.biome.Biome;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -60,7 +61,7 @@ public interface UnitModifier extends Block.Setter, Biome.Setter {
* *
* @param biome the biome to fill * @param biome the biome to fill
*/ */
void fillBiome(@NotNull Biome biome); void fillBiome(@NotNull DynamicRegistry.Key<Biome> biome);
interface Supplier { interface Supplier {
@NotNull Block get(int x, int y, int z); @NotNull Block get(int x, int y, int z);

View File

@ -16,7 +16,7 @@ public abstract class Heightmap {
public Heightmap(Chunk chunk) { public Heightmap(Chunk chunk) {
this.chunk = chunk; this.chunk = chunk;
minHeight = chunk.getInstance().getDimensionType().minY() - 1; minHeight = chunk.getInstance().getCachedDimensionType().minY() - 1;
} }
protected abstract boolean checkBlock(@NotNull Block block); protected abstract boolean checkBlock(@NotNull Block block);
@ -57,13 +57,13 @@ public abstract class Heightmap {
} }
public long[] getNBT() { public long[] getNBT() {
final int dimensionHeight = chunk.getInstance().getDimensionType().height(); final int dimensionHeight = chunk.getInstance().getCachedDimensionType().height();
final int bitsForHeight = MathUtils.bitsToRepresent(dimensionHeight); final int bitsForHeight = MathUtils.bitsToRepresent(dimensionHeight);
return encode(heights, bitsForHeight); return encode(heights, bitsForHeight);
} }
public void loadFrom(long[] data) { public void loadFrom(long[] data) {
final int dimensionHeight = chunk.getInstance().getDimensionType().height(); final int dimensionHeight = chunk.getInstance().getCachedDimensionType().height();
final int bitsPerEntry = MathUtils.bitsToRepresent(dimensionHeight); final int bitsPerEntry = MathUtils.bitsToRepresent(dimensionHeight);
final int entriesPerLong = 64 / bitsPerEntry; final int entriesPerLong = 64 / bitsPerEntry;
@ -94,7 +94,7 @@ public abstract class Heightmap {
} }
public static int getHighestBlockSection(Chunk chunk) { public static int getHighestBlockSection(Chunk chunk) {
int y = chunk.getInstance().getDimensionType().maxY(); int y = chunk.getInstance().getCachedDimensionType().maxY();
final int sectionsCount = chunk.getMaxSection() - chunk.getMinSection(); final int sectionsCount = chunk.getMaxSection() - chunk.getMinSection();
for (int i = 0; i < sectionsCount; i++) { for (int i = 0; i < sectionsCount; i++) {

View File

@ -52,7 +52,7 @@ final class SkyLight implements Light {
if (c instanceof LightingChunk lc) { if (c instanceof LightingChunk lc) {
int[] heightmap = lc.getOcclusionMap(); int[] heightmap = lc.getOcclusionMap();
int maxY = c.getInstance().getDimensionType().minY() + c.getInstance().getDimensionType().height(); int maxY = c.getInstance().getCachedDimensionType().minY() + c.getInstance().getCachedDimensionType().height();
int sectionMaxY = (sectionY + 1) * 16 - 1; int sectionMaxY = (sectionY + 1) * 16 - 1;
int sectionMinY = sectionY * 16; int sectionMinY = sectionY * 16;

View File

@ -2,10 +2,8 @@ package net.minestom.server.item.armor;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.minestom.server.item.Material; import net.minestom.server.item.Material;
import net.minestom.server.registry.DynamicRegistry; import net.minestom.server.network.NetworkBuffer;
import net.minestom.server.registry.DynamicRegistryImpl; import net.minestom.server.registry.*;
import net.minestom.server.registry.ProtocolObject;
import net.minestom.server.registry.Registry;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.NamespaceID;
import net.minestom.server.utils.nbt.BinaryTagSerializer; import net.minestom.server.utils.nbt.BinaryTagSerializer;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
@ -17,7 +15,8 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
public sealed interface TrimMaterial extends ProtocolObject permits TrimMaterialImpl { public sealed interface TrimMaterial extends ProtocolObject permits TrimMaterialImpl {
@NotNull BinaryTagSerializer<TrimMaterial> NBT_TYPE = TrimMaterialImpl.NBT_TYPE; @NotNull NetworkBuffer.Type<DynamicRegistry.Key<TrimMaterial>> NETWORK_TYPE = NetworkBuffer.registryKey(Registries::trimMaterial);
@NotNull BinaryTagSerializer<DynamicRegistry.Key<TrimMaterial>> NBT_TYPE = BinaryTagSerializer.registryKey(Registries::trimMaterial);
static @NotNull TrimMaterial create( static @NotNull TrimMaterial create(
@NotNull NamespaceID namespace, @NotNull NamespaceID namespace,
@ -49,7 +48,7 @@ public sealed interface TrimMaterial extends ProtocolObject permits TrimMaterial
@ApiStatus.Internal @ApiStatus.Internal
static @NotNull DynamicRegistry<TrimMaterial> createDefaultRegistry() { static @NotNull DynamicRegistry<TrimMaterial> createDefaultRegistry() {
return new DynamicRegistryImpl<>( return new DynamicRegistryImpl<>(
"minecraft:trim_material", NBT_TYPE, Registry.Resource.TRIM_MATERIALS, "minecraft:trim_material", TrimMaterialImpl.REGISTRY_NBT_TYPE, Registry.Resource.TRIM_MATERIALS,
(namespace, props) -> new TrimMaterialImpl(Registry.trimMaterial(namespace, props)) (namespace, props) -> new TrimMaterialImpl(Registry.trimMaterial(namespace, props))
); );
} }

View File

@ -22,7 +22,7 @@ record TrimMaterialImpl(
@Nullable Registry.TrimMaterialEntry registry @Nullable Registry.TrimMaterialEntry registry
) implements TrimMaterial { ) implements TrimMaterial {
static final BinaryTagSerializer<TrimMaterial> NBT_TYPE = BinaryTagSerializer.COMPOUND.map( static final BinaryTagSerializer<TrimMaterial> REGISTRY_NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
tag -> { tag -> {
throw new UnsupportedOperationException("TrimMaterial is read-only"); throw new UnsupportedOperationException("TrimMaterial is read-only");
}, },

View File

@ -2,10 +2,8 @@ package net.minestom.server.item.armor;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.minestom.server.item.Material; import net.minestom.server.item.Material;
import net.minestom.server.registry.DynamicRegistry; import net.minestom.server.network.NetworkBuffer;
import net.minestom.server.registry.DynamicRegistryImpl; import net.minestom.server.registry.*;
import net.minestom.server.registry.ProtocolObject;
import net.minestom.server.registry.Registry;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.NamespaceID;
import net.minestom.server.utils.nbt.BinaryTagSerializer; import net.minestom.server.utils.nbt.BinaryTagSerializer;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
@ -14,7 +12,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public sealed interface TrimPattern extends ProtocolObject permits TrimPatternImpl { public sealed interface TrimPattern extends ProtocolObject permits TrimPatternImpl {
@NotNull BinaryTagSerializer<TrimPattern> NBT_TYPE = TrimPatternImpl.NBT_TYPE; @NotNull NetworkBuffer.Type<DynamicRegistry.Key<TrimPattern>> NETWORK_TYPE = NetworkBuffer.registryKey(Registries::trimPattern);
@NotNull BinaryTagSerializer<DynamicRegistry.Key<TrimPattern>> NBT_TYPE = BinaryTagSerializer.registryKey(Registries::trimPattern);
static @NotNull TrimPattern create( static @NotNull TrimPattern create(
@NotNull NamespaceID namespace, @NotNull NamespaceID namespace,
@ -42,7 +41,7 @@ public sealed interface TrimPattern extends ProtocolObject permits TrimPatternIm
@ApiStatus.Internal @ApiStatus.Internal
static @NotNull DynamicRegistry<TrimPattern> createDefaultRegistry() { static @NotNull DynamicRegistry<TrimPattern> createDefaultRegistry() {
return new DynamicRegistryImpl<>( return new DynamicRegistryImpl<>(
"minecraft:trim_pattern", NBT_TYPE, Registry.Resource.TRIM_PATTERNS, "minecraft:trim_pattern", TrimPatternImpl.REGISTRY_NBT_TYPE, Registry.Resource.TRIM_PATTERNS,
(namespace, props) -> new TrimPatternImpl(Registry.trimPattern(namespace, props)) (namespace, props) -> new TrimPatternImpl(Registry.trimPattern(namespace, props))
); );
} }

View File

@ -19,7 +19,7 @@ record TrimPatternImpl(
@Nullable Registry.TrimPatternEntry registry @Nullable Registry.TrimPatternEntry registry
) implements TrimPattern { ) implements TrimPattern {
static final BinaryTagSerializer<TrimPattern> NBT_TYPE = BinaryTagSerializer.COMPOUND.map( static final BinaryTagSerializer<TrimPattern> REGISTRY_NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
tag -> { tag -> {
throw new UnsupportedOperationException("TrimMaterial is read-only"); throw new UnsupportedOperationException("TrimMaterial is read-only");
}, },

View File

@ -4,38 +4,37 @@ import net.kyori.adventure.nbt.CompoundBinaryTag;
import net.minestom.server.item.armor.TrimMaterial; import net.minestom.server.item.armor.TrimMaterial;
import net.minestom.server.item.armor.TrimPattern; import net.minestom.server.item.armor.TrimPattern;
import net.minestom.server.network.NetworkBuffer; import net.minestom.server.network.NetworkBuffer;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.utils.nbt.BinaryTagSerializer; import net.minestom.server.utils.nbt.BinaryTagSerializer;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public record ArmorTrim(@NotNull TrimMaterial material, @NotNull TrimPattern pattern, boolean showInTooltip) { public record ArmorTrim(@NotNull DynamicRegistry.Key<TrimMaterial> material, @NotNull DynamicRegistry.Key<TrimPattern> pattern, boolean showInTooltip) {
public static final NetworkBuffer.Type<ArmorTrim> NETWORK_TYPE = new NetworkBuffer.Type<>() { public static final NetworkBuffer.Type<ArmorTrim> NETWORK_TYPE = new NetworkBuffer.Type<>() {
@Override @Override
public void write(@NotNull NetworkBuffer buffer, ArmorTrim value) { public void write(@NotNull NetworkBuffer buffer, ArmorTrim value) {
// buffer.write(NetworkBuffer.VAR_INT, value.material.id()); buffer.write(TrimMaterial.NETWORK_TYPE, value.material);
// buffer.write(NetworkBuffer.VAR_INT, value.pattern.id()); buffer.write(TrimPattern.NETWORK_TYPE, value.pattern);
buffer.write(NetworkBuffer.BOOLEAN, value.showInTooltip); buffer.write(NetworkBuffer.BOOLEAN, value.showInTooltip);
} }
@Override @Override
public ArmorTrim read(@NotNull NetworkBuffer buffer) { public ArmorTrim read(@NotNull NetworkBuffer buffer) {
// TrimMaterial material = Objects.requireNonNull(TrimMaterial.fromId(buffer.read(NetworkBuffer.VAR_INT)), "unknown trim material"); return new ArmorTrim(buffer.read(TrimMaterial.NETWORK_TYPE),
// TrimPattern pattern = Objects.requireNonNull(TrimPattern.fromId(buffer.read(NetworkBuffer.VAR_INT)), "unknown trim pattern"); buffer.read(TrimPattern.NETWORK_TYPE),
// return new ArmorTrim(material, pattern, buffer.read(NetworkBuffer.BOOLEAN)); buffer.read(NetworkBuffer.BOOLEAN));
throw new UnsupportedOperationException("Not implemented");
} }
}; };
public static final BinaryTagSerializer<ArmorTrim> NBT_TYPE = BinaryTagSerializer.COMPOUND.map( public static final BinaryTagSerializer<ArmorTrim> NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
tag -> { tag -> {
// TrimMaterial material = Objects.requireNonNull(TrimMaterial.fromNamespaceId(tag.getString("material")), "unknown trim material"); DynamicRegistry.Key<TrimMaterial> material = TrimMaterial.NBT_TYPE.read(tag.get("material"));
// TrimPattern pattern = Objects.requireNonNull(TrimPattern.fromNamespaceId(tag.getString("pattern")), "unknown trim pattern"); DynamicRegistry.Key<TrimPattern> pattern = TrimPattern.NBT_TYPE.read(tag.get("pattern"));
// boolean showInTooltip = tag.getBoolean("show_in_tooltip", true); boolean showInTooltip = tag.getBoolean("show_in_tooltip", true);
// return new ArmorTrim(material, pattern, showInTooltip); return new ArmorTrim(material, pattern, showInTooltip);
throw new UnsupportedOperationException("Not implemented");
}, },
value -> CompoundBinaryTag.builder() value -> CompoundBinaryTag.builder()
.putString("material", value.material.name()) .put("material", TrimMaterial.NBT_TYPE.write(value.material))
.putString("pattern", value.pattern.name()) .putString("pattern", value.pattern.name())
.putBoolean("show_in_tooltip", value.showInTooltip) .putBoolean("show_in_tooltip", value.showInTooltip)
.build() .build()

View File

@ -30,6 +30,7 @@ import net.minestom.server.network.packet.server.play.AcknowledgeBlockChangePack
import net.minestom.server.network.packet.server.play.BlockChangePacket; import net.minestom.server.network.packet.server.play.BlockChangePacket;
import net.minestom.server.utils.chunk.ChunkUtils; import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.utils.validate.Check; import net.minestom.server.utils.validate.Check;
import net.minestom.server.world.DimensionType;
public class BlockPlacementListener { public class BlockPlacementListener {
private static final BlockManager BLOCK_MANAGER = MinecraftServer.getBlockManager(); private static final BlockManager BLOCK_MANAGER = MinecraftServer.getBlockManager();
@ -117,8 +118,10 @@ public class BlockPlacementListener {
} }
} }
if (placementPosition.y() >= instance.getDimensionType().maxY() final DimensionType instanceDim = instance.getCachedDimensionType();
|| placementPosition.y() < instance.getDimensionType().minY()) return; if (placementPosition.y() >= instanceDim.maxY() || placementPosition.y() < instanceDim.minY()) {
return;
}
// Ensure that the final placement position is inside the world border. // Ensure that the final placement position is inside the world border.
if (!instance.getWorldBorder().isInside(placementPosition)) { if (!instance.getWorldBorder().isInside(placementPosition)) {

View File

@ -5,13 +5,11 @@ import net.minestom.server.registry.DynamicRegistryImpl;
import net.minestom.server.registry.ProtocolObject; import net.minestom.server.registry.ProtocolObject;
import net.minestom.server.registry.Registry; import net.minestom.server.registry.Registry;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.NamespaceID;
import net.minestom.server.utils.nbt.BinaryTagSerializer;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public sealed interface ChatType extends ProtocolObject, ChatTypes permits ChatTypeImpl { public sealed interface ChatType extends ProtocolObject, ChatTypes permits ChatTypeImpl {
@NotNull BinaryTagSerializer<ChatType> NBT_TYPE = ChatTypeImpl.NBT_TYPE;
static @NotNull ChatType create( static @NotNull ChatType create(
@NotNull NamespaceID namespace, @NotNull NamespaceID namespace,
@ -37,7 +35,7 @@ public sealed interface ChatType extends ProtocolObject, ChatTypes permits ChatT
@ApiStatus.Internal @ApiStatus.Internal
static @NotNull DynamicRegistry<ChatType> createDefaultRegistry() { static @NotNull DynamicRegistry<ChatType> createDefaultRegistry() {
return new DynamicRegistryImpl<>( return new DynamicRegistryImpl<>(
"minecraft:chat_type", NBT_TYPE, Registry.Resource.CHAT_TYPES, "minecraft:chat_type", ChatTypeImpl.REGISTRY_NBT_TYPE, Registry.Resource.CHAT_TYPES,
(namespace, props) -> new ChatTypeImpl(Registry.chatType(namespace, props)) (namespace, props) -> new ChatTypeImpl(Registry.chatType(namespace, props))
); );
} }

View File

@ -15,7 +15,7 @@ record ChatTypeImpl(
@Nullable Registry.ChatTypeEntry registry @Nullable Registry.ChatTypeEntry registry
) implements ChatType { ) implements ChatType {
static final BinaryTagSerializer<ChatType> NBT_TYPE = BinaryTagSerializer.COMPOUND.map( static final BinaryTagSerializer<ChatType> REGISTRY_NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
tag -> { tag -> {
throw new UnsupportedOperationException("ChatType is read-only"); throw new UnsupportedOperationException("ChatType is read-only");
}, },

View File

@ -2,6 +2,7 @@ package net.minestom.server.network;
import net.kyori.adventure.nbt.BinaryTag; import net.kyori.adventure.nbt.BinaryTag;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.minestom.server.MinecraftServer;
import net.minestom.server.coordinate.Point; import net.minestom.server.coordinate.Point;
import net.minestom.server.entity.Entity; import net.minestom.server.entity.Entity;
import net.minestom.server.entity.metadata.animal.ArmadilloMeta; import net.minestom.server.entity.metadata.animal.ArmadilloMeta;
@ -11,6 +12,9 @@ import net.minestom.server.entity.metadata.animal.tameable.CatMeta;
import net.minestom.server.entity.metadata.other.PaintingMeta; import net.minestom.server.entity.metadata.other.PaintingMeta;
import net.minestom.server.network.packet.server.play.data.WorldPos; import net.minestom.server.network.packet.server.play.data.WorldPos;
import net.minestom.server.particle.Particle; import net.minestom.server.particle.Particle;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.registry.ProtocolObject;
import net.minestom.server.registry.Registries;
import net.minestom.server.utils.Direction; import net.minestom.server.utils.Direction;
import net.minestom.server.utils.Unit; import net.minestom.server.utils.Unit;
import net.minestom.server.utils.nbt.BinaryTagReader; import net.minestom.server.utils.nbt.BinaryTagReader;
@ -76,6 +80,29 @@ public final class NetworkBuffer {
public static final Type<SnifferMeta.State> SNIFFER_STATE = NetworkBufferTypeImpl.fromEnum(SnifferMeta.State.class); public static final Type<SnifferMeta.State> SNIFFER_STATE = NetworkBufferTypeImpl.fromEnum(SnifferMeta.State.class);
public static final Type<ArmadilloMeta.State> ARMADILLO_STATE = NetworkBufferTypeImpl.fromEnum(ArmadilloMeta.State.class); public static final Type<ArmadilloMeta.State> ARMADILLO_STATE = NetworkBufferTypeImpl.fromEnum(ArmadilloMeta.State.class);
public static <T extends ProtocolObject> Type<DynamicRegistry.Key<T>> registryKey(@NotNull Function<Registries, DynamicRegistry<T>> selector) {
return new NetworkBuffer.Type<>() {
@Override
public void write(@NotNull NetworkBuffer buffer, DynamicRegistry.Key<T> value) {
Check.stateCondition(buffer.registries == null, "Buffer does not have registries");
final DynamicRegistry<T> registry = selector.apply(buffer.registries);
final int id = registry.getId(value);
Check.argCondition(id == -1, "Key is not registered: {0} > {1}", registry, value);
buffer.write(VAR_INT, id);
}
@Override
public DynamicRegistry.Key<T> read(@NotNull NetworkBuffer buffer) {
Check.stateCondition(buffer.registries == null, "Buffer does not have registries");
DynamicRegistry<T> registry = selector.apply(buffer.registries);
final int id = buffer.read(VAR_INT);
final DynamicRegistry.Key<T> key = registry.getKey(id);
Check.argCondition(key == null, "No such ID in registry: {0} > {1}", registry, id);
return key;
}
};
}
public static <E extends Enum<E>> Type<E> fromEnum(@NotNull Class<E> enumClass) { public static <E extends Enum<E>> Type<E> fromEnum(@NotNull Class<E> enumClass) {
return NetworkBufferTypeImpl.fromEnum(enumClass); return NetworkBufferTypeImpl.fromEnum(enumClass);
} }
@ -106,6 +133,9 @@ public final class NetworkBuffer {
BinaryTagWriter nbtWriter; BinaryTagWriter nbtWriter;
BinaryTagReader nbtReader; BinaryTagReader nbtReader;
// In the future, this should be passed as a parameter.
final Registries registries = MinecraftServer.process();
public NetworkBuffer(@NotNull ByteBuffer buffer, boolean resizable) { public NetworkBuffer(@NotNull ByteBuffer buffer, boolean resizable) {
this.nioBuffer = buffer.order(ByteOrder.BIG_ENDIAN); this.nioBuffer = buffer.order(ByteOrder.BIG_ENDIAN);
this.resizable = resizable; this.resizable = resizable;

View File

@ -1,20 +1,61 @@
package net.minestom.server.registry; package net.minestom.server.registry;
import net.kyori.adventure.key.Keyed;
import net.minestom.server.entity.Player; import net.minestom.server.entity.Player;
import net.minestom.server.network.packet.server.SendablePacket; import net.minestom.server.network.packet.server.SendablePacket;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.NamespaceID;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.List; import java.util.List;
public interface DynamicRegistry<T extends ProtocolObject> { public sealed interface DynamicRegistry<T extends ProtocolObject> permits DynamicRegistryImpl {
/**
* A key for a {@link ProtocolObject} in a {@link DynamicRegistry}.
*
* @param <T> Unused, except to provide compile-time safety and self documentation.
*/
sealed interface Key<T extends ProtocolObject> extends Keyed permits DynamicRegistryImpl.KeyImpl {
static <T extends ProtocolObject> @NotNull Key<T> of(@NotNull String namespace) {
return new DynamicRegistryImpl.KeyImpl<>(NamespaceID.from(namespace));
}
static <T extends ProtocolObject> @NotNull Key<T> of(@NotNull NamespaceID namespace) {
return new DynamicRegistryImpl.KeyImpl<>(namespace);
}
@Contract(pure = true)
@NotNull NamespaceID namespace();
@Contract(pure = true)
default @NotNull String name() {
return namespace().asString();
}
@Override
@Contract(pure = true)
default @NotNull net.kyori.adventure.key.Key key() {
return namespace();
}
}
@Nullable T get(int id); @Nullable T get(int id);
@Nullable T get(@NotNull NamespaceID namespace); @Nullable T get(@NotNull NamespaceID namespace);
default @Nullable T get(@NotNull Key<T> key) {
return get(key.namespace());
}
@Nullable Key<T> getKey(int id);
@Nullable NamespaceID getName(int id);
int getId(@NotNull NamespaceID id); int getId(@NotNull NamespaceID id);
default int getId(@NotNull Key<T> key) {
return getId(key.namespace());
}
/** /**
* <p>Returns the entries in this registry as an immutable list. The indices in the returned list correspond * <p>Returns the entries in this registry as an immutable list. The indices in the returned list correspond
@ -36,7 +77,7 @@ public interface DynamicRegistry<T extends ProtocolObject> {
* @param object The entry to register * @param object The entry to register
* @return The new ID of the registered object * @return The new ID of the registered object
*/ */
int register(@NotNull T object); @NotNull DynamicRegistry.Key<T> register(@NotNull T object);
/** /**
* <p>Removes an object from this registry.</p> * <p>Removes an object from this registry.</p>

View File

@ -11,20 +11,27 @@ import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.*; import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
@ApiStatus.Internal @ApiStatus.Internal
public class DynamicRegistryImpl<T extends ProtocolObject> implements DynamicRegistry<T> { public final class DynamicRegistryImpl<T extends ProtocolObject> implements DynamicRegistry<T> {
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'"); 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<T extends ProtocolObject>(NamespaceID namespace) implements Key<T> {
}
private final CachedPacket vanillaRegistryDataPacket = new CachedPacket(() -> createRegistryDataPacket(true)); private final CachedPacket vanillaRegistryDataPacket = new CachedPacket(() -> createRegistryDataPacket(true));
private final ReentrantLock lock = new ReentrantLock(); // Protects entryById (except when used alone, it is safe), entryByName, and idByName private final ReentrantLock lock = new ReentrantLock(); // Protects writes
private final List<T> entryById = new CopyOnWriteArrayList<>(); // We use a CopyOnWriteArrayList even with the lock above because it handles concurrent iteration private final List<T> entryById = new CopyOnWriteArrayList<>(); // We use a CopyOnWriteArrayList even with the lock above because it handles concurrent iteration
private final Map<NamespaceID, T> entryByName = new HashMap<>(); private final Map<NamespaceID, T> entryByName = new ConcurrentHashMap<>();
private final List<NamespaceID> idByName = new ArrayList<>(); private final List<NamespaceID> idByName = new CopyOnWriteArrayList<>();
private final String id; private final String id;
private final BinaryTagSerializer<T> nbtType; private final BinaryTagSerializer<T> nbtType;
@ -49,22 +56,26 @@ public class DynamicRegistryImpl<T extends ProtocolObject> implements DynamicReg
@Override @Override
public @Nullable T get(@NotNull NamespaceID namespace) { public @Nullable T get(@NotNull NamespaceID namespace) {
lock.lock();
try {
return entryByName.get(namespace); return entryByName.get(namespace);
} finally {
lock.unlock();
} }
@Override
public @Nullable Key<T> getKey(int id) {
if (id < 0 || id >= entryById.size())
return null;
return Key.of(idByName.get(id));
}
@Override
public @Nullable NamespaceID getName(int id) {
if (id < 0 || id >= entryById.size())
return null;
return idByName.get(id);
} }
@Override @Override
public int getId(@NotNull NamespaceID id) { public int getId(@NotNull NamespaceID id) {
lock.lock();
try {
return idByName.indexOf(id); return idByName.indexOf(id);
} finally {
lock.unlock();
}
} }
@Override @Override
@ -73,7 +84,7 @@ public class DynamicRegistryImpl<T extends ProtocolObject> implements DynamicReg
} }
@Override @Override
public int register(@NotNull T object) { public @NotNull DynamicRegistry.Key<T> register(@NotNull T object) {
lock.lock(); lock.lock();
try { try {
int id = idByName.indexOf(object.namespace()); int id = idByName.indexOf(object.namespace());
@ -83,7 +94,7 @@ public class DynamicRegistryImpl<T extends ProtocolObject> implements DynamicReg
entryByName.put(object.namespace(), object); entryByName.put(object.namespace(), object);
idByName.add(object.namespace()); idByName.add(object.namespace());
vanillaRegistryDataPacket.invalidate(); vanillaRegistryDataPacket.invalidate();
return id; return Key.of(object.namespace());
} finally { } finally {
lock.unlock(); lock.unlock();
} }
@ -116,8 +127,6 @@ public class DynamicRegistryImpl<T extends ProtocolObject> implements DynamicReg
} }
private @NotNull RegistryDataPacket createRegistryDataPacket(boolean excludeVanilla) { private @NotNull RegistryDataPacket createRegistryDataPacket(boolean excludeVanilla) {
lock.lock();
try {
var entries = new ArrayList<RegistryDataPacket.Entry>(entryById.size()); var entries = new ArrayList<RegistryDataPacket.Entry>(entryById.size());
for (var entry : entryById) { for (var entry : entryById) {
CompoundBinaryTag data = null; CompoundBinaryTag data = null;
@ -135,9 +144,6 @@ public class DynamicRegistryImpl<T extends ProtocolObject> implements DynamicReg
entries.add(new RegistryDataPacket.Entry(entry.name(), data)); entries.add(new RegistryDataPacket.Entry(entry.name(), data));
} }
return new RegistryDataPacket(id, entries); return new RegistryDataPacket(id, entries);
} finally {
lock.unlock();
}
} }
private void loadStaticRegistry(@NotNull Registry.Resource resource, @NotNull Registry.Container.Loader<T> loader) { private void loadStaticRegistry(@NotNull Registry.Resource resource, @NotNull Registry.Container.Loader<T> loader) {

View File

@ -2,6 +2,7 @@ package net.minestom.server.snapshot;
import net.minestom.server.coordinate.Point; import net.minestom.server.coordinate.Point;
import net.minestom.server.instance.block.Block; import net.minestom.server.instance.block.Block;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.tag.TagReadable; import net.minestom.server.tag.TagReadable;
import net.minestom.server.world.DimensionType; import net.minestom.server.world.DimensionType;
import net.minestom.server.world.biome.Biome; import net.minestom.server.world.biome.Biome;
@ -16,7 +17,7 @@ import static net.minestom.server.utils.chunk.ChunkUtils.getChunkCoordinate;
public sealed interface InstanceSnapshot extends Snapshot, Block.Getter, Biome.Getter, TagReadable public sealed interface InstanceSnapshot extends Snapshot, Block.Getter, Biome.Getter, TagReadable
permits SnapshotImpl.Instance { permits SnapshotImpl.Instance {
@NotNull DimensionType dimensionType(); @NotNull DynamicRegistry.Key<DimensionType> dimensionType();
long worldAge(); long worldAge();
@ -29,7 +30,7 @@ public sealed interface InstanceSnapshot extends Snapshot, Block.Getter, Biome.G
} }
@Override @Override
default @NotNull Biome getBiome(int x, int y, int z) { default @NotNull DynamicRegistry.Key<Biome> getBiome(int x, int y, int z) {
ChunkSnapshot chunk = chunk(getChunkCoordinate(x), getChunkCoordinate(z)); ChunkSnapshot chunk = chunk(getChunkCoordinate(x), getChunkCoordinate(z));
return Objects.requireNonNull(chunk).getBiome(x, y, z); return Objects.requireNonNull(chunk).getBiome(x, y, z);
} }

View File

@ -8,10 +8,12 @@ import net.minestom.server.entity.EntityType;
import net.minestom.server.entity.GameMode; import net.minestom.server.entity.GameMode;
import net.minestom.server.instance.Section; import net.minestom.server.instance.Section;
import net.minestom.server.instance.block.Block; import net.minestom.server.instance.block.Block;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.tag.Tag; import net.minestom.server.tag.Tag;
import net.minestom.server.tag.TagReadable; import net.minestom.server.tag.TagReadable;
import net.minestom.server.utils.collection.IntMappedArray; import net.minestom.server.utils.collection.IntMappedArray;
import net.minestom.server.utils.collection.MappedCollection; import net.minestom.server.utils.collection.MappedCollection;
import net.minestom.server.utils.validate.Check;
import net.minestom.server.world.DimensionType; import net.minestom.server.world.DimensionType;
import net.minestom.server.world.biome.Biome; import net.minestom.server.world.biome.Biome;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
@ -44,7 +46,7 @@ public final class SnapshotImpl {
} }
public record Instance(AtomicReference<ServerSnapshot> serverRef, public record Instance(AtomicReference<ServerSnapshot> serverRef,
DimensionType dimensionType, long worldAge, long time, DynamicRegistry.Key<DimensionType> dimensionType, long worldAge, long time,
Map<Long, AtomicReference<ChunkSnapshot>> chunksMap, Map<Long, AtomicReference<ChunkSnapshot>> chunksMap,
int[] entitiesIds, int[] entitiesIds,
TagReadable tagReadable) implements InstanceSnapshot { TagReadable tagReadable) implements InstanceSnapshot {
@ -99,11 +101,13 @@ public final class SnapshotImpl {
} }
@Override @Override
public @NotNull Biome getBiome(int x, int y, int z) { public @NotNull DynamicRegistry.Key<Biome> getBiome(int x, int y, int z) {
final Section section = sections[getChunkCoordinate(y) - minSection]; final Section section = sections[getChunkCoordinate(y) - minSection];
final int id = section.biomePalette() final int id = section.biomePalette()
.get(toSectionRelativeCoordinate(x) / 4, toSectionRelativeCoordinate(y) / 4, toSectionRelativeCoordinate(z) / 4); .get(toSectionRelativeCoordinate(x) / 4, toSectionRelativeCoordinate(y) / 4, toSectionRelativeCoordinate(z) / 4);
return MinecraftServer.getBiomeRegistry().get(id); DynamicRegistry.Key<Biome> key = MinecraftServer.getBiomeRegistry().getKey(id);
Check.notNull(key, "Biome with id {0} is not registered", id);
return key;
} }
@Override @Override

View File

@ -4,10 +4,15 @@ import net.kyori.adventure.nbt.*;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.Style; import net.kyori.adventure.text.format.Style;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.minestom.server.MinecraftServer;
import net.minestom.server.adventure.serializer.nbt.NbtComponentSerializer; import net.minestom.server.adventure.serializer.nbt.NbtComponentSerializer;
import net.minestom.server.item.ItemStack; import net.minestom.server.item.ItemStack;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.registry.ProtocolObject;
import net.minestom.server.registry.Registries;
import net.minestom.server.utils.UniqueIdUtils; import net.minestom.server.utils.UniqueIdUtils;
import net.minestom.server.utils.Unit; import net.minestom.server.utils.Unit;
import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.io.IOException; import java.io.IOException;
@ -217,6 +222,19 @@ public interface BinaryTagSerializer<T> {
} }
}; };
static <T extends ProtocolObject> @NotNull BinaryTagSerializer<DynamicRegistry.Key<T>> registryKey(@NotNull Function<Registries, DynamicRegistry<T>> registrySelector) {
//todo need to pass Registries as context here somehow.
return STRING.map(
s -> {
final DynamicRegistry<T> registry = registrySelector.apply(MinecraftServer.process());
final DynamicRegistry.Key<T> key = DynamicRegistry.Key.of(s);
Check.argCondition(registry.get(key) == null, "Key is not registered: {0} > {1}", registry, s);
return key;
},
DynamicRegistry.Key::name
);
}
@NotNull BinaryTag write(@NotNull T value); @NotNull BinaryTag write(@NotNull T value);
@NotNull T read(@NotNull BinaryTag tag); @NotNull T read(@NotNull BinaryTag tag);

View File

@ -5,7 +5,6 @@ import net.minestom.server.registry.DynamicRegistryImpl;
import net.minestom.server.registry.ProtocolObject; import net.minestom.server.registry.ProtocolObject;
import net.minestom.server.registry.Registry; import net.minestom.server.registry.Registry;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.NamespaceID;
import net.minestom.server.utils.nbt.BinaryTagSerializer;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -15,7 +14,6 @@ import org.jetbrains.annotations.Nullable;
* https://minecraft.wiki/w/Custom_dimension * https://minecraft.wiki/w/Custom_dimension
*/ */
public sealed interface DimensionType extends ProtocolObject, DimensionTypes permits DimensionTypeImpl { public sealed interface DimensionType extends ProtocolObject, DimensionTypes permits DimensionTypeImpl {
@NotNull BinaryTagSerializer<DimensionType> NBT_TYPE = DimensionTypeImpl.NBT_TYPE;
int VANILLA_MIN_Y = -64; int VANILLA_MIN_Y = -64;
int VANILLA_MAX_Y = 319; int VANILLA_MAX_Y = 319;
@ -36,7 +34,7 @@ public sealed interface DimensionType extends ProtocolObject, DimensionTypes per
@ApiStatus.Internal @ApiStatus.Internal
static @NotNull DynamicRegistry<DimensionType> createDefaultRegistry() { static @NotNull DynamicRegistry<DimensionType> createDefaultRegistry() {
return new DynamicRegistryImpl<>( return new DynamicRegistryImpl<>(
"minecraft:dimension_type", NBT_TYPE, Registry.Resource.DIMENSION_TYPES, "minecraft:dimension_type", DimensionTypeImpl.REGISTRY_NBT_TYPE, Registry.Resource.DIMENSION_TYPES,
(namespace, props) -> new DimensionTypeImpl(Registry.dimensionType(namespace, props)) (namespace, props) -> new DimensionTypeImpl(Registry.dimensionType(namespace, props))
); );
} }

View File

@ -28,7 +28,7 @@ record DimensionTypeImpl(
@Nullable Registry.DimensionTypeEntry registry @Nullable Registry.DimensionTypeEntry registry
) implements DimensionType { ) implements DimensionType {
static final BinaryTagSerializer<DimensionType> NBT_TYPE = BinaryTagSerializer.COMPOUND.map( static final BinaryTagSerializer<DimensionType> REGISTRY_NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
tag -> { tag -> {
throw new UnsupportedOperationException("DimensionType is read-only"); throw new UnsupportedOperationException("DimensionType is read-only");
}, },

View File

@ -6,14 +6,12 @@ import net.minestom.server.registry.DynamicRegistryImpl;
import net.minestom.server.registry.ProtocolObject; import net.minestom.server.registry.ProtocolObject;
import net.minestom.server.registry.Registry; import net.minestom.server.registry.Registry;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.NamespaceID;
import net.minestom.server.utils.nbt.BinaryTagSerializer;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public sealed interface Biome extends Biomes, ProtocolObject permits BiomeImpl { public sealed interface Biome extends Biomes, ProtocolObject permits BiomeImpl {
@NotNull BinaryTagSerializer<Biome> NBT_TYPE = BiomeImpl.NBT_TYPE;
static @NotNull Builder builder(@NotNull String namespace) { static @NotNull Builder builder(@NotNull String namespace) {
return builder(NamespaceID.from(namespace)); return builder(NamespaceID.from(namespace));
@ -31,7 +29,7 @@ public sealed interface Biome extends Biomes, ProtocolObject permits BiomeImpl {
@ApiStatus.Internal @ApiStatus.Internal
static @NotNull DynamicRegistry<Biome> createDefaultRegistry() { static @NotNull DynamicRegistry<Biome> createDefaultRegistry() {
return new DynamicRegistryImpl<>( return new DynamicRegistryImpl<>(
"minecraft:worldgen/biome", NBT_TYPE, Registry.Resource.BIOMES, "minecraft:worldgen/biome", BiomeImpl.REGISTRY_NBT_TYPE, Registry.Resource.BIOMES,
(namespace, props) -> new BiomeImpl(Registry.biome(namespace, props)) (namespace, props) -> new BiomeImpl(Registry.biome(namespace, props))
); );
} }
@ -57,17 +55,17 @@ public sealed interface Biome extends Biomes, ProtocolObject permits BiomeImpl {
} }
interface Setter { interface Setter {
void setBiome(int x, int y, int z, @NotNull Biome biome); void setBiome(int x, int y, int z, @NotNull DynamicRegistry.Key<Biome> biome);
default void setBiome(@NotNull Point blockPosition, @NotNull Biome biome) { default void setBiome(@NotNull Point blockPosition, @NotNull DynamicRegistry.Key<Biome> biome) {
setBiome(blockPosition.blockX(), blockPosition.blockY(), blockPosition.blockZ(), biome); setBiome(blockPosition.blockX(), blockPosition.blockY(), blockPosition.blockZ(), biome);
} }
} }
interface Getter { interface Getter {
@NotNull Biome getBiome(int x, int y, int z); @NotNull DynamicRegistry.Key<Biome> getBiome(int x, int y, int z);
default @NotNull Biome getBiome(@NotNull Point point) { default @NotNull DynamicRegistry.Key<Biome> getBiome(@NotNull Point point) {
return getBiome(point.blockX(), point.blockY(), point.blockZ()); return getBiome(point.blockX(), point.blockY(), point.blockZ());
} }
} }

View File

@ -21,7 +21,7 @@ record BiomeImpl(
// https://minecraft.wiki/w/Rain // https://minecraft.wiki/w/Rain
private final static Double SNOW_TEMPERATURE = 0.15; private final static Double SNOW_TEMPERATURE = 0.15;
static final BinaryTagSerializer<Biome> NBT_TYPE = BinaryTagSerializer.COMPOUND.map( static final BinaryTagSerializer<Biome> REGISTRY_NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
tag -> { tag -> {
throw new UnsupportedOperationException("Biome is read-only"); throw new UnsupportedOperationException("Biome is read-only");
}, },

View File

@ -146,7 +146,7 @@ public class PlayerIntegrationTest {
public void refreshPlayerTest(Env env) { public void refreshPlayerTest(Env env) {
final int TEST_PERMISSION_LEVEL = 2; final int TEST_PERMISSION_LEVEL = 2;
final var testDimension = DimensionType.builder(NamespaceID.from("minestom:test_dimension")).build(); final var testDimension = DimensionType.builder(NamespaceID.from("minestom:test_dimension")).build();
env.process().dimension().addDimension(testDimension); env.process().dimensionType().register(testDimension);
var instance = env.createFlatInstance(); var instance = env.createFlatInstance();
var instance2 = env.process().instance().createInstanceContainer(testDimension); var instance2 = env.process().instance().createInstanceContainer(testDimension);
@ -182,7 +182,7 @@ public class PlayerIntegrationTest {
public void deathLocationTest(Env env) { public void deathLocationTest(Env env) {
String dimensionNamespace = "minestom:test_dimension"; String dimensionNamespace = "minestom:test_dimension";
final var testDimension = DimensionType.builder(NamespaceID.from(dimensionNamespace)).build(); final var testDimension = DimensionType.builder(NamespaceID.from(dimensionNamespace)).build();
env.process().dimension().addDimension(testDimension); env.process().dimensionType().register(testDimension);
var instance = env.process().instance().createInstanceContainer(testDimension); var instance = env.process().instance().createInstanceContainer(testDimension);
var connection = env.createConnection(); var connection = env.createConnection();