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);
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;
json = GSON.fromJson(new InputStreamReader(resourceFile), JsonObject.class);
@ -93,12 +95,12 @@ public class CodeGenerator {
.replace(".", "_")
.toUpperCase(Locale.ROOT);
blockConstantsClass.addField(
FieldSpec.builder(namespaceIdClass, constantName)
FieldSpec.builder(typedRegistryKeyClass, constantName)
.addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
.initializer(
// TypeClass.STONE = NamespaceID.from("minecraft:stone")
"$T.from($S)",
namespaceIdClass,
"$T.of($S)",
registryKeyClass,
namespace
)
.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_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("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
new FluidGenerator(resource("fluids.json"), outputFolder).generate();

View File

@ -1,99 +1,99 @@
package net.minestom.server.entity.damage;
import net.minestom.server.utils.NamespaceID;
import net.minestom.server.registry.DynamicRegistry;
/**
* Code autogenerated, do not edit!
*/
@SuppressWarnings("unused")
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;
import net.minestom.server.utils.NamespaceID;
import net.minestom.server.registry.DynamicRegistry;
/**
* Code autogenerated, do not edit!
*/
@SuppressWarnings("unused")
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;
import net.minestom.server.utils.NamespaceID;
import net.minestom.server.registry.DynamicRegistry;
/**
* Code autogenerated, do not edit!
*/
@SuppressWarnings("unused")
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;
import net.minestom.server.utils.NamespaceID;
import net.minestom.server.registry.DynamicRegistry;
/**
* Code autogenerated, do not edit!
*/
@SuppressWarnings("unused")
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;
import net.minestom.server.utils.NamespaceID;
import net.minestom.server.registry.DynamicRegistry;
/**
* Code autogenerated, do not edit!
*/
@SuppressWarnings("unused")
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;
import net.minestom.server.utils.NamespaceID;
import net.minestom.server.registry.DynamicRegistry;
/**
* Code autogenerated, do not edit!
*/
@SuppressWarnings("unused")
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;
import net.minestom.server.utils.NamespaceID;
import net.minestom.server.registry.DynamicRegistry;
/**
* Code autogenerated, do not edit!
*/
@SuppressWarnings("unused")
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;
import net.minestom.server.utils.NamespaceID;
import net.minestom.server.registry.DynamicRegistry;
/**
* Code autogenerated, do not edit!
*/
@SuppressWarnings("unused")
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.SoundEffectPacket;
import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.scoreboard.Team;
import net.minestom.server.sound.SoundEvent;
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));
}
@ -382,7 +383,7 @@ public class LivingEntity extends Entity implements EquipmentHandler {
* @param type the 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;
}

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.SnifferMeta;
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.item.ItemStack;
import net.minestom.server.network.NetworkBuffer;
import net.minestom.server.network.packet.server.play.EntityMetaDataPacket;
import net.minestom.server.particle.Particle;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.utils.Direction;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
@ -149,6 +151,10 @@ public final class Metadata {
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
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.SnifferMeta;
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.instance.block.Block;
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_POSE, Pose(Entity.Pose.STANDING));
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));
// OptGlobalPos
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
if (getInstance() != null)
setDeathLocation(getInstance().getDimensionType(), getPosition());
setDeathLocation(getInstance().getDimensionName(), getPosition());
}
super.kill();
}
@ -1035,9 +1035,9 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
}
@Override
public boolean isImmune(@NotNull DamageType type) {
public boolean isImmune(@NotNull DynamicRegistry.Key<DamageType> type) {
if (!getGameMode().canTakeDamage()) {
return !DamageType.OUT_OF_WORLD.equals(type.namespace());
return !DamageType.OUT_OF_WORLD.equals(type);
}
return super.isImmune(type);
}
@ -1222,8 +1222,12 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
teleport(getPosition());
}
public void setDeathLocation(@NotNull DimensionType type, @NotNull Pos position) {
this.deathLocation = new WorldPos(type.name(), position);
public void setDeathLocation(@NotNull Pos position) {
setDeathLocation(getInstance().getDimensionName(), position);
}
public void setDeathLocation(@NotNull String dimension, @NotNull Pos position) {
this.deathLocation = new WorldPos(dimension, position);
}
public @Nullable WorldPos getDeathLocation() {
@ -1646,10 +1650,10 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
*
* @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),
"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,
0, gameMode, gameMode, false, levelFlat,
deathLocation, portalCooldown, RespawnPacket.COPY_ALL));

View File

@ -1,13 +1,16 @@
package net.minestom.server.entity.damage;
import net.kyori.adventure.text.Component;
import net.minestom.server.MinecraftServer;
import net.minestom.server.coordinate.Point;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.LivingEntity;
import net.minestom.server.entity.Player;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.sound.SoundEvent;
import net.minestom.server.tag.TagHandler;
import net.minestom.server.tag.Taggable;
import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull;
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.
*/
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 Entity source;
private final Entity attacker;
@ -33,8 +38,10 @@ public class Damage implements Taggable {
* @param type the type of this damage
* @param amount amount of damage
*/
public Damage(@NotNull DamageType type, @Nullable Entity source, @Nullable Entity attacker, @Nullable Point sourcePosition, float amount) {
this.type = type;
public Damage(@NotNull DynamicRegistry.Key<DamageType> type, @Nullable Entity source, @Nullable Entity attacker, @Nullable Point sourcePosition, float amount) {
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.attacker = attacker;
this.sourcePosition = sourcePosition;
@ -48,8 +55,8 @@ public class Damage implements Taggable {
*
* @return the damage type
*/
public @NotNull DamageType getType() {
return type;
public @NotNull DynamicRegistry.Key<DamageType> getType() {
return typeKey;
}
/**
@ -128,7 +135,7 @@ public class Damage implements Taggable {
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);
}

View File

@ -5,13 +5,11 @@ import net.minestom.server.registry.DynamicRegistryImpl;
import net.minestom.server.registry.ProtocolObject;
import net.minestom.server.registry.Registry;
import net.minestom.server.utils.NamespaceID;
import net.minestom.server.utils.nbt.BinaryTagSerializer;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public sealed interface DamageType extends ProtocolObject, DamageTypes permits DamageTypeImpl {
@NotNull BinaryTagSerializer<DamageType> NBT_TYPE = DamageTypeImpl.NBT_TYPE;
static @NotNull DamageType create(
@NotNull NamespaceID namespace,
@ -38,7 +36,7 @@ public sealed interface DamageType extends ProtocolObject, DamageTypes permits D
@ApiStatus.Internal
static @NotNull DynamicRegistry<DamageType> createDefaultRegistry() {
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))
);
}

View File

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

View File

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

View File

@ -1,21 +1,16 @@
package net.minestom.server.entity.damage;
import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.Entity;
import net.minestom.server.registry.DynamicRegistry;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
/**
* Represents damage inflicted by an entity, via a projectile.
*/
public class EntityProjectileDamage extends Damage {
private static final DynamicRegistry<DamageType> DAMAGE_TYPES = MinecraftServer.getDamageTypeRegistry();
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;
import net.minestom.server.coordinate.Point;
import net.minestom.server.registry.DynamicRegistry;
import org.jetbrains.annotations.NotNull;
/**
@ -8,12 +9,8 @@ import org.jetbrains.annotations.NotNull;
*/
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);
}
@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.minestom.server.entity.Entity;
import net.minestom.server.entity.Metadata;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.registry.DynamicRegistryImpl;
import net.minestom.server.registry.ProtocolObject;
import net.minestom.server.registry.Registry;
import net.minestom.server.network.NetworkBuffer;
import net.minestom.server.registry.*;
import net.minestom.server.utils.NamespaceID;
import net.minestom.server.utils.nbt.BinaryTagSerializer;
import net.minestom.server.utils.validate.Check;
@ -20,7 +18,7 @@ import java.util.List;
public class WolfMeta extends TameableAnimalMeta {
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) {
super(entity, metadata);
@ -52,8 +50,17 @@ public class WolfMeta extends TameableAnimalMeta {
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 {
@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(
@NotNull NamespaceID namespace,
@ -81,7 +88,7 @@ public class WolfMeta extends TameableAnimalMeta {
@ApiStatus.Internal
static @NotNull DynamicRegistry<Variant> createDefaultRegistry() {
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))
);
}
@ -149,7 +156,7 @@ public class WolfMeta extends TameableAnimalMeta {
) implements Variant {
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 -> {
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.utils.chunk.ChunkSupplier;
import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.world.DimensionType;
import net.minestom.server.world.biome.Biome;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
@ -70,8 +71,9 @@ public abstract class Chunk implements Block.Getter, Block.Setter, Biome.Getter,
this.chunkX = chunkX;
this.chunkZ = chunkZ;
this.shouldGenerate = shouldGenerate;
this.minSection = instance.getDimensionType().minY() / CHUNK_SECTION_SIZE;
this.maxSection = (instance.getDimensionType().minY() + instance.getDimensionType().height()) / CHUNK_SECTION_SIZE;
final DimensionType instanceDim = instance.getCachedDimensionType();
this.minSection = instanceDim.minY() / CHUNK_SECTION_SIZE;
this.maxSection = (instanceDim.minY() + instanceDim.height()) / CHUNK_SECTION_SIZE;
final List<SharedInstance> shared = instance instanceof InstanceContainer instanceContainer ?
instanceContainer.getSharedInstances() : List.of();
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.utils.ArrayUtils;
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 org.jetbrains.annotations.NotNull;
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,
@Nullable BlockHandler.Placement placement,
@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 [{}, {}): {}",
instance.getDimensionType().minY(), instance.getDimensionType().maxY(), y);
instanceDim.minY(), instanceDim.maxY(), y);
return;
}
assertLock();
@ -136,7 +139,7 @@ public class DynamicChunk extends Chunk {
}
@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();
this.chunkCache.invalidate();
Section section = getSectionAt(y);
@ -216,17 +219,14 @@ public class DynamicChunk extends Chunk {
}
@Override
public @NotNull Biome getBiome(int x, int y, int z) {
public @NotNull DynamicRegistry.Key<Biome> getBiome(int x, int y, int z) {
assertLock();
final Section section = getSectionAt(y);
final int id = section.biomePalette()
.get(toSectionRelativeCoordinate(x) / 4, toSectionRelativeCoordinate(y) / 4, toSectionRelativeCoordinate(z) / 4);
Biome biome = BIOME_REGISTRY.get(id);
if (biome == null) {
throw new IllegalStateException("Biome with id " + id + " is not registered");
}
DynamicRegistry.Key<Biome> biome = BIOME_REGISTRY.getKey(id);
Check.notNull(biome, "Biome with id {0} is not registered", id);
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.palette.Palette;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.utils.validate.Check;
import net.minestom.server.world.biome.Biome;
import org.jetbrains.annotations.NotNull;
@ -223,10 +224,10 @@ final class GeneratorImpl {
}
@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");
var id = BIOME_MANAGER.getId(biome.namespace());
if (id == -1) throw new IllegalStateException("Biome has not been registered: " + biome.namespace());
var id = BIOME_MANAGER.getId(biome);
Check.argCondition(id == -1, "Biome has not been registered: {0}", biome);
this.biomePalette.set(
toSectionRelativeCoordinate(x) / 4,
@ -273,10 +274,10 @@ final class GeneratorImpl {
}
@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");
var id = BIOME_MANAGER.getId(biome.namespace());
if (id == -1) throw new IllegalStateException("Biome has not been registered: " + biome.namespace());
var id = BIOME_MANAGER.getId(biome);
Check.argCondition(id == -1, "Biome has not been registered: {0}", biome);
this.biomePalette.fill(id);
}
@ -310,7 +311,7 @@ final class GeneratorImpl {
}
@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);
final GenerationUnit section = findAbsoluteSection(x, y, z);
y -= start.y();
@ -362,7 +363,7 @@ final class GeneratorImpl {
}
@Override
public void fillBiome(@NotNull Biome biome) {
public void fillBiome(@NotNull DynamicRegistry.Key<Biome> biome) {
for (GenerationUnit section : sections) {
section.modifier().fillBiome(biome);
}

View File

@ -72,8 +72,8 @@ public abstract class Instance implements Block.Getter, Block.Setter,
private boolean registered;
private final int dimensionTypeId;
private final DimensionType cachedDimensionType;
private final DynamicRegistry.Key<DimensionType> dimensionType;
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 WorldBorder worldBorder;
@ -123,7 +123,7 @@ public abstract class Instance implements Block.Getter, Block.Setter,
* @param uniqueId the {@link UUID} 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());
}
@ -133,11 +133,11 @@ public abstract class Instance implements Block.Getter, Block.Setter,
* @param uniqueId the {@link UUID} 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.dimensionTypeId = DIMENSION_REGISTRY.getId(dimensionType.namespace());
Check.argCondition(this.dimensionTypeId == -1, "The dimension " + dimensionType.name() + " is not registered! Please add it to the registry (`MinecraftServer.getDimensionTypeRegistry().registry(dimensionType)`).");
this.cachedDimensionType = dimensionType;
this.dimensionType = dimensionType;
this.cachedDimensionType = DIMENSION_REGISTRY.get(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.worldBorder = new WorldBorder(this);
@ -399,7 +399,12 @@ public abstract class Instance implements Block.Getter, Block.Setter,
*
* @return the dimension of the instance
*/
public DimensionType getDimensionType() {
public DynamicRegistry.Key<DimensionType> getDimensionType() {
return dimensionType;
}
@ApiStatus.Internal
public @NotNull DimensionType getCachedDimensionType() {
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.EffectPacket;
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.PacketUtils;
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
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());
}
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);
}
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());
}
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);
setChunkSupplier(DynamicChunk::new);
setChunkLoader(Objects.requireNonNullElse(loader, DEFAULT_LOADER));
@ -132,8 +133,9 @@ public class InstanceContainer extends Instance {
@Nullable BlockHandler.Placement placement, @Nullable BlockHandler.Destroy destroy,
boolean doBlockUpdates, int updateDistance) {
if (chunk.isReadOnly()) return;
if (y >= getDimensionType().maxY() || y < getDimensionType().minY()) {
LOGGER.warn("tried to set a block outside the world bounds, should be within [{}, {}): {}", getDimensionType().minY(), getDimensionType().maxY(), y);
final DimensionType dim = getCachedDimensionType();
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;
}
@ -438,7 +440,7 @@ public class InstanceContainer extends Instance {
@Override
public boolean isInVoid(@NotNull Point point) {
// 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 neighborY = blockPosition.blockY() + direction.normalY();
final int neighborZ = blockPosition.blockZ() + direction.normalZ();
if (neighborY < getDimensionType().minY() || neighborY > getDimensionType().height())
if (neighborY < getCachedDimensionType().minY() || neighborY > getCachedDimensionType().height())
continue;
final Block neighborBlock = cache.getBlock(neighborX, neighborY, neighborZ, Condition.TYPE);
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.instance.InstanceRegisterEvent;
import net.minestom.server.event.instance.InstanceUnregisterEvent;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.utils.validate.Check;
import net.minestom.server.world.DimensionType;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
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;
/**
@ -42,20 +46,19 @@ public final class InstanceManager {
* @return the created {@link InstanceContainer}
*/
@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);
registerInstance(instanceContainer);
return instanceContainer;
}
public @NotNull InstanceContainer createInstanceContainer(@NotNull DimensionType dimensionType) {
public @NotNull InstanceContainer createInstanceContainer(@NotNull DynamicRegistry.Key<DimensionType> dimensionType) {
return createInstanceContainer(dimensionType, null);
}
@ApiStatus.Experimental
public @NotNull InstanceContainer createInstanceContainer(@Nullable IChunkLoader loader) {
DimensionType defaultDimension = Objects.requireNonNull(MinecraftServer.getDimensionTypeRegistry().get(DimensionType.OVERWORLD));
return createInstanceContainer(defaultDimension, loader);
return createInstanceContainer(DimensionType.OVERWORLD, loader);
}
/**
@ -64,8 +67,7 @@ public final class InstanceManager {
* @return the created {@link InstanceContainer}
*/
public @NotNull InstanceContainer createInstanceContainer() {
DimensionType defaultDimension = Objects.requireNonNull(MinecraftServer.getDimensionTypeRegistry().get(DimensionType.OVERWORLD));
return createInstanceContainer(defaultDimension, null);
return createInstanceContainer(DimensionType.OVERWORLD, null);
}
/**

View File

@ -210,7 +210,7 @@ public class LightingChunk extends DynamicChunk {
if (this.occlusionMap != null) return this.occlusionMap;
var occlusionMap = new int[CHUNK_SIZE_X * CHUNK_SIZE_Z];
int minY = instance.getDimensionType().minY();
int minY = instance.getCachedDimensionType().minY();
highestBlock = minY - 1;
synchronized (this) {
@ -249,9 +249,8 @@ public class LightingChunk extends DynamicChunk {
List<byte[]> skyLights = new ArrayList<>();
List<byte[]> blockLights = new ArrayList<>();
int chunkMin = instance.getDimensionType().minY();
int highestNeighborBlock = instance.getDimensionType().minY();
int chunkMin = instance.getCachedDimensionType().minY();
int highestNeighborBlock = instance.getCachedDimensionType().minY();
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
Chunk neighborChunk = instance.getChunk(chunkX + i, chunkZ + j);
@ -286,7 +285,7 @@ public class LightingChunk extends DynamicChunk {
final int sectionMinY = index * 16 + chunkMin;
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();
if (skyLight.length != 0 && skyLight != emptyContent) {
@ -433,7 +432,7 @@ public class LightingChunk extends DynamicChunk {
Set<Point> collected = new HashSet<>();
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 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++) {
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 (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)
if (x % 4 == 0 && sectionLocalY % 4 == 0 && z % 4 == 0) {
int biomeIndex = (x / 4) + (sectionLocalY / 4) * 4 * 4 + (z / 4) * 4;
final Biome biome = chunk.getBiome(x, y, z);
final BinaryTag biomeName = StringBinaryTag.stringBinaryTag(biome.name());
final DynamicRegistry.Key<Biome> biomeKey = chunk.getBiome(x, y, z);
final BinaryTag biomeName = StringBinaryTag.stringBinaryTag(biomeKey.name());
int biomePaletteIndex = biomePalette.indexOf(biomeName);
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.Registry;
import net.minestom.server.utils.NamespaceID;
import net.minestom.server.utils.nbt.BinaryTagSerializer;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public sealed interface BannerPattern extends ProtocolObject, BannerPatterns permits BannerPatternImpl {
@NotNull BinaryTagSerializer<BannerPattern> NBT_TYPE = BannerPatternImpl.NBT_TYPE;
static @NotNull BannerPattern create(
@NotNull NamespaceID namespace,
@ -38,7 +36,7 @@ public sealed interface BannerPattern extends ProtocolObject, BannerPatterns per
@ApiStatus.Internal
static @NotNull DynamicRegistry<BannerPattern> createDefaultRegistry() {
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))
);
}

View File

@ -15,7 +15,7 @@ record BannerPatternImpl(
@Nullable Registry.BannerPatternEntry registry
) implements BannerPattern {
static final BinaryTagSerializer<BannerPattern> NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
static final BinaryTagSerializer<BannerPattern> REGISTRY_NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
tag -> {
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.instance.block.Block;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.world.biome.Biome;
import org.jetbrains.annotations.NotNull;
@ -60,7 +61,7 @@ public interface UnitModifier extends Block.Setter, Biome.Setter {
*
* @param biome the biome to fill
*/
void fillBiome(@NotNull Biome biome);
void fillBiome(@NotNull DynamicRegistry.Key<Biome> biome);
interface Supplier {
@NotNull Block get(int x, int y, int z);

View File

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

View File

@ -52,7 +52,7 @@ final class SkyLight implements Light {
if (c instanceof LightingChunk lc) {
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 sectionMinY = sectionY * 16;

View File

@ -2,10 +2,8 @@ package net.minestom.server.item.armor;
import net.kyori.adventure.text.Component;
import net.minestom.server.item.Material;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.registry.DynamicRegistryImpl;
import net.minestom.server.registry.ProtocolObject;
import net.minestom.server.registry.Registry;
import net.minestom.server.network.NetworkBuffer;
import net.minestom.server.registry.*;
import net.minestom.server.utils.NamespaceID;
import net.minestom.server.utils.nbt.BinaryTagSerializer;
import org.jetbrains.annotations.ApiStatus;
@ -17,7 +15,8 @@ import java.util.HashMap;
import java.util.Map;
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(
@NotNull NamespaceID namespace,
@ -49,7 +48,7 @@ public sealed interface TrimMaterial extends ProtocolObject permits TrimMaterial
@ApiStatus.Internal
static @NotNull DynamicRegistry<TrimMaterial> createDefaultRegistry() {
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))
);
}

View File

@ -22,7 +22,7 @@ record TrimMaterialImpl(
@Nullable Registry.TrimMaterialEntry registry
) implements TrimMaterial {
static final BinaryTagSerializer<TrimMaterial> NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
static final BinaryTagSerializer<TrimMaterial> REGISTRY_NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
tag -> {
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.minestom.server.item.Material;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.registry.DynamicRegistryImpl;
import net.minestom.server.registry.ProtocolObject;
import net.minestom.server.registry.Registry;
import net.minestom.server.network.NetworkBuffer;
import net.minestom.server.registry.*;
import net.minestom.server.utils.NamespaceID;
import net.minestom.server.utils.nbt.BinaryTagSerializer;
import org.jetbrains.annotations.ApiStatus;
@ -14,7 +12,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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(
@NotNull NamespaceID namespace,
@ -42,7 +41,7 @@ public sealed interface TrimPattern extends ProtocolObject permits TrimPatternIm
@ApiStatus.Internal
static @NotNull DynamicRegistry<TrimPattern> createDefaultRegistry() {
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))
);
}

View File

@ -19,7 +19,7 @@ record TrimPatternImpl(
@Nullable Registry.TrimPatternEntry registry
) implements TrimPattern {
static final BinaryTagSerializer<TrimPattern> NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
static final BinaryTagSerializer<TrimPattern> REGISTRY_NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
tag -> {
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.TrimPattern;
import net.minestom.server.network.NetworkBuffer;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.utils.nbt.BinaryTagSerializer;
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<>() {
@Override
public void write(@NotNull NetworkBuffer buffer, ArmorTrim value) {
// buffer.write(NetworkBuffer.VAR_INT, value.material.id());
// buffer.write(NetworkBuffer.VAR_INT, value.pattern.id());
buffer.write(TrimMaterial.NETWORK_TYPE, value.material);
buffer.write(TrimPattern.NETWORK_TYPE, value.pattern);
buffer.write(NetworkBuffer.BOOLEAN, value.showInTooltip);
}
@Override
public ArmorTrim read(@NotNull NetworkBuffer buffer) {
// TrimMaterial material = Objects.requireNonNull(TrimMaterial.fromId(buffer.read(NetworkBuffer.VAR_INT)), "unknown trim material");
// TrimPattern pattern = Objects.requireNonNull(TrimPattern.fromId(buffer.read(NetworkBuffer.VAR_INT)), "unknown trim pattern");
// return new ArmorTrim(material, pattern, buffer.read(NetworkBuffer.BOOLEAN));
throw new UnsupportedOperationException("Not implemented");
return new ArmorTrim(buffer.read(TrimMaterial.NETWORK_TYPE),
buffer.read(TrimPattern.NETWORK_TYPE),
buffer.read(NetworkBuffer.BOOLEAN));
}
};
public static final BinaryTagSerializer<ArmorTrim> NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
tag -> {
// TrimMaterial material = Objects.requireNonNull(TrimMaterial.fromNamespaceId(tag.getString("material")), "unknown trim material");
// TrimPattern pattern = Objects.requireNonNull(TrimPattern.fromNamespaceId(tag.getString("pattern")), "unknown trim pattern");
// boolean showInTooltip = tag.getBoolean("show_in_tooltip", true);
// return new ArmorTrim(material, pattern, showInTooltip);
throw new UnsupportedOperationException("Not implemented");
DynamicRegistry.Key<TrimMaterial> material = TrimMaterial.NBT_TYPE.read(tag.get("material"));
DynamicRegistry.Key<TrimPattern> pattern = TrimPattern.NBT_TYPE.read(tag.get("pattern"));
boolean showInTooltip = tag.getBoolean("show_in_tooltip", true);
return new ArmorTrim(material, pattern, showInTooltip);
},
value -> CompoundBinaryTag.builder()
.putString("material", value.material.name())
.put("material", TrimMaterial.NBT_TYPE.write(value.material))
.putString("pattern", value.pattern.name())
.putBoolean("show_in_tooltip", value.showInTooltip)
.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.utils.chunk.ChunkUtils;
import net.minestom.server.utils.validate.Check;
import net.minestom.server.world.DimensionType;
public class BlockPlacementListener {
private static final BlockManager BLOCK_MANAGER = MinecraftServer.getBlockManager();
@ -117,8 +118,10 @@ public class BlockPlacementListener {
}
}
if (placementPosition.y() >= instance.getDimensionType().maxY()
|| placementPosition.y() < instance.getDimensionType().minY()) return;
final DimensionType instanceDim = instance.getCachedDimensionType();
if (placementPosition.y() >= instanceDim.maxY() || placementPosition.y() < instanceDim.minY()) {
return;
}
// Ensure that the final placement position is inside the world border.
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.Registry;
import net.minestom.server.utils.NamespaceID;
import net.minestom.server.utils.nbt.BinaryTagSerializer;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public sealed interface ChatType extends ProtocolObject, ChatTypes permits ChatTypeImpl {
@NotNull BinaryTagSerializer<ChatType> NBT_TYPE = ChatTypeImpl.NBT_TYPE;
static @NotNull ChatType create(
@NotNull NamespaceID namespace,
@ -37,7 +35,7 @@ public sealed interface ChatType extends ProtocolObject, ChatTypes permits ChatT
@ApiStatus.Internal
static @NotNull DynamicRegistry<ChatType> createDefaultRegistry() {
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))
);
}

View File

@ -15,7 +15,7 @@ record ChatTypeImpl(
@Nullable Registry.ChatTypeEntry registry
) implements ChatType {
static final BinaryTagSerializer<ChatType> NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
static final BinaryTagSerializer<ChatType> REGISTRY_NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
tag -> {
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.text.Component;
import net.minestom.server.MinecraftServer;
import net.minestom.server.coordinate.Point;
import net.minestom.server.entity.Entity;
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.network.packet.server.play.data.WorldPos;
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.Unit;
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<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) {
return NetworkBufferTypeImpl.fromEnum(enumClass);
}
@ -106,6 +133,9 @@ public final class NetworkBuffer {
BinaryTagWriter nbtWriter;
BinaryTagReader nbtReader;
// In the future, this should be passed as a parameter.
final Registries registries = MinecraftServer.process();
public NetworkBuffer(@NotNull ByteBuffer buffer, boolean resizable) {
this.nioBuffer = buffer.order(ByteOrder.BIG_ENDIAN);
this.resizable = resizable;

View File

@ -1,20 +1,61 @@
package net.minestom.server.registry;
import net.kyori.adventure.key.Keyed;
import net.minestom.server.entity.Player;
import net.minestom.server.network.packet.server.SendablePacket;
import net.minestom.server.utils.NamespaceID;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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(@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);
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
@ -36,7 +77,7 @@ public interface DynamicRegistry<T extends ProtocolObject> {
* @param object The entry to register
* @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>

View File

@ -11,20 +11,27 @@ import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
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.locks.ReentrantLock;
@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'");
record KeyImpl<T extends ProtocolObject>(NamespaceID namespace) implements Key<T> {
}
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 Map<NamespaceID, T> entryByName = new HashMap<>();
private final List<NamespaceID> idByName = new ArrayList<>();
private final Map<NamespaceID, T> entryByName = new ConcurrentHashMap<>();
private final List<NamespaceID> idByName = new CopyOnWriteArrayList<>();
private final String id;
private final BinaryTagSerializer<T> nbtType;
@ -49,22 +56,26 @@ public class DynamicRegistryImpl<T extends ProtocolObject> implements DynamicReg
@Override
public @Nullable T get(@NotNull NamespaceID namespace) {
lock.lock();
try {
return entryByName.get(namespace);
} finally {
lock.unlock();
}
return entryByName.get(namespace);
}
@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
public int getId(@NotNull NamespaceID id) {
lock.lock();
try {
return idByName.indexOf(id);
} finally {
lock.unlock();
}
return idByName.indexOf(id);
}
@Override
@ -73,7 +84,7 @@ public class DynamicRegistryImpl<T extends ProtocolObject> implements DynamicReg
}
@Override
public int register(@NotNull T object) {
public @NotNull DynamicRegistry.Key<T> register(@NotNull T object) {
lock.lock();
try {
int id = idByName.indexOf(object.namespace());
@ -83,7 +94,7 @@ public class DynamicRegistryImpl<T extends ProtocolObject> implements DynamicReg
entryByName.put(object.namespace(), object);
idByName.add(object.namespace());
vanillaRegistryDataPacket.invalidate();
return id;
return Key.of(object.namespace());
} finally {
lock.unlock();
}
@ -116,28 +127,23 @@ public class DynamicRegistryImpl<T extends ProtocolObject> implements DynamicReg
}
private @NotNull RegistryDataPacket createRegistryDataPacket(boolean excludeVanilla) {
lock.lock();
try {
var entries = new ArrayList<RegistryDataPacket.Entry>(entryById.size());
for (var entry : entryById) {
CompoundBinaryTag data = null;
// sorta todo, sorta just a note:
// Right now we very much only support the minecraft:core (vanilla) 'pack'. Any entry which was not loaded
// from static data will be treated as non vanilla and always sent completely. However, we really should
// support arbitrary packs and associate all registry data with a datapack. Additionally, we should generate
// all data for the experimental datapacks built in to vanilla such as the next update experimental (1.21 at
// the time of writing). Datagen currently behaves kind of badly in that the registry inspecting generators
// like material, block, etc generate entries which are behind feature flags, whereas the ones which inspect
// static assets (the traditionally dynamic registries), do not generate those assets.
if (!excludeVanilla || entry.registry() == null) {
data = (CompoundBinaryTag) nbtType.write(entry);
}
entries.add(new RegistryDataPacket.Entry(entry.name(), data));
var entries = new ArrayList<RegistryDataPacket.Entry>(entryById.size());
for (var entry : entryById) {
CompoundBinaryTag data = null;
// sorta todo, sorta just a note:
// Right now we very much only support the minecraft:core (vanilla) 'pack'. Any entry which was not loaded
// from static data will be treated as non vanilla and always sent completely. However, we really should
// support arbitrary packs and associate all registry data with a datapack. Additionally, we should generate
// all data for the experimental datapacks built in to vanilla such as the next update experimental (1.21 at
// the time of writing). Datagen currently behaves kind of badly in that the registry inspecting generators
// like material, block, etc generate entries which are behind feature flags, whereas the ones which inspect
// static assets (the traditionally dynamic registries), do not generate those assets.
if (!excludeVanilla || entry.registry() == null) {
data = (CompoundBinaryTag) nbtType.write(entry);
}
return new RegistryDataPacket(id, entries);
} finally {
lock.unlock();
entries.add(new RegistryDataPacket.Entry(entry.name(), data));
}
return new RegistryDataPacket(id, entries);
}
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.instance.block.Block;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.tag.TagReadable;
import net.minestom.server.world.DimensionType;
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
permits SnapshotImpl.Instance {
@NotNull DimensionType dimensionType();
@NotNull DynamicRegistry.Key<DimensionType> dimensionType();
long worldAge();
@ -29,7 +30,7 @@ public sealed interface InstanceSnapshot extends Snapshot, Block.Getter, Biome.G
}
@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));
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.instance.Section;
import net.minestom.server.instance.block.Block;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.tag.Tag;
import net.minestom.server.tag.TagReadable;
import net.minestom.server.utils.collection.IntMappedArray;
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.biome.Biome;
import org.jetbrains.annotations.ApiStatus;
@ -44,7 +46,7 @@ public final class SnapshotImpl {
}
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,
int[] entitiesIds,
TagReadable tagReadable) implements InstanceSnapshot {
@ -99,11 +101,13 @@ public final class SnapshotImpl {
}
@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 int id = section.biomePalette()
.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

View File

@ -4,10 +4,15 @@ import net.kyori.adventure.nbt.*;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.Style;
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.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.Unit;
import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull;
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 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.Registry;
import net.minestom.server.utils.NamespaceID;
import net.minestom.server.utils.nbt.BinaryTagSerializer;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
@ -15,7 +14,6 @@ import org.jetbrains.annotations.Nullable;
* https://minecraft.wiki/w/Custom_dimension
*/
public sealed interface DimensionType extends ProtocolObject, DimensionTypes permits DimensionTypeImpl {
@NotNull BinaryTagSerializer<DimensionType> NBT_TYPE = DimensionTypeImpl.NBT_TYPE;
int VANILLA_MIN_Y = -64;
int VANILLA_MAX_Y = 319;
@ -36,7 +34,7 @@ public sealed interface DimensionType extends ProtocolObject, DimensionTypes per
@ApiStatus.Internal
static @NotNull DynamicRegistry<DimensionType> createDefaultRegistry() {
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))
);
}

View File

@ -28,7 +28,7 @@ record DimensionTypeImpl(
@Nullable Registry.DimensionTypeEntry registry
) implements DimensionType {
static final BinaryTagSerializer<DimensionType> NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
static final BinaryTagSerializer<DimensionType> REGISTRY_NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
tag -> {
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.Registry;
import net.minestom.server.utils.NamespaceID;
import net.minestom.server.utils.nbt.BinaryTagSerializer;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public sealed interface Biome extends Biomes, ProtocolObject permits BiomeImpl {
@NotNull BinaryTagSerializer<Biome> NBT_TYPE = BiomeImpl.NBT_TYPE;
static @NotNull Builder builder(@NotNull String namespace) {
return builder(NamespaceID.from(namespace));
@ -31,7 +29,7 @@ public sealed interface Biome extends Biomes, ProtocolObject permits BiomeImpl {
@ApiStatus.Internal
static @NotNull DynamicRegistry<Biome> createDefaultRegistry() {
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))
);
}
@ -57,17 +55,17 @@ public sealed interface Biome extends Biomes, ProtocolObject permits BiomeImpl {
}
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);
}
}
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());
}
}

View File

@ -21,7 +21,7 @@ record BiomeImpl(
// https://minecraft.wiki/w/Rain
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 -> {
throw new UnsupportedOperationException("Biome is read-only");
},

View File

@ -146,7 +146,7 @@ public class PlayerIntegrationTest {
public void refreshPlayerTest(Env env) {
final int TEST_PERMISSION_LEVEL = 2;
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 instance2 = env.process().instance().createInstanceContainer(testDimension);
@ -182,7 +182,7 @@ public class PlayerIntegrationTest {
public void deathLocationTest(Env env) {
String dimensionNamespace = "minestom:test_dimension";
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 connection = env.createConnection();