From 141a251c1ba13b59e48e9430070118263dd66048 Mon Sep 17 00:00:00 2001 From: mworzala Date: Thu, 30 May 2024 20:13:46 -0400 Subject: [PATCH] feat: new packets, new registries except stubbed out enchantments, other minor changes --- .../net/minestom/codegen/CodeGenerator.java | 6 +- .../minestom/codegen/ConstantsGenerator.java | 82 ++++++++ .../java/net/minestom/codegen/Generators.java | 5 +- .../java/net/minestom/demo/PlayerInit.java | 13 ++ .../minestom/server/MinecraftConstants.java | 16 ++ .../server/entity/attribute/Attributes.java | 18 ++ .../server/entity/damage/DamageTypes.java | 4 + .../metadata/other/PaintingVariants.java | 109 +++++++++++ .../instance/block/banner/BannerPatterns.java | 4 + .../instance/block/jukebox/JukeboxSongs.java | 47 +++++ .../net/minestom/server/item/Materials.java | 10 +- .../server/item/armor/TrimPatterns.java | 4 + .../server/item/enchant/Enchantments.java | 86 +++++---- .../minestom/server/sound/SoundEvents.java | 12 +- .../net/minestom/server/MinecraftServer.java | 21 +- .../minestom/server/ServerProcessImpl.java | 24 +++ .../registry/ArgumentEnchantment.java | 8 +- .../net/minestom/server/entity/Metadata.java | 4 +- .../entity/attribute/AttributeImpl.java | 2 - .../entity/attribute/AttributeInstance.java | 91 ++++++--- .../entity/attribute/AttributeModifier.java | 93 +++------ .../entity/attribute/AttributeOperation.java | 5 + .../entity/metadata/other/PaintingMeta.java | 179 ++++++++++-------- .../instance/block/jukebox/JukeboxSong.java | 99 ++++++++++ .../block/jukebox/JukeboxSongImpl.java | 45 +++++ .../type/EnchantmentTableInventory.java | 17 +- .../minestom/server/item/ItemComponent.java | 1 + .../server/item/attribute/AttributeSlot.java | 5 + .../server/item/component/AttributeList.java | 96 ++++------ .../item/component/EnchantmentList.java | 43 +++-- .../minestom/server/item/component/Food.java | 28 ++- .../item/component/JukeboxPlayable.java | 59 ++++++ .../server/item/enchant/Enchantment.java | 67 ++++--- .../server/item/enchant/EnchantmentImpl.java | 37 ++-- .../server/network/ConnectionManager.java | 4 + .../server/network/NetworkBuffer.java | 19 ++ .../client/play/ClientUseItemPacket.java | 7 +- .../packet/server/ServerPacketIdentifier.java | 4 + .../common/CustomReportDetailsPacket.java | 37 ++++ .../server/common/ServerLinksPacket.java | 97 ++++++++++ .../server/play/EntityAttributesPacket.java | 45 +---- .../server/play/ProjectilePowerPacket.java | 7 +- .../minestom/server/registry/Registries.java | 9 + .../minestom/server/registry/Registry.java | 78 +++++--- 44 files changed, 1204 insertions(+), 443 deletions(-) create mode 100644 code-generators/src/main/java/net/minestom/codegen/ConstantsGenerator.java create mode 100644 src/autogenerated/java/net/minestom/server/MinecraftConstants.java create mode 100644 src/autogenerated/java/net/minestom/server/entity/metadata/other/PaintingVariants.java create mode 100644 src/autogenerated/java/net/minestom/server/instance/block/jukebox/JukeboxSongs.java create mode 100644 src/main/java/net/minestom/server/instance/block/jukebox/JukeboxSong.java create mode 100644 src/main/java/net/minestom/server/instance/block/jukebox/JukeboxSongImpl.java create mode 100644 src/main/java/net/minestom/server/item/component/JukeboxPlayable.java create mode 100644 src/main/java/net/minestom/server/network/packet/server/common/CustomReportDetailsPacket.java create mode 100644 src/main/java/net/minestom/server/network/packet/server/common/ServerLinksPacket.java diff --git a/code-generators/src/main/java/net/minestom/codegen/CodeGenerator.java b/code-generators/src/main/java/net/minestom/codegen/CodeGenerator.java index a95913afe..8aa876ec2 100644 --- a/code-generators/src/main/java/net/minestom/codegen/CodeGenerator.java +++ b/code-generators/src/main/java/net/minestom/codegen/CodeGenerator.java @@ -8,6 +8,7 @@ import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.lang.model.SourceVersion; import javax.lang.model.element.Modifier; import java.io.File; import java.io.IOException; @@ -90,10 +91,13 @@ public class CodeGenerator { // Use data json.keySet().forEach(namespace -> { - final String constantName = namespace + String constantName = namespace .replace("minecraft:", "") .replace(".", "_") .toUpperCase(Locale.ROOT); + if (!SourceVersion.isName(constantName)) { + constantName = "_" + constantName; + } blockConstantsClass.addField( FieldSpec.builder(typedRegistryKeyClass, constantName) .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) diff --git a/code-generators/src/main/java/net/minestom/codegen/ConstantsGenerator.java b/code-generators/src/main/java/net/minestom/codegen/ConstantsGenerator.java new file mode 100644 index 000000000..0ce81d41a --- /dev/null +++ b/code-generators/src/main/java/net/minestom/codegen/ConstantsGenerator.java @@ -0,0 +1,82 @@ +package net.minestom.codegen; + +import com.google.gson.JsonObject; +import com.squareup.javapoet.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.lang.model.element.Modifier; +import java.io.File; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.List; + +public class ConstantsGenerator extends MinestomCodeGenerator { + private static final Logger LOGGER = LoggerFactory.getLogger(ConstantsGenerator.class); + private final InputStream constantsFile; + private final File outputFolder; + + public ConstantsGenerator(@Nullable InputStream constantsFile, @NotNull File outputFolder) { + this.constantsFile = constantsFile; + this.outputFolder = outputFolder; + } + + @Override + public void generate() { + if (constantsFile == null) { + LOGGER.error("Failed to find constants.json."); + LOGGER.error("Stopped code generation for recipe types."); + return; + } + if (!outputFolder.exists() && !outputFolder.mkdirs()) { + LOGGER.error("Output folder for code generation does not exist and could not be created."); + return; + } + + // Important classes we use alot + JsonObject constants = GSON.fromJson(new InputStreamReader(constantsFile), JsonObject.class); + ClassName minecraftConstantsCN = ClassName.get("net.minestom.server", "MinecraftConstants"); + TypeSpec.Builder constantsInterface = TypeSpec.interfaceBuilder(minecraftConstantsCN) + .addJavadoc("AUTOGENERATED by " + getClass().getSimpleName()); + + constantsInterface.addField(FieldSpec.builder(String.class, "VERSION_NAME") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .initializer("$S", constants.get("name").getAsString()) + .build() + ); + constantsInterface.addField(FieldSpec.builder(TypeName.INT, "PROTOCOL_VERSION") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .initializer("$L", constants.get("protocol").getAsInt()) + .build() + ); + constantsInterface.addField(FieldSpec.builder(TypeName.INT, "DATA_VERSION") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .initializer("$L", constants.get("world").getAsInt()) + .build() + ); + constantsInterface.addField(FieldSpec.builder(TypeName.INT, "RESOURCE_PACK_VERSION") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .initializer("$L", constants.get("resourcepack").getAsInt()) + .build() + ); + constantsInterface.addField(FieldSpec.builder(TypeName.INT, "DATA_PACK_VERSION") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .initializer("$L", constants.get("datapack").getAsInt()) + .build() + ); + + // Write files to outputFolder + writeFiles( + List.of( + JavaFile.builder("net.minestom.server", constantsInterface.build()) + .indent(" ") + .skipJavaLangImports(true) + .build() + ), + outputFolder + ); + } + +} diff --git a/code-generators/src/main/java/net/minestom/codegen/Generators.java b/code-generators/src/main/java/net/minestom/codegen/Generators.java index 870ec604d..0db7d9f81 100644 --- a/code-generators/src/main/java/net/minestom/codegen/Generators.java +++ b/code-generators/src/main/java/net/minestom/codegen/Generators.java @@ -24,6 +24,7 @@ public class Generators { new DyeColorGenerator(resource("dye_colors.json"), outputFolder).generate(); new RecipeTypeGenerator(resource("recipe_types.json"), outputFolder).generate(); new ParticleGenerator(resource("particles.json"), outputFolder).generate(); + new ConstantsGenerator(resource("constants.json"), outputFolder).generate(); var generator = new CodeGenerator(outputFolder); @@ -31,7 +32,6 @@ public class Generators { generator.generate(resource("blocks.json"), "net.minestom.server.instance.block", "Block", "BlockImpl", "Blocks"); generator.generate(resource("items.json"), "net.minestom.server.item", "Material", "MaterialImpl", "Materials"); generator.generate(resource("entities.json"), "net.minestom.server.entity", "EntityType", "EntityTypeImpl", "EntityTypes"); - generator.generate(resource("enchantments.json"), "net.minestom.server.item.enchant", "Enchantment", "EnchantmentImpl", "Enchantments"); generator.generate(resource("potion_effects.json"), "net.minestom.server.potion", "PotionEffect", "PotionEffectImpl", "PotionEffects"); generator.generate(resource("potions.json"), "net.minestom.server.potion", "PotionType", "PotionTypeImpl", "PotionTypes"); generator.generate(resource("sounds.json"), "net.minestom.server.sound", "SoundEvent", "BuiltinSoundEvent", "SoundEvents"); @@ -47,6 +47,9 @@ public class Generators { 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", "WolfMeta.Variant", "WolfVariants"); + generator.generateKeys(resource("enchantments.json"), "net.minestom.server.item.enchant", "Enchantment", "Enchantments"); + generator.generateKeys(resource("painting_variants.json"), "net.minestom.server.entity.metadata.other", "PaintingMeta.Variant", "PaintingVariants"); + generator.generateKeys(resource("jukebox_songs.json"), "net.minestom.server.instance.block.jukebox", "JukeboxSong", "JukeboxSongs"); // Generate fluids new FluidGenerator(resource("fluids.json"), outputFolder).generate(); diff --git a/demo/src/main/java/net/minestom/demo/PlayerInit.java b/demo/src/main/java/net/minestom/demo/PlayerInit.java index d1d3fd639..2fba4c221 100644 --- a/demo/src/main/java/net/minestom/demo/PlayerInit.java +++ b/demo/src/main/java/net/minestom/demo/PlayerInit.java @@ -39,6 +39,8 @@ import net.minestom.server.item.component.ItemBlockState; import net.minestom.server.item.component.PotionContents; import net.minestom.server.monitoring.BenchmarkManager; import net.minestom.server.monitoring.TickMonitor; +import net.minestom.server.network.packet.server.common.CustomReportDetailsPacket; +import net.minestom.server.network.packet.server.common.ServerLinksPacket; import net.minestom.server.potion.CustomPotionEffect; import net.minestom.server.potion.PotionEffect; import net.minestom.server.sound.SoundEvent; @@ -114,6 +116,16 @@ public class PlayerInit { .build(); player.getInventory().addItemStack(itemStack); + player.sendPacket(new CustomReportDetailsPacket(Map.of( + "hello", "world" + ))); + + player.sendPacket(new ServerLinksPacket( + new ServerLinksPacket.Entry(ServerLinksPacket.KnownLinkType.NEWS, "https://minestom.net"), + new ServerLinksPacket.Entry(ServerLinksPacket.KnownLinkType.BUG_REPORT, "https://minestom.net"), + new ServerLinksPacket.Entry(Component.text("Hello world!"), "https://minestom.net") + )); + ItemStack bundle = ItemStack.builder(Material.BUNDLE) .set(ItemComponent.BUNDLE_CONTENTS, List.of( ItemStack.of(Material.DIAMOND, 5), @@ -136,6 +148,7 @@ public class PlayerInit { ))) .build()); + if (event.isFirstSpawn()) { Notification notification = new Notification( Component.text("Welcome!"), diff --git a/src/autogenerated/java/net/minestom/server/MinecraftConstants.java b/src/autogenerated/java/net/minestom/server/MinecraftConstants.java new file mode 100644 index 000000000..928650717 --- /dev/null +++ b/src/autogenerated/java/net/minestom/server/MinecraftConstants.java @@ -0,0 +1,16 @@ +package net.minestom.server; + +/** + * AUTOGENERATED by ConstantsGenerator + */ +interface MinecraftConstants { + String VERSION_NAME = "1.21 Pre-Release 1"; + + int PROTOCOL_VERSION = 1073742023; + + int DATA_VERSION = 3948; + + int RESOURCE_PACK_VERSION = 34; + + int DATA_PACK_VERSION = 46; +} diff --git a/src/autogenerated/java/net/minestom/server/entity/attribute/Attributes.java b/src/autogenerated/java/net/minestom/server/entity/attribute/Attributes.java index 9f22bbe56..e660d3b29 100644 --- a/src/autogenerated/java/net/minestom/server/entity/attribute/Attributes.java +++ b/src/autogenerated/java/net/minestom/server/entity/attribute/Attributes.java @@ -19,6 +19,10 @@ interface Attributes { Attribute PLAYER_BLOCK_INTERACTION_RANGE = AttributeImpl.get("minecraft:player.block_interaction_range"); + Attribute GENERIC_BURNING_TIME = AttributeImpl.get("minecraft:generic.burning_time"); + + Attribute GENERIC_EXPLOSION_KNOCKBACK_RESISTANCE = AttributeImpl.get("minecraft:generic.explosion_knockback_resistance"); + Attribute PLAYER_ENTITY_INTERACTION_RANGE = AttributeImpl.get("minecraft:player.entity_interaction_range"); Attribute GENERIC_FALL_DAMAGE_MULTIPLIER = AttributeImpl.get("minecraft:generic.fall_damage_multiplier"); @@ -39,13 +43,27 @@ interface Attributes { Attribute GENERIC_MAX_HEALTH = AttributeImpl.get("minecraft:generic.max_health"); + Attribute PLAYER_MINING_EFFICIENCY = AttributeImpl.get("minecraft:player.mining_efficiency"); + + Attribute GENERIC_MOVEMENT_EFFICIENCY = AttributeImpl.get("minecraft:generic.movement_efficiency"); + Attribute GENERIC_MOVEMENT_SPEED = AttributeImpl.get("minecraft:generic.movement_speed"); + Attribute GENERIC_OXYGEN_BONUS = AttributeImpl.get("minecraft:generic.oxygen_bonus"); + Attribute GENERIC_SAFE_FALL_DISTANCE = AttributeImpl.get("minecraft:generic.safe_fall_distance"); Attribute GENERIC_SCALE = AttributeImpl.get("minecraft:generic.scale"); + Attribute PLAYER_SNEAKING_SPEED = AttributeImpl.get("minecraft:player.sneaking_speed"); + Attribute ZOMBIE_SPAWN_REINFORCEMENTS = AttributeImpl.get("minecraft:zombie.spawn_reinforcements"); Attribute GENERIC_STEP_HEIGHT = AttributeImpl.get("minecraft:generic.step_height"); + + Attribute PLAYER_SUBMERGED_MINING_SPEED = AttributeImpl.get("minecraft:player.submerged_mining_speed"); + + Attribute PLAYER_SWEEPING_DAMAGE_RATIO = AttributeImpl.get("minecraft:player.sweeping_damage_ratio"); + + Attribute GENERIC_WATER_MOVEMENT_EFFICIENCY = AttributeImpl.get("minecraft:generic.water_movement_efficiency"); } diff --git a/src/autogenerated/java/net/minestom/server/entity/damage/DamageTypes.java b/src/autogenerated/java/net/minestom/server/entity/damage/DamageTypes.java index 51def07fa..806d7a300 100644 --- a/src/autogenerated/java/net/minestom/server/entity/damage/DamageTypes.java +++ b/src/autogenerated/java/net/minestom/server/entity/damage/DamageTypes.java @@ -25,6 +25,8 @@ interface DamageTypes { DynamicRegistry.Key MOB_PROJECTILE = DynamicRegistry.Key.of("minecraft:mob_projectile"); + DynamicRegistry.Key CAMPFIRE = DynamicRegistry.Key.of("minecraft:campfire"); + DynamicRegistry.Key THROWN = DynamicRegistry.Key.of("minecraft:thrown"); DynamicRegistry.Key FALLING_STALACTITE = DynamicRegistry.Key.of("minecraft:falling_stalactite"); @@ -33,6 +35,8 @@ interface DamageTypes { DynamicRegistry.Key FALLING_BLOCK = DynamicRegistry.Key.of("minecraft:falling_block"); + DynamicRegistry.Key WIND_CHARGE = DynamicRegistry.Key.of("minecraft:wind_charge"); + DynamicRegistry.Key PLAYER_EXPLOSION = DynamicRegistry.Key.of("minecraft:player_explosion"); DynamicRegistry.Key SPIT = DynamicRegistry.Key.of("minecraft:spit"); diff --git a/src/autogenerated/java/net/minestom/server/entity/metadata/other/PaintingVariants.java b/src/autogenerated/java/net/minestom/server/entity/metadata/other/PaintingVariants.java new file mode 100644 index 000000000..80ceffc3d --- /dev/null +++ b/src/autogenerated/java/net/minestom/server/entity/metadata/other/PaintingVariants.java @@ -0,0 +1,109 @@ +package net.minestom.server.entity.metadata.other; + +import net.minestom.server.registry.DynamicRegistry; + +/** + * Code autogenerated, do not edit! + */ +@SuppressWarnings("unused") +interface PaintingVariants { + DynamicRegistry.Key BOUQUET = DynamicRegistry.Key.of("minecraft:bouquet"); + + DynamicRegistry.Key WITHER = DynamicRegistry.Key.of("minecraft:wither"); + + DynamicRegistry.Key ALBAN = DynamicRegistry.Key.of("minecraft:alban"); + + DynamicRegistry.Key UNPACKED = DynamicRegistry.Key.of("minecraft:unpacked"); + + DynamicRegistry.Key AZTEC = DynamicRegistry.Key.of("minecraft:aztec"); + + DynamicRegistry.Key MATCH = DynamicRegistry.Key.of("minecraft:match"); + + DynamicRegistry.Key FINDING = DynamicRegistry.Key.of("minecraft:finding"); + + DynamicRegistry.Key BAROQUE = DynamicRegistry.Key.of("minecraft:baroque"); + + DynamicRegistry.Key ENDBOSS = DynamicRegistry.Key.of("minecraft:endboss"); + + DynamicRegistry.Key ORB = DynamicRegistry.Key.of("minecraft:orb"); + + DynamicRegistry.Key AZTEC2 = DynamicRegistry.Key.of("minecraft:aztec2"); + + DynamicRegistry.Key SUNFLOWERS = DynamicRegistry.Key.of("minecraft:sunflowers"); + + DynamicRegistry.Key CHANGING = DynamicRegistry.Key.of("minecraft:changing"); + + DynamicRegistry.Key WASTELAND = DynamicRegistry.Key.of("minecraft:wasteland"); + + DynamicRegistry.Key DONKEY_KONG = DynamicRegistry.Key.of("minecraft:donkey_kong"); + + DynamicRegistry.Key BUST = DynamicRegistry.Key.of("minecraft:bust"); + + DynamicRegistry.Key POOL = DynamicRegistry.Key.of("minecraft:pool"); + + DynamicRegistry.Key PIGSCENE = DynamicRegistry.Key.of("minecraft:pigscene"); + + DynamicRegistry.Key BURNING_SKULL = DynamicRegistry.Key.of("minecraft:burning_skull"); + + DynamicRegistry.Key FIRE = DynamicRegistry.Key.of("minecraft:fire"); + + DynamicRegistry.Key SEA = DynamicRegistry.Key.of("minecraft:sea"); + + DynamicRegistry.Key SUNSET = DynamicRegistry.Key.of("minecraft:sunset"); + + DynamicRegistry.Key POND = DynamicRegistry.Key.of("minecraft:pond"); + + DynamicRegistry.Key HUMBLE = DynamicRegistry.Key.of("minecraft:humble"); + + DynamicRegistry.Key TIDES = DynamicRegistry.Key.of("minecraft:tides"); + + DynamicRegistry.Key PRAIRIE_RIDE = DynamicRegistry.Key.of("minecraft:prairie_ride"); + + DynamicRegistry.Key FERN = DynamicRegistry.Key.of("minecraft:fern"); + + DynamicRegistry.Key PASSAGE = DynamicRegistry.Key.of("minecraft:passage"); + + DynamicRegistry.Key LOWMIST = DynamicRegistry.Key.of("minecraft:lowmist"); + + DynamicRegistry.Key COURBET = DynamicRegistry.Key.of("minecraft:courbet"); + + DynamicRegistry.Key WANDERER = DynamicRegistry.Key.of("minecraft:wanderer"); + + DynamicRegistry.Key BACKYARD = DynamicRegistry.Key.of("minecraft:backyard"); + + DynamicRegistry.Key EARTH = DynamicRegistry.Key.of("minecraft:earth"); + + DynamicRegistry.Key SKULL_AND_ROSES = DynamicRegistry.Key.of("minecraft:skull_and_roses"); + + DynamicRegistry.Key CAVEBIRD = DynamicRegistry.Key.of("minecraft:cavebird"); + + DynamicRegistry.Key FIGHTERS = DynamicRegistry.Key.of("minecraft:fighters"); + + DynamicRegistry.Key COTAN = DynamicRegistry.Key.of("minecraft:cotan"); + + DynamicRegistry.Key CREEBET = DynamicRegistry.Key.of("minecraft:creebet"); + + DynamicRegistry.Key OWLEMONS = DynamicRegistry.Key.of("minecraft:owlemons"); + + DynamicRegistry.Key GRAHAM = DynamicRegistry.Key.of("minecraft:graham"); + + DynamicRegistry.Key MEDITATIVE = DynamicRegistry.Key.of("minecraft:meditative"); + + DynamicRegistry.Key KEBAB = DynamicRegistry.Key.of("minecraft:kebab"); + + DynamicRegistry.Key STAGE = DynamicRegistry.Key.of("minecraft:stage"); + + DynamicRegistry.Key BOMB = DynamicRegistry.Key.of("minecraft:bomb"); + + DynamicRegistry.Key PLANT = DynamicRegistry.Key.of("minecraft:plant"); + + DynamicRegistry.Key WATER = DynamicRegistry.Key.of("minecraft:water"); + + DynamicRegistry.Key POINTER = DynamicRegistry.Key.of("minecraft:pointer"); + + DynamicRegistry.Key SKELETON = DynamicRegistry.Key.of("minecraft:skeleton"); + + DynamicRegistry.Key VOID = DynamicRegistry.Key.of("minecraft:void"); + + DynamicRegistry.Key WIND = DynamicRegistry.Key.of("minecraft:wind"); +} diff --git a/src/autogenerated/java/net/minestom/server/instance/block/banner/BannerPatterns.java b/src/autogenerated/java/net/minestom/server/instance/block/banner/BannerPatterns.java index 290173045..2a4a50994 100644 --- a/src/autogenerated/java/net/minestom/server/instance/block/banner/BannerPatterns.java +++ b/src/autogenerated/java/net/minestom/server/instance/block/banner/BannerPatterns.java @@ -13,6 +13,8 @@ interface BannerPatterns { DynamicRegistry.Key STRIPE_RIGHT = DynamicRegistry.Key.of("minecraft:stripe_right"); + DynamicRegistry.Key FLOW = DynamicRegistry.Key.of("minecraft:flow"); + DynamicRegistry.Key RHOMBUS = DynamicRegistry.Key.of("minecraft:rhombus"); DynamicRegistry.Key TRIANGLES_TOP = DynamicRegistry.Key.of("minecraft:triangles_top"); @@ -53,6 +55,8 @@ interface BannerPatterns { DynamicRegistry.Key STRIPE_DOWNRIGHT = DynamicRegistry.Key.of("minecraft:stripe_downright"); + DynamicRegistry.Key GUSTER = DynamicRegistry.Key.of("minecraft:guster"); + DynamicRegistry.Key GRADIENT_UP = DynamicRegistry.Key.of("minecraft:gradient_up"); DynamicRegistry.Key DIAGONAL_RIGHT = DynamicRegistry.Key.of("minecraft:diagonal_right"); diff --git a/src/autogenerated/java/net/minestom/server/instance/block/jukebox/JukeboxSongs.java b/src/autogenerated/java/net/minestom/server/instance/block/jukebox/JukeboxSongs.java new file mode 100644 index 000000000..3b18fbfd0 --- /dev/null +++ b/src/autogenerated/java/net/minestom/server/instance/block/jukebox/JukeboxSongs.java @@ -0,0 +1,47 @@ +package net.minestom.server.instance.block.jukebox; + +import net.minestom.server.registry.DynamicRegistry; + +/** + * Code autogenerated, do not edit! + */ +@SuppressWarnings("unused") +interface JukeboxSongs { + DynamicRegistry.Key PRECIPICE = DynamicRegistry.Key.of("minecraft:precipice"); + + DynamicRegistry.Key STAL = DynamicRegistry.Key.of("minecraft:stal"); + + DynamicRegistry.Key STRAD = DynamicRegistry.Key.of("minecraft:strad"); + + DynamicRegistry.Key CREATOR_MUSIC_BOX = DynamicRegistry.Key.of("minecraft:creator_music_box"); + + DynamicRegistry.Key _13 = DynamicRegistry.Key.of("minecraft:13"); + + DynamicRegistry.Key RELIC = DynamicRegistry.Key.of("minecraft:relic"); + + DynamicRegistry.Key FAR = DynamicRegistry.Key.of("minecraft:far"); + + DynamicRegistry.Key BLOCKS = DynamicRegistry.Key.of("minecraft:blocks"); + + DynamicRegistry.Key _5 = DynamicRegistry.Key.of("minecraft:5"); + + DynamicRegistry.Key OTHERSIDE = DynamicRegistry.Key.of("minecraft:otherside"); + + DynamicRegistry.Key MELLOHI = DynamicRegistry.Key.of("minecraft:mellohi"); + + DynamicRegistry.Key MALL = DynamicRegistry.Key.of("minecraft:mall"); + + DynamicRegistry.Key CHIRP = DynamicRegistry.Key.of("minecraft:chirp"); + + DynamicRegistry.Key CREATOR = DynamicRegistry.Key.of("minecraft:creator"); + + DynamicRegistry.Key PIGSTEP = DynamicRegistry.Key.of("minecraft:pigstep"); + + DynamicRegistry.Key WARD = DynamicRegistry.Key.of("minecraft:ward"); + + DynamicRegistry.Key CAT = DynamicRegistry.Key.of("minecraft:cat"); + + DynamicRegistry.Key WAIT = DynamicRegistry.Key.of("minecraft:wait"); + + DynamicRegistry.Key _11 = DynamicRegistry.Key.of("minecraft:11"); +} diff --git a/src/autogenerated/java/net/minestom/server/item/Materials.java b/src/autogenerated/java/net/minestom/server/item/Materials.java index 622f5a00e..23f5ff7ba 100644 --- a/src/autogenerated/java/net/minestom/server/item/Materials.java +++ b/src/autogenerated/java/net/minestom/server/item/Materials.java @@ -1603,6 +1603,8 @@ interface Materials { Material FLINT_AND_STEEL = MaterialImpl.get("minecraft:flint_and_steel"); + Material BOWL = MaterialImpl.get("minecraft:bowl"); + Material APPLE = MaterialImpl.get("minecraft:apple"); Material BOW = MaterialImpl.get("minecraft:bow"); @@ -1701,8 +1703,6 @@ interface Materials { Material STICK = MaterialImpl.get("minecraft:stick"); - Material BOWL = MaterialImpl.get("minecraft:bowl"); - Material MUSHROOM_STEW = MaterialImpl.get("minecraft:mushroom_stew"); Material STRING = MaterialImpl.get("minecraft:string"); @@ -2349,6 +2349,10 @@ interface Materials { Material MUSIC_DISC_CHIRP = MaterialImpl.get("minecraft:music_disc_chirp"); + Material MUSIC_DISC_CREATOR = MaterialImpl.get("minecraft:music_disc_creator"); + + Material MUSIC_DISC_CREATOR_MUSIC_BOX = MaterialImpl.get("minecraft:music_disc_creator_music_box"); + Material MUSIC_DISC_FAR = MaterialImpl.get("minecraft:music_disc_far"); Material MUSIC_DISC_MALL = MaterialImpl.get("minecraft:music_disc_mall"); @@ -2373,6 +2377,8 @@ interface Materials { Material MUSIC_DISC_PIGSTEP = MaterialImpl.get("minecraft:music_disc_pigstep"); + Material MUSIC_DISC_PRECIPICE = MaterialImpl.get("minecraft:music_disc_precipice"); + Material DISC_FRAGMENT_5 = MaterialImpl.get("minecraft:disc_fragment_5"); Material TRIDENT = MaterialImpl.get("minecraft:trident"); diff --git a/src/autogenerated/java/net/minestom/server/item/armor/TrimPatterns.java b/src/autogenerated/java/net/minestom/server/item/armor/TrimPatterns.java index 14b62e767..a11a09285 100644 --- a/src/autogenerated/java/net/minestom/server/item/armor/TrimPatterns.java +++ b/src/autogenerated/java/net/minestom/server/item/armor/TrimPatterns.java @@ -11,6 +11,8 @@ interface TrimPatterns { DynamicRegistry.Key RIB = DynamicRegistry.Key.of("minecraft:rib"); + DynamicRegistry.Key BOLT = DynamicRegistry.Key.of("minecraft:bolt"); + DynamicRegistry.Key HOST = DynamicRegistry.Key.of("minecraft:host"); DynamicRegistry.Key SILENCE = DynamicRegistry.Key.of("minecraft:silence"); @@ -19,6 +21,8 @@ interface TrimPatterns { DynamicRegistry.Key WAYFINDER = DynamicRegistry.Key.of("minecraft:wayfinder"); + DynamicRegistry.Key FLOW = DynamicRegistry.Key.of("minecraft:flow"); + DynamicRegistry.Key DUNE = DynamicRegistry.Key.of("minecraft:dune"); DynamicRegistry.Key RAISER = DynamicRegistry.Key.of("minecraft:raiser"); diff --git a/src/autogenerated/java/net/minestom/server/item/enchant/Enchantments.java b/src/autogenerated/java/net/minestom/server/item/enchant/Enchantments.java index ff95445ae..03f8dad26 100644 --- a/src/autogenerated/java/net/minestom/server/item/enchant/Enchantments.java +++ b/src/autogenerated/java/net/minestom/server/item/enchant/Enchantments.java @@ -1,91 +1,93 @@ package net.minestom.server.item.enchant; +import net.minestom.server.registry.DynamicRegistry; + /** * Code autogenerated, do not edit! */ @SuppressWarnings("unused") interface Enchantments { - Enchantment PROTECTION = EnchantmentImpl.get("minecraft:protection"); + DynamicRegistry.Key DEPTH_STRIDER = DynamicRegistry.Key.of("minecraft:depth_strider"); - Enchantment FIRE_PROTECTION = EnchantmentImpl.get("minecraft:fire_protection"); + DynamicRegistry.Key VANISHING_CURSE = DynamicRegistry.Key.of("minecraft:vanishing_curse"); - Enchantment FEATHER_FALLING = EnchantmentImpl.get("minecraft:feather_falling"); + DynamicRegistry.Key EFFICIENCY = DynamicRegistry.Key.of("minecraft:efficiency"); - Enchantment BLAST_PROTECTION = EnchantmentImpl.get("minecraft:blast_protection"); + DynamicRegistry.Key IMPALING = DynamicRegistry.Key.of("minecraft:impaling"); - Enchantment PROJECTILE_PROTECTION = EnchantmentImpl.get("minecraft:projectile_protection"); + DynamicRegistry.Key WIND_BURST = DynamicRegistry.Key.of("minecraft:wind_burst"); - Enchantment RESPIRATION = EnchantmentImpl.get("minecraft:respiration"); + DynamicRegistry.Key BANE_OF_ARTHROPODS = DynamicRegistry.Key.of("minecraft:bane_of_arthropods"); - Enchantment AQUA_AFFINITY = EnchantmentImpl.get("minecraft:aqua_affinity"); + DynamicRegistry.Key BINDING_CURSE = DynamicRegistry.Key.of("minecraft:binding_curse"); - Enchantment THORNS = EnchantmentImpl.get("minecraft:thorns"); + DynamicRegistry.Key PUNCH = DynamicRegistry.Key.of("minecraft:punch"); - Enchantment DEPTH_STRIDER = EnchantmentImpl.get("minecraft:depth_strider"); + DynamicRegistry.Key FLAME = DynamicRegistry.Key.of("minecraft:flame"); - Enchantment FROST_WALKER = EnchantmentImpl.get("minecraft:frost_walker"); + DynamicRegistry.Key RIPTIDE = DynamicRegistry.Key.of("minecraft:riptide"); - Enchantment BINDING_CURSE = EnchantmentImpl.get("minecraft:binding_curse"); + DynamicRegistry.Key BLAST_PROTECTION = DynamicRegistry.Key.of("minecraft:blast_protection"); - Enchantment SOUL_SPEED = EnchantmentImpl.get("minecraft:soul_speed"); + DynamicRegistry.Key FROST_WALKER = DynamicRegistry.Key.of("minecraft:frost_walker"); - Enchantment SWIFT_SNEAK = EnchantmentImpl.get("minecraft:swift_sneak"); + DynamicRegistry.Key PROTECTION = DynamicRegistry.Key.of("minecraft:protection"); - Enchantment SHARPNESS = EnchantmentImpl.get("minecraft:sharpness"); + DynamicRegistry.Key FIRE_ASPECT = DynamicRegistry.Key.of("minecraft:fire_aspect"); - Enchantment SMITE = EnchantmentImpl.get("minecraft:smite"); + DynamicRegistry.Key LOYALTY = DynamicRegistry.Key.of("minecraft:loyalty"); - Enchantment BANE_OF_ARTHROPODS = EnchantmentImpl.get("minecraft:bane_of_arthropods"); + DynamicRegistry.Key SWEEPING_EDGE = DynamicRegistry.Key.of("minecraft:sweeping_edge"); - Enchantment KNOCKBACK = EnchantmentImpl.get("minecraft:knockback"); + DynamicRegistry.Key FIRE_PROTECTION = DynamicRegistry.Key.of("minecraft:fire_protection"); - Enchantment FIRE_ASPECT = EnchantmentImpl.get("minecraft:fire_aspect"); + DynamicRegistry.Key QUICK_CHARGE = DynamicRegistry.Key.of("minecraft:quick_charge"); - Enchantment LOOTING = EnchantmentImpl.get("minecraft:looting"); + DynamicRegistry.Key RESPIRATION = DynamicRegistry.Key.of("minecraft:respiration"); - Enchantment SWEEPING_EDGE = EnchantmentImpl.get("minecraft:sweeping_edge"); + DynamicRegistry.Key LUCK_OF_THE_SEA = DynamicRegistry.Key.of("minecraft:luck_of_the_sea"); - Enchantment EFFICIENCY = EnchantmentImpl.get("minecraft:efficiency"); + DynamicRegistry.Key SOUL_SPEED = DynamicRegistry.Key.of("minecraft:soul_speed"); - Enchantment SILK_TOUCH = EnchantmentImpl.get("minecraft:silk_touch"); + DynamicRegistry.Key DENSITY = DynamicRegistry.Key.of("minecraft:density"); - Enchantment UNBREAKING = EnchantmentImpl.get("minecraft:unbreaking"); + DynamicRegistry.Key POWER = DynamicRegistry.Key.of("minecraft:power"); - Enchantment FORTUNE = EnchantmentImpl.get("minecraft:fortune"); + DynamicRegistry.Key SILK_TOUCH = DynamicRegistry.Key.of("minecraft:silk_touch"); - Enchantment POWER = EnchantmentImpl.get("minecraft:power"); + DynamicRegistry.Key CHANNELING = DynamicRegistry.Key.of("minecraft:channeling"); - Enchantment PUNCH = EnchantmentImpl.get("minecraft:punch"); + DynamicRegistry.Key FORTUNE = DynamicRegistry.Key.of("minecraft:fortune"); - Enchantment FLAME = EnchantmentImpl.get("minecraft:flame"); + DynamicRegistry.Key LOOTING = DynamicRegistry.Key.of("minecraft:looting"); - Enchantment INFINITY = EnchantmentImpl.get("minecraft:infinity"); + DynamicRegistry.Key BREACH = DynamicRegistry.Key.of("minecraft:breach"); - Enchantment LUCK_OF_THE_SEA = EnchantmentImpl.get("minecraft:luck_of_the_sea"); + DynamicRegistry.Key PIERCING = DynamicRegistry.Key.of("minecraft:piercing"); - Enchantment LURE = EnchantmentImpl.get("minecraft:lure"); + DynamicRegistry.Key MENDING = DynamicRegistry.Key.of("minecraft:mending"); - Enchantment LOYALTY = EnchantmentImpl.get("minecraft:loyalty"); + DynamicRegistry.Key FEATHER_FALLING = DynamicRegistry.Key.of("minecraft:feather_falling"); - Enchantment IMPALING = EnchantmentImpl.get("minecraft:impaling"); + DynamicRegistry.Key SHARPNESS = DynamicRegistry.Key.of("minecraft:sharpness"); - Enchantment RIPTIDE = EnchantmentImpl.get("minecraft:riptide"); + DynamicRegistry.Key KNOCKBACK = DynamicRegistry.Key.of("minecraft:knockback"); - Enchantment CHANNELING = EnchantmentImpl.get("minecraft:channeling"); + DynamicRegistry.Key SMITE = DynamicRegistry.Key.of("minecraft:smite"); - Enchantment MULTISHOT = EnchantmentImpl.get("minecraft:multishot"); + DynamicRegistry.Key INFINITY = DynamicRegistry.Key.of("minecraft:infinity"); - Enchantment QUICK_CHARGE = EnchantmentImpl.get("minecraft:quick_charge"); + DynamicRegistry.Key PROJECTILE_PROTECTION = DynamicRegistry.Key.of("minecraft:projectile_protection"); - Enchantment PIERCING = EnchantmentImpl.get("minecraft:piercing"); + DynamicRegistry.Key THORNS = DynamicRegistry.Key.of("minecraft:thorns"); - Enchantment DENSITY = EnchantmentImpl.get("minecraft:density"); + DynamicRegistry.Key AQUA_AFFINITY = DynamicRegistry.Key.of("minecraft:aqua_affinity"); - Enchantment BREACH = EnchantmentImpl.get("minecraft:breach"); + DynamicRegistry.Key LURE = DynamicRegistry.Key.of("minecraft:lure"); - Enchantment WIND_BURST = EnchantmentImpl.get("minecraft:wind_burst"); + DynamicRegistry.Key MULTISHOT = DynamicRegistry.Key.of("minecraft:multishot"); - Enchantment MENDING = EnchantmentImpl.get("minecraft:mending"); + DynamicRegistry.Key SWIFT_SNEAK = DynamicRegistry.Key.of("minecraft:swift_sneak"); - Enchantment VANISHING_CURSE = EnchantmentImpl.get("minecraft:vanishing_curse"); + DynamicRegistry.Key UNBREAKING = DynamicRegistry.Key.of("minecraft:unbreaking"); } diff --git a/src/autogenerated/java/net/minestom/server/sound/SoundEvents.java b/src/autogenerated/java/net/minestom/server/sound/SoundEvents.java index 0947fdba6..f886a7aa7 100644 --- a/src/autogenerated/java/net/minestom/server/sound/SoundEvents.java +++ b/src/autogenerated/java/net/minestom/server/sound/SoundEvents.java @@ -1371,11 +1371,11 @@ interface SoundEvents { SoundEvent BLOCK_TRIAL_SPAWNER_DETECT_PLAYER = BuiltinSoundEvent.get("minecraft:block.trial_spawner.detect_player"); - SoundEvent BLOCK_TRIAL_SPAWNER_CHARGE_ACTIVATE = BuiltinSoundEvent.get("minecraft:block.trial_spawner.charge_activate"); + SoundEvent BLOCK_TRIAL_SPAWNER_OMINOUS_ACTIVATE = BuiltinSoundEvent.get("minecraft:block.trial_spawner.ominous_activate"); SoundEvent BLOCK_TRIAL_SPAWNER_AMBIENT = BuiltinSoundEvent.get("minecraft:block.trial_spawner.ambient"); - SoundEvent BLOCK_TRIAL_SPAWNER_AMBIENT_CHARGED = BuiltinSoundEvent.get("minecraft:block.trial_spawner.ambient_charged"); + SoundEvent BLOCK_TRIAL_SPAWNER_AMBIENT_OMINOUS = BuiltinSoundEvent.get("minecraft:block.trial_spawner.ambient_ominous"); SoundEvent BLOCK_TRIAL_SPAWNER_OPEN_SHUTTER = BuiltinSoundEvent.get("minecraft:block.trial_spawner.open_shutter"); @@ -1777,6 +1777,12 @@ interface SoundEvents { SoundEvent MUSIC_DISC_RELIC = BuiltinSoundEvent.get("minecraft:music_disc.relic"); + SoundEvent MUSIC_DISC_CREATOR = BuiltinSoundEvent.get("minecraft:music_disc.creator"); + + SoundEvent MUSIC_DISC_CREATOR_MUSIC_BOX = BuiltinSoundEvent.get("minecraft:music_disc.creator_music_box"); + + SoundEvent MUSIC_DISC_PRECIPICE = BuiltinSoundEvent.get("minecraft:music_disc.precipice"); + SoundEvent MUSIC_DRAGON = BuiltinSoundEvent.get("minecraft:music.dragon"); SoundEvent MUSIC_END = BuiltinSoundEvent.get("minecraft:music.end"); @@ -2883,6 +2889,8 @@ interface SoundEvents { SoundEvent BLOCK_VAULT_EJECT_ITEM = BuiltinSoundEvent.get("minecraft:block.vault.eject_item"); + SoundEvent BLOCK_VAULT_REJECT_REWARDED_PLAYER = BuiltinSoundEvent.get("minecraft:block.vault.reject_rewarded_player"); + SoundEvent BLOCK_VAULT_FALL = BuiltinSoundEvent.get("minecraft:block.vault.fall"); SoundEvent BLOCK_VAULT_HIT = BuiltinSoundEvent.get("minecraft:block.vault.hit"); diff --git a/src/main/java/net/minestom/server/MinecraftServer.java b/src/main/java/net/minestom/server/MinecraftServer.java index 28aed186b..58c2a5b96 100644 --- a/src/main/java/net/minestom/server/MinecraftServer.java +++ b/src/main/java/net/minestom/server/MinecraftServer.java @@ -6,14 +6,17 @@ import net.minestom.server.adventure.bossbar.BossBarManager; import net.minestom.server.command.CommandManager; import net.minestom.server.entity.damage.DamageType; import net.minestom.server.entity.metadata.animal.tameable.WolfMeta; +import net.minestom.server.entity.metadata.other.PaintingMeta; import net.minestom.server.event.GlobalEventHandler; import net.minestom.server.exception.ExceptionManager; import net.minestom.server.gamedata.tags.TagManager; import net.minestom.server.instance.InstanceManager; import net.minestom.server.instance.block.BlockManager; import net.minestom.server.instance.block.banner.BannerPattern; +import net.minestom.server.instance.block.jukebox.JukeboxSong; import net.minestom.server.item.armor.TrimMaterial; import net.minestom.server.item.armor.TrimPattern; +import net.minestom.server.item.enchant.Enchantment; import net.minestom.server.listener.manager.PacketListenerManager; import net.minestom.server.message.ChatType; import net.minestom.server.monitoring.BenchmarkManager; @@ -46,14 +49,10 @@ import java.net.SocketAddress; * The server needs to be initialized with {@link #init()} and started with {@link #start(String, int)}. * You should register all of your dimensions, biomes, commands, events, etc... in-between. */ -public final class MinecraftServer { +public final class MinecraftServer implements MinecraftConstants { public static final ComponentLogger LOGGER = ComponentLogger.logger(MinecraftServer.class); - public static final String VERSION_NAME = "1.20.6"; - public static final int PROTOCOL_VERSION = 766; - public static final int DATA_VERSION = 3839; - // Threads public static final String THREAD_NAME_BENCHMARK = "Ms-Benchmark"; @@ -287,6 +286,18 @@ public final class MinecraftServer { return serverProcess.wolfVariant(); } + public static @NotNull DynamicRegistry getEnchantmentRegistry() { + return serverProcess.enchantment(); + } + + public static @NotNull DynamicRegistry getPaintingVariantRegistry() { + return serverProcess.paintingVariant(); + } + + public static @NotNull DynamicRegistry getJukeboxSongRegistry() { + return serverProcess.jukeboxSong(); + } + public static Server getServer() { return serverProcess.server(); } diff --git a/src/main/java/net/minestom/server/ServerProcessImpl.java b/src/main/java/net/minestom/server/ServerProcessImpl.java index 9ae36f889..fbad727bf 100644 --- a/src/main/java/net/minestom/server/ServerProcessImpl.java +++ b/src/main/java/net/minestom/server/ServerProcessImpl.java @@ -7,6 +7,7 @@ import net.minestom.server.command.CommandManager; import net.minestom.server.entity.Entity; import net.minestom.server.entity.damage.DamageType; import net.minestom.server.entity.metadata.animal.tameable.WolfMeta; +import net.minestom.server.entity.metadata.other.PaintingMeta; import net.minestom.server.event.EventDispatcher; import net.minestom.server.event.GlobalEventHandler; import net.minestom.server.event.server.ServerTickMonitorEvent; @@ -17,8 +18,10 @@ import net.minestom.server.instance.Instance; import net.minestom.server.instance.InstanceManager; import net.minestom.server.instance.block.BlockManager; import net.minestom.server.instance.block.banner.BannerPattern; +import net.minestom.server.instance.block.jukebox.JukeboxSong; import net.minestom.server.item.armor.TrimMaterial; import net.minestom.server.item.armor.TrimPattern; +import net.minestom.server.item.enchant.Enchantment; import net.minestom.server.listener.manager.PacketListenerManager; import net.minestom.server.message.ChatType; import net.minestom.server.monitoring.BenchmarkManager; @@ -63,6 +66,9 @@ final class ServerProcessImpl implements ServerProcess { private final DynamicRegistry trimPattern; private final DynamicRegistry bannerPattern; private final DynamicRegistry wolfVariant; + private final DynamicRegistry enchantment; + private final DynamicRegistry paintingVariant; + private final DynamicRegistry jukeboxSong; private final ConnectionManager connection; private final PacketListenerManager packetListener; @@ -98,6 +104,9 @@ final class ServerProcessImpl implements ServerProcess { this.trimPattern = TrimPattern.createDefaultRegistry(); this.bannerPattern = BannerPattern.createDefaultRegistry(); this.wolfVariant = WolfMeta.Variant.createDefaultRegistry(); + this.enchantment = Enchantment.createDefaultRegistry(); + this.paintingVariant = PaintingMeta.Variant.createDefaultRegistry(); + this.jukeboxSong = JukeboxSong.createDefaultRegistry(); this.connection = new ConnectionManager(); this.packetListener = new PacketListenerManager(); @@ -150,6 +159,21 @@ final class ServerProcessImpl implements ServerProcess { return wolfVariant; } + @Override + public @NotNull DynamicRegistry enchantment() { + return enchantment; + } + + @Override + public @NotNull DynamicRegistry paintingVariant() { + return paintingVariant; + } + + @Override + public @NotNull DynamicRegistry jukeboxSong() { + return jukeboxSong; + } + @Override public @NotNull ConnectionManager connection() { return connection; diff --git a/src/main/java/net/minestom/server/command/builder/arguments/minecraft/registry/ArgumentEnchantment.java b/src/main/java/net/minestom/server/command/builder/arguments/minecraft/registry/ArgumentEnchantment.java index aee915c3d..4d0609af4 100644 --- a/src/main/java/net/minestom/server/command/builder/arguments/minecraft/registry/ArgumentEnchantment.java +++ b/src/main/java/net/minestom/server/command/builder/arguments/minecraft/registry/ArgumentEnchantment.java @@ -1,12 +1,13 @@ package net.minestom.server.command.builder.arguments.minecraft.registry; import net.minestom.server.item.enchant.Enchantment; +import net.minestom.server.registry.DynamicRegistry; import org.jetbrains.annotations.NotNull; /** * Represents an argument giving an {@link Enchantment}. */ -public class ArgumentEnchantment extends ArgumentRegistry { +public class ArgumentEnchantment extends ArgumentRegistry> { public ArgumentEnchantment(String id) { super(id); @@ -18,8 +19,9 @@ public class ArgumentEnchantment extends ArgumentRegistry { } @Override - public Enchantment getRegistry(@NotNull String value) { - return Enchantment.fromNamespaceId(value); + public DynamicRegistry.Key getRegistry(@NotNull String value) { +// return Enchantment.fromNamespaceId(value); + throw new UnsupportedOperationException("todo"); } @Override diff --git a/src/main/java/net/minestom/server/entity/Metadata.java b/src/main/java/net/minestom/server/entity/Metadata.java index 367db67d1..f86dbf2aa 100644 --- a/src/main/java/net/minestom/server/entity/Metadata.java +++ b/src/main/java/net/minestom/server/entity/Metadata.java @@ -146,13 +146,11 @@ public final class Metadata { return new MetadataImpl.EntryImpl<>(TYPE_WOLF_VARIANT, value, WolfMeta.Variant.NETWORK_TYPE); } - // WOLF VARIANT - public static Entry FrogVariant(@NotNull FrogMeta.Variant value) { return new MetadataImpl.EntryImpl<>(TYPE_FROG_VARIANT, value, FrogMeta.Variant.NETWORK_TYPE); } - public static Entry PaintingVariant(@NotNull PaintingMeta.Variant value) { + public static Entry> PaintingVariant(@NotNull DynamicRegistry.Key value) { return new MetadataImpl.EntryImpl<>(TYPE_PAINTING_VARIANT, value, PaintingMeta.Variant.NETWORK_TYPE); } diff --git a/src/main/java/net/minestom/server/entity/attribute/AttributeImpl.java b/src/main/java/net/minestom/server/entity/attribute/AttributeImpl.java index 41209852a..89ba36f58 100644 --- a/src/main/java/net/minestom/server/entity/attribute/AttributeImpl.java +++ b/src/main/java/net/minestom/server/entity/attribute/AttributeImpl.java @@ -1,8 +1,6 @@ package net.minestom.server.entity.attribute; -import net.minestom.server.network.NetworkBuffer; import net.minestom.server.registry.Registry; -import net.minestom.server.utils.nbt.BinaryTagSerializer; import org.jetbrains.annotations.NotNull; import java.util.Collection; diff --git a/src/main/java/net/minestom/server/entity/attribute/AttributeInstance.java b/src/main/java/net/minestom/server/entity/attribute/AttributeInstance.java index 6c1c9f98c..6f5a3b0ad 100644 --- a/src/main/java/net/minestom/server/entity/attribute/AttributeInstance.java +++ b/src/main/java/net/minestom/server/entity/attribute/AttributeInstance.java @@ -1,28 +1,52 @@ package net.minestom.server.entity.attribute; +import net.minestom.server.network.NetworkBuffer; +import net.minestom.server.utils.NamespaceID; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; +import java.util.*; import java.util.function.Consumer; /** * Represents an instance of an attribute and its modifiers. */ public final class AttributeInstance { + public static final NetworkBuffer.Type NETWORK_TYPE = new NetworkBuffer.Type<>() { + @Override + public void write(@NotNull NetworkBuffer buffer, AttributeInstance value) { + buffer.write(Attribute.NETWORK_TYPE, value.attribute()); + buffer.write(NetworkBuffer.DOUBLE, value.getBaseValue()); + buffer.writeCollection(AttributeModifier.NETWORK_TYPE, value.modifiers()); + } + + @Override + public AttributeInstance read(@NotNull NetworkBuffer buffer) { + return new AttributeInstance(buffer.read(Attribute.NETWORK_TYPE), buffer.read(NetworkBuffer.DOUBLE), + buffer.readCollection(AttributeModifier.NETWORK_TYPE, Short.MAX_VALUE), null); + } + }; + private final Attribute attribute; - private final Map modifiers = new HashMap<>(); - private final Consumer propertyChangeListener; + private final Map modifiers; + private final Collection unmodifiableModifiers; private double baseValue; + + private final Consumer propertyChangeListener; private double cachedValue = 0.0f; public AttributeInstance(@NotNull Attribute attribute, @Nullable Consumer listener) { + this(attribute, attribute.defaultValue(), new ArrayList<>(), listener); + } + + public AttributeInstance(@NotNull Attribute attribute, double baseValue, @NotNull Collection modifiers, @Nullable Consumer listener) { this.attribute = attribute; + this.modifiers = new HashMap<>(); + for (var modifier : modifiers) this.modifiers.put(modifier.id(), modifier); + this.unmodifiableModifiers = Collections.unmodifiableCollection(this.modifiers.values()); + this.baseValue = baseValue; + this.propertyChangeListener = listener; - this.baseValue = attribute.defaultValue(); refreshCachedValue(); } @@ -31,7 +55,7 @@ public final class AttributeInstance { * * @return the associated attribute */ - public @NotNull Attribute getAttribute() { + public @NotNull Attribute attribute() { return attribute; } @@ -58,13 +82,23 @@ public final class AttributeInstance { } } + /** + * Get the modifiers applied to this instance. + * + * @return an immutable collection of the modifiers applied to this attribute. + */ + @NotNull + public Collection modifiers() { + return unmodifiableModifiers; + } + /** * Add a modifier to this instance. * * @param modifier the modifier to add */ public void addModifier(@NotNull AttributeModifier modifier) { - if (modifiers.putIfAbsent(modifier.getId(), modifier) == null) { + if (modifiers.putIfAbsent(modifier.id(), modifier) == null) { refreshCachedValue(); } } @@ -75,7 +109,7 @@ public final class AttributeInstance { * @param modifier the modifier to remove */ public void removeModifier(@NotNull AttributeModifier modifier) { - removeModifier(modifier.getId()); + removeModifier(modifier.id()); } /** @@ -83,22 +117,12 @@ public final class AttributeInstance { * * @param uuid The UUID of the modifier to remove */ - public void removeModifier(@NotNull UUID uuid) { - if (modifiers.remove(uuid) != null) { + public void removeModifier(@NotNull NamespaceID id) { + if (modifiers.remove(id) != null) { refreshCachedValue(); } } - /** - * Get the modifiers applied to this instance. - * - * @return the modifiers. - */ - @NotNull - public Collection getModifiers() { - return modifiers.values(); - } - /** * Gets the value of this instance calculated with modifiers applied. * @@ -115,17 +139,17 @@ public final class AttributeInstance { final Collection modifiers = getModifiers(); double base = getBaseValue(); - for (var modifier : modifiers.stream().filter(mod -> mod.getOperation() == AttributeOperation.ADD_VALUE).toArray(AttributeModifier[]::new)) { - base += modifier.getAmount(); + for (var modifier : modifiers.stream().filter(mod -> mod.operation() == AttributeOperation.ADD_VALUE).toArray(AttributeModifier[]::new)) { + base += modifier.amount(); } double result = base; - for (var modifier : modifiers.stream().filter(mod -> mod.getOperation() == AttributeOperation.MULTIPLY_BASE).toArray(AttributeModifier[]::new)) { - result += (base * modifier.getAmount()); + for (var modifier : modifiers.stream().filter(mod -> mod.operation() == AttributeOperation.MULTIPLY_BASE).toArray(AttributeModifier[]::new)) { + result += (base * modifier.amount()); } - for (var modifier : modifiers.stream().filter(mod -> mod.getOperation() == AttributeOperation.MULTIPLY_TOTAL).toArray(AttributeModifier[]::new)) { - result *= (1.0f + modifier.getAmount()); + for (var modifier : modifiers.stream().filter(mod -> mod.operation() == AttributeOperation.MULTIPLY_TOTAL).toArray(AttributeModifier[]::new)) { + result *= (1.0f + modifier.amount()); } this.cachedValue = Math.clamp(result, getAttribute().minValue(), getAttribute().maxValue()); @@ -135,4 +159,15 @@ public final class AttributeInstance { propertyChangeListener.accept(this); } } + + @Deprecated + @NotNull + public Collection getModifiers() { + return modifiers(); + } + + @Deprecated + public @NotNull Attribute getAttribute() { + return attribute; + } } diff --git a/src/main/java/net/minestom/server/entity/attribute/AttributeModifier.java b/src/main/java/net/minestom/server/entity/attribute/AttributeModifier.java index c25827bf9..dd2cfba9e 100644 --- a/src/main/java/net/minestom/server/entity/attribute/AttributeModifier.java +++ b/src/main/java/net/minestom/server/entity/attribute/AttributeModifier.java @@ -1,81 +1,48 @@ package net.minestom.server.entity.attribute; +import net.kyori.adventure.nbt.CompoundBinaryTag; import net.minestom.server.network.NetworkBuffer; +import net.minestom.server.utils.NamespaceID; +import net.minestom.server.utils.nbt.BinaryTagSerializer; import org.jetbrains.annotations.NotNull; -import java.util.UUID; - /** * Represent an attribute modifier. */ -public record AttributeModifier( - @NotNull UUID id, - @NotNull String name, - double amount, - @NotNull AttributeOperation operation -) implements NetworkBuffer.Writer { +public record AttributeModifier(@NotNull NamespaceID id, double amount, @NotNull AttributeOperation operation) { + public static final NetworkBuffer.Type NETWORK_TYPE = new NetworkBuffer.Type<>() { + @Override + public void write(@NotNull NetworkBuffer buffer, AttributeModifier value) { + buffer.write(NetworkBuffer.STRING, value.id.asString()); + buffer.write(NetworkBuffer.DOUBLE, value.amount); + buffer.write(AttributeOperation.NETWORK_TYPE, value.operation); + } + + @Override + public AttributeModifier read(@NotNull NetworkBuffer buffer) { + return new AttributeModifier(NamespaceID.from(buffer.read(NetworkBuffer.STRING)), + buffer.read(NetworkBuffer.DOUBLE), buffer.read(AttributeOperation.NETWORK_TYPE)); + } + }; + public static final BinaryTagSerializer NBT_TYPE = BinaryTagSerializer.COMPOUND.map( + tag -> new AttributeModifier(NamespaceID.from(tag.getString("id")), tag.getDouble("amount"), + AttributeOperation.NBT_TYPE.read(tag.get("operation"))), + value -> CompoundBinaryTag.builder() + .putString("id", value.id.asString()) + .putDouble("amount", value.amount) + .put("operation", AttributeOperation.NBT_TYPE.write(value.operation)) + .build() + ); /** * Creates a new modifier with a random id. * - * @param name the name of this modifier + * @param id the (namespace) id of this modifier * @param amount the value of this modifier * @param operation the operation to apply this modifier with */ - public AttributeModifier(@NotNull String name, double amount, @NotNull AttributeOperation operation) { - this(UUID.randomUUID(), name, amount, operation); + public AttributeModifier(@NotNull String id, double amount, @NotNull AttributeOperation operation) { + this(NamespaceID.from(id), amount, operation); } - public AttributeModifier(@NotNull NetworkBuffer reader) { - this(reader.read(NetworkBuffer.UUID), reader.read(NetworkBuffer.STRING), - reader.read(NetworkBuffer.DOUBLE), reader.readEnum(AttributeOperation.class)); - } - - @Override - public void write(@NotNull NetworkBuffer writer) { - writer.write(NetworkBuffer.UUID, id); - writer.write(NetworkBuffer.STRING, name); - writer.write(NetworkBuffer.DOUBLE, amount); - writer.writeEnum(AttributeOperation.class, operation); - } - - /** - * Gets the id of this modifier. - * - * @return the id of this modifier - */ - @Deprecated - public @NotNull UUID getId() { - return id; - } - - /** - * Gets the name of this modifier. - * - * @return the name of this modifier - */ - @Deprecated - public @NotNull String getName() { - return name; - } - - /** - * Gets the value of this modifier. - * - * @return the value of this modifier - */ - @Deprecated - public double getAmount() { - return amount; - } - - /** - * Gets the operation of this modifier. - * - * @return the operation of this modifier - */ - @Deprecated - public @NotNull AttributeOperation getOperation() { - return operation; - } } diff --git a/src/main/java/net/minestom/server/entity/attribute/AttributeOperation.java b/src/main/java/net/minestom/server/entity/attribute/AttributeOperation.java index 2a66e7d04..c19da8b12 100644 --- a/src/main/java/net/minestom/server/entity/attribute/AttributeOperation.java +++ b/src/main/java/net/minestom/server/entity/attribute/AttributeOperation.java @@ -1,5 +1,7 @@ package net.minestom.server.entity.attribute; +import net.minestom.server.network.NetworkBuffer; +import net.minestom.server.utils.nbt.BinaryTagSerializer; import org.jetbrains.annotations.Nullable; public enum AttributeOperation { @@ -7,6 +9,9 @@ public enum AttributeOperation { MULTIPLY_BASE(1), MULTIPLY_TOTAL(2); + public static final NetworkBuffer.Type NETWORK_TYPE = NetworkBuffer.Enum(AttributeOperation.class); + public static final BinaryTagSerializer NBT_TYPE = BinaryTagSerializer.fromEnumStringable(AttributeOperation.class); + private static final AttributeOperation[] VALUES = new AttributeOperation[]{ADD_VALUE, MULTIPLY_BASE, MULTIPLY_TOTAL}; private final int id; diff --git a/src/main/java/net/minestom/server/entity/metadata/other/PaintingMeta.java b/src/main/java/net/minestom/server/entity/metadata/other/PaintingMeta.java index 9b8b071bb..7475484eb 100644 --- a/src/main/java/net/minestom/server/entity/metadata/other/PaintingMeta.java +++ b/src/main/java/net/minestom/server/entity/metadata/other/PaintingMeta.java @@ -1,18 +1,23 @@ package net.minestom.server.entity.metadata.other; +import net.kyori.adventure.nbt.CompoundBinaryTag; import net.minestom.server.entity.Entity; import net.minestom.server.entity.Metadata; import net.minestom.server.entity.metadata.EntityMeta; import net.minestom.server.entity.metadata.ObjectDataProvider; import net.minestom.server.network.NetworkBuffer; -import net.minestom.server.registry.StaticProtocolObject; +import net.minestom.server.registry.DynamicRegistry; +import net.minestom.server.registry.ProtocolObject; +import net.minestom.server.registry.Registries; +import net.minestom.server.registry.Registry; import net.minestom.server.utils.NamespaceID; +import net.minestom.server.utils.nbt.BinaryTagSerializer; import net.minestom.server.utils.validate.Check; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Locale; - public class PaintingMeta extends EntityMeta implements ObjectDataProvider { public static final byte OFFSET = EntityMeta.MAX_OFFSET; public static final byte MAX_OFFSET = OFFSET + 1; @@ -23,11 +28,11 @@ public class PaintingMeta extends EntityMeta implements ObjectDataProvider { super(entity, metadata); } - public @NotNull Variant getVariant() { + public @NotNull DynamicRegistry.Key getVariant() { return super.metadata.getIndex(OFFSET, Variant.KEBAB); } - public void setVariant(@NotNull Variant value) { + public void setVariant(@NotNull DynamicRegistry.Key value) { super.metadata.setIndex(OFFSET, Metadata.PaintingVariant(value)); } @@ -74,90 +79,110 @@ public class PaintingMeta extends EntityMeta implements ObjectDataProvider { } } - public enum Variant implements StaticProtocolObject { - KEBAB(16, 16), - AZTEC(16, 16), - ALBAN(16, 16), - AZTEC2(16, 16), - BOMB(16, 16), - PLANT(16, 16), - WASTELAND(16, 16), - POOL(32, 16), - COURBET(32, 16), - SEA(32, 16), - SUNSET(32, 16), - CREEBET(32, 16), - WANDERER(16, 32), - GRAHAM(16, 32), - MATCH(32, 32), - BUST(32, 32), - STAGE(32, 32), - VOID(32, 32), - SKULL_AND_ROSES(32, 32), - WITHER(32, 32), - FIGHTERS(64, 32), - POINTER(64, 64), - PIGSCENE(64, 64), - BURNING_SKULL(64, 64), - SKELETON(64, 48), - EARTH(32, 32), - WIND(32, 32), - WATER(32, 32), - FIRE(32, 32), - DONKEY_KONG(64, 48); + public sealed interface Variant extends ProtocolObject, PaintingVariants permits VariantImpl { + @NotNull NetworkBuffer.Type> NETWORK_TYPE = NetworkBuffer.RegistryKey(Registries::paintingVariant); + @NotNull BinaryTagSerializer> NBT_TYPE = BinaryTagSerializer.registryKey(Registries::paintingVariant); - public static final NetworkBuffer.Type NETWORK_TYPE = NetworkBuffer.Enum(Variant.class); - - private static final Variant[] VALUES = values(); - - public static @Nullable Variant fromId(int id) { - if (id < 0 || id >= VALUES.length) { - return null; - } - return VALUES[id]; + static @NotNull Variant create( + @NotNull NamespaceID namespace, + @NotNull NamespaceID assetId, + int width, int height + ) { + return new VariantImpl(namespace, assetId, width, height, null); } - public static @Nullable Variant fromNamespaceId(@Nullable String namespaceId) { - if (namespaceId == null) return null; - return fromNamespaceId(NamespaceID.from(namespaceId)); + static @NotNull Builder builder(@NotNull String namespace) { + return builder(NamespaceID.from(namespace)); } - public static @Nullable Variant fromNamespaceId(@Nullable NamespaceID namespaceId) { - if (namespaceId == null) return null; - for (Variant value : VALUES) { - if (value.namespace().equals(namespaceId)) { - return value; - } - } - return null; + static @NotNull Builder builder(@NotNull NamespaceID namespace) { + return new Builder(namespace); } - private final NamespaceID namespace; - private final int width; - private final int height; - - Variant(int width, int height) { - this.namespace = NamespaceID.from("minecraft", name().toLowerCase(Locale.ROOT)); - this.width = width; - this.height = height; + /** + *

Creates a new registry for painting variants, loading the vanilla painting variants.

+ * + * @see net.minestom.server.MinecraftServer to get an existing instance of the registry + */ + @ApiStatus.Internal + static @NotNull DynamicRegistry createDefaultRegistry() { + return DynamicRegistry.create( + "minecraft:painting_variant", VariantImpl.REGISTRY_NBT_TYPE, Registry.Resource.PAINTING_VARIANTS, + (namespace, props) -> new VariantImpl(Registry.paintingVariant(namespace, props)) + ); } + @NotNull NamespaceID assetId(); + + int width(); + + int height(); + @Override - public int id() { - return ordinal(); + @Nullable Registry.PaintingVariantEntry registry(); + + class Builder { + private final NamespaceID namespace; + private NamespaceID assetId; + private int width; + private int height; + + private Builder(@NotNull NamespaceID namespace) { + this.namespace = namespace; + } + + @Contract(value = "_ -> this", pure = true) + public @NotNull Builder assetId(@NotNull NamespaceID assetId) { + this.assetId = assetId; + return this; + } + + @Contract(value = "_ -> this", pure = true) + public @NotNull Builder width(int width) { + this.width = width; + return this; + } + + @Contract(value = "_ -> this", pure = true) + public @NotNull Builder height(int height) { + this.height = height; + return this; + } + + public @NotNull Variant build() { + return new VariantImpl(namespace, assetId, width, height, null); + } + } + } + + record VariantImpl( + @NotNull NamespaceID namespace, + @NotNull NamespaceID assetId, + int width, + int height, + @Nullable Registry.PaintingVariantEntry registry + ) implements Variant { + private static final BinaryTagSerializer REGISTRY_NBT_TYPE = BinaryTagSerializer.COMPOUND.map( + tag -> { + throw new UnsupportedOperationException("PaintingVariant is read-only"); + }, + variant -> CompoundBinaryTag.builder() + .putString("asset_id", variant.assetId().asString()) + .putInt("width", variant.width()) + .putInt("height", variant.height()) + .build() + ); + + @SuppressWarnings("ConstantValue") // The builder can violate the nullability constraints + VariantImpl { + Check.notNull(namespace, "Namespace cannot be null"); + Check.argCondition(assetId == null, "missing asset id: {0}", namespace); + Check.argCondition(width <= 0, "width must be positive: {0}", namespace); + Check.argCondition(height <= 0, "height must be positive: {0}", namespace); } - public int width() { - return width; - } - - public int height() { - return height; - } - - @Override - public @NotNull NamespaceID namespace() { - return namespace; + VariantImpl(@NotNull Registry.PaintingVariantEntry registry) { + this(registry.namespace(), registry.assetId(), registry.width(), registry.height(), registry); } } diff --git a/src/main/java/net/minestom/server/instance/block/jukebox/JukeboxSong.java b/src/main/java/net/minestom/server/instance/block/jukebox/JukeboxSong.java new file mode 100644 index 000000000..08231a0dd --- /dev/null +++ b/src/main/java/net/minestom/server/instance/block/jukebox/JukeboxSong.java @@ -0,0 +1,99 @@ +package net.minestom.server.instance.block.jukebox; + +import net.kyori.adventure.text.Component; +import net.minestom.server.network.NetworkBuffer; +import net.minestom.server.registry.DynamicRegistry; +import net.minestom.server.registry.ProtocolObject; +import net.minestom.server.registry.Registries; +import net.minestom.server.registry.Registry; +import net.minestom.server.sound.SoundEvent; +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 JukeboxSong extends ProtocolObject, JukeboxSongs permits JukeboxSongImpl { + + @NotNull NetworkBuffer.Type> NETWORK_TYPE = NetworkBuffer.RegistryKey(Registries::jukeboxSong); + @NotNull BinaryTagSerializer> NBT_TYPE = BinaryTagSerializer.registryKey(Registries::jukeboxSong); + + static @NotNull JukeboxSong create( + @NotNull NamespaceID namespace, + @NotNull SoundEvent soundEvent, + @NotNull Component description, + float lengthInSeconds, + int comparatorOutput + ) { + return new JukeboxSongImpl(namespace, soundEvent, description, lengthInSeconds, comparatorOutput, null); + } + + static @NotNull Builder builder(@NotNull String namespace) { + return builder(NamespaceID.from(namespace)); + } + + static @NotNull Builder builder(@NotNull NamespaceID namespace) { + return new Builder(namespace); + } + + /** + *

Creates a new registry for banner patterns, loading the vanilla banner patterns.

+ * + * @see net.minestom.server.MinecraftServer to get an existing instance of the registry + */ + @ApiStatus.Internal + static @NotNull DynamicRegistry createDefaultRegistry() { + return DynamicRegistry.create( + "minecraft:jukebox_song", JukeboxSongImpl.REGISTRY_NBT_TYPE, Registry.Resource.JUKEBOX_SONGS, + (namespace, props) -> new JukeboxSongImpl(Registry.jukeboxSong(namespace, props)) + ); + } + + @NotNull SoundEvent soundEvent(); + + @NotNull Component description(); + + float lengthInSeconds(); + + int comparatorOutput(); + + @Override + @Nullable Registry.JukeboxSongEntry registry(); + + final class Builder { + private final NamespaceID namespace; + private SoundEvent soundEvent; + private Component description; + private float lengthInSeconds; + private int comparatorOutput = 0; + + private Builder(@NotNull NamespaceID namespace) { + this.namespace = namespace; + } + + public @NotNull Builder soundEvent(@NotNull SoundEvent soundEvent) { + this.soundEvent = soundEvent; + return this; + } + + public @NotNull Builder description(@NotNull Component description) { + this.description = description; + return this; + } + + public @NotNull Builder lengthInSeconds(float lengthInSeconds) { + this.lengthInSeconds = lengthInSeconds; + return this; + } + + public @NotNull Builder comparatorOutput(int comparatorOutput) { + this.comparatorOutput = comparatorOutput; + return this; + } + + public @NotNull JukeboxSong build() { + return new JukeboxSongImpl(namespace, soundEvent, description, lengthInSeconds, comparatorOutput, null); + } + } + +} diff --git a/src/main/java/net/minestom/server/instance/block/jukebox/JukeboxSongImpl.java b/src/main/java/net/minestom/server/instance/block/jukebox/JukeboxSongImpl.java new file mode 100644 index 000000000..b29924711 --- /dev/null +++ b/src/main/java/net/minestom/server/instance/block/jukebox/JukeboxSongImpl.java @@ -0,0 +1,45 @@ +package net.minestom.server.instance.block.jukebox; + +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.kyori.adventure.text.Component; +import net.minestom.server.registry.Registry; +import net.minestom.server.sound.SoundEvent; +import net.minestom.server.utils.NamespaceID; +import net.minestom.server.utils.nbt.BinaryTagSerializer; +import net.minestom.server.utils.validate.Check; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +record JukeboxSongImpl( + @NotNull NamespaceID namespace, + @NotNull SoundEvent soundEvent, + @NotNull Component description, + float lengthInSeconds, + int comparatorOutput, + @Nullable Registry.JukeboxSongEntry registry +) implements JukeboxSong { + + static final BinaryTagSerializer REGISTRY_NBT_TYPE = BinaryTagSerializer.COMPOUND.map( + tag -> { + throw new UnsupportedOperationException("JukeboxSong is read-only"); + }, + jukeboxSong -> CompoundBinaryTag.builder() + .putString("sound_event", jukeboxSong.soundEvent().name()) + .put("description", BinaryTagSerializer.NBT_COMPONENT.write(jukeboxSong.description())) + .putFloat("length_in_seconds", jukeboxSong.lengthInSeconds()) + .putInt("comparator_output", jukeboxSong.comparatorOutput()) + .build() + ); + + @SuppressWarnings("ConstantValue") // The builder can violate the nullability constraints + JukeboxSongImpl { + Check.notNull(namespace, "Namespace cannot be null"); + Check.argCondition(soundEvent == null, "missing sound event: {0}", namespace); + Check.argCondition(description == null, "missing description: {0}", namespace); + } + + JukeboxSongImpl(@NotNull Registry.JukeboxSongEntry registry) { + this(registry.namespace(), registry.soundEvent(), registry.description(), registry.lengthInSeconds(), registry.comparatorOutput(), registry); + } + +} diff --git a/src/main/java/net/minestom/server/inventory/type/EnchantmentTableInventory.java b/src/main/java/net/minestom/server/inventory/type/EnchantmentTableInventory.java index c89fe1da0..e03ff2ac9 100644 --- a/src/main/java/net/minestom/server/inventory/type/EnchantmentTableInventory.java +++ b/src/main/java/net/minestom/server/inventory/type/EnchantmentTableInventory.java @@ -76,7 +76,8 @@ public class EnchantmentTableInventory extends Inventory { final short id = enchantmentShown[enchantmentSlot.ordinal()]; if (id == -1) return null; - return Enchantment.fromId(id); +// return Enchantment.fromId(id); + throw new UnsupportedOperationException("todo"); } /** @@ -88,13 +89,13 @@ public class EnchantmentTableInventory extends Inventory { * @param enchantment the enchantment */ public void setEnchantmentShown(EnchantmentSlot enchantmentSlot, Enchantment enchantment) { - final short id = enchantment == null ? -1 : (short) enchantment.id(); - switch (enchantmentSlot) { - case TOP -> sendProperty(InventoryProperty.ENCHANTMENT_TABLE_ENCH_ID_TOP, id); - case MIDDLE -> sendProperty(InventoryProperty.ENCHANTMENT_TABLE_ENCH_ID_MIDDLE, id); - case BOTTOM -> sendProperty(InventoryProperty.ENCHANTMENT_TABLE_ENCH_ID_BOTTOM, id); - } - this.enchantmentShown[enchantmentSlot.ordinal()] = id; +// final short id = enchantment == null ? -1 : (short) enchantment.id(); +// switch (enchantmentSlot) { +// case TOP -> sendProperty(InventoryProperty.ENCHANTMENT_TABLE_ENCH_ID_TOP, id); +// case MIDDLE -> sendProperty(InventoryProperty.ENCHANTMENT_TABLE_ENCH_ID_MIDDLE, id); +// case BOTTOM -> sendProperty(InventoryProperty.ENCHANTMENT_TABLE_ENCH_ID_BOTTOM, id); +// } +// this.enchantmentShown[enchantmentSlot.ordinal()] = id; } /** diff --git a/src/main/java/net/minestom/server/item/ItemComponent.java b/src/main/java/net/minestom/server/item/ItemComponent.java index 74969a9ef..b5ebe4a78 100644 --- a/src/main/java/net/minestom/server/item/ItemComponent.java +++ b/src/main/java/net/minestom/server/item/ItemComponent.java @@ -58,6 +58,7 @@ public final class ItemComponent { public static final DataComponent BLOCK_ENTITY_DATA = DataComponent.register("block_entity_data", CustomData.NETWORK_TYPE, CustomData.NBT_TYPE); public static final DataComponent INSTRUMENT = DataComponent.register("instrument", NetworkBuffer.STRING, BinaryTagSerializer.STRING); public static final DataComponent OMINOUS_BOTTLE_AMPLIFIER = DataComponent.register("ominous_bottle_amplifier", NetworkBuffer.VAR_INT, BinaryTagSerializer.INT); + public static final DataComponent JUKEBOX_PLAYABLE = DataComponent.register("jukebox_playable", JukeboxPlayable.NETWORK_TYPE, JukeboxPlayable.NBT_TYPE); public static final DataComponent> RECIPES = DataComponent.register("recipes", NetworkBuffer.STRING.list(Short.MAX_VALUE), BinaryTagSerializer.STRING.list()); public static final DataComponent LODESTONE_TRACKER = DataComponent.register("lodestone_tracker", LodestoneTracker.NETWORK_TYPE, LodestoneTracker.NBT_TYPE); public static final DataComponent FIREWORK_EXPLOSION = DataComponent.register("firework_explosion", FireworkExplosion.NETWORK_TYPE, FireworkExplosion.NBT_TYPE); diff --git a/src/main/java/net/minestom/server/item/attribute/AttributeSlot.java b/src/main/java/net/minestom/server/item/attribute/AttributeSlot.java index 5d2613cb4..688994322 100644 --- a/src/main/java/net/minestom/server/item/attribute/AttributeSlot.java +++ b/src/main/java/net/minestom/server/item/attribute/AttributeSlot.java @@ -1,6 +1,8 @@ package net.minestom.server.item.attribute; import net.minestom.server.entity.EquipmentSlot; +import net.minestom.server.network.NetworkBuffer; +import net.minestom.server.utils.nbt.BinaryTagSerializer; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -16,6 +18,9 @@ public enum AttributeSlot { ARMOR(EquipmentSlot.CHESTPLATE, EquipmentSlot.LEGGINGS, EquipmentSlot.BOOTS, EquipmentSlot.HELMET), BODY(EquipmentSlot.CHESTPLATE, EquipmentSlot.LEGGINGS); + public static final NetworkBuffer.Type NETWORK_TYPE = NetworkBuffer.Enum(AttributeSlot.class); + public static final BinaryTagSerializer NBT_TYPE = BinaryTagSerializer.fromEnumStringable(AttributeSlot.class); + private final List equipmentSlots; AttributeSlot(@NotNull EquipmentSlot... equipmentSlots) { diff --git a/src/main/java/net/minestom/server/item/component/AttributeList.java b/src/main/java/net/minestom/server/item/component/AttributeList.java index f5e0c236d..ab4122cf0 100644 --- a/src/main/java/net/minestom/server/item/component/AttributeList.java +++ b/src/main/java/net/minestom/server/item/component/AttributeList.java @@ -1,18 +1,18 @@ package net.minestom.server.item.component; -import net.kyori.adventure.nbt.*; +import net.kyori.adventure.nbt.BinaryTag; +import net.kyori.adventure.nbt.BinaryTagTypes; +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.kyori.adventure.nbt.ListBinaryTag; import net.minestom.server.entity.attribute.Attribute; import net.minestom.server.entity.attribute.AttributeModifier; -import net.minestom.server.entity.attribute.AttributeOperation; import net.minestom.server.item.attribute.AttributeSlot; import net.minestom.server.network.NetworkBuffer; -import net.minestom.server.utils.UniqueIdUtils; import net.minestom.server.utils.nbt.BinaryTagSerializer; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; -import java.util.Locale; public record AttributeList(@NotNull List modifiers, boolean showInTooltip) { public static final AttributeList EMPTY = new AttributeList(List.of(), true); @@ -20,13 +20,13 @@ public record AttributeList(@NotNull List modifiers, boolean showInToo public static final NetworkBuffer.Type NETWORK_TYPE = new NetworkBuffer.Type<>() { @Override public void write(@NotNull NetworkBuffer buffer, AttributeList value) { - buffer.writeCollection(value.modifiers); + buffer.writeCollection(Modifier.NETWORK_TYPE, value.modifiers); buffer.write(NetworkBuffer.BOOLEAN, value.showInTooltip); } @Override public AttributeList read(@NotNull NetworkBuffer buffer) { - return new AttributeList(buffer.readCollection(Modifier::new, Short.MAX_VALUE), + return new AttributeList(buffer.readCollection(Modifier.NETWORK_TYPE, Short.MAX_VALUE), buffer.read(NetworkBuffer.BOOLEAN)); } }; @@ -34,16 +34,9 @@ public record AttributeList(@NotNull List modifiers, boolean showInToo public static final BinaryTagSerializer NBT_TYPE = new BinaryTagSerializer<>() { @Override public @NotNull BinaryTag write(@NotNull AttributeList value) { - ListBinaryTag.Builder modifiers = ListBinaryTag.builder(BinaryTagTypes.COMPOUND); + ListBinaryTag.Builder modifiers = ListBinaryTag.builder(); for (Modifier modifier : value.modifiers) { - modifiers.add(CompoundBinaryTag.builder() - .putString("type", modifier.attribute.name()) - .putString("slot", modifier.slot.name().toLowerCase(Locale.ROOT)) - .put("uuid", UniqueIdUtils.toNbt(modifier.modifier.id())) - .putString("name", modifier.modifier.name()) - .putDouble("amount", modifier.modifier.amount()) - .putString("operation", modifier.modifier.operation().name().toLowerCase(Locale.ROOT)) - .build()); + modifiers.add(Modifier.NBT_TYPE.write(modifier)); } return CompoundBinaryTag.builder() .put("modifiers", modifiers.build()) @@ -53,50 +46,45 @@ public record AttributeList(@NotNull List modifiers, boolean showInToo @Override public @NotNull AttributeList read(@NotNull BinaryTag tag) { - boolean showInTooltip = true; - ListBinaryTag modifiersTag; - if (tag instanceof CompoundBinaryTag compound) { - modifiersTag = compound.getList("modifiers", BinaryTagTypes.COMPOUND); - showInTooltip = compound.getBoolean("show_in_tooltip", true); - } else if (tag instanceof ListBinaryTag list) { - modifiersTag = list; - } else return EMPTY; - List modifiers = new ArrayList<>(modifiersTag.size()); - for (BinaryTag modifierTagRaw : modifiersTag) { - if (!(modifierTagRaw instanceof CompoundBinaryTag modifierTag)) continue; - Attribute attribute = Attribute.fromNamespaceId(modifierTag.getString("type")); - if (attribute == null) continue; // Unknown attribute, skip - AttributeSlot slot = AttributeSlot.valueOf(modifierTag.getString("slot").toUpperCase(Locale.ROOT)); - AttributeModifier modifier = new AttributeModifier( - UniqueIdUtils.fromNbt((IntArrayBinaryTag) modifierTag.get("uuid")), - modifierTag.getString("name"), - modifierTag.getDouble("amount"), - AttributeOperation.valueOf(modifierTag.getString("operation").toUpperCase(Locale.ROOT)) + return switch (tag) { + case CompoundBinaryTag compound -> new AttributeList( + compound.getList("modifiers", BinaryTagTypes.COMPOUND).stream().map(Modifier.NBT_TYPE::read).toList(), + compound.getBoolean("show_in_tooltip", true) ); - modifiers.add(new Modifier(attribute, modifier, slot)); - } - return new AttributeList(modifiers, showInTooltip); + case ListBinaryTag list -> new AttributeList(list.stream().map(Modifier.NBT_TYPE::read).toList()); + default -> EMPTY; + }; } }; - public record Modifier( - @NotNull Attribute attribute, - @NotNull AttributeModifier modifier, - @NotNull AttributeSlot slot - ) implements NetworkBuffer.Writer { + public record Modifier(@NotNull Attribute attribute, @NotNull AttributeModifier modifier, @NotNull AttributeSlot slot) { + public static final NetworkBuffer.Type NETWORK_TYPE = new NetworkBuffer.Type<>() { + @Override + public void write(@NotNull NetworkBuffer buffer, Modifier value) { + buffer.write(Attribute.NETWORK_TYPE, value.attribute); + buffer.write(AttributeModifier.NETWORK_TYPE, value.modifier); + buffer.writeEnum(AttributeSlot.class, value.slot); + } - public Modifier(@NotNull NetworkBuffer reader) { - this(reader.read(Attribute.NETWORK_TYPE), - new AttributeModifier(reader), - reader.readEnum(AttributeSlot.class)); - } - - @Override - public void write(@NotNull NetworkBuffer writer) { - writer.write(Attribute.NETWORK_TYPE, attribute); - modifier.write(writer); - writer.writeEnum(AttributeSlot.class, slot); - } + @Override + public Modifier read(@NotNull NetworkBuffer buffer) { + return new Modifier(buffer.read(Attribute.NETWORK_TYPE), + buffer.read(AttributeModifier.NETWORK_TYPE), + buffer.readEnum(AttributeSlot.class)); + } + }; + public static final BinaryTagSerializer NBT_TYPE = BinaryTagSerializer.COMPOUND.map( + tag -> new Modifier( + Attribute.NBT_TYPE.read(tag.get("type")), + AttributeModifier.NBT_TYPE.read(tag), + tag.get("slot") instanceof BinaryTag slot ? AttributeSlot.NBT_TYPE.read(slot) : AttributeSlot.ANY + ), + modifier -> CompoundBinaryTag.builder() + .put("type", Attribute.NBT_TYPE.write(modifier.attribute)) + .put((CompoundBinaryTag) AttributeModifier.NBT_TYPE.write(modifier.modifier)) + .put("slot", AttributeSlot.NBT_TYPE.write(modifier.slot)) + .build() + ); } public AttributeList { diff --git a/src/main/java/net/minestom/server/item/component/EnchantmentList.java b/src/main/java/net/minestom/server/item/component/EnchantmentList.java index 75b40fb5e..ccfb4e495 100644 --- a/src/main/java/net/minestom/server/item/component/EnchantmentList.java +++ b/src/main/java/net/minestom/server/item/component/EnchantmentList.java @@ -4,6 +4,7 @@ import net.kyori.adventure.nbt.BinaryTag; import net.kyori.adventure.nbt.CompoundBinaryTag; import net.minestom.server.item.enchant.Enchantment; import net.minestom.server.network.NetworkBuffer; +import net.minestom.server.registry.DynamicRegistry; import net.minestom.server.utils.nbt.BinaryTagSerializer; import net.minestom.server.utils.validate.Check; import org.jetbrains.annotations.NotNull; @@ -11,15 +12,15 @@ import org.jetbrains.annotations.NotNull; import java.util.HashMap; import java.util.Map; -public record EnchantmentList(@NotNull Map enchantments, boolean showInTooltip) { +public record EnchantmentList(@NotNull Map, Integer> enchantments, boolean showInTooltip) { public static final EnchantmentList EMPTY = new EnchantmentList(Map.of(), true); public static NetworkBuffer.Type NETWORK_TYPE = new NetworkBuffer.Type<>() { @Override public void write(@NotNull NetworkBuffer buffer, @NotNull EnchantmentList value) { buffer.write(NetworkBuffer.VAR_INT, value.enchantments.size()); - for (Map.Entry entry : value.enchantments.entrySet()) { - buffer.write(NetworkBuffer.VAR_INT, entry.getKey().id()); + for (Map.Entry, Integer> entry : value.enchantments.entrySet()) { +// buffer.write(NetworkBuffer.VAR_INT, entry.getKey().id()); buffer.write(NetworkBuffer.VAR_INT, entry.getValue()); } buffer.write(NetworkBuffer.BOOLEAN, value.showInTooltip); @@ -29,11 +30,11 @@ public record EnchantmentList(@NotNull Map enchantments, b public @NotNull EnchantmentList read(@NotNull NetworkBuffer buffer) { int size = buffer.read(NetworkBuffer.VAR_INT); Check.argCondition(size < 0 || size > Short.MAX_VALUE, "Invalid enchantment list size: {0}", size); - Map enchantments = new HashMap<>(size); + Map, Integer> enchantments = new HashMap<>(size); for (int i = 0; i < size; i++) { - Enchantment enchantment = Enchantment.fromId(buffer.read(NetworkBuffer.VAR_INT)); - int level = buffer.read(NetworkBuffer.VAR_INT); - enchantments.put(enchantment, level); +// Enchantment enchantment = Enchantment.fromId(buffer.read(NetworkBuffer.VAR_INT)); +// int level = buffer.read(NetworkBuffer.VAR_INT); +// enchantments.put(enchantment, level); } boolean showInTooltip = buffer.read(NetworkBuffer.BOOLEAN); return new EnchantmentList(enchantments, showInTooltip); @@ -44,12 +45,12 @@ public record EnchantmentList(@NotNull Map enchantments, b tag -> { // We have two variants of the enchantment list, one with {levels: {...}, show_in_tooltip: boolean} and one with {...}. CompoundBinaryTag levels = tag.keySet().contains("levels") ? tag.getCompound("levels") : tag; - Map enchantments = new HashMap<>(levels.size()); + Map, Integer> enchantments = new HashMap<>(levels.size()); for (Map.Entry entry : levels) { - Enchantment enchantment = Enchantment.fromNamespaceId(entry.getKey()); - Check.notNull(enchantment, "Unknown enchantment: {0}", entry.getKey()); - int level = BinaryTagSerializer.INT.read(entry.getValue()); - if (level > 0) enchantments.put(enchantment, level); +// Enchantment enchantment = Enchantment.fromNamespaceId(entry.getKey()); +// Check.notNull(enchantment, "Unknown enchantment: {0}", entry.getKey()); +// int level = BinaryTagSerializer.INT.read(entry.getValue()); +// if (level > 0) enchantments.put(enchantment, level); } // Doesnt matter which variant we chose, the default will work. @@ -59,7 +60,7 @@ public record EnchantmentList(@NotNull Map enchantments, b }, value -> { CompoundBinaryTag.Builder levels = CompoundBinaryTag.builder(); - for (Map.Entry entry : value.enchantments.entrySet()) { + for (Map.Entry, Integer> entry : value.enchantments.entrySet()) { levels.put(entry.getKey().name(), BinaryTagSerializer.INT.write(entry.getValue())); } @@ -74,30 +75,30 @@ public record EnchantmentList(@NotNull Map enchantments, b enchantments = Map.copyOf(enchantments); } - public EnchantmentList(@NotNull Map enchantments) { + public EnchantmentList(@NotNull Map, Integer> enchantments) { this(enchantments, true); } - public EnchantmentList(@NotNull Enchantment enchantment, int level) { + public EnchantmentList(@NotNull DynamicRegistry.Key enchantment, int level) { this(Map.of(enchantment, level), true); } - public boolean has(@NotNull Enchantment enchantment) { + public boolean has(@NotNull DynamicRegistry.Key enchantment) { return enchantments.containsKey(enchantment); } - public int level(@NotNull Enchantment enchantment) { + public int level(@NotNull DynamicRegistry.Key enchantment) { return enchantments.getOrDefault(enchantment, 0); } - public @NotNull EnchantmentList with(@NotNull Enchantment enchantment, int level) { - Map newEnchantments = new HashMap<>(enchantments); + public @NotNull EnchantmentList with(@NotNull DynamicRegistry.Key enchantment, int level) { + Map, Integer> newEnchantments = new HashMap<>(enchantments); newEnchantments.put(enchantment, level); return new EnchantmentList(newEnchantments, showInTooltip); } - public @NotNull EnchantmentList remove(@NotNull Enchantment enchantment) { - Map newEnchantments = new HashMap<>(enchantments); + public @NotNull EnchantmentList remove(@NotNull DynamicRegistry.Key enchantment) { + Map, Integer> newEnchantments = new HashMap<>(enchantments); newEnchantments.remove(enchantment); return new EnchantmentList(newEnchantments, showInTooltip); } diff --git a/src/main/java/net/minestom/server/item/component/Food.java b/src/main/java/net/minestom/server/item/component/Food.java index 29394e3a0..ac109c470 100644 --- a/src/main/java/net/minestom/server/item/component/Food.java +++ b/src/main/java/net/minestom/server/item/component/Food.java @@ -1,8 +1,10 @@ package net.minestom.server.item.component; +import net.kyori.adventure.nbt.BinaryTag; import net.kyori.adventure.nbt.BinaryTagTypes; import net.kyori.adventure.nbt.CompoundBinaryTag; import net.minestom.server.ServerFlag; +import net.minestom.server.item.ItemStack; import net.minestom.server.network.NetworkBuffer; import net.minestom.server.potion.CustomPotionEffect; import net.minestom.server.utils.nbt.BinaryTagSerializer; @@ -10,7 +12,8 @@ import org.jetbrains.annotations.NotNull; import java.util.List; -public record Food(int nutrition, float saturationModifier, boolean canAlwaysEat, float eatSeconds, @NotNull List effects) { +public record Food(int nutrition, float saturationModifier, boolean canAlwaysEat, float eatSeconds, + @NotNull ItemStack usingConvertsTo, @NotNull List effects) { public static final float DEFAULT_EAT_SECONDS = 1.6f; public static final NetworkBuffer.Type NETWORK_TYPE = new NetworkBuffer.Type<>() { @@ -20,6 +23,7 @@ public record Food(int nutrition, float saturationModifier, boolean canAlwaysEat buffer.write(NetworkBuffer.FLOAT, value.saturationModifier); buffer.write(NetworkBuffer.BOOLEAN, value.canAlwaysEat); buffer.write(NetworkBuffer.FLOAT, value.eatSeconds); + buffer.write(ItemStack.OPTIONAL_NETWORK_TYPE, value.usingConvertsTo); buffer.writeCollection(EffectChance.NETWORK_TYPE, value.effects); } @@ -30,6 +34,7 @@ public record Food(int nutrition, float saturationModifier, boolean canAlwaysEat buffer.read(NetworkBuffer.FLOAT), buffer.read(NetworkBuffer.BOOLEAN), buffer.read(NetworkBuffer.FLOAT), + buffer.read(ItemStack.OPTIONAL_NETWORK_TYPE), buffer.readCollection(EffectChance.NETWORK_TYPE, Short.MAX_VALUE) ); } @@ -40,14 +45,21 @@ public record Food(int nutrition, float saturationModifier, boolean canAlwaysEat tag.getFloat("saturation_modifier"), tag.getBoolean("can_always_eat"), tag.getFloat("eat_seconds", DEFAULT_EAT_SECONDS), + tag.get("using_converts_to") instanceof BinaryTag usingConvertsTo + ? ItemStack.NBT_TYPE.read(usingConvertsTo) : ItemStack.AIR, EffectChance.NBT_LIST_TYPE.read(tag.getList("effects", BinaryTagTypes.COMPOUND))), - value -> CompoundBinaryTag.builder() - .putInt("nutrition", value.nutrition) - .putFloat("saturationModifier", value.saturationModifier) - .putBoolean("canAlwaysEat", value.canAlwaysEat) - .putFloat("eatSeconds", value.eatSeconds) - .put("effects", EffectChance.NBT_LIST_TYPE.write(value.effects)) - .build() + value -> { + CompoundBinaryTag.Builder builder = CompoundBinaryTag.builder() + .putInt("nutrition", value.nutrition) + .putFloat("saturation_odifier", value.saturationModifier) + .putBoolean("can_always_eat", value.canAlwaysEat) + .putFloat("eat_seconds", value.eatSeconds) + .put("effects", EffectChance.NBT_LIST_TYPE.write(value.effects)); + if (!value.usingConvertsTo.isAir()) { + builder.put("using_converts_to", ItemStack.NBT_TYPE.write(value.usingConvertsTo)); + } + return builder.build(); + } ); public Food { diff --git a/src/main/java/net/minestom/server/item/component/JukeboxPlayable.java b/src/main/java/net/minestom/server/item/component/JukeboxPlayable.java new file mode 100644 index 000000000..695a9476d --- /dev/null +++ b/src/main/java/net/minestom/server/item/component/JukeboxPlayable.java @@ -0,0 +1,59 @@ +package net.minestom.server.item.component; + +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.minestom.server.MinecraftServer; +import net.minestom.server.instance.block.jukebox.JukeboxSong; +import net.minestom.server.network.NetworkBuffer; +import net.minestom.server.registry.DynamicRegistry; +import net.minestom.server.utils.nbt.BinaryTagSerializer; +import net.minestom.server.utils.validate.Check; +import org.jetbrains.annotations.NotNull; + +public record JukeboxPlayable(@NotNull DynamicRegistry.Key song, boolean showInTooltip) { + public static final NetworkBuffer.Type NETWORK_TYPE = new NetworkBuffer.Type<>() { + // For some reason I(matt) cannot discern, the wire format for this type can write the song + // as either a registry ID or a namespace ID. Minestom always writes as a registry id. + + @Override + public void write(@NotNull NetworkBuffer buffer, JukeboxPlayable value) { + buffer.write(NetworkBuffer.BOOLEAN, true); // First option (registry id) + buffer.write(JukeboxSong.NETWORK_TYPE, value.song); + buffer.write(NetworkBuffer.BOOLEAN, value.showInTooltip); + } + + @Override + public JukeboxPlayable read(@NotNull NetworkBuffer buffer) { + DynamicRegistry.Key song; + if (buffer.read(NetworkBuffer.BOOLEAN)) { + song = buffer.read(JukeboxSong.NETWORK_TYPE); + } else { + song = DynamicRegistry.Key.of(buffer.read(NetworkBuffer.STRING)); + final DynamicRegistry registry = MinecraftServer.getJukeboxSongRegistry(); + Check.stateCondition(registry.get(song) != null, "unknown song: {0}", song); + } + return new JukeboxPlayable(song, buffer.read(NetworkBuffer.BOOLEAN)); + } + }; + public static final BinaryTagSerializer NBT_TYPE = BinaryTagSerializer.COMPOUND.map( + tag -> new JukeboxPlayable( + JukeboxSong.NBT_TYPE.read(tag.get("song")), + tag.getBoolean("show_in_tooltip")), + value -> CompoundBinaryTag.builder() + .put("song", JukeboxSong.NBT_TYPE.write(value.song)) + .putBoolean("show_in_tooltip", value.showInTooltip) + .build() + ); + + public JukeboxPlayable(@NotNull DynamicRegistry.Key song) { + this(song, true); + } + + public @NotNull JukeboxPlayable withSong(@NotNull DynamicRegistry.Key song) { + return new JukeboxPlayable(song, showInTooltip); + } + + public @NotNull JukeboxPlayable withTooltip(boolean showInTooltip) { + return new JukeboxPlayable(song, showInTooltip); + } + +} diff --git a/src/main/java/net/minestom/server/item/enchant/Enchantment.java b/src/main/java/net/minestom/server/item/enchant/Enchantment.java index 8a43f9129..7f4ff8b0b 100644 --- a/src/main/java/net/minestom/server/item/enchant/Enchantment.java +++ b/src/main/java/net/minestom/server/item/enchant/Enchantment.java @@ -1,47 +1,56 @@ package net.minestom.server.item.enchant; +import net.minestom.server.network.NetworkBuffer; +import net.minestom.server.registry.DynamicRegistry; +import net.minestom.server.registry.ProtocolObject; +import net.minestom.server.registry.Registries; import net.minestom.server.registry.Registry; -import net.minestom.server.registry.StaticProtocolObject; import net.minestom.server.utils.NamespaceID; -import org.jetbrains.annotations.Contract; +import net.minestom.server.utils.nbt.BinaryTagSerializer; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Collection; +public sealed interface Enchantment extends ProtocolObject, Enchantments permits EnchantmentImpl { + @NotNull NetworkBuffer.Type> NETWORK_TYPE = NetworkBuffer.RegistryKey(Registries::enchantment); + @NotNull BinaryTagSerializer> NBT_TYPE = BinaryTagSerializer.registryKey(Registries::enchantment); -public sealed interface Enchantment extends StaticProtocolObject, Enchantments permits EnchantmentImpl { + static @NotNull Builder builder(@NotNull String namespace) { + return builder(NamespaceID.from(namespace)); + } + + static @NotNull Builder builder(@NotNull NamespaceID namespace) { + return new Builder(namespace); + } /** - * Returns the enchantment registry. + *

Creates a new registry for enchantments, loading the vanilla enchantments.

* - * @return the enchantment registry + * @see net.minestom.server.MinecraftServer to get an existing instance of the registry */ - @Contract(pure = true) - @NotNull Registry.EnchantmentEntry registry(); - - @Override - default @NotNull NamespaceID namespace() { - return registry().namespace(); + @ApiStatus.Internal + static @NotNull DynamicRegistry createDefaultRegistry() { + return DynamicRegistry.create( + "minecraft:enchantment", EnchantmentImpl.REGISTRY_NBT_TYPE + //todo reenable to load vanilla enchants. +// Registry.Resource.ENCHANTMENTS, +// (namespace, props) -> new EnchantmentImpl(Registry.enchantment(namespace, props)) + ); } @Override - default int id() { - return registry().id(); + @Nullable Registry.EnchantmentEntry registry(); + + class Builder { + private final NamespaceID namespace; + + private Builder(@NotNull NamespaceID namespace) { + this.namespace = namespace; + } + + public @NotNull Enchantment build() { + return new EnchantmentImpl(namespace, null); + } } - static @NotNull Collection<@NotNull Enchantment> values() { - return EnchantmentImpl.values(); - } - - static @Nullable Enchantment fromNamespaceId(@NotNull String namespaceID) { - return EnchantmentImpl.getSafe(namespaceID); - } - - static @Nullable Enchantment fromNamespaceId(@NotNull NamespaceID namespaceID) { - return fromNamespaceId(namespaceID.asString()); - } - - static @Nullable Enchantment fromId(int id) { - return EnchantmentImpl.getId(id); - } } diff --git a/src/main/java/net/minestom/server/item/enchant/EnchantmentImpl.java b/src/main/java/net/minestom/server/item/enchant/EnchantmentImpl.java index 295c7594a..9840b0282 100644 --- a/src/main/java/net/minestom/server/item/enchant/EnchantmentImpl.java +++ b/src/main/java/net/minestom/server/item/enchant/EnchantmentImpl.java @@ -1,32 +1,29 @@ package net.minestom.server.item.enchant; import net.minestom.server.registry.Registry; +import net.minestom.server.utils.NamespaceID; +import net.minestom.server.utils.nbt.BinaryTagSerializer; +import net.minestom.server.utils.validate.Check; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import java.util.Collection; +record EnchantmentImpl(@NotNull NamespaceID namespace, @Nullable Registry.EnchantmentEntry registry) implements Enchantment { -record EnchantmentImpl(Registry.EnchantmentEntry registry) implements Enchantment { - private static final Registry.Container CONTAINER = Registry.createStaticContainer(Registry.Resource.ENCHANTMENTS, - (namespace, properties) -> new EnchantmentImpl(Registry.enchantment(namespace, properties))); + static final BinaryTagSerializer REGISTRY_NBT_TYPE = BinaryTagSerializer.COMPOUND.map( + tag -> { + throw new UnsupportedOperationException("BannerPattern is read-only"); + }, + bannerPattern -> { + throw new UnsupportedOperationException("todo"); + } + ); - static Enchantment get(@NotNull String namespace) { - return CONTAINER.get(namespace); + EnchantmentImpl { + Check.notNull(namespace, "Namespace cannot be null"); } - static Enchantment getSafe(@NotNull String namespace) { - return CONTAINER.getSafe(namespace); + EnchantmentImpl(@NotNull Registry.EnchantmentEntry registry) { + this(registry.namespace(), registry); } - static Enchantment getId(int id) { - return CONTAINER.getId(id); - } - - static Collection values() { - return CONTAINER.values(); - } - - @Override - public String toString() { - return name(); - } } diff --git a/src/main/java/net/minestom/server/network/ConnectionManager.java b/src/main/java/net/minestom/server/network/ConnectionManager.java index 329fc8fcf..6f0a7eb95 100644 --- a/src/main/java/net/minestom/server/network/ConnectionManager.java +++ b/src/main/java/net/minestom/server/network/ConnectionManager.java @@ -295,6 +295,7 @@ public final class ConnectionManager { throw new RuntimeException("Error receiving known packs", e); } boolean excludeVanilla = !knownPacks.contains(SelectKnownPacksPacket.MINECRAFT_CORE); + excludeVanilla = false; //todo var serverProcess = MinecraftServer.process(); player.sendPacket(serverProcess.chatType().registryDataPacket(excludeVanilla)); @@ -305,6 +306,9 @@ public final class ConnectionManager { player.sendPacket(serverProcess.trimPattern().registryDataPacket(excludeVanilla)); player.sendPacket(serverProcess.bannerPattern().registryDataPacket(excludeVanilla)); player.sendPacket(serverProcess.wolfVariant().registryDataPacket(excludeVanilla)); + player.sendPacket(serverProcess.enchantment().registryDataPacket(excludeVanilla)); + player.sendPacket(serverProcess.paintingVariant().registryDataPacket(excludeVanilla)); + player.sendPacket(serverProcess.jukeboxSong().registryDataPacket(excludeVanilla)); player.sendPacket(TagsPacket.DEFAULT_TAGS); } diff --git a/src/main/java/net/minestom/server/network/NetworkBuffer.java b/src/main/java/net/minestom/server/network/NetworkBuffer.java index 8d9ce8ba6..4a51b45c4 100644 --- a/src/main/java/net/minestom/server/network/NetworkBuffer.java +++ b/src/main/java/net/minestom/server/network/NetworkBuffer.java @@ -193,6 +193,25 @@ public final class NetworkBuffer { return values; } + public @NotNull Map writeMap(@NotNull NetworkBuffer.Type keyType, @NotNull NetworkBuffer.Type valueType, @NotNull Map map) { + write(VAR_INT, map.size()); + for (Map.Entry entry : map.entrySet()) { + write(keyType, entry.getKey()); + write(valueType, entry.getValue()); + } + return map; + } + + public @NotNull Map readMap(@NotNull NetworkBuffer.Type keyType, @NotNull NetworkBuffer.Type valueType, int maxSize) { + final int size = read(VAR_INT); + Check.argCondition(size > maxSize, "Map size ({0}) is higher than the maximum allowed size ({1})", size, maxSize); + final Map map = new HashMap<>(size); + for (int i = 0; i < size; i++) { + map.put(read(keyType), read(valueType)); + } + return map; + } + public > void writeEnum(@NotNull Class enumClass, @NotNull E value) { write(VAR_INT, value.ordinal()); } diff --git a/src/main/java/net/minestom/server/network/packet/client/play/ClientUseItemPacket.java b/src/main/java/net/minestom/server/network/packet/client/play/ClientUseItemPacket.java index 178cc2b50..6d6fffdf7 100644 --- a/src/main/java/net/minestom/server/network/packet/client/play/ClientUseItemPacket.java +++ b/src/main/java/net/minestom/server/network/packet/client/play/ClientUseItemPacket.java @@ -7,14 +7,17 @@ import org.jetbrains.annotations.NotNull; import static net.minestom.server.network.NetworkBuffer.VAR_INT; -public record ClientUseItemPacket(@NotNull Player.Hand hand, int sequence) implements ClientPacket { +public record ClientUseItemPacket(@NotNull Player.Hand hand, int sequence, float yaw, float pitch) implements ClientPacket { public ClientUseItemPacket(@NotNull NetworkBuffer reader) { - this(reader.readEnum(Player.Hand.class), reader.read(VAR_INT)); + this(reader.readEnum(Player.Hand.class), reader.read(VAR_INT), + reader.read(NetworkBuffer.FLOAT), reader.read(NetworkBuffer.FLOAT)); } @Override public void write(@NotNull NetworkBuffer writer) { writer.writeEnum(Player.Hand.class, hand); writer.write(VAR_INT, sequence); + writer.write(NetworkBuffer.FLOAT, yaw); + writer.write(NetworkBuffer.FLOAT, pitch); } } diff --git a/src/main/java/net/minestom/server/network/packet/server/ServerPacketIdentifier.java b/src/main/java/net/minestom/server/network/packet/server/ServerPacketIdentifier.java index 3390174ff..0d48a9c3f 100644 --- a/src/main/java/net/minestom/server/network/packet/server/ServerPacketIdentifier.java +++ b/src/main/java/net/minestom/server/network/packet/server/ServerPacketIdentifier.java @@ -33,6 +33,8 @@ public final class ServerPacketIdentifier { public static final int CONFIGURATION_UPDATE_ENABLED_FEATURES = nextConfigurationId(); public static final int CONFIGURATION_TAGS = nextConfigurationId(); public static final int CONFIGURATION_SELECT_KNOWN_PACKS = nextConfigurationId(); + public static final int CONFIGURATION_CUSTOM_REPORT_DETAILS = nextConfigurationId(); + public static final int CONFIGURATION_SERVER_LINKS = nextConfigurationId(); public static final int BUNDLE = nextPlayId(); public static final int SPAWN_ENTITY = nextPlayId(); @@ -156,6 +158,8 @@ public final class ServerPacketIdentifier { public static final int DECLARE_RECIPES = nextPlayId(); public static final int TAGS = nextPlayId(); public static final int PROJECTILE_POWER = nextPlayId(); + public static final int CUSTOM_REPORT_DETAILS = nextPlayId(); + public static final int SERVER_LINKS = nextPlayId(); private static int nextStatusId() { return STATUS_ID.getAndIncrement(); diff --git a/src/main/java/net/minestom/server/network/packet/server/common/CustomReportDetailsPacket.java b/src/main/java/net/minestom/server/network/packet/server/common/CustomReportDetailsPacket.java new file mode 100644 index 000000000..548637286 --- /dev/null +++ b/src/main/java/net/minestom/server/network/packet/server/common/CustomReportDetailsPacket.java @@ -0,0 +1,37 @@ +package net.minestom.server.network.packet.server.common; + +import net.minestom.server.network.NetworkBuffer; +import net.minestom.server.network.packet.server.ServerPacket; +import net.minestom.server.network.packet.server.ServerPacketIdentifier; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; + +public record CustomReportDetailsPacket( + @NotNull Map details +) implements ServerPacket.Configuration, ServerPacket.Play { + private static final int MAX_DETAILS = 32; + + public CustomReportDetailsPacket { + details = Map.copyOf(details); + } + + public CustomReportDetailsPacket(@NotNull NetworkBuffer reader) { + this(reader.readMap(NetworkBuffer.STRING, NetworkBuffer.STRING, MAX_DETAILS)); + } + + @Override + public void write(@NotNull NetworkBuffer writer) { + writer.writeMap(NetworkBuffer.STRING, NetworkBuffer.STRING, details); + } + + @Override + public int configurationId() { + return ServerPacketIdentifier.CONFIGURATION_CUSTOM_REPORT_DETAILS; + } + + @Override + public int playId() { + return ServerPacketIdentifier.CUSTOM_REPORT_DETAILS; + } +} diff --git a/src/main/java/net/minestom/server/network/packet/server/common/ServerLinksPacket.java b/src/main/java/net/minestom/server/network/packet/server/common/ServerLinksPacket.java new file mode 100644 index 000000000..3c98bc06d --- /dev/null +++ b/src/main/java/net/minestom/server/network/packet/server/common/ServerLinksPacket.java @@ -0,0 +1,97 @@ +package net.minestom.server.network.packet.server.common; + +import net.kyori.adventure.text.Component; +import net.minestom.server.network.NetworkBuffer; +import net.minestom.server.network.packet.server.ServerPacket; +import net.minestom.server.network.packet.server.ServerPacketIdentifier; +import net.minestom.server.utils.validate.Check; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public record ServerLinksPacket(@NotNull List entries) implements ServerPacket.Configuration, ServerPacket.Play { + private static final int MAX_ENTRIES = 100; + + public ServerLinksPacket { + entries = List.copyOf(entries); + } + + public ServerLinksPacket(@NotNull Entry... entries) { + this(List.of(entries)); + } + + public ServerLinksPacket(@NotNull NetworkBuffer reader) { + this(reader.read(Entry.LIST_NETWORK_TYPE)); + } + + @Override + public void write(@NotNull NetworkBuffer writer) { + writer.write(Entry.LIST_NETWORK_TYPE, entries); + } + + @Override + public int configurationId() { + return ServerPacketIdentifier.CONFIGURATION_SERVER_LINKS; + } + + @Override + public int playId() { + return ServerPacketIdentifier.SERVER_LINKS; + } + + public record Entry(@Nullable KnownLinkType knownType, @Nullable Component customType, @NotNull String link) { + public static final NetworkBuffer.Type NETWORK_TYPE = new NetworkBuffer.Type<>() { + @Override + public void write(@NotNull NetworkBuffer buffer, Entry value) { + buffer.write(NetworkBuffer.BOOLEAN, value.knownType != null); + if (value.knownType != null) { + buffer.write(KnownLinkType.NETWORK_TYPE, value.knownType); + } else { + assert value.customType != null; + buffer.write(NetworkBuffer.COMPONENT, value.customType); + } + buffer.write(NetworkBuffer.STRING, value.link); + } + + @Override + public Entry read(@NotNull NetworkBuffer buffer) { + boolean known = buffer.read(NetworkBuffer.BOOLEAN); + if (known) { + return new Entry(buffer.read(KnownLinkType.NETWORK_TYPE), buffer.read(NetworkBuffer.STRING)); + } else { + return new Entry(buffer.read(NetworkBuffer.COMPONENT), buffer.read(NetworkBuffer.STRING)); + } + } + }; + public static final NetworkBuffer.Type> LIST_NETWORK_TYPE = NETWORK_TYPE.list(MAX_ENTRIES); + + public Entry { + Check.argCondition(knownType == null && customType == null, "One of knownType and customType must be present"); + Check.argCondition(knownType != null && customType != null, "Only one of knownType and customType may be present"); + } + + public Entry(@NotNull KnownLinkType type, @NotNull String link) { + this(type, null, link); + } + + public Entry(@NotNull Component type, @NotNull String link) { + this(null, type, link); + } + } + + public enum KnownLinkType { + BUG_REPORT, + COMMUNITY_GUIDELINES, + SUPPORT, + STATUS, + FEEDBACK, + COMMUNITY, + WEBSITE, + FORUMS, + NEWS, + ANNOUNCEMENTS; + + public static final NetworkBuffer.Type NETWORK_TYPE = NetworkBuffer.Enum(KnownLinkType.class); + } +} diff --git a/src/main/java/net/minestom/server/network/packet/server/play/EntityAttributesPacket.java b/src/main/java/net/minestom/server/network/packet/server/play/EntityAttributesPacket.java index 78859e440..faa46bb74 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/EntityAttributesPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/EntityAttributesPacket.java @@ -1,65 +1,30 @@ package net.minestom.server.network.packet.server.play; -import net.minestom.server.entity.attribute.Attribute; import net.minestom.server.entity.attribute.AttributeInstance; -import net.minestom.server.entity.attribute.AttributeModifier; -import net.minestom.server.entity.attribute.AttributeOperation; import net.minestom.server.network.NetworkBuffer; import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.network.packet.server.ServerPacketIdentifier; -import net.minestom.server.utils.validate.Check; import org.jetbrains.annotations.NotNull; -import java.util.Collection; import java.util.List; -import static net.minestom.server.network.NetworkBuffer.*; +import static net.minestom.server.network.NetworkBuffer.VAR_INT; -public record EntityAttributesPacket(int entityId, List properties) implements ServerPacket.Play { +public record EntityAttributesPacket(int entityId, List attributes) implements ServerPacket.Play { public static final int MAX_ENTRIES = 1024; public EntityAttributesPacket { - properties = List.copyOf(properties); + attributes = List.copyOf(attributes); } public EntityAttributesPacket(@NotNull NetworkBuffer reader) { - this(reader.read(VAR_INT), reader.readCollection(r -> { - int id = reader.read(VAR_INT); - final Attribute attribute = Attribute.fromId(id); - Check.notNull(attribute, "Unknown attribute id: " + id); - - final double value = reader.read(DOUBLE); - int modifierCount = reader.read(VAR_INT); - AttributeInstance instance = new AttributeInstance(attribute, null); - for (int i = 0; i < modifierCount; i++) { - AttributeModifier modifier = new AttributeModifier(reader.read(UUID), "", reader.read(DOUBLE), AttributeOperation.fromId(reader.read(BYTE))); - instance.addModifier(modifier); - } - return instance; - }, MAX_ENTRIES)); + this(reader.read(VAR_INT), reader.readCollection(AttributeInstance.NETWORK_TYPE, MAX_ENTRIES)); } @Override public void write(@NotNull NetworkBuffer writer) { writer.write(VAR_INT, entityId); - writer.write(VAR_INT, properties.size()); - for (AttributeInstance instance : properties) { - final Attribute attribute = instance.getAttribute(); - - writer.write(VAR_INT, attribute.id()); - writer.write(DOUBLE, instance.getBaseValue()); - - { - Collection modifiers = instance.getModifiers(); - writer.write(VAR_INT, modifiers.size()); - - for (var modifier : modifiers) { - writer.write(UUID, modifier.getId()); - writer.write(DOUBLE, modifier.getAmount()); - writer.write(BYTE, (byte) modifier.getOperation().getId()); - } - } - } + writer.writeCollection(AttributeInstance.NETWORK_TYPE, attributes); } @Override diff --git a/src/main/java/net/minestom/server/network/packet/server/play/ProjectilePowerPacket.java b/src/main/java/net/minestom/server/network/packet/server/play/ProjectilePowerPacket.java index e147b15fa..262a8d7de 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/ProjectilePowerPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/ProjectilePowerPacket.java @@ -1,23 +1,22 @@ package net.minestom.server.network.packet.server.play; -import net.minestom.server.coordinate.Point; import net.minestom.server.network.NetworkBuffer; import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.network.packet.server.ServerPacketIdentifier; import org.jetbrains.annotations.NotNull; public record ProjectilePowerPacket( - int entityId, @NotNull Point power + int entityId, double accelerationPower ) implements ServerPacket.Play { public ProjectilePowerPacket(@NotNull NetworkBuffer buffer) { - this(buffer.read(NetworkBuffer.VAR_INT), buffer.read(NetworkBuffer.VECTOR3D)); + this(buffer.read(NetworkBuffer.VAR_INT), buffer.read(NetworkBuffer.DOUBLE)); } @Override public void write(@NotNull NetworkBuffer writer) { writer.write(NetworkBuffer.VAR_INT, entityId); - writer.write(NetworkBuffer.VECTOR3D, power); + writer.write(NetworkBuffer.DOUBLE, accelerationPower); } @Override diff --git a/src/main/java/net/minestom/server/registry/Registries.java b/src/main/java/net/minestom/server/registry/Registries.java index f70d977ba..e825744f2 100644 --- a/src/main/java/net/minestom/server/registry/Registries.java +++ b/src/main/java/net/minestom/server/registry/Registries.java @@ -2,9 +2,12 @@ package net.minestom.server.registry; import net.minestom.server.entity.damage.DamageType; import net.minestom.server.entity.metadata.animal.tameable.WolfMeta; +import net.minestom.server.entity.metadata.other.PaintingMeta; import net.minestom.server.instance.block.banner.BannerPattern; +import net.minestom.server.instance.block.jukebox.JukeboxSong; import net.minestom.server.item.armor.TrimMaterial; import net.minestom.server.item.armor.TrimPattern; +import net.minestom.server.item.enchant.Enchantment; import net.minestom.server.message.ChatType; import net.minestom.server.world.DimensionType; import net.minestom.server.world.biome.Biome; @@ -34,4 +37,10 @@ public interface Registries { @NotNull DynamicRegistry wolfVariant(); + @NotNull DynamicRegistry enchantment(); + + @NotNull DynamicRegistry paintingVariant(); + + @NotNull DynamicRegistry jukeboxSong(); + } diff --git a/src/main/java/net/minestom/server/registry/Registry.java b/src/main/java/net/minestom/server/registry/Registry.java index 204c45417..3c299219d 100644 --- a/src/main/java/net/minestom/server/registry/Registry.java +++ b/src/main/java/net/minestom/server/registry/Registry.java @@ -22,6 +22,7 @@ import net.minestom.server.entity.EquipmentSlot; import net.minestom.server.instance.block.Block; import net.minestom.server.item.Material; import net.minestom.server.message.ChatTypeDecoration; +import net.minestom.server.sound.SoundEvent; import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.collection.ObjectArray; import net.minestom.server.utils.validate.Check; @@ -67,11 +68,6 @@ public final class Registry { return new EntityEntry(namespace, main, null); } - @ApiStatus.Internal - public static EnchantmentEntry enchantment(String namespace, @NotNull Properties main) { - return new EnchantmentEntry(namespace, main, null); - } - @ApiStatus.Internal public static PotionEffectEntry potionEffect(String namespace, @NotNull Properties main) { return new PotionEffectEntry(namespace, main, null); @@ -112,6 +108,21 @@ public final class Registry { return new ChatTypeEntry(namespace, main, null); } + @ApiStatus.Internal + public static EnchantmentEntry enchantment(String namespace, @NotNull Properties main) { + return new EnchantmentEntry(namespace, main, null); + } + + @ApiStatus.Internal + public static PaintingVariantEntry paintingVariant(String namespace, @NotNull Properties main) { + return new PaintingVariantEntry(namespace, main, null); + } + + @ApiStatus.Internal + public static JukeboxSongEntry jukeboxSong(String namespace, @NotNull Properties main) { + return new JukeboxSongEntry(namespace, main, null); + } + @ApiStatus.Internal public static Map> load(Resource resource) { Map> map = new HashMap<>(); @@ -242,7 +253,6 @@ public final class Registry { BLOCKS("blocks.json"), ITEMS("items.json"), ENTITIES("entities.json"), - ENCHANTMENTS("enchantments.json"), SOUNDS("sounds.json"), COMMAND_ARGUMENTS("command_arguments.json"), STATISTICS("custom_statistics.json"), @@ -262,7 +272,10 @@ public final class Registry { ATTRIBUTES("attributes.json"), BANNER_PATTERNS("banner_patterns.json"), WOLF_VARIANTS("wolf_variants.json"), - CHAT_TYPES("chat_types.json"); + CHAT_TYPES("chat_types.json"), + ENCHANTMENTS("enchantments.json"), + PAINTING_VARIANTS("painting_variants.json"), + JUKEBOX_SONGS("jukebox_songs.json"); private final String name; @@ -791,27 +804,6 @@ public final class Registry { } } - public record EnchantmentEntry(NamespaceID namespace, int id, - String translationKey, - double maxLevel, - boolean isCursed, - boolean isDiscoverable, - boolean isTradeable, - boolean isTreasureOnly, - Properties custom) implements Entry { - public EnchantmentEntry(String namespace, Properties main, Properties custom) { - this(NamespaceID.from(namespace), - main.getInt("id"), - main.getString("translationKey"), - main.getDouble("maxLevel"), - main.getBoolean("curse", false), - main.getBoolean("discoverable", true), - main.getBoolean("tradeable", true), - main.getBoolean("treasureOnly", false), - custom); - } - } - public record PotionEffectEntry(NamespaceID namespace, int id, String translationKey, int color, @@ -927,6 +919,36 @@ public final class Registry { } + public record EnchantmentEntry(NamespaceID namespace, Properties custom) implements Entry { + public EnchantmentEntry(String namespace, Properties main, Properties custom) { + this(NamespaceID.from(namespace), + //todo + custom); + } + } + + public record PaintingVariantEntry(NamespaceID namespace, NamespaceID assetId, int width, int height, Properties custom) implements Entry { + public PaintingVariantEntry(String namespace, Properties main, Properties custom) { + this(NamespaceID.from(namespace), + NamespaceID.from(main.getString("asset_id")), + main.getInt("width"), + main.getInt("height"), + custom); + } + } + + public record JukeboxSongEntry(NamespaceID namespace, SoundEvent soundEvent, Component description, + float lengthInSeconds, int comparatorOutput, Properties custom) implements Entry { + public JukeboxSongEntry(String namespace, Properties main, Properties custom) { + this(NamespaceID.from(namespace), + SoundEvent.fromNamespaceId(main.getString("sound_event")), + GsonComponentSerializer.gson().deserialize(main.section("description").toString()), + (float) main.getDouble("length_in_seconds"), + main.getInt("comparator_output"), + custom); + } + } + public interface Entry { @ApiStatus.Experimental Properties custom();