diff --git a/build.gradle.kts b/build.gradle.kts index d09530656..a5ea6ee52 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -23,6 +23,7 @@ allprojects { description = shortDescription repositories { + mavenLocal() mavenCentral() } 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 8ccdd8cfb..870ec604d 100644 --- a/code-generators/src/main/java/net/minestom/codegen/Generators.java +++ b/code-generators/src/main/java/net/minestom/codegen/Generators.java @@ -2,8 +2,8 @@ package net.minestom.codegen; import net.minestom.codegen.color.DyeColorGenerator; import net.minestom.codegen.fluid.FluidGenerator; -import net.minestom.codegen.recipe.RecipeTypeGenerator; import net.minestom.codegen.particle.ParticleGenerator; +import net.minestom.codegen.recipe.RecipeTypeGenerator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,7 +34,6 @@ public class Generators { 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("particles.json"), "net.minestom.server.particle", "Particle", "ParticleImpl", "Particles"); generator.generate(resource("sounds.json"), "net.minestom.server.sound", "SoundEvent", "BuiltinSoundEvent", "SoundEvents"); generator.generate(resource("custom_statistics.json"), "net.minestom.server.statistic", "StatisticType", "StatisticTypeImpl", "StatisticTypes"); generator.generate(resource("attributes.json"), "net.minestom.server.entity.attribute", "Attribute", "AttributeImpl", "Attributes"); diff --git a/code-generators/src/main/java/net/minestom/codegen/color/DyeColorGenerator.java b/code-generators/src/main/java/net/minestom/codegen/color/DyeColorGenerator.java index dce68d71a..da85a1d66 100644 --- a/code-generators/src/main/java/net/minestom/codegen/color/DyeColorGenerator.java +++ b/code-generators/src/main/java/net/minestom/codegen/color/DyeColorGenerator.java @@ -58,7 +58,7 @@ public class DyeColorGenerator extends MinestomCodeGenerator { dyeColorEnum.addFields( List.of( FieldSpec.builder(networkBufferTypeCN, "NETWORK_TYPE", Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) - .initializer("$T.fromEnum($T.class)", networkBufferCN, dyeColorCN) + .initializer("$T.Enum($T.class)", networkBufferCN, dyeColorCN) .build(), FieldSpec.builder(binaryTagSerializerTypeCN, "NBT_TYPE", Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) .initializer("$T.fromEnumStringable($T.class)", binaryTagSerializerCN, dyeColorCN) diff --git a/code-generators/src/main/java/net/minestom/codegen/particle/ParticleGenerator.java b/code-generators/src/main/java/net/minestom/codegen/particle/ParticleGenerator.java index ea8209911..6bef1051d 100644 --- a/code-generators/src/main/java/net/minestom/codegen/particle/ParticleGenerator.java +++ b/code-generators/src/main/java/net/minestom/codegen/particle/ParticleGenerator.java @@ -2,7 +2,10 @@ package net.minestom.codegen.particle; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import com.squareup.javapoet.*; +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.JavaFile; +import com.squareup.javapoet.TypeSpec; import net.minestom.codegen.MinestomCodeGenerator; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -13,27 +16,14 @@ import javax.lang.model.element.Modifier; import java.io.File; import java.io.InputStream; import java.io.InputStreamReader; -import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Map; +import java.util.regex.Pattern; public class ParticleGenerator extends MinestomCodeGenerator { private static final Logger LOGGER = LoggerFactory.getLogger(ParticleGenerator.class); - // Maintenance note: all you should need to do is add/remove an entry on this map - private static final Map PARTICLE_DATA_CLASS_NAMES = Map.of( - "minecraft:block", ClassName.get("net.minestom.server.particle", "BlockParticle"), - "minecraft:block_marker", ClassName.get("net.minestom.server.particle", "BlockParticle"), - "minecraft:dust", ClassName.get("net.minestom.server.particle", "DustParticle"), - "minecraft:dust_color_transition", ClassName.get("net.minestom.server.particle", "DustColorTransitionParticle"), - "minecraft:falling_dust", ClassName.get("net.minestom.server.particle", "BlockParticle"), - "minecraft:sculk_charge", ClassName.get("net.minestom.server.particle", "SculkChargeParticle"), - "minecraft:item", ClassName.get("net.minestom.server.particle", "ItemParticle"), - "minecraft:vibration", ClassName.get("net.minestom.server.particle", "VibrationParticle"), - "minecraft:shriek", ClassName.get("net.minestom.server.particle", "ShriekParticle") - ); - private final InputStream particlesFile; private final File outputFolder; @@ -54,9 +44,6 @@ public class ParticleGenerator extends MinestomCodeGenerator { return; } - // Notify us if not all unique particle data key ids were found and stop the generation - List remainingParticleDataClasses = new ArrayList<>(PARTICLE_DATA_CLASS_NAMES.keySet()); - // Important classes we use alot ClassName particleCN = ClassName.get("net.minestom.server.particle", "Particle"); ClassName particleImplCN = ClassName.get("net.minestom.server.particle", "ParticleImpl"); @@ -73,12 +60,19 @@ public class ParticleGenerator extends MinestomCodeGenerator { for (Map.Entry particleIdObjectEntry : orderedParticleIdObjectEntries) { final String key = particleIdObjectEntry.getKey(); - ClassName fieldCN = PARTICLE_DATA_CLASS_NAMES.getOrDefault(key, particleCN); + final JsonObject value = particleIdObjectEntry.getValue().getAsJsonObject(); + + ClassName fieldCN = particleCN; + if (value.get("hasData").getAsBoolean()) { + // This particle has data, use the particle implementation class + fieldCN = ClassName.get("net.minestom.server.particle", + toPascalCase(key.replace("minecraft:", "")) + "Particle"); + } + String cast = ""; if (!fieldCN.equals(particleCN)) { // This is one of the unique particle classes with particle data, cast this cast = "(" + fieldCN.simpleName() + ") "; - remainingParticleDataClasses.remove(key); } String fieldName = key.replace("minecraft:", "").toUpperCase(); @@ -88,14 +82,6 @@ public class ParticleGenerator extends MinestomCodeGenerator { .initializer("$L$T.get($S)", cast, particleImplCN, key).build()); } - if (!remainingParticleDataClasses.isEmpty()) { - remainingParticleDataClasses.forEach(key -> { - LOGGER.error("Could not find unique particle data key: " + key + " in particles.json, was this key name changed?"); - }); - LOGGER.error("Stopped code generation for particles."); - return; - } - writeFiles( List.of(JavaFile.builder("net.minestom.server.particle", particlesInterface.build()) .indent(" ") @@ -103,4 +89,11 @@ public class ParticleGenerator extends MinestomCodeGenerator { .build()), outputFolder); } + + private static String toPascalCase(@NotNull String input) { + String camelCase = Pattern.compile("_([a-z])") + .matcher(input) + .replaceAll(m -> m.group(1).toUpperCase()); + return camelCase.substring(0, 1).toUpperCase() + camelCase.substring(1); + } } diff --git a/code-generators/src/main/java/net/minestom/codegen/recipe/RecipeTypeGenerator.java b/code-generators/src/main/java/net/minestom/codegen/recipe/RecipeTypeGenerator.java index 1a8ecbc07..749dfc091 100644 --- a/code-generators/src/main/java/net/minestom/codegen/recipe/RecipeTypeGenerator.java +++ b/code-generators/src/main/java/net/minestom/codegen/recipe/RecipeTypeGenerator.java @@ -55,7 +55,7 @@ public class RecipeTypeGenerator extends MinestomCodeGenerator { recipeTypeEnum.addFields( List.of( FieldSpec.builder(networkBufferTypeCN, "NETWORK_TYPE", Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) - .initializer("$T.fromEnum($T.class)", networkBufferCN, recipeTypeCN) + .initializer("$T.Enum($T.class)", networkBufferCN, recipeTypeCN) .build(), FieldSpec.builder(namespaceIdCN, "namespace", Modifier.PRIVATE, Modifier.FINAL).build() ) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 57188a3a4..cb5ce218a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ metadata.format.version = "1.1" [versions] # Important dependencies -data = "1.20.5-rv2" +data = "1.20.5-dev" adventure = "4.17.0" jetbrainsAnnotations = "23.0.0" slf4j = "2.0.7" diff --git a/src/autogenerated/java/net/minestom/server/particle/Particles.java b/src/autogenerated/java/net/minestom/server/particle/Particles.java index 214f48afb..3920b4470 100644 --- a/src/autogenerated/java/net/minestom/server/particle/Particles.java +++ b/src/autogenerated/java/net/minestom/server/particle/Particles.java @@ -8,7 +8,7 @@ interface Particles { BlockParticle BLOCK = (BlockParticle) ParticleImpl.get("minecraft:block"); - BlockParticle BLOCK_MARKER = (BlockParticle) ParticleImpl.get("minecraft:block_marker"); + BlockMarkerParticle BLOCK_MARKER = (BlockMarkerParticle) ParticleImpl.get("minecraft:block_marker"); Particle BUBBLE = ParticleImpl.get("minecraft:bubble"); @@ -44,7 +44,7 @@ interface Particles { Particle END_ROD = ParticleImpl.get("minecraft:end_rod"); - Particle ENTITY_EFFECT = ParticleImpl.get("minecraft:entity_effect"); + EntityEffectParticle ENTITY_EFFECT = (EntityEffectParticle) ParticleImpl.get("minecraft:entity_effect"); Particle EXPLOSION_EMITTER = ParticleImpl.get("minecraft:explosion_emitter"); @@ -60,7 +60,7 @@ interface Particles { Particle SONIC_BOOM = ParticleImpl.get("minecraft:sonic_boom"); - BlockParticle FALLING_DUST = (BlockParticle) ParticleImpl.get("minecraft:falling_dust"); + FallingDustParticle FALLING_DUST = (FallingDustParticle) ParticleImpl.get("minecraft:falling_dust"); Particle FIREWORK = ParticleImpl.get("minecraft:firework"); @@ -214,7 +214,7 @@ interface Particles { Particle VAULT_CONNECTION = ParticleImpl.get("minecraft:vault_connection"); - Particle DUST_PILLAR = ParticleImpl.get("minecraft:dust_pillar"); + DustPillarParticle DUST_PILLAR = (DustPillarParticle) ParticleImpl.get("minecraft:dust_pillar"); Particle OMINOUS_SPAWNING = ParticleImpl.get("minecraft:ominous_spawning"); diff --git a/src/main/java/net/minestom/server/item/ItemStack.java b/src/main/java/net/minestom/server/item/ItemStack.java index 1673492a8..90abb2a09 100644 --- a/src/main/java/net/minestom/server/item/ItemStack.java +++ b/src/main/java/net/minestom/server/item/ItemStack.java @@ -14,6 +14,7 @@ import net.minestom.server.tag.Tag; import net.minestom.server.tag.TagReadable; import net.minestom.server.tag.TagWritable; import net.minestom.server.utils.nbt.BinaryTagSerializer; +import net.minestom.server.utils.validate.Check; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -33,9 +34,36 @@ import java.util.function.UnaryOperator; public sealed interface ItemStack extends TagReadable, DataComponent.Holder, HoverEventSource permits ItemStackImpl { - @NotNull NetworkBuffer.Type NETWORK_TYPE = ItemStackImpl.NETWORK_TYPE; - @NotNull NetworkBuffer.Type STRICT_NETWORK_TYPE = ItemStackImpl.STRICT_NETWORK_TYPE; - @NotNull BinaryTagSerializer NBT_TYPE = ItemStackImpl.NBT_TYPE; + @NotNull NetworkBuffer.Type NETWORK_TYPE = new NetworkBuffer.Type<>() { + @Override + public void write(@NotNull NetworkBuffer buffer, ItemStack value) { + if (value.isAir()) { + buffer.write(NetworkBuffer.VAR_INT, 0); + return; + } + + buffer.write(NetworkBuffer.VAR_INT, value.amount()); + buffer.write(NetworkBuffer.VAR_INT, value.material().id()); + buffer.write(DataComponentMap.PATCH_NETWORK_TYPE, ((ItemStackImpl) value).components()); + } + + @Override + public ItemStack read(@NotNull NetworkBuffer buffer) { + int amount = buffer.read(NetworkBuffer.VAR_INT); + if (amount <= 0) return ItemStack.AIR; + Material material = Material.fromId(buffer.read(NetworkBuffer.VAR_INT)); + DataComponentMap components = buffer.read(DataComponentMap.PATCH_NETWORK_TYPE); + return ItemStackImpl.create(material, amount, components); + } + }; + @NotNull NetworkBuffer.Type STRICT_NETWORK_TYPE = NETWORK_TYPE.map(itemStack -> { + Check.argCondition(itemStack.amount() == 0 || itemStack.isAir(), "ItemStack cannot be empty"); + return itemStack; + }, itemStack -> { + Check.argCondition(itemStack.amount() == 0 || itemStack.isAir(), "ItemStack cannot be empty"); + return itemStack; + }); + @NotNull BinaryTagSerializer NBT_TYPE = BinaryTagSerializer.COMPOUND.map(ItemStackImpl::fromCompound, ItemStackImpl::toCompound); /** * Constant AIR item. Should be used instead of 'null'. diff --git a/src/main/java/net/minestom/server/item/ItemStackImpl.java b/src/main/java/net/minestom/server/item/ItemStackImpl.java index be56d7a40..e29f1be35 100644 --- a/src/main/java/net/minestom/server/item/ItemStackImpl.java +++ b/src/main/java/net/minestom/server/item/ItemStackImpl.java @@ -4,9 +4,7 @@ import net.kyori.adventure.nbt.CompoundBinaryTag; import net.minestom.server.component.DataComponent; import net.minestom.server.component.DataComponentMap; import net.minestom.server.item.component.CustomData; -import net.minestom.server.network.NetworkBuffer; import net.minestom.server.tag.Tag; -import net.minestom.server.utils.nbt.BinaryTagSerializer; import net.minestom.server.utils.validate.Check; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -16,37 +14,6 @@ import java.util.function.Consumer; record ItemStackImpl(Material material, int amount, DataComponentMap components) implements ItemStack { - static final NetworkBuffer.Type NETWORK_TYPE = new NetworkBuffer.Type<>() { - @Override - public void write(@NotNull NetworkBuffer buffer, ItemStack value) { - if (value.isAir()) { - buffer.write(NetworkBuffer.VAR_INT, 0); - return; - } - - buffer.write(NetworkBuffer.VAR_INT, value.amount()); - buffer.write(NetworkBuffer.VAR_INT, value.material().id()); - buffer.write(DataComponentMap.PATCH_NETWORK_TYPE, ((ItemStackImpl) value).components); - } - - @Override - public ItemStack read(@NotNull NetworkBuffer buffer) { - int amount = buffer.read(NetworkBuffer.VAR_INT); - if (amount <= 0) return ItemStack.AIR; - Material material = Material.fromId(buffer.read(NetworkBuffer.VAR_INT)); - DataComponentMap components = buffer.read(DataComponentMap.PATCH_NETWORK_TYPE); - return create(material, amount, components); - } - }; - static final NetworkBuffer.Type STRICT_NETWORK_TYPE = NETWORK_TYPE.map(itemStack -> { - Check.argCondition(itemStack.amount() == 0 || itemStack.isAir(), "ItemStack cannot be empty"); - return itemStack; - }, itemStack -> { - Check.argCondition(itemStack.amount() == 0 || itemStack.isAir(), "ItemStack cannot be empty"); - return itemStack; - }); - static final BinaryTagSerializer NBT_TYPE = BinaryTagSerializer.COMPOUND.map(ItemStackImpl::fromCompound, ItemStackImpl::toCompound); - static ItemStack create(Material material, int amount, DataComponentMap components) { if (amount <= 0) return AIR; return new ItemStackImpl(material, amount, components); @@ -132,7 +99,7 @@ record ItemStackImpl(Material material, int amount, DataComponentMap components) return new Builder(material, amount, components.toBuilder()); } - private static @NotNull ItemStack fromCompound(@NotNull CompoundBinaryTag tag) { + static @NotNull ItemStack fromCompound(@NotNull CompoundBinaryTag tag) { String id = tag.getString("id"); Material material = Material.fromNamespaceId(id); Check.notNull(material, "Unknown material: {0}", id); @@ -141,7 +108,7 @@ record ItemStackImpl(Material material, int amount, DataComponentMap components) return new ItemStackImpl(material, count, patch); } - private static @NotNull CompoundBinaryTag toCompound(@NotNull ItemStack itemStack) { + static @NotNull CompoundBinaryTag toCompound(@NotNull ItemStack itemStack) { CompoundBinaryTag.Builder tag = CompoundBinaryTag.builder(); tag.putString("id", itemStack.material().name()); tag.putInt("count", itemStack.amount()); diff --git a/src/main/java/net/minestom/server/item/Material.java b/src/main/java/net/minestom/server/item/Material.java index 1d2827815..98fe2c878 100644 --- a/src/main/java/net/minestom/server/item/Material.java +++ b/src/main/java/net/minestom/server/item/Material.java @@ -16,8 +16,8 @@ import java.util.Collection; public sealed interface Material extends StaticProtocolObject, Materials permits MaterialImpl { - NetworkBuffer.Type NETWORK_TYPE = MaterialImpl.NETWORK_TYPE; - BinaryTagSerializer NBT_TYPE = BinaryTagSerializer.lazy(() -> MaterialImpl.NBT_TYPE); + NetworkBuffer.Type NETWORK_TYPE = NetworkBuffer.VAR_INT.map(MaterialImpl::getId, Material::id); + BinaryTagSerializer NBT_TYPE = BinaryTagSerializer.STRING.map(MaterialImpl::getSafe, Material::name); /** * Returns the raw registry data for the material. diff --git a/src/main/java/net/minestom/server/item/MaterialImpl.java b/src/main/java/net/minestom/server/item/MaterialImpl.java index 3ec4837b2..38c1c8236 100644 --- a/src/main/java/net/minestom/server/item/MaterialImpl.java +++ b/src/main/java/net/minestom/server/item/MaterialImpl.java @@ -1,8 +1,6 @@ package net.minestom.server.item; -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; @@ -11,9 +9,6 @@ record MaterialImpl(Registry.MaterialEntry registry) implements Material { private static final Registry.Container CONTAINER = Registry.createStaticContainer(Registry.Resource.ITEMS, (namespace, properties) -> new MaterialImpl(Registry.material(namespace, properties))); - static final NetworkBuffer.Type NETWORK_TYPE = NetworkBuffer.VAR_INT.map(MaterialImpl::getId, Material::id); - static final BinaryTagSerializer NBT_TYPE = BinaryTagSerializer.STRING.map(MaterialImpl::getSafe, Material::name); - static Material get(@NotNull String namespace) { return CONTAINER.get(namespace); } diff --git a/src/main/java/net/minestom/server/network/NetworkBufferTypeImpl.java b/src/main/java/net/minestom/server/network/NetworkBufferTypeImpl.java index 18a408a6c..6c32c5831 100644 --- a/src/main/java/net/minestom/server/network/NetworkBufferTypeImpl.java +++ b/src/main/java/net/minestom/server/network/NetworkBufferTypeImpl.java @@ -8,7 +8,6 @@ import net.minestom.server.coordinate.Point; import net.minestom.server.coordinate.Vec; import net.minestom.server.network.packet.server.play.data.WorldPos; import net.minestom.server.particle.Particle; -import net.minestom.server.particle.data.ParticleData; import net.minestom.server.registry.DynamicRegistry; import net.minestom.server.registry.ProtocolObject; import net.minestom.server.registry.Registries; diff --git a/src/main/java/net/minestom/server/network/packet/server/play/ParticlePacket.java b/src/main/java/net/minestom/server/network/packet/server/play/ParticlePacket.java index 33f6bd002..efb2a8442 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/ParticlePacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/ParticlePacket.java @@ -46,7 +46,7 @@ public record ParticlePacket(@NotNull Particle particle, boolean longDistance, d Particle particle = Particle.fromId(reader.read(VAR_INT)); Objects.requireNonNull(particle); - return new ParticlePacket(particle.readData(reader), longDistance, x, y, z, offsetX, offsetY, offsetZ, maxSpeed, particleCount, data); + return new ParticlePacket(particle.readData(reader), longDistance, x, y, z, offsetX, offsetY, offsetZ, maxSpeed, particleCount); } @Override diff --git a/src/main/java/net/minestom/server/particle/BlockMarkerParticle.java b/src/main/java/net/minestom/server/particle/BlockMarkerParticle.java new file mode 100644 index 000000000..e6398124c --- /dev/null +++ b/src/main/java/net/minestom/server/particle/BlockMarkerParticle.java @@ -0,0 +1,39 @@ +package net.minestom.server.particle; + +import net.minestom.server.instance.block.Block; +import net.minestom.server.network.NetworkBuffer; +import net.minestom.server.utils.NamespaceID; +import net.minestom.server.utils.validate.Check; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +public final class BlockMarkerParticle extends ParticleImpl { + private final @NotNull Block block; + + BlockMarkerParticle(@NotNull NamespaceID namespace, int id, @NotNull Block block) { + super(namespace, id); + this.block = block; + } + + @Contract(pure = true) + public @NotNull BlockMarkerParticle withBlock(@NotNull Block block) { + return new BlockMarkerParticle(namespace(), id(), block); + } + + public @NotNull Block block() { + return block; + } + + @Override + public @NotNull BlockMarkerParticle readData(@NotNull NetworkBuffer reader) { + short blockState = reader.read(NetworkBuffer.VAR_INT).shortValue(); + Block block = Block.fromStateId(blockState); + Check.stateCondition(block == null, "Block state " + blockState + " is invalid"); + return this.withBlock(block); + } + + @Override + public void writeData(@NotNull NetworkBuffer writer) { + writer.write(NetworkBuffer.VAR_INT, (int) block.stateId()); + } +} diff --git a/src/main/java/net/minestom/server/particle/DustPillarParticle.java b/src/main/java/net/minestom/server/particle/DustPillarParticle.java new file mode 100644 index 000000000..762f2dfa7 --- /dev/null +++ b/src/main/java/net/minestom/server/particle/DustPillarParticle.java @@ -0,0 +1,39 @@ +package net.minestom.server.particle; + +import net.minestom.server.instance.block.Block; +import net.minestom.server.network.NetworkBuffer; +import net.minestom.server.utils.NamespaceID; +import net.minestom.server.utils.validate.Check; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +public final class DustPillarParticle extends ParticleImpl { + private final @NotNull Block block; + + DustPillarParticle(@NotNull NamespaceID namespace, int id, @NotNull Block block) { + super(namespace, id); + this.block = block; + } + + @Contract(pure = true) + public @NotNull DustPillarParticle withBlock(@NotNull Block block) { + return new DustPillarParticle(namespace(), id(), block); + } + + public @NotNull Block block() { + return block; + } + + @Override + public @NotNull DustPillarParticle readData(@NotNull NetworkBuffer reader) { + short blockState = reader.read(NetworkBuffer.VAR_INT).shortValue(); + Block block = Block.fromStateId(blockState); + Check.stateCondition(block == null, "Block state " + blockState + " is invalid"); + return this.withBlock(block); + } + + @Override + public void writeData(@NotNull NetworkBuffer writer) { + writer.write(NetworkBuffer.VAR_INT, (int) block.stateId()); + } +} diff --git a/src/main/java/net/minestom/server/particle/EntityEffectParticle.java b/src/main/java/net/minestom/server/particle/EntityEffectParticle.java new file mode 100644 index 000000000..b482e9c53 --- /dev/null +++ b/src/main/java/net/minestom/server/particle/EntityEffectParticle.java @@ -0,0 +1,36 @@ +package net.minestom.server.particle; + +import net.kyori.adventure.util.RGBLike; +import net.minestom.server.color.Color; +import net.minestom.server.network.NetworkBuffer; +import net.minestom.server.utils.NamespaceID; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +public final class EntityEffectParticle extends ParticleImpl { + private final @NotNull RGBLike color; + + EntityEffectParticle(@NotNull NamespaceID namespace, int id, @NotNull RGBLike color) { + super(namespace, id); + this.color = color; + } + + @Contract(pure = true) + public @NotNull EntityEffectParticle withColor(@NotNull RGBLike color) { + return new EntityEffectParticle(namespace(), id(), color); + } + + public @NotNull RGBLike color() { + return color; + } + + @Override + public @NotNull EntityEffectParticle readData(@NotNull NetworkBuffer reader) { + return withColor(reader.read(Color.NETWORK_TYPE)); + } + + @Override + public void writeData(@NotNull NetworkBuffer writer) { + writer.write(Color.NETWORK_TYPE, color); + } +} diff --git a/src/main/java/net/minestom/server/particle/FallingDustParticle.java b/src/main/java/net/minestom/server/particle/FallingDustParticle.java new file mode 100644 index 000000000..d4f2c9e14 --- /dev/null +++ b/src/main/java/net/minestom/server/particle/FallingDustParticle.java @@ -0,0 +1,39 @@ +package net.minestom.server.particle; + +import net.minestom.server.instance.block.Block; +import net.minestom.server.network.NetworkBuffer; +import net.minestom.server.utils.NamespaceID; +import net.minestom.server.utils.validate.Check; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +public final class FallingDustParticle extends ParticleImpl { + private final @NotNull Block block; + + FallingDustParticle(@NotNull NamespaceID namespace, int id, @NotNull Block block) { + super(namespace, id); + this.block = block; + } + + @Contract(pure = true) + public @NotNull FallingDustParticle withBlock(@NotNull Block block) { + return new FallingDustParticle(namespace(), id(), block); + } + + public @NotNull Block block() { + return block; + } + + @Override + public @NotNull FallingDustParticle readData(@NotNull NetworkBuffer reader) { + short blockState = reader.read(NetworkBuffer.VAR_INT).shortValue(); + Block block = Block.fromStateId(blockState); + Check.stateCondition(block == null, "Block state " + blockState + " is invalid"); + return this.withBlock(block); + } + + @Override + public void writeData(@NotNull NetworkBuffer writer) { + writer.write(NetworkBuffer.VAR_INT, (int) block.stateId()); + } +} diff --git a/src/main/java/net/minestom/server/particle/ItemParticle.java b/src/main/java/net/minestom/server/particle/ItemParticle.java index 92cea2f48..6afabb3c4 100644 --- a/src/main/java/net/minestom/server/particle/ItemParticle.java +++ b/src/main/java/net/minestom/server/particle/ItemParticle.java @@ -25,11 +25,11 @@ public final class ItemParticle extends ParticleImpl { @Override public @NotNull ItemParticle readData(@NotNull NetworkBuffer reader) { - return this.withItem(reader.read(NetworkBuffer.ITEM)); + return this.withItem(reader.read(ItemStack.NETWORK_TYPE)); } @Override public void writeData(@NotNull NetworkBuffer writer) { - writer.write(NetworkBuffer.ITEM, item); + writer.write(ItemStack.NETWORK_TYPE, item); } } \ No newline at end of file diff --git a/src/main/java/net/minestom/server/particle/ParticleImpl.java b/src/main/java/net/minestom/server/particle/ParticleImpl.java index 983a6dbbe..1df4676b6 100644 --- a/src/main/java/net/minestom/server/particle/ParticleImpl.java +++ b/src/main/java/net/minestom/server/particle/ParticleImpl.java @@ -9,11 +9,9 @@ import net.minestom.server.registry.Registry; import net.minestom.server.utils.NamespaceID; import org.jetbrains.annotations.NotNull; -import java.awt.*; import java.util.Collection; -sealed class ParticleImpl implements Particle permits BlockParticle, DustParticle, DustColorTransitionParticle, - SculkChargeParticle, ItemParticle, VibrationParticle, ShriekParticle { +sealed class ParticleImpl implements Particle permits BlockMarkerParticle, BlockParticle, DustColorTransitionParticle, DustParticle, DustPillarParticle, EntityEffectParticle, FallingDustParticle, ItemParticle, SculkChargeParticle, ShriekParticle, VibrationParticle { private static final Registry.Container CONTAINER = Registry.createStaticContainer(Registry.Resource.PARTICLES, (namespace, properties) -> defaultParticle(NamespaceID.from(namespace), properties.getInt("id"))); @@ -67,7 +65,10 @@ sealed class ParticleImpl implements Particle permits BlockParticle, DustParticl private static Particle defaultParticle(@NotNull NamespaceID namespace, int id) { return switch (namespace.asString()) { - case "minecraft:block", "minecraft:block_marker", "minecraft:falling_dust" -> new BlockParticle(namespace, id, Block.STONE); + case "minecraft:block" -> new BlockParticle(namespace, id, Block.STONE); + case "minecraft:block_marker" -> new BlockMarkerParticle(namespace, id, Block.STONE); + case "minecraft:falling_dust" -> new FallingDustParticle(namespace, id, Block.STONE); + case "minecraft:dust_pillar" -> new DustPillarParticle(namespace, id, Block.STONE); case "minecraft:dust" -> new DustParticle(namespace, id, new Color(255, 255, 255), 1); case "minecraft:dust_color_transition" -> new DustColorTransitionParticle(namespace, id, new Color(255, 255, 255), 1, new Color(255, 255, 255)); @@ -75,6 +76,7 @@ sealed class ParticleImpl implements Particle permits BlockParticle, DustParticl case "minecraft:item" -> new ItemParticle(namespace, id, ItemStack.AIR); case "minecraft:vibration" -> new VibrationParticle(namespace, id, VibrationParticle.SourceType.BLOCK, Vec.ZERO, 0, 0, 0); case "minecraft:shriek" -> new ShriekParticle(namespace, id, 0); + case "minecraft:entity_effect" -> new EntityEffectParticle(namespace, id, new Color(0)); default -> new ParticleImpl(namespace, id); }; } diff --git a/src/test/java/net/minestom/server/entity/AreaEffectCloudTest.java b/src/test/java/net/minestom/server/entity/AreaEffectCloudTest.java index d65e8b143..0dd389849 100644 --- a/src/test/java/net/minestom/server/entity/AreaEffectCloudTest.java +++ b/src/test/java/net/minestom/server/entity/AreaEffectCloudTest.java @@ -5,11 +5,10 @@ import net.minestom.server.entity.metadata.other.AreaEffectCloudMeta; import net.minestom.server.instance.block.Block; import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; -import net.minestom.server.network.NetworkBuffer; import net.minestom.server.particle.*; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertNotNull; public class AreaEffectCloudTest { @Test @@ -102,7 +101,7 @@ public class AreaEffectCloudTest { var gotParticle = meta.getParticle(); assert gotParticle == particle; - BlockParticle gotBlock = (BlockParticle) gotParticle; + BlockMarkerParticle gotBlock = (BlockMarkerParticle) gotParticle; assert gotBlock.block() == block; }