From 292ce911c23bf16403ca2184e641e0eae60c81c8 Mon Sep 17 00:00:00 2001 From: libraryaddict Date: Sun, 10 Nov 2024 21:58:12 +1300 Subject: [PATCH] Handle 1.21.3 update --- gradle/libs.versions.toml | 6 +- .../v1_21_R1/ReflectionManager.java | 11 +- nms/v1_21_R2/build.gradle.kts | 21 + .../v1_21_R2/ReflectionManager.java | 487 ++++++++++++++++++ .../disguise/disguisetypes/Disguise.java | 3 +- .../disguisetypes/DisguiseInternals.java | 2 +- .../disguise/disguisetypes/DisguiseType.java | 82 ++- .../disguise/disguisetypes/FlagWatcher.java | 1 + .../disguise/disguisetypes/MetaIndex.java | 29 +- .../watchers/AgeableAquaWatcher.java | 44 ++ .../disguisetypes/watchers/AllayWatcher.java | 2 + .../disguisetypes/watchers/BoatWatcher.java | 7 + .../watchers/DolphinWatcher.java | 2 +- .../disguisetypes/watchers/GoatWatcher.java | 2 + .../disguisetypes/watchers/LivingWatcher.java | 57 +- .../disguisetypes/watchers/SalmonWatcher.java | 23 + .../disguisetypes/watchers/SquidWatcher.java | 2 +- .../disguisetypes/watchers/WolfWatcher.java | 1 + .../utilities/params/ParamInfoManager.java | 3 +- .../utilities/params/ParamInfoTypes.java | 5 + .../types/custom/ParamInfoParticle.java | 248 ++++++--- .../utilities/parser/DisguiseParser.java | 10 +- .../utilities/parser/WatcherMethod.java | 1 + .../utilities/reflection/NmsVersion.java | 1 + .../reflection/ReflectionManager.java | 78 ++- .../reflection/annotations/NmsSupported.java | 19 + .../utilities/sounds/DisguiseSoundEnums.java | 417 +++++++-------- .../utilities/sounds/SoundManager.java | 4 +- .../utilities/translations/LibsMsg.java | 2 + .../utilities/watchers/DisguiseMethods.java | 7 +- .../utilities/watchers/CompileMethods.java | 28 +- .../src/main/resources/configs/dangerous.yml | 2 +- .../params/DisguiseParamParticleTest.java | 203 +++++--- 33 files changed, 1385 insertions(+), 425 deletions(-) create mode 100644 nms/v1_21_R2/build.gradle.kts create mode 100644 nms/v1_21_R2/src/main/java/me/libraryaddict/disguise/utilities/reflection/v1_21_R2/ReflectionManager.java create mode 100644 plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/AgeableAquaWatcher.java create mode 100644 plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/SalmonWatcher.java create mode 100644 plugin/src/main/java/me/libraryaddict/disguise/utilities/reflection/annotations/NmsSupported.java diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0e5c3194cad..42e693421ea 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,12 +14,12 @@ junit-jupiter-version = "5.9.3" mockito-version = "5.12.0" net-kyori-adventure-api = "4.17.0" -com-retro-packetevents = "2.5.0-SNAPSHOT" +com-retro-packetevents = "2.6.0" placeholder-api = "2.11.6" bungeecord-chat = "1.16-R0.4" -org-spigotmc-spigot = "1.21-R0.1-SNAPSHOT" -io-papermc-paper-api = "1.21.1-R0.1-SNAPSHOT" +org-spigotmc-spigot = "1.21.3-R0.1-SNAPSHOT" +io-papermc-paper-api = "1.21.3-R0.1-SNAPSHOT" [libraries] diff --git a/nms/v1_21_R1/src/main/java/me/libraryaddict/disguise/utilities/reflection/v1_21_R1/ReflectionManager.java b/nms/v1_21_R1/src/main/java/me/libraryaddict/disguise/utilities/reflection/v1_21_R1/ReflectionManager.java index d51dbc5eb5d..1357cd83c1a 100644 --- a/nms/v1_21_R1/src/main/java/me/libraryaddict/disguise/utilities/reflection/v1_21_R1/ReflectionManager.java +++ b/nms/v1_21_R1/src/main/java/me/libraryaddict/disguise/utilities/reflection/v1_21_R1/ReflectionManager.java @@ -81,7 +81,7 @@ public class ReflectionManager implements ReflectionManagerAbstract { private Field dataItemsField; - private final Field trackedEntityField; + private final Field entityTrackerField; private final AtomicInteger entityCounter; private final Method entityDefaultSoundMethod; private final UnsafeValues craftMagicNumbers; @@ -101,8 +101,9 @@ public ReflectionManager() { entityCounter.setAccessible(true); this.entityCounter = (AtomicInteger) entityCounter.get(null); - trackedEntityField = ChunkMap.TrackedEntity.class.getDeclaredField("b"); - trackedEntityField.setAccessible(true); + // Known as PlayerChunkMap in mojang mappings + entityTrackerField = ChunkMap.TrackedEntity.class.getDeclaredField("b"); + entityTrackerField.setAccessible(true); // Default is protected method, 1.0F on EntityLiving.class entityDefaultSoundMethod = net.minecraft.world.entity.LivingEntity.class.getDeclaredMethod("fa"); @@ -151,7 +152,7 @@ public net.minecraft.world.entity.Entity createEntityInstance(String entityName) Optional> optional = net.minecraft.world.entity.EntityType.byString(entityName.toLowerCase(Locale.ENGLISH)); - if (!optional.isPresent()) { + if (optional.isEmpty()) { return null; } @@ -235,7 +236,7 @@ public ServerEntity getEntityTrackerEntry(Entity target) throws Exception { return null; } - return (ServerEntity) trackedEntityField.get(trackedEntity); + return (ServerEntity) entityTrackerField.get(trackedEntity); } @Override diff --git a/nms/v1_21_R2/build.gradle.kts b/nms/v1_21_R2/build.gradle.kts new file mode 100644 index 00000000000..c56d15df574 --- /dev/null +++ b/nms/v1_21_R2/build.gradle.kts @@ -0,0 +1,21 @@ +plugins { + `java-library` +} + +apply(from = rootProject.file("nms/nmsModule.gradle")) + +extra["craftbukkitVersion"] = "1.21.3-R0.1-SNAPSHOT"; + +description = "v1_21_R2" + +dependencies { + compileOnly(libs.com.mojang.authlib.new) + compileOnly(libs.io.netty.netty.buffer) + compileOnly(libs.it.unimi.dsi.fastutil) + compileOnly(libs.com.mojang.datafixerupper) +} + +java { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 +} \ No newline at end of file diff --git a/nms/v1_21_R2/src/main/java/me/libraryaddict/disguise/utilities/reflection/v1_21_R2/ReflectionManager.java b/nms/v1_21_R2/src/main/java/me/libraryaddict/disguise/utilities/reflection/v1_21_R2/ReflectionManager.java new file mode 100644 index 00000000000..38a3ed6d449 --- /dev/null +++ b/nms/v1_21_R2/src/main/java/me/libraryaddict/disguise/utilities/reflection/v1_21_R2/ReflectionManager.java @@ -0,0 +1,487 @@ +package me.libraryaddict.disguise.utilities.reflection.v1_21_R2; + +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.ProfileLookupCallback; +import com.mojang.authlib.minecraft.MinecraftSessionService; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.JavaOps; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.PooledByteBufAllocator; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import lombok.SneakyThrows; +import me.libraryaddict.disguise.utilities.reflection.ReflectionManagerAbstract; +import net.minecraft.core.Registry; +import net.minecraft.core.component.DataComponentPatch; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ClientInformation; +import net.minecraft.server.level.ParticleStatus; +import net.minecraft.server.level.ServerChunkCache; +import net.minecraft.server.level.ServerEntity; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.network.ServerGamePacketListenerImpl; +import net.minecraft.server.network.ServerPlayerConnection; +import net.minecraft.world.entity.EntityDimensions; +import net.minecraft.world.entity.EntitySpawnReason; +import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.entity.animal.CatVariant; +import net.minecraft.world.entity.animal.FrogVariant; +import net.minecraft.world.entity.animal.WolfVariant; +import net.minecraft.world.entity.decoration.PaintingVariant; +import net.minecraft.world.entity.player.ChatVisiblity; +import net.minecraft.world.flag.FeatureFlagSet; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import org.bukkit.Art; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.Sound; +import org.bukkit.UnsafeValues; +import org.bukkit.World; +import org.bukkit.block.data.BlockData; +import org.bukkit.craftbukkit.v1_21_R2.CraftArt; +import org.bukkit.craftbukkit.v1_21_R2.CraftServer; +import org.bukkit.craftbukkit.v1_21_R2.CraftSound; +import org.bukkit.craftbukkit.v1_21_R2.CraftWorld; +import org.bukkit.craftbukkit.v1_21_R2.block.data.CraftBlockData; +import org.bukkit.craftbukkit.v1_21_R2.entity.CraftCat; +import org.bukkit.craftbukkit.v1_21_R2.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_21_R2.entity.CraftFrog; +import org.bukkit.craftbukkit.v1_21_R2.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_21_R2.entity.CraftWolf; +import org.bukkit.craftbukkit.v1_21_R2.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_21_R2.inventory.SerializableMeta; +import org.bukkit.craftbukkit.v1_21_R2.util.CraftMagicNumbers; +import org.bukkit.craftbukkit.v1_21_R2.util.CraftNamespacedKey; +import org.bukkit.entity.Cat; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Frog; +import org.bukkit.entity.Player; +import org.bukkit.entity.Wolf; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; + +public class ReflectionManager implements ReflectionManagerAbstract { + private Field dataItemsField; + private final Field entityTrackerField; + private final AtomicInteger entityCounter; + private final Method entityDefaultSoundMethod; + private final UnsafeValues craftMagicNumbers; + + @SneakyThrows + public ReflectionManager() { + for (Field f : SynchedEntityData.class.getDeclaredFields()) { + if (!f.getType().isArray()) { + continue; + } + + f.setAccessible(true); + dataItemsField = f; + } + + Field entityCounter = net.minecraft.world.entity.Entity.class.getDeclaredField("c"); + entityCounter.setAccessible(true); + this.entityCounter = (AtomicInteger) entityCounter.get(null); + + // Known as PlayerChunkMap in mojang mappings + entityTrackerField = ChunkMap.TrackedEntity.class.getDeclaredField("b"); + entityTrackerField.setAccessible(true); + + // Default is protected method, 1.0F on EntityLiving.class + entityDefaultSoundMethod = net.minecraft.world.entity.LivingEntity.class.getDeclaredMethod("fg"); + entityDefaultSoundMethod.setAccessible(true); + + craftMagicNumbers = (UnsafeValues) CraftMagicNumbers.class.getField("INSTANCE").get(null); + } + + public boolean hasInvul(Entity entity) { + net.minecraft.world.entity.Entity nmsEntity = ((CraftEntity) entity).getHandle(); + + if (nmsEntity instanceof net.minecraft.world.entity.LivingEntity) { + return nmsEntity.invulnerableTime > 0; + } else { + return nmsEntity.isInvulnerableToBase(nmsEntity.damageSources().generic()); + } + } + + @Override + public int getIncrementedStateId(Player player) { + ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle(); + return serverPlayer.containerMenu.incrementStateId(); // TODO Check correct container + } + + @Override + public int getNewEntityId() { + return getNewEntityId(true); + } + + @Override + public int getNewEntityId(boolean increment) { + if (increment) { + return entityCounter.incrementAndGet(); + } else { + return entityCounter.get(); + } + } + + @Override + public ServerGamePacketListenerImpl getPlayerConnectionOrPlayer(Player player) { + return ((CraftPlayer) player).getHandle().connection; + } + + @Override + public net.minecraft.world.entity.Entity createEntityInstance(String entityName) { + Optional> optional = + net.minecraft.world.entity.EntityType.byString(entityName.toLowerCase(Locale.ENGLISH)); + + if (optional.isEmpty()) { + return null; + } + + net.minecraft.world.entity.EntityType entityType = optional.get(); + ServerLevel world = getWorldServer(Bukkit.getWorlds().get(0)); + net.minecraft.world.entity.Entity entity; + if (entityType == net.minecraft.world.entity.EntityType.PLAYER) { + GameProfile gameProfile = new GameProfile(new UUID(0, 0), "Steve"); + ClientInformation information = + new ClientInformation("english", 10, ChatVisiblity.FULL, true, 0, HumanoidArm.RIGHT, true, true, ParticleStatus.ALL); + entity = new ServerPlayer(getMinecraftServer(), world, gameProfile, information); + } else { + entity = entityType.create(world, EntitySpawnReason.LOAD); + } + + if (entity == null) { + return null; + } + + // Workaround for paper being 2 smart 4 me + entity.setPos(1.0, 1.0, 1.0); + entity.setPos(0.0, 0.0, 0.0); + return entity; + } + + @Override + public AABB getBoundingBox(Entity entity) { + return ((CraftEntity) entity).getHandle().getBoundingBox(); + } + + @Override + public double getXBoundingBox(Entity entity) { + return getBoundingBox(entity).maxX - getBoundingBox(entity).minX; + } + + @Override + public double getYBoundingBox(Entity entity) { + return getBoundingBox(entity).maxY - getBoundingBox(entity).minY; + } + + @Override + public double getZBoundingBox(Entity entity) { + return getBoundingBox(entity).maxZ - getBoundingBox(entity).minZ; + } + + @Override + public ServerPlayer getPlayerFromPlayerConnection(Object nmsEntity) { + return ((ServerPlayerConnection) nmsEntity).getPlayer(); + } + + @Override + public Entity getBukkitEntity(Object nmsEntity) { + return ((net.minecraft.world.entity.Entity) nmsEntity).getBukkitEntity(); + } + + @Override + public ItemStack getBukkitItem(Object nmsItem) { + return CraftItemStack.asBukkitCopy((net.minecraft.world.item.ItemStack) nmsItem); + } + + @Override + public ItemStack getCraftItem(ItemStack bukkitItem) { + return CraftItemStack.asCraftCopy(bukkitItem); + } + + @Override + public ChunkMap.TrackedEntity getEntityTracker(Entity target) { + ServerLevel world = ((CraftWorld) target.getWorld()).getHandle(); + ServerChunkCache chunkSource = world.getChunkSource(); + ChunkMap chunkMap = chunkSource.chunkMap; + Int2ObjectMap entityMap = chunkMap.entityMap; + + return entityMap.get(target.getEntityId()); + } + + @Override + public ServerEntity getEntityTrackerEntry(Entity target) throws Exception { + ChunkMap.TrackedEntity trackedEntity = getEntityTracker(target); + + if (trackedEntity == null) { + return null; + } + + return (ServerEntity) entityTrackerField.get(trackedEntity); + } + + @Override + public DedicatedServer getMinecraftServer() { + return ((CraftServer) Bukkit.getServer()).getServer(); + } + + @Override + public Object getNmsEntity(Entity entity) { + return ((CraftEntity) entity).getHandle(); + } + + @Override + public double getPing(Player player) { + return player.getPing(); + } + + @Override + public float[] getSize(Entity entity) { + net.minecraft.world.entity.Entity nmsEntity = ((CraftEntity) entity).getHandle(); + EntityDimensions dimensions = nmsEntity.getDimensions(net.minecraft.world.entity.Pose.STANDING); + return new float[]{dimensions.width(), nmsEntity.getEyeHeight()}; + } + + @Override + public MinecraftSessionService getMinecraftSessionService() { + return getMinecraftServer().getSessionService(); + } + + @Override + public Float getSoundModifier(Object entity) { + // Default is 1.0F on EntityLiving + if (!(entity instanceof net.minecraft.world.entity.LivingEntity)) { + return 0.0f; + } else { + try { + return (Float) entityDefaultSoundMethod.invoke(entity); + } catch (InvocationTargetException | IllegalAccessException e) { + e.printStackTrace(); + } + } + + return 0f; + } + + @Override + public void injectCallback(String playername, ProfileLookupCallback callback) { + getMinecraftServer().getProfileRepository().findProfilesByNames(new String[]{playername}, callback); + } + + @Override + public void setBoundingBox(Entity entity, double x, double y, double z) { + Location loc = entity.getLocation(); + ((CraftEntity) entity).getHandle().setBoundingBox( + new AABB(loc.getX() - x / 2, loc.getY() - y / 2, loc.getZ() - z / 2, loc.getX() + x / 2, loc.getY() + y / 2, + loc.getZ() + z / 2)); + } + + @Override + public String getSoundString(Sound sound) { + return CraftSound.bukkitToMinecraft(sound).location().toString(); + } + + @Override + public Material getMaterial(String name) { + return craftMagicNumbers.getMaterial(name, craftMagicNumbers.getDataVersion()); + } + + @Override + public String getItemName(Material material) { + return BuiltInRegistries.ITEM.getKey(CraftMagicNumbers.getItem(material)).getPath(); + } + + @Override + public ResourceLocation createMinecraftKey(String name) { + return ResourceLocation.withDefaultNamespace(name); + } + + @Override + public net.minecraft.world.entity.EntityType getEntityType(EntityType entityType) { + return net.minecraft.world.entity.EntityType.byString( + entityType.getName() == null ? entityType.name().toLowerCase(Locale.ENGLISH) : entityType.getName()).orElse(null); + } + + @Override + public Object registerEntityType(NamespacedKey key) { + net.minecraft.world.entity.EntityType newEntity = + new net.minecraft.world.entity.EntityType<>(null, null, false, false, false, false, null, null, 0, 0, 0, + "descId." + key.toString(), Optional.empty(), FeatureFlagSet.of()); + Registry.register(BuiltInRegistries.ENTITY_TYPE, CraftNamespacedKey.toMinecraft(key), newEntity); + newEntity.getDescriptionId(); + return newEntity; // TODO ??? Some reflection in legacy that I'm unsure about + } + + @Override + public int getEntityTypeId(Object entityTypes) { + net.minecraft.world.entity.EntityType entityType = (net.minecraft.world.entity.EntityType) entityTypes; + + return BuiltInRegistries.ENTITY_TYPE.getIdOrThrow(entityType); + } + + @Override + public int getEntityTypeId(EntityType entityType) { + return getEntityTypeId(getEntityType(entityType)); + } + + @Override + public Object getEntityType(NamespacedKey name) { + return BuiltInRegistries.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(name)); + } + + @Override + public int getCombinedIdByBlockData(BlockData data) { + BlockState state = ((CraftBlockData) data).getState(); + return Block.getId(state); + } + + @Override + public int getCombinedIdByItemStack(ItemStack itemStack) { + Block block = CraftMagicNumbers.getBlock(itemStack.getType()); + return Block.getId(block.defaultBlockState()); + } + + @Override + public BlockData getBlockDataByCombinedId(int id) { + return CraftBlockData.fromData(Block.stateById(id)); + } + + @Override + public ItemStack getItemStackByCombinedId(int id) { + return new ItemStack(CraftMagicNumbers.getMaterial(Block.stateById(id).getBlock())); + } + + @Override + public ServerLevel getWorldServer(World w) { + return ((CraftWorld) w).getHandle(); + } + + @Override + public ItemMeta getDeserializedItemMeta(Map meta) { + try { + return SerializableMeta.deserialize(meta); + } catch (Throwable e) { + e.printStackTrace(); + } + + return null; + } + + @SneakyThrows + @Override + public ByteBuf getDataWatcherValues(Entity entity) { + SynchedEntityData watcher = ((CraftEntity) entity).getHandle().getEntityData(); + SynchedEntityData.DataItem[] dataItems = (SynchedEntityData.DataItem[]) dataItemsField.get(watcher); + + ByteBuf buf = PooledByteBufAllocator.DEFAULT.buffer(); + RegistryFriendlyByteBuf serializer = RegistryFriendlyByteBuf.decorator(this.getMinecraftServer().registryAccess()).apply(buf); + + for (SynchedEntityData.DataItem dataItem : dataItems) { + dataItem.value().write(serializer); + } + + serializer.writeByte(255); + + return buf; + } + + @Override + public GameProfile getMCGameProfile(Player player) { + return ((CraftPlayer) player).getProfile(); + } + + @Override + public Cat.Type getCatTypeFromInt(int catType) { + Registry registry = MinecraftServer.getDefaultRegistryAccess().lookupOrThrow(Registries.CAT_VARIANT); + + return CraftCat.CraftType.minecraftHolderToBukkit(registry.get(catType).get()); + } + + @Override + public int getCatVariantAsInt(Cat.Type type) { + Registry registry = MinecraftServer.getDefaultRegistryAccess().lookupOrThrow(Registries.CAT_VARIANT); + + return registry.getIdOrThrow(CraftCat.CraftType.bukkitToMinecraft(type)); + } + + @Override + public Frog.Variant getFrogVariantFromInt(int frogType) { + Registry registry = MinecraftServer.getDefaultRegistryAccess().lookupOrThrow(Registries.FROG_VARIANT); + + return CraftFrog.CraftVariant.minecraftHolderToBukkit(registry.get(frogType).get()); + } + + @Override + public int getFrogVariantAsInt(Frog.Variant type) { + Registry registry = MinecraftServer.getDefaultRegistryAccess().lookupOrThrow(Registries.FROG_VARIANT); + + return registry.getIdOrThrow(CraftFrog.CraftVariant.bukkitToMinecraft(type)); + } + + @Override + public Art getPaintingFromInt(int paintingId) { + Registry registry = MinecraftServer.getDefaultRegistryAccess().lookupOrThrow(Registries.PAINTING_VARIANT); + + return CraftArt.minecraftHolderToBukkit(registry.get(paintingId - 1).get()); + } + + @Override + public int getPaintingAsInt(Art type) { + Registry registry = MinecraftServer.getDefaultRegistryAccess().lookupOrThrow(Registries.PAINTING_VARIANT); + + return registry.getIdOrThrow(CraftArt.bukkitToMinecraft(type)) + 1; + } + + @Override + public Wolf.Variant getWolfVariantFromInt(int wolfVariant) { + Registry registry = MinecraftServer.getDefaultRegistryAccess().lookupOrThrow(Registries.WOLF_VARIANT); + + return CraftWolf.CraftVariant.minecraftHolderToBukkit(registry.get(wolfVariant - 1).get()); + } + + @Override + public int getWolfVariantAsInt(Wolf.Variant type) { + Registry registry = MinecraftServer.getDefaultRegistryAccess().lookupOrThrow(Registries.WOLF_VARIANT); + + return registry.getIdOrThrow(CraftWolf.CraftVariant.bukkitToMinecraft(type)) + 1; + } + + @Override + public Object serializeComponents(ItemStack itemStack) { + if (itemStack == null) { + return null; + } + + net.minecraft.world.item.ItemStack item = CraftItemStack.asNMSCopy(itemStack); + DataComponentPatch comps = item.getComponentsPatch(); + + if (comps == null) { + return null; + } + + DataResult cond = DataComponentPatch.CODEC.encodeStart(JavaOps.INSTANCE, comps); + + return cond.result().orElse(null); + } +} diff --git a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/Disguise.java b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/Disguise.java index 42b3141d92e..1f4487c7e5d 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/Disguise.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/Disguise.java @@ -28,7 +28,6 @@ import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.BaseComponent; import org.bukkit.Bukkit; -import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeInstance; import org.bukkit.attribute.AttributeModifier; import org.bukkit.boss.BarColor; @@ -621,7 +620,7 @@ private void adjustSelfDisguiseScale(double prevPersonalDisguiseScaleMax, double } // Now we figure out the scale we need to have the player at the same eye level of the disguise - AttributeInstance attribute = ((Player) getEntity()).getAttribute(Attribute.GENERIC_SCALE); + AttributeInstance attribute = ((Player) getEntity()).getAttribute(DisguiseUtilities.getScaleAttribute()); AttributeModifier modifier = attribute.getModifiers().stream().filter(a -> a.getKey().equals(DisguiseUtilities.getSelfDisguiseScaleNamespace())).findAny() .orElse(null); diff --git a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/DisguiseInternals.java b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/DisguiseInternals.java index cd6280a1cd6..ade376e82b1 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/DisguiseInternals.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/DisguiseInternals.java @@ -37,7 +37,7 @@ private final NamespacedKey bossBar = new NamespacedKey("libsdisguises", UUID.randomUUID().toString()); protected double getActualEntityScale() { - return ((LivingEntity) disguise.getEntity()).getAttribute(Attribute.GENERIC_SCALE).getValue(); + return ((LivingEntity) disguise.getEntity()).getAttribute(DisguiseUtilities.getScaleAttribute()).getValue(); } protected double getRawEntityScaleWithoutLibsDisguises() { diff --git a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/DisguiseType.java b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/DisguiseType.java index f04623346fe..29664eb3cc7 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/DisguiseType.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/DisguiseType.java @@ -18,6 +18,10 @@ import java.util.Locale; public enum DisguiseType { + @NmsAddedIn(NmsVersion.v1_21_R2) ACACIA_BOAT, + + @NmsAddedIn(NmsVersion.v1_21_R2) ACACIA_CHEST_BOAT, + @NmsAddedIn(NmsVersion.v1_19_R1) ALLAY, AREA_EFFECT_CLOUD(3), @@ -30,15 +34,23 @@ public enum DisguiseType { @NmsAddedIn(NmsVersion.v1_17) AXOLOTL, + @NmsAddedIn(NmsVersion.v1_21_R2) BAMBOO_CHEST_RAFT, + + @NmsAddedIn(NmsVersion.v1_21_R2) BAMBOO_RAFT, + BAT, @NmsAddedIn(NmsVersion.v1_15) BEE, + @NmsAddedIn(NmsVersion.v1_21_R2) BIRCH_BOAT, + + @NmsAddedIn(NmsVersion.v1_21_R2) BIRCH_CHEST_BOAT, + BLAZE, @NmsAddedIn(NmsVersion.v1_19_R3) BLOCK_DISPLAY, - BOAT(1), + @NmsRemovedIn(NmsVersion.v1_21_R2) BOAT(1), @NmsAddedIn(NmsVersion.v1_21_R1) BOGGED, @@ -52,30 +64,46 @@ public enum DisguiseType { CAVE_SPIDER, - CHICKEN, + @NmsAddedIn(NmsVersion.v1_21_R2) CHERRY_BOAT, - @NmsAddedIn(NmsVersion.v1_19_R1) CHEST_BOAT, + @NmsAddedIn(NmsVersion.v1_21_R2) CHERRY_CHEST_BOAT, + + @NmsAddedIn(NmsVersion.v1_19_R1) @NmsRemovedIn(NmsVersion.v1_21_R2) CHEST_BOAT, + + CHICKEN, @NmsAddedIn(NmsVersion.v1_13) COD, COW, + @NmsAddedIn(NmsVersion.UNSUPPORTED) CREAKING, + + @NmsAddedIn(NmsVersion.UNSUPPORTED) CREAKING_TRANSIENT, + CREEPER, + @NmsAddedIn(NmsVersion.v1_21_R2) DARK_OAK_BOAT, + + @NmsAddedIn(NmsVersion.v1_21_R2) DARK_OAK_CHEST_BOAT, + @NmsAddedIn(NmsVersion.v1_13) DOLPHIN, DONKEY, DRAGON_FIREBALL(93), - @NmsAddedIn(NmsVersion.v1_13) DROWNED, - DROPPED_ITEM(2, "item", 1), + @NmsAddedIn(NmsVersion.v1_13) DROWNED, + EGG(62), ELDER_GUARDIAN, + ENDERMAN, + + ENDERMITE, + ENDER_CRYSTAL(51, "end_crystal"), ENDER_DRAGON, @@ -84,10 +112,6 @@ public enum DisguiseType { ENDER_SIGNAL(72, "eye_of_ender"), - ENDERMAN, - - ENDERMITE, - EVOKER, EVOKER_FANGS(79), @@ -102,10 +126,10 @@ public enum DisguiseType { FISHING_HOOK(90, "fishing_bobber"), - @NmsAddedIn(NmsVersion.v1_19_R1) FROG, - @NmsAddedIn(NmsVersion.v1_14) FOX, + @NmsAddedIn(NmsVersion.v1_19_R1) FROG, + GHAST, GIANT, @@ -134,14 +158,22 @@ public enum DisguiseType { ITEM_FRAME(71), - LLAMA, + @NmsAddedIn(NmsVersion.v1_21_R2) JUNGLE_BOAT, - LLAMA_SPIT(68), + @NmsAddedIn(NmsVersion.v1_21_R2) JUNGLE_CHEST_BOAT, LEASH_HITCH(77, "leash_knot"), + LLAMA, + + LLAMA_SPIT(68), + MAGMA_CUBE, + @NmsAddedIn(NmsVersion.v1_21_R2) MANGROVE_BOAT, + + @NmsAddedIn(NmsVersion.v1_21_R2) MANGROVE_CHEST_BOAT, + @NmsAddedIn(NmsVersion.v1_17) MARKER, MINECART(10), @@ -158,20 +190,28 @@ public enum DisguiseType { MINECART_TNT(10, "tnt_minecart", 3), - MODDED_MISC, - MODDED_LIVING, + MODDED_MISC, + MULE, MUSHROOM_COW("mooshroom"), + @NmsAddedIn(NmsVersion.v1_21_R2) OAK_BOAT, + + @NmsAddedIn(NmsVersion.v1_21_R2) OAK_CHEST_BOAT, + OCELOT, @NmsAddedIn(NmsVersion.v1_21_R1) OMINOUS_ITEM_SPAWNER, PAINTING, + @NmsAddedIn(NmsVersion.v1_21_R2) PALE_OAK_BOAT, + + @NmsAddedIn(NmsVersion.v1_21_R2) PALE_OAK_CHEST_BOAT, + @NmsAddedIn(NmsVersion.v1_14) PANDA, PARROT, @@ -180,12 +220,12 @@ public enum DisguiseType { PIG, - @NmsRemovedIn(NmsVersion.v1_16) PIG_ZOMBIE("zombified_piglin"), - @NmsAddedIn(NmsVersion.v1_16) PIGLIN, @NmsAddedIn(NmsVersion.v1_16) PIGLIN_BRUTE, + @NmsRemovedIn(NmsVersion.v1_16) PIG_ZOMBIE("zombified_piglin"), + @NmsAddedIn(NmsVersion.v1_14) PILLAGER, PLAYER, @@ -230,6 +270,10 @@ public enum DisguiseType { SPLASH_POTION(73, "potion"), + @NmsAddedIn(NmsVersion.v1_21_R2) SPRUCE_BOAT, + + @NmsAddedIn(NmsVersion.v1_21_R2) SPRUCE_CHEST_BOAT, + SQUID, STRAY, @@ -244,10 +288,10 @@ public enum DisguiseType { @NmsRemovedIn(NmsVersion.v1_14) TIPPED_ARROW(60), - @NmsAddedIn(NmsVersion.v1_13) TRIDENT(94), - @NmsAddedIn(NmsVersion.v1_14) TRADER_LLAMA, + @NmsAddedIn(NmsVersion.v1_13) TRIDENT(94), + @NmsAddedIn(NmsVersion.v1_13) TROPICAL_FISH, @NmsAddedIn(NmsVersion.v1_13) TURTLE, diff --git a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java index d1a8e51a386..e138ac65f8e 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java @@ -1021,6 +1021,7 @@ protected void updatePose() { } } + @NmsAddedIn(NmsVersion.v1_17) public int getTicksFrozen() { return getData(MetaIndex.ENTITY_TICKS_FROZEN); } diff --git a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/MetaIndex.java b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/MetaIndex.java index c6c0b3c986c..f9d2dd4dc8c 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/MetaIndex.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/MetaIndex.java @@ -87,6 +87,7 @@ import me.libraryaddict.disguise.disguisetypes.watchers.PufferFishWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.RabbitWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.RaiderWatcher; +import me.libraryaddict.disguise.disguisetypes.watchers.SalmonWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.SheepWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.ShulkerWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.SkeletonWatcher; @@ -136,6 +137,7 @@ import org.bukkit.entity.Panda; import org.bukkit.entity.Parrot; import org.bukkit.entity.Rabbit; +import org.bukkit.entity.Salmon; import org.bukkit.entity.Wolf; import org.bukkit.inventory.ItemStack; @@ -248,6 +250,9 @@ public class MetaIndex { @NmsAddedIn(NmsVersion.v1_14) public static MetaIndex ARROW_PIERCE_LEVEL = new MetaIndex<>(ArrowWatcher.class, 2, (byte) 0); + @NmsAddedIn(NmsVersion.v1_21_R2) + public static MetaIndex ARROW_IN_GROUND = new MetaIndex<>(ArrowWatcher.class, 3, false); + @NmsAddedIn(NmsVersion.v1_17) public static MetaIndex AXOLOTL_VARIANT = new MetaIndex<>(AxolotlWatcher.class, 0, NmsVersion.v1_17.isSupported() ? Axolotl.Variant.LUCY : null); @@ -277,15 +282,15 @@ public class MetaIndex { public static MetaIndex BLOCK_DISPLAY_BLOCK_STATE = new MetaIndex<>(BlockDisplayWatcher.class, 0, WrappedBlockState.getDefaultState(StateTypes.AIR)); + public static MetaIndex BOAT_LAST_HIT = new MetaIndex<>(BoatWatcher.class, 0, 0); + + public static MetaIndex BOAT_DIRECTION = new MetaIndex<>(BoatWatcher.class, 1, 1); + /** * How damaged the boat is */ public static MetaIndex BOAT_DAMAGE = new MetaIndex<>(BoatWatcher.class, 2, 0F); - public static MetaIndex BOAT_DIRECTION = new MetaIndex<>(BoatWatcher.class, 1, 1); - - public static MetaIndex BOAT_LAST_HIT = new MetaIndex<>(BoatWatcher.class, 0, 0); - public static MetaIndex BOAT_LEFT_PADDLING = new MetaIndex<>(BoatWatcher.class, 5, false); public static MetaIndex BOAT_RIGHT_PADDLING = new MetaIndex<>(BoatWatcher.class, 4, false); @@ -297,6 +302,7 @@ public class MetaIndex { public static MetaIndex BOAT_TYPE_OLD = new MetaIndex<>(BoatWatcher.class, 3, TreeSpecies.GENERIC); @NmsAddedIn(NmsVersion.v1_19_R1) + @NmsRemovedIn(NmsVersion.v1_21_R2) public static MetaIndex BOAT_TYPE_NEW = new MetaIndex<>(BoatWatcher.class, 3, NmsVersion.v1_19_R1.isSupported() ? Boat.Type.OAK : null); @@ -763,6 +769,10 @@ public class MetaIndex { @NmsAddedIn(NmsVersion.v1_14) public static MetaIndex RAIDER_CASTING_SPELL = new MetaIndex<>(RaiderWatcher.class, 0, false); + @NmsAddedIn(NmsVersion.v1_21_R2) + public static MetaIndex SALMON_VARIANT = + new MetaIndex<>(SalmonWatcher.class, 0, NmsVersion.v1_21_R2.isSupported() ? Salmon.Variant.MEDIUM : null); + /** * Also has 'is sheared' meta */ @@ -956,6 +966,7 @@ private static void orderMetaIndexes() { public static void validateMetadata() { HashMap maxValues = new HashMap<>(); + // Put the amount of indexes in a FlagWatcher class into a map, so we know FlagWatcher.class has say, 8 total indexes in that class for (MetaIndex type : values()) { if (maxValues.containsKey(type.getFlagWatcher()) && maxValues.get(type.getFlagWatcher()) > type.getIndex()) { continue; @@ -967,15 +978,19 @@ public static void validateMetadata() { for (Entry entry : maxValues.entrySet()) { loop: + // Loop over every class with a MetaIndex owned for (int i = 0; i < entry.getValue(); i++) { MetaIndex found = null; + // Loop over every MetaIndex for (MetaIndex type : values()) { + // If the index does not match the entry if (type.getIndex() != i) { continue; } - if (!ReflectionManager.isAssignableFrom(entry.getKey(), type.getFlagWatcher())) { + // If the MetaIndex is not a superclass of the entry + if (!ReflectionManager.isAssignableFrom(type.getFlagWatcher(), entry.getKey())) { continue; } @@ -1055,7 +1070,7 @@ public static MetaIndex getMetaIndex(Class watcherClass, continue; } - if (!ReflectionManager.isAssignableFrom(watcherClass, type.getFlagWatcher())) { + if (!ReflectionManager.isAssignableFrom(type.getFlagWatcher(), watcherClass)) { continue; } @@ -1073,7 +1088,7 @@ public static ArrayList getMetaIndexes(Class w ArrayList list = new ArrayList<>(); for (MetaIndex type : values()) { - if (type == null || !ReflectionManager.isAssignableFrom(watcherClass, type.getFlagWatcher())) { + if (type == null || !ReflectionManager.isAssignableFrom(type.getFlagWatcher(), watcherClass)) { continue; } diff --git a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/AgeableAquaWatcher.java b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/AgeableAquaWatcher.java new file mode 100644 index 00000000000..d27c8038dc6 --- /dev/null +++ b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/AgeableAquaWatcher.java @@ -0,0 +1,44 @@ +package me.libraryaddict.disguise.disguisetypes.watchers; + +import me.libraryaddict.disguise.disguisetypes.Disguise; +import me.libraryaddict.disguise.utilities.reflection.NmsVersion; +import me.libraryaddict.disguise.utilities.reflection.annotations.MethodDescription; +import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn; +import org.jetbrains.annotations.ApiStatus; + +public abstract class AgeableAquaWatcher extends AgeableWatcher { + public AgeableAquaWatcher(Disguise disguise) { + super(disguise); + } + + @ApiStatus.AvailableSince("1.21.3") + @NmsAddedIn(NmsVersion.v1_21_R2) + public boolean isAdult() { + return super.isAdult(); + } + + @ApiStatus.AvailableSince("1.21.3") + @NmsAddedIn(NmsVersion.v1_21_R2) + public boolean isBaby() { + return super.isBaby(); + } + + @MethodDescription("Is this a baby?") + @ApiStatus.AvailableSince("1.21.3") + @NmsAddedIn(NmsVersion.v1_21_R2) + public void setBaby(boolean isBaby) { + super.setBaby(isBaby); + } + + @ApiStatus.AvailableSince("1.21.3") + @NmsAddedIn(NmsVersion.v1_21_R2) + public void setAdult() { + super.setAdult(); + } + + @ApiStatus.AvailableSince("1.21.3") + @NmsAddedIn(NmsVersion.v1_21_R2) + public void setBaby() { + super.setBaby(); + } +} diff --git a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/AllayWatcher.java b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/AllayWatcher.java index e0f0a871e30..a2a0d3c6443 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/AllayWatcher.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/AllayWatcher.java @@ -12,6 +12,7 @@ public AllayWatcher(Disguise disguise) { super(disguise); } + @NmsAddedIn(NmsVersion.v1_19_R1) public boolean isDancing() { return getData(MetaIndex.ALLAY_DANCING); } @@ -22,6 +23,7 @@ public void setDancing(boolean dancing) { sendData(MetaIndex.ALLAY_DANCING, dancing); } + @NmsAddedIn(NmsVersion.v1_19_R1) public boolean isCanDuplicate() { return getData(MetaIndex.ALLAY_CAN_DUPLICATE); } diff --git a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/BoatWatcher.java b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/BoatWatcher.java index bcc574b2278..917be903417 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/BoatWatcher.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/BoatWatcher.java @@ -16,6 +16,11 @@ public class BoatWatcher extends FlagWatcher { public BoatWatcher(Disguise disguise) { super(disguise); + // As of 1.21.3, boat types are now different entity types + if (NmsVersion.v1_21_R2.isSupported()) { + return; + } + if (NmsVersion.v1_19_R1.isSupported()) { setType(Boat.Type.OAK); } else { @@ -62,12 +67,14 @@ public void setBoatShake(int number) { } @NmsAddedIn(NmsVersion.v1_19_R1) + @NmsRemovedIn(NmsVersion.v1_21_R2) @MethodMappedAs("getBoatType") public Boat.Type getType() { return getData(MetaIndex.BOAT_TYPE_NEW); } @NmsAddedIn(NmsVersion.v1_19_R1) + @NmsRemovedIn(NmsVersion.v1_21_R2) @MethodMappedAs("setBoatType") @MethodDescription("What type of wood is this boat made of?") public void setType(Boat.Type type) { diff --git a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/DolphinWatcher.java b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/DolphinWatcher.java index fcaace25674..1f99605690a 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/DolphinWatcher.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/DolphinWatcher.java @@ -2,7 +2,7 @@ import me.libraryaddict.disguise.disguisetypes.Disguise; -public class DolphinWatcher extends InsentientWatcher { +public class DolphinWatcher extends AgeableAquaWatcher { public DolphinWatcher(Disguise disguise) { super(disguise); } diff --git a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/GoatWatcher.java b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/GoatWatcher.java index fdfbab3ff8d..7f77b0045ca 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/GoatWatcher.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/GoatWatcher.java @@ -18,6 +18,7 @@ public void setScreaming(boolean screaming) { sendData(MetaIndex.GOAT_SCREAMING, screaming); } + @NmsAddedIn(NmsVersion.v1_19_R1) public boolean hasLeftHorn() { return getData(MetaIndex.GOAT_HAS_LEFT_HORN); } @@ -27,6 +28,7 @@ public void setHasLeftHorn(boolean hasHorn) { sendData(MetaIndex.GOAT_HAS_LEFT_HORN, hasHorn); } + @NmsAddedIn(NmsVersion.v1_19_R1) public boolean hasRightHorn() { return getData(MetaIndex.GOAT_HAS_RIGHT_HORN); } diff --git a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/LivingWatcher.java b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/LivingWatcher.java index dae0d64484e..59c42c4e99e 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/LivingWatcher.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/LivingWatcher.java @@ -2,6 +2,10 @@ import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.protocol.attribute.Attributes; +import com.github.retrooper.packetevents.protocol.particle.Particle; +import com.github.retrooper.packetevents.protocol.particle.data.ParticleColorData; +import com.github.retrooper.packetevents.protocol.particle.data.ParticleData; +import com.github.retrooper.packetevents.protocol.particle.type.ParticleTypes; import com.github.retrooper.packetevents.util.Vector3i; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes; import lombok.Getter; @@ -26,7 +30,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; -import java.util.Iterator; +import java.util.List; import java.util.Optional; public class LivingWatcher extends FlagWatcher { @@ -246,15 +250,48 @@ public void setPotionParticlesAmbient(boolean particles) { sendData(MetaIndex.LIVING_POTION_AMBIENT, particles); } + @NmsAddedIn(NmsVersion.v1_20_R4) + public void addParticle(Particle particle) { + getData(MetaIndex.LIVING_PARTICLES).add(particle); + sendData(MetaIndex.LIVING_PARTICLES); + } + + @SafeVarargs + @NmsAddedIn(NmsVersion.v1_20_R4) + public final void removeParticles(Particle... particles) { + for (Particle particle : particles) { + getData(MetaIndex.LIVING_PARTICLES).remove(particle); + } + + sendData(MetaIndex.LIVING_PARTICLES); + } + + @NmsAddedIn(NmsVersion.v1_20_R4) + public List> getParticles() { + return Collections.unmodifiableList(getData(MetaIndex.LIVING_PARTICLES)); + } + public Color getParticlesColor() { - int color = getData(MetaIndex.LIVING_POTIONS); - return Color.fromRGB(color); + if (!NmsVersion.v1_20_R4.isSupported()) { + return Color.fromRGB(getData(MetaIndex.LIVING_POTIONS)); + } + + return getData(MetaIndex.LIVING_PARTICLES).stream().filter(p -> p.getType() == ParticleTypes.ENTITY_EFFECT).findAny() + .map(p -> Color.fromRGB(((ParticleColorData) p.getData()).getColor())).orElse(Color.BLACK); } public void setParticlesColor(Color color) { potionEffects.clear(); - sendData(MetaIndex.LIVING_POTIONS, color.asRGB()); + if (NmsVersion.v1_20_R4.isSupported()) { + List> particles = new ArrayList<>(getData(MetaIndex.LIVING_PARTICLES)); + particles.removeIf(d -> d.getType() == ParticleTypes.ENTITY_EFFECT); + particles.add(new Particle<>(ParticleTypes.ENTITY_EFFECT, new ParticleColorData(color.asRGB()))); + + sendData(MetaIndex.LIVING_PARTICLES, particles); + } else { + sendData(MetaIndex.LIVING_POTIONS, color.asRGB()); + } } private int getPotions() { @@ -289,19 +326,19 @@ private int getPotions() { return color.mixColors(colors.toArray(new Color[0])).asRGB(); } + @Deprecated public boolean hasPotionEffect(PotionEffectType type) { return potionEffects.contains(type.getName()); } + @Deprecated public PotionEffectType[] getPotionEffects() { PotionEffectType[] effects = new PotionEffectType[potionEffects.size()]; int i = 0; - Iterator itel = potionEffects.iterator(); - - while (itel.hasNext()) { - PotionEffectType type = PotionEffectType.getByName(itel.next()); + for (String potionEffect : potionEffects) { + PotionEffectType type = PotionEffectType.getByName(potionEffect); effects[i++] = type; } @@ -309,6 +346,8 @@ public PotionEffectType[] getPotionEffects() { return effects; } + @Deprecated + @NmsRemovedIn(NmsVersion.v1_20_R4) public void addPotionEffect(PotionEffectType potionEffect) { if (!hasPotionEffect(potionEffect)) { potionEffects.add(potionEffect.getName()); @@ -317,6 +356,8 @@ public void addPotionEffect(PotionEffectType potionEffect) { sendPotionEffects(); } + @Deprecated + @NmsRemovedIn(NmsVersion.v1_20_R4) public void removePotionEffect(PotionEffectType potionEffect) { if (hasPotionEffect(potionEffect)) { potionEffects.remove(potionEffect.getId()); diff --git a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/SalmonWatcher.java b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/SalmonWatcher.java new file mode 100644 index 00000000000..a04175c50e5 --- /dev/null +++ b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/SalmonWatcher.java @@ -0,0 +1,23 @@ +package me.libraryaddict.disguise.disguisetypes.watchers; + +import me.libraryaddict.disguise.disguisetypes.Disguise; +import me.libraryaddict.disguise.disguisetypes.MetaIndex; +import me.libraryaddict.disguise.utilities.reflection.NmsVersion; +import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn; +import org.bukkit.entity.Salmon; + +public class SalmonWatcher extends FishWatcher { + public SalmonWatcher(Disguise disguise) { + super(disguise); + } + + @NmsAddedIn(NmsVersion.v1_21_R2) + public Salmon.Variant getVariant() { + return getData(MetaIndex.SALMON_VARIANT); + } + + @NmsAddedIn(NmsVersion.v1_21_R2) + public void setVariant(Salmon.Variant variant) { + sendData(MetaIndex.SALMON_VARIANT, variant); + } +} diff --git a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/SquidWatcher.java b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/SquidWatcher.java index 3cb896999d8..104ebd99dab 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/SquidWatcher.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/SquidWatcher.java @@ -2,7 +2,7 @@ import me.libraryaddict.disguise.disguisetypes.Disguise; -public class SquidWatcher extends InsentientWatcher { +public class SquidWatcher extends AgeableAquaWatcher { public SquidWatcher(Disguise disguise) { super(disguise); } diff --git a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/WolfWatcher.java b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/WolfWatcher.java index 2a592f0b306..cff2167f7ad 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/WolfWatcher.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/WolfWatcher.java @@ -73,6 +73,7 @@ public void setAngry(boolean angry) { } } + @NmsAddedIn(NmsVersion.v1_16) public int getAnger() { return getData(MetaIndex.WOLF_ANGER); } diff --git a/plugin/src/main/java/me/libraryaddict/disguise/utilities/params/ParamInfoManager.java b/plugin/src/main/java/me/libraryaddict/disguise/utilities/params/ParamInfoManager.java index a611bc0dee8..de53a99ae8e 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/utilities/params/ParamInfoManager.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/utilities/params/ParamInfoManager.java @@ -9,6 +9,7 @@ import me.libraryaddict.disguise.utilities.params.types.custom.ParamInfoSoundGroup; import me.libraryaddict.disguise.utilities.parser.DisguisePerm; import me.libraryaddict.disguise.utilities.parser.WatcherMethod; +import me.libraryaddict.disguise.utilities.reflection.ReflectionManager; import me.libraryaddict.disguise.utilities.watchers.DisguiseMethods; import java.util.ArrayList; @@ -138,7 +139,7 @@ public static int getValue(WatcherMethod method) { if (declaring == LivingWatcher.class) { return 1; - } else if (!(FlagWatcher.class.isAssignableFrom(declaring)) || declaring == FlagWatcher.class) { + } else if (!(ReflectionManager.isAssignableFrom(FlagWatcher.class, declaring)) || declaring == FlagWatcher.class) { return 2; } diff --git a/plugin/src/main/java/me/libraryaddict/disguise/utilities/params/ParamInfoTypes.java b/plugin/src/main/java/me/libraryaddict/disguise/utilities/params/ParamInfoTypes.java index 8d3df21b438..f4fb0b7c32a 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/utilities/params/ParamInfoTypes.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/utilities/params/ParamInfoTypes.java @@ -64,6 +64,7 @@ import org.bukkit.entity.Parrot; import org.bukkit.entity.Pose; import org.bukkit.entity.Rabbit; +import org.bukkit.entity.Salmon; import org.bukkit.entity.Sniffer; import org.bukkit.entity.TextDisplay; import org.bukkit.entity.TropicalFish; @@ -199,6 +200,10 @@ public List getParamInfos() { paramInfos.add(new ParamInfoEnum(ArmadilloState.class, "Armadillo State", "The current state of an Armadillo")); } + if (NmsVersion.v1_21_R2.isSupported()) { + paramInfos.add(new ParamInfoEnum(Salmon.Variant.class, "Salmon Variant", "The size of a salmon")); + } + paramInfos.add(new ParamInfoEnum(DisguiseConfig.NotifyBar.class, "NotifyBar", "Where the disguised indicator should appear")); paramInfos.add(new ParamInfoEnum(BarColor.class, "BarColor", "The color of the boss bar")); paramInfos.add(new ParamInfoEnum(BarStyle.class, "BarStyle", "The style of the boss bar")); diff --git a/plugin/src/main/java/me/libraryaddict/disguise/utilities/params/types/custom/ParamInfoParticle.java b/plugin/src/main/java/me/libraryaddict/disguise/utilities/params/types/custom/ParamInfoParticle.java index 6e5ae6e0b1d..0fff65acaa0 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/utilities/params/types/custom/ParamInfoParticle.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/utilities/params/types/custom/ParamInfoParticle.java @@ -1,5 +1,7 @@ package me.libraryaddict.disguise.utilities.params.types.custom; +import com.github.retrooper.packetevents.protocol.color.AlphaColor; +import com.github.retrooper.packetevents.protocol.color.Color; import com.github.retrooper.packetevents.protocol.item.type.ItemTypes; import com.github.retrooper.packetevents.protocol.particle.data.ParticleBlockStateData; import com.github.retrooper.packetevents.protocol.particle.data.ParticleColorData; @@ -9,24 +11,27 @@ import com.github.retrooper.packetevents.protocol.particle.data.ParticleItemStackData; import com.github.retrooper.packetevents.protocol.particle.data.ParticleSculkChargeData; import com.github.retrooper.packetevents.protocol.particle.data.ParticleShriekData; +import com.github.retrooper.packetevents.protocol.particle.data.ParticleTrailData; import com.github.retrooper.packetevents.protocol.particle.data.ParticleVibrationData; import com.github.retrooper.packetevents.protocol.particle.type.ParticleType; import com.github.retrooper.packetevents.protocol.particle.type.ParticleTypes; import com.github.retrooper.packetevents.protocol.world.positionsource.builtin.BlockPositionSource; import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState; import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes; +import com.github.retrooper.packetevents.util.Vector3d; import com.github.retrooper.packetevents.util.Vector3i; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.RequiredArgsConstructor; +import lombok.Setter; import lombok.SneakyThrows; +import lombok.experimental.Accessors; import me.libraryaddict.disguise.utilities.DisguiseUtilities; import me.libraryaddict.disguise.utilities.params.ParamInfoManager; import me.libraryaddict.disguise.utilities.params.types.ParamInfoEnum; import me.libraryaddict.disguise.utilities.parser.DisguiseParseException; import me.libraryaddict.disguise.utilities.translations.LibsMsg; import org.apache.commons.lang.StringUtils; -import org.bukkit.Color; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.Nullable; @@ -51,39 +56,121 @@ private static class ParticleInfo { private final Class data; } + public static class PacketColorParser { + private final String[] args; + private final boolean decimalMode; + private final boolean alphaColor; + + PacketColorParser(String[] args, boolean alphaColor) { + this.args = args; + + decimalMode = Arrays.stream(args).anyMatch(s -> s.contains(".")); + this.alphaColor = alphaColor; + } + + private void validateArgs() { + int expect = (args.length >= 3 ? 3 : 1); + + if (expect != args.length && alphaColor) { + expect++; + } + + if (args.length != expect) { + throw new IllegalArgumentException("Expected " + expect + " args, but got " + args.length); + } + } + + public Color parseFromNameOrInt() throws DisguiseParseException { + // At least 1 arg, max of 2 + // Alpha can only have "alpha:colorname" or "int" + + String colorStr = args[args.length - 1]; + + // Must not have 2 args if its an int + if (colorStr.matches("-?\\d+")) { + if (args.length != 1) { + throw new IllegalArgumentException("Only expected 1 arg, not 2 when parsing int color"); + } + + if (alphaColor) { + return new AlphaColor(Integer.parseInt(colorStr)); + } + + return new Color(Integer.parseInt(colorStr)); + } + + int alpha = args.length > 1 ? getInt(args[0]) : 255; + + String[] toPass = args; + + if (alphaColor && (toPass.length == 2 || toPass.length == 4)) { + toPass = Arrays.copyOfRange(toPass, 1, toPass.length); + } + + org.bukkit.Color color = + ((ParamInfoColor) ParamInfoManager.getParamInfo(org.bukkit.Color.class)).parseToColor(StringUtils.join(toPass, ",")); + + if (alphaColor) { + return new AlphaColor(alpha, color.getRed(), color.getGreen(), color.getBlue()); + } + + return new Color(color.getRed(), color.getGreen(), color.getBlue()); + } + + public Color parseFromRGB() { + // At least 3 args were given + + int r = getInt(args[args.length - 3]); + int g = getInt(args[args.length - 2]); + int b = getInt(args[args.length - 1]); + + if (alphaColor) { + int alpha = args.length > 3 ? getInt(args[0]) : 255; + + return new AlphaColor(alpha, r, g, b); + } + + return new Color(r, g, b); + } + + public Color parse() throws DisguiseParseException { + validateArgs(); + + if (args.length > 2) { + return parseFromRGB(); + } + + return parseFromNameOrInt(); + } + + private int getInt(String s) { + if (decimalMode) { + return (int) (Double.parseDouble(s) * 255); + } + + return Integer.parseInt(s); + } + + } + @RequiredArgsConstructor + @Accessors(chain = true) + @Setter private static class ColorParser { private final String[] split; - private final boolean decimalPointColor; + private boolean alphaColor; @Getter private int argsConsumed; - public float[] getColor() throws DisguiseParseException { + public Color getColor() throws DisguiseParseException { + // Might need to redo this whole class, esp for alpha support int need = getArgsNeed(); int start = split.length - (argsConsumed + need); String[] copyOf = Arrays.copyOfRange(split, start, start + need); argsConsumed += need; - if (copyOf.length == 3) { - return new float[]{Float.parseFloat(copyOf[0]), Float.parseFloat(copyOf[1]), Float.parseFloat(copyOf[2])}; - } else if (copyOf[0].equals("-1")) { - return new float[]{-1, -1, -1}; - } - - Color color = ((ParamInfoColor) ParamInfoManager.getParamInfo(Color.class)).parseToColor(StringUtils.join(copyOf, ",")); - - float r = color.getRed(); - float g = color.getGreen(); - float b = color.getBlue(); - - if (decimalPointColor) { - r /= 255f; - g /= 255f; - b /= 255f; - } - - return new float[]{r, g, b}; + return new PacketColorParser(copyOf, alphaColor).parse(); } public int getArgsRemaining() { @@ -91,6 +178,11 @@ public int getArgsRemaining() { } private int getArgsNeed() { + if (alphaColor) { + // We always expect to consume all args at the current state of it, so return everything + return getArgsRemaining(); + } + return split[split.length - (1 + argsConsumed)].matches("-?\\d+(\\.\\d+)?") ? 3 : 1; } @@ -203,39 +295,39 @@ public Set getEnums(String tabComplete) { return enums; } - private String colorToString(int color) { - for (Map.Entry entry : ParamInfoColor.getStaticColors().entrySet()) { - Color c = entry.getValue(); + private String alphaColorToString(int color) { + if (color == -1) { + return String.valueOf(color); + } + + AlphaColor alphaColor = new AlphaColor(color); + + for (Map.Entry entry : ParamInfoColor.getStaticColors().entrySet()) { + org.bukkit.Color c = entry.getValue(); - if (c.asRGB() != color) { + if (c.getRed() != alphaColor.red() || c.getGreen() != alphaColor.green() || c.getBlue() != alphaColor.blue()) { continue; } - return entry.getKey(); + // Always include the alpha to show usage + return alphaColor.alpha() + ":" + entry.getKey(); } - return String.valueOf(color); + // Return in Alpha:Red,Green,Blue format to be more readable + return alphaColor.alpha() + ":" + alphaColor.red() + "," + alphaColor.green() + "," + alphaColor.blue(); } - private String colorToString(float red, float green, float blue) { - int r = (int) red * 255; - int g = (int) green * 255; - int b = (int) blue * 255; + private String colorToString(int red, int green, int blue) { + for (Map.Entry entry : ParamInfoColor.getStaticColors().entrySet()) { + org.bukkit.Color c = entry.getValue(); - for (Map.Entry entry : ParamInfoColor.getStaticColors().entrySet()) { - Color c = entry.getValue(); - - if (r != c.getRed() || g != c.getGreen() || b != c.getBlue()) { + if (red != c.getRed() || green != c.getGreen() || blue != c.getBlue()) { continue; } return entry.getKey(); } - if (red % 1 == 0 && green % 1 == 0 && blue % 1 == 0) { - return (int) red + "," + (int) green + "," + (int) blue; - } - return red + "," + green + "," + blue; } @@ -260,9 +352,14 @@ public String toString(Object object) { returns += ":" + dust.getScale(); } - returns += ":" + colorToString(dust.getRed(), dust.getGreen(), dust.getBlue()); + returns += ":" + colorToString((int) (dust.getRed() * 255), (int) (dust.getGreen() * 255), (int) (dust.getBlue() * 255)); } else if (data instanceof ParticleColorData) { - returns += ":" + colorToString(((ParticleColorData) data).getColor()); + returns += ":" + alphaColorToString(((ParticleColorData) data).getColor()); + } else if (data instanceof ParticleTrailData) { + ParticleTrailData trail = (ParticleTrailData) data; + + returns += ":" + trail.getTarget().getX() + "," + trail.getTarget().getY() + "," + trail.getTarget().getZ() + ":" + + colorToString(trail.getColor().red(), trail.getColor().green(), trail.getColor().blue()); } else if (data instanceof ParticleDustColorTransitionData) { ParticleDustColorTransitionData dust = (ParticleDustColorTransitionData) data; @@ -272,9 +369,10 @@ public String toString(Object object) { returns += dust.getScale() + ":"; } - returns += colorToString(dust.getStartRed(), dust.getStartGreen(), dust.getStartBlue()); + returns += + colorToString((int) (dust.getStartRed() * 255), (int) (dust.getStartGreen() * 255), (int) (dust.getStartBlue() * 255)); returns += ":"; - returns += colorToString(dust.getEndRed(), dust.getEndGreen(), dust.getEndBlue()); + returns += colorToString((int) (dust.getEndRed() * 255), (int) (dust.getEndGreen() * 255), (int) (dust.getEndBlue() * 255)); } else if (data instanceof ParticleSculkChargeData) { returns += ":" + ((ParticleSculkChargeData) data).getRoll(); } else if (data instanceof ParticleVibrationData) { @@ -352,11 +450,11 @@ public Object fromString(String string) throws DisguiseParseException { } } else if (cl == ParticleDustData.class) { - float[] color = new float[3]; + Color color = new Color(0, 0, 0); float scale = 1; if (split.length > 0) { - ColorParser parser = new ColorParser(split, true); + ColorParser parser = new ColorParser(split).setAlphaColor(false); if (!parser.canConsume()) { throw new DisguiseParseException(LibsMsg.PARSE_PARTICLE_DUST, name, string); @@ -381,7 +479,7 @@ public Object fromString(String string) throws DisguiseParseException { } } - data = new ParticleDustData(scale, color[0], color[1], color[2]); + data = new ParticleDustData(scale, color); } else if (cl == ParticleDustColorTransitionData.class) { // Scale is optional, color is either a name, or three numbers. Same for the second color. // So it can be from 1 to 7 args. @@ -390,10 +488,10 @@ public Object fromString(String string) throws DisguiseParseException { // We work backwards. Figure out the last color, then if we have enough args, another color, then if we have enough args, the // scale, then if we have enough args, throw. - ColorParser parser = new ColorParser(split, true); + ColorParser parser = new ColorParser(split).setAlphaColor(false); - float[] color1; - float[] color2; + Color color1; + Color color2; try { color2 = parser.getColor(); @@ -415,7 +513,7 @@ public Object fromString(String string) throws DisguiseParseException { scale = Math.min(100, Math.max(0.2f, scale)); } - data = new ParticleDustColorTransitionData(scale, color1[0], color1[1], color1[2], color2[0], color2[1], color2[2]); + data = new ParticleDustColorTransitionData(scale, color1, color2); } else if (cl == ParticleShriekData.class) { int delay = 60; @@ -442,7 +540,7 @@ public Object fromString(String string) throws DisguiseParseException { data = new ParticleSculkChargeData(roll); } else if (cl == ParticleColorData.class) { - int color = getColorAsInt(string, split, name); + int color = getColorAsInt(string, split, name, true); data = new ParticleColorData(color); } else if (cl == ParticleVibrationData.class) { @@ -468,6 +566,40 @@ public Object fromString(String string) throws DisguiseParseException { } data = new ParticleVibrationData(startBlock, sourceBlock, ticks); + } else if (cl == ParticleTrailData.class) { + // x,y,z + // x,y,z,red + // x,y,z,red,blue,green + // 3, 4, 6 + if (split.length < 3 || split.length == 5 || split.length > 6) { + throw new DisguiseParseException(LibsMsg.PARSE_PARTICLE_TRAIL, name, string); + } + + // Verify the first 3 args are doubles + for (int i = 0; i < 3; i++) { + if (split[i].matches("-?\\d+(\\.\\d+)?")) { + continue; + } + + throw new DisguiseParseException(LibsMsg.PARSE_PARTICLE_TRAIL, name, string); + } + + Vector3d target = new Vector3d(Double.parseDouble(split[0]), Double.parseDouble(split[1]), Double.parseDouble(split[2])); + + Color color; + + if (split.length > 3) { + try { + color = new ColorParser(Arrays.copyOfRange(split, 3, split.length)).getColor(); + } catch (Exception ex) { + throw new DisguiseParseException(LibsMsg.PARSE_PARTICLE_TRAIL, name, string); + } + } else { + // Creaking has two colors 16545810 : 6250335 + color = new Color(95, 95, 255); + } + + data = new ParticleTrailData(target, color); } if (data == null) { @@ -482,19 +614,16 @@ public Object fromString(String string) throws DisguiseParseException { return new com.github.retrooper.packetevents.protocol.particle.Particle<>(pType, data); } - private static int getColorAsInt(String string, String[] split, String name) throws DisguiseParseException { - int color = 0; + private static int getColorAsInt(String string, String[] split, String name, boolean alphaColor) throws DisguiseParseException { + int color = alphaColor ? -1 : 0; if (split.length == 1 && split[0].matches("-?\\d+")) { color = Integer.parseInt(split[0]); } else if (split.length > 0) { - ColorParser parser = new ColorParser(split, false); + ColorParser parser = new ColorParser(split).setAlphaColor(alphaColor); try { - float[] colors = parser.getColor(); - - color = - new com.github.retrooper.packetevents.protocol.color.Color((int) colors[0], (int) colors[1], (int) colors[2]).asRGB(); + color = parser.getColor().asRGB(); } catch (Exception ex) { throw new DisguiseParseException(LibsMsg.PARSE_PARTICLE_COLOR, name, string); } @@ -503,6 +632,7 @@ private static int getColorAsInt(String string, String[] split, String name) thr throw new DisguiseParseException(LibsMsg.PARSE_PARTICLE_COLOR, name, string); } } + return color; } diff --git a/plugin/src/main/java/me/libraryaddict/disguise/utilities/parser/DisguiseParser.java b/plugin/src/main/java/me/libraryaddict/disguise/utilities/parser/DisguiseParser.java index 2eca066f255..18b7bb77a68 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/utilities/parser/DisguiseParser.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/utilities/parser/DisguiseParser.java @@ -187,13 +187,19 @@ public static void createDefaultMethods() { continue; } + if (getMethod.getAdded() != setMethod.getAdded() || getMethod.getRemoved() != setMethod.getRemoved()) { + LibsDisguises.getInstance().getLogger().severe(String.format( + "The methods %s and %s do not have matching NmsAdded and NmsRemoved, this is an oversight by the author of " + + "LibsDisguises", getMethod.getName(), setMethod.getName())); + } + Object defaultValue = null; // Value is randomish so shouldn't be checked, should always specify value when setting if (!setMethod.isRandomDefault()) { Object invokeWith = watcher; - if (!FlagWatcher.class.isAssignableFrom(getMethod.getWatcherClass())) { + if (!ReflectionManager.isAssignableFrom(FlagWatcher.class, getMethod.getWatcherClass())) { invokeWith = disguise; } @@ -1116,7 +1122,7 @@ public static Disguise parseDisguise(CommandSender sender, Entity target, String MethodHandle handle = m.getMethod(); - if (FlagWatcher.class.isAssignableFrom(m.getWatcherClass())) { + if (ReflectionManager.isAssignableFrom(FlagWatcher.class, m.getWatcherClass())) { handle = handle.bindTo(disguise.getWatcher()); } else { handle = handle.bindTo(disguise); diff --git a/plugin/src/main/java/me/libraryaddict/disguise/utilities/parser/WatcherMethod.java b/plugin/src/main/java/me/libraryaddict/disguise/utilities/parser/WatcherMethod.java index fc2c822c6ae..d4a3c476b47 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/utilities/parser/WatcherMethod.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/utilities/parser/WatcherMethod.java @@ -26,6 +26,7 @@ public class WatcherMethod { private final boolean[] hiddenFor; private final String description; private final boolean noVisibleDifference; + private final int added, removed; // Used for verifying correctness public boolean isUsable(DisguiseType type) { return !unusableBy[type.ordinal()]; diff --git a/plugin/src/main/java/me/libraryaddict/disguise/utilities/reflection/NmsVersion.java b/plugin/src/main/java/me/libraryaddict/disguise/utilities/reflection/NmsVersion.java index 023292823c8..d7af1651133 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/utilities/reflection/NmsVersion.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/utilities/reflection/NmsVersion.java @@ -18,6 +18,7 @@ public enum NmsVersion { v1_20_R3("1.20.3", "1.20.4"), v1_20_R4("1.20.5", "1.20.6"), v1_21_R1("1.21", "1.21.1"), + v1_21_R2("1.21.3"), // 1.21.2 was hotfixed by 1.21.3 UNSUPPORTED("N/A"); @Getter diff --git a/plugin/src/main/java/me/libraryaddict/disguise/utilities/reflection/ReflectionManager.java b/plugin/src/main/java/me/libraryaddict/disguise/utilities/reflection/ReflectionManager.java index 406d6e74fcc..daa271f6a7c 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/utilities/reflection/ReflectionManager.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/utilities/reflection/ReflectionManager.java @@ -31,8 +31,11 @@ import me.libraryaddict.disguise.disguisetypes.FlagWatcher; import me.libraryaddict.disguise.disguisetypes.MetaIndex; import me.libraryaddict.disguise.disguisetypes.RabbitType; +import me.libraryaddict.disguise.disguisetypes.watchers.AgeableAquaWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.AgeableWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.ArrowWatcher; +import me.libraryaddict.disguise.disguisetypes.watchers.BoatWatcher; +import me.libraryaddict.disguise.disguisetypes.watchers.ChestBoatWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.FishWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.GuardianWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.IllagerWizardWatcher; @@ -94,6 +97,7 @@ import org.bukkit.entity.Parrot; import org.bukkit.entity.Player; import org.bukkit.entity.Rabbit; +import org.bukkit.entity.Salmon; import org.bukkit.entity.Tameable; import org.bukkit.entity.Wolf; import org.bukkit.entity.Zombie; @@ -1452,6 +1456,8 @@ public static T convertMetaFromSerialized(MetaIndex index, Object value) return (T) nmsReflection.getPaintingFromInt((int) value); } else if (index == MetaIndex.WOLF_VARIANT) { return (T) nmsReflection.getWolfVariantFromInt((int) value); + } else if (index == MetaIndex.SALMON_VARIANT) { + return (T) Salmon.Variant.valueOf(((String) value).toUpperCase(Locale.ENGLISH)); } else if (index == MetaIndex.CAT_COLLAR || index == MetaIndex.WOLF_COLLAR) { return (T) AnimalColor.getColorByWool((int) value); } else if (index.isItemStack()) { @@ -1543,6 +1549,12 @@ public static Object convertMetaToSerialized(MetaIndex index, Object value) { if (value instanceof Wolf.Variant) { return nmsReflection.getWolfVariantAsInt((Wolf.Variant) value); } + + if (NmsVersion.v1_21_R2.isSupported()) { + if (value instanceof Salmon.Variant) { + return ((Salmon.Variant) value).name().toLowerCase(Locale.ENGLISH); + } + } } } } @@ -1647,14 +1659,27 @@ public static String getItemName(Material material) { return null; } - public static boolean isAssignableFrom(Class toCheck, Class checkAgainst) { - if (!NmsVersion.v1_14.isSupported() && toCheck != checkAgainst) { - if (toCheck == OcelotWatcher.class) { - toCheck = TameableWatcher.class; + public static boolean isAssignableFrom(Class baseAbstractClass, Class extendingClass) { + if (!NmsVersion.v1_14.isSupported() && extendingClass != baseAbstractClass) { + if (extendingClass == OcelotWatcher.class) { + extendingClass = TameableWatcher.class; } } - return checkAgainst.isAssignableFrom(toCheck); + if (!NmsVersion.v1_21_R2.isSupported() && extendingClass != baseAbstractClass) { + // We want to make sure that AquaWatcher does not say it is owned by AgeableWatcher + + // If AquaWatcher is extended by extendingClass + // If baseAbstractClass is or extends AgeableWatcher + // Then we can make it jump + if (AgeableAquaWatcher.class.isAssignableFrom(extendingClass) && baseAbstractClass.isAssignableFrom(AgeableWatcher.class)) { + extendingClass = InsentientWatcher.class; + } + } + + // If adding more in here, don't forget to change getSuperClass + + return baseAbstractClass.isAssignableFrom(extendingClass); } public static Class getSuperClass(Class cl) { @@ -1662,12 +1687,16 @@ public static Class getSuperClass(Class cl) { return null; } - if (!NmsVersion.v1_14.isSupported()) { - if (cl == OcelotWatcher.class) { - return TameableWatcher.class; - } + if (!NmsVersion.v1_14.isSupported() && cl == OcelotWatcher.class) { + return TameableWatcher.class; + } + + if (!NmsVersion.v1_21_R2.isSupported() && cl == AgeableAquaWatcher.class) { + return InsentientWatcher.class; } + // If adding more in here, don't forget to change isAssignableFrom + return cl.getSuperclass(); } @@ -1945,7 +1974,6 @@ private static Class getFlagWatcher(DisguiseType disguise watcherClass = ModdedWatcher.class; break; case COD: - case SALMON: watcherClass = FishWatcher.class; break; case SPECTRAL_ARROW: @@ -1960,7 +1988,6 @@ private static Class getFlagWatcher(DisguiseType disguise case MINECART_TNT: watcherClass = MinecartWatcher.class; break; - case SPIDER: case CAVE_SPIDER: watcherClass = SpiderWatcher.class; break; @@ -1983,6 +2010,30 @@ private static Class getFlagWatcher(DisguiseType disguise case PUFFERFISH: watcherClass = PufferFishWatcher.class; break; + case ACACIA_CHEST_BOAT: + case BAMBOO_CHEST_RAFT: + case BIRCH_CHEST_BOAT: + case CHERRY_CHEST_BOAT: + case DARK_OAK_CHEST_BOAT: + case JUNGLE_CHEST_BOAT: + case MANGROVE_CHEST_BOAT: + case OAK_CHEST_BOAT: + case PALE_OAK_CHEST_BOAT: + case SPRUCE_CHEST_BOAT: + watcherClass = ChestBoatWatcher.class; + break; + case ACACIA_BOAT: + case BAMBOO_RAFT: + case BIRCH_BOAT: + case CHERRY_BOAT: + case DARK_OAK_BOAT: + case JUNGLE_BOAT: + case MANGROVE_BOAT: + case OAK_BOAT: + case PALE_OAK_BOAT: + case SPRUCE_BOAT: + watcherClass = BoatWatcher.class; + break; default: watcherClass = (Class) Class.forName( "me.libraryaddict.disguise.disguisetypes.watchers." + toReadable(disguiseType.name()) + "Watcher"); @@ -2480,6 +2531,11 @@ public static EntityDataType getEntityDataType(MetaIndex index, Field field) { return EntityDataTypes.BLOCK_FACE; } else if (index == MetaIndex.AREA_EFFECT_CLOUD_COLOR) { return EntityDataTypes.INT; + } else if (index == MetaIndex.SALMON_VARIANT) { + // TODO PacketEvents may add Salmon variant at a future date, also could be doing something redundant here + // Such as could be mapping the variant to what we serialize + // Doubt it though + return EntityDataTypes.STRING; } Type type1 = ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]; diff --git a/plugin/src/main/java/me/libraryaddict/disguise/utilities/reflection/annotations/NmsSupported.java b/plugin/src/main/java/me/libraryaddict/disguise/utilities/reflection/annotations/NmsSupported.java new file mode 100644 index 00000000000..8537da3b5ca --- /dev/null +++ b/plugin/src/main/java/me/libraryaddict/disguise/utilities/reflection/annotations/NmsSupported.java @@ -0,0 +1,19 @@ +package me.libraryaddict.disguise.utilities.reflection.annotations; + +import me.libraryaddict.disguise.disguisetypes.FlagWatcher; +import me.libraryaddict.disguise.utilities.reflection.NmsVersion; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * The disguises that use this FlagWatcher only supported this feature in [Version] + *
+ * Eg, FishWatcher only supported AgeableWatcher in 1.21.3 + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface NmsSupported { + NmsVersion version(); + + Class watcher(); +} diff --git a/plugin/src/main/java/me/libraryaddict/disguise/utilities/sounds/DisguiseSoundEnums.java b/plugin/src/main/java/me/libraryaddict/disguise/utilities/sounds/DisguiseSoundEnums.java index fc3f0383f19..1832215879c 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/utilities/sounds/DisguiseSoundEnums.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/utilities/sounds/DisguiseSoundEnums.java @@ -3,9 +3,7 @@ import lombok.Getter; import me.libraryaddict.disguise.LibsDisguises; import me.libraryaddict.disguise.utilities.sounds.SoundGroup.SoundType; -import org.bukkit.Sound; -import java.util.Arrays; import java.util.HashMap; /** @@ -13,187 +11,179 @@ */ @Getter public enum DisguiseSoundEnums { - ALLAY(Sound.ENTITY_ALLAY_HURT, null, Sound.ENTITY_ALLAY_DEATH, - new Sound[]{Sound.ENTITY_ALLAY_AMBIENT_WITHOUT_ITEM, Sound.ENTITY_ALLAY_AMBIENT_WITH_ITEM}, Sound.ENTITY_ALLAY_ITEM_GIVEN, - Sound.ENTITY_ALLAY_ITEM_TAKEN, Sound.ENTITY_ALLAY_ITEM_THROWN), + ALLAY("ENTITY_ALLAY_HURT", null, "ENTITY_ALLAY_DEATH", + new String[]{"ENTITY_ALLAY_AMBIENT_WITHOUT_ITEM", "ENTITY_ALLAY_AMBIENT_WITH_ITEM"}, "ENTITY_ALLAY_ITEM_GIVEN", + "ENTITY_ALLAY_ITEM_TAKEN", "ENTITY_ALLAY_ITEM_THROWN"), - ARMADILLO(new Sound[]{Sound.ENTITY_ARMADILLO_HURT, Sound.ENTITY_ARMADILLO_HURT_REDUCED}, Sound.ENTITY_ARMADILLO_STEP, - Sound.ENTITY_ARMADILLO_DEATH, Sound.ENTITY_ARMADILLO_AMBIENT, Sound.ENTITY_ARMADILLO_BRUSH, Sound.ENTITY_ARMADILLO_PEEK, - Sound.ENTITY_ARMADILLO_ROLL, Sound.ENTITY_ARMADILLO_LAND, Sound.ENTITY_ARMADILLO_SCUTE_DROP, Sound.ENTITY_ARMADILLO_UNROLL_FINISH, - Sound.ENTITY_ARMADILLO_UNROLL_START), + ARMADILLO(new String[]{"ENTITY_ARMADILLO_HURT", "ENTITY_ARMADILLO_HURT_REDUCED"}, "ENTITY_ARMADILLO_STEP", "ENTITY_ARMADILLO_DEATH", + "ENTITY_ARMADILLO_AMBIENT", "ENTITY_ARMADILLO_BRUSH", "ENTITY_ARMADILLO_PEEK", "ENTITY_ARMADILLO_ROLL", "ENTITY_ARMADILLO_LAND", + "ENTITY_ARMADILLO_SCUTE_DROP", "ENTITY_ARMADILLO_UNROLL_FINISH", "ENTITY_ARMADILLO_UNROLL_START"), - ARMOR_STAND(Sound.ENTITY_ARMOR_STAND_HIT, null, Sound.ENTITY_ARMOR_STAND_BREAK, Sound.ENTITY_ARMOR_STAND_FALL, - Sound.ENTITY_ARMOR_STAND_PLACE), + ARMOR_STAND("ENTITY_ARMOR_STAND_HIT", null, "ENTITY_ARMOR_STAND_BREAK", "ENTITY_ARMOR_STAND_FALL", "ENTITY_ARMOR_STAND_PLACE"), - ARROW(null, null, null, null, Sound.ENTITY_ARROW_HIT, Sound.ENTITY_ARROW_SHOOT), + ARROW(null, null, null, null, "ENTITY_ARROW_HIT", "ENTITY_ARROW_SHOOT"), - AXOLOTL(Sound.ENTITY_AXOLOTL_HURT, Sound.ENTITY_AXOLOTL_SWIM, Sound.ENTITY_AXOLOTL_DEATH, - new Sound[]{Sound.ENTITY_AXOLOTL_IDLE_WATER, Sound.ENTITY_AXOLOTL_IDLE_AIR}, Sound.ENTITY_AXOLOTL_ATTACK, - Sound.ENTITY_AXOLOTL_SPLASH), + AXOLOTL("ENTITY_AXOLOTL_HURT", "ENTITY_AXOLOTL_SWIM", "ENTITY_AXOLOTL_DEATH", + new String[]{"ENTITY_AXOLOTL_IDLE_WATER", "ENTITY_AXOLOTL_IDLE_AIR"}, "ENTITY_AXOLOTL_ATTACK", "ENTITY_AXOLOTL_SPLASH"), - BAT(Sound.ENTITY_BAT_HURT, null, Sound.ENTITY_BAT_DEATH, Sound.ENTITY_BAT_AMBIENT, Sound.ENTITY_PLAYER_SMALL_FALL, - Sound.ENTITY_BAT_LOOP, Sound.ENTITY_PLAYER_BIG_FALL, Sound.ENTITY_BAT_TAKEOFF), + BAT("ENTITY_BAT_HURT", null, "ENTITY_BAT_DEATH", "ENTITY_BAT_AMBIENT", "ENTITY_PLAYER_SMALL_FALL", "ENTITY_BAT_LOOP", + "ENTITY_PLAYER_BIG_FALL", "ENTITY_BAT_TAKEOFF"), - BEE(Sound.ENTITY_BEE_HURT, null, Sound.ENTITY_BEE_DEATH, null, Sound.ENTITY_BEE_LOOP, Sound.ENTITY_BEE_LOOP_AGGRESSIVE, - Sound.ENTITY_BEE_POLLINATE, Sound.ENTITY_BEE_STING), + BEE("ENTITY_BEE_HURT", null, "ENTITY_BEE_DEATH", null, "ENTITY_BEE_LOOP", "ENTITY_BEE_LOOP_AGGRESSIVE", "ENTITY_BEE_POLLINATE", + "ENTITY_BEE_STING"), - BLAZE(Sound.ENTITY_BLAZE_HURT, null, Sound.ENTITY_BLAZE_DEATH, Sound.ENTITY_BLAZE_AMBIENT, Sound.ENTITY_PLAYER_SMALL_FALL, - Sound.ENTITY_PLAYER_BIG_FALL, Sound.ENTITY_BLAZE_BURN, Sound.ENTITY_BLAZE_SHOOT), + BLAZE("ENTITY_BLAZE_HURT", null, "ENTITY_BLAZE_DEATH", "ENTITY_BLAZE_AMBIENT", "ENTITY_PLAYER_SMALL_FALL", "ENTITY_PLAYER_BIG_FALL", + "ENTITY_BLAZE_BURN", "ENTITY_BLAZE_SHOOT"), BLOCK_DISPLAY(null, null, null, null), - BOAT(null, Sound.ENTITY_BOAT_PADDLE_WATER, null, null, Sound.ENTITY_BOAT_PADDLE_LAND), + BOAT(null, "ENTITY_BOAT_PADDLE_WATER", null, null, "ENTITY_BOAT_PADDLE_LAND"), - BOGGED(Sound.ENTITY_BOGGED_HURT, Sound.ENTITY_BOGGED_STEP, Sound.ENTITY_BOGGED_DEATH, Sound.ENTITY_BOGGED_AMBIENT, - Sound.ENTITY_BOGGED_SHEAR), + BOGGED("ENTITY_BOGGED_HURT", "ENTITY_BOGGED_STEP", "ENTITY_BOGGED_DEATH", "ENTITY_BOGGED_AMBIENT", "ENTITY_BOGGED_SHEAR"), - BREEZE(Sound.ENTITY_BREEZE_HURT, null, Sound.ENTITY_BREEZE_DEATH, - new Sound[]{Sound.ENTITY_BREEZE_IDLE_AIR, Sound.ENTITY_BREEZE_IDLE_GROUND}, Sound.ENTITY_BREEZE_LAND, Sound.ENTITY_BREEZE_JUMP, - Sound.ENTITY_BREEZE_INHALE, Sound.ENTITY_BREEZE_SHOOT, Sound.ENTITY_BREEZE_SLIDE, Sound.ENTITY_BREEZE_WIND_BURST), + BREEZE("ENTITY_BREEZE_HURT", null, "ENTITY_BREEZE_DEATH", new String[]{"ENTITY_BREEZE_IDLE_AIR", "ENTITY_BREEZE_IDLE_GROUND"}, + "ENTITY_BREEZE_LAND", "ENTITY_BREEZE_JUMP", "ENTITY_BREEZE_INHALE", "ENTITY_BREEZE_SHOOT", "ENTITY_BREEZE_SLIDE", + "ENTITY_BREEZE_WIND_BURST"), - BREEZE_WIND_CHARGE(null, null, Sound.ENTITY_WIND_CHARGE_WIND_BURST, null, Sound.ENTITY_WIND_CHARGE_THROW), + BREEZE_WIND_CHARGE(null, null, "ENTITY_WIND_CHARGE_WIND_BURST", null, "ENTITY_WIND_CHARGE_THROW"), - CAMEL(Sound.ENTITY_CAMEL_HURT, new Sound[]{Sound.ENTITY_CAMEL_STEP, Sound.ENTITY_CAMEL_STEP_SAND}, Sound.ENTITY_CAMEL_DEATH, - Sound.ENTITY_CAMEL_AMBIENT, Sound.ENTITY_CAMEL_DASH, Sound.ENTITY_CAMEL_DASH_READY, Sound.ENTITY_CAMEL_EAT, - Sound.ENTITY_CAMEL_SADDLE, Sound.ENTITY_CAMEL_SIT, Sound.ENTITY_CAMEL_STAND), + CAMEL("ENTITY_CAMEL_HURT", new String[]{"ENTITY_CAMEL_STEP", "ENTITY_CAMEL_STEP_SAND"}, "ENTITY_CAMEL_DEATH", "ENTITY_CAMEL_AMBIENT", + "ENTITY_CAMEL_DASH", "ENTITY_CAMEL_DASH_READY", "ENTITY_CAMEL_EAT", "ENTITY_CAMEL_SADDLE", "ENTITY_CAMEL_SIT", + "ENTITY_CAMEL_STAND"), - CAT(Sound.ENTITY_CAT_HURT, null, Sound.ENTITY_CAT_DEATH, Sound.ENTITY_CAT_AMBIENT, Sound.ENTITY_CAT_PURR, Sound.ENTITY_CAT_PURREOW, - Sound.ENTITY_CAT_HISS), + CAT("ENTITY_CAT_HURT", null, "ENTITY_CAT_DEATH", "ENTITY_CAT_AMBIENT", "ENTITY_CAT_PURR", "ENTITY_CAT_PURREOW", "ENTITY_CAT_HISS"), - CAVE_SPIDER(Sound.ENTITY_SPIDER_HURT, Sound.ENTITY_SPIDER_STEP, Sound.ENTITY_SPIDER_DEATH, Sound.ENTITY_SPIDER_AMBIENT), + CAVE_SPIDER("ENTITY_SPIDER_HURT", "ENTITY_SPIDER_STEP", "ENTITY_SPIDER_DEATH", "ENTITY_SPIDER_AMBIENT"), - CHEST_BOAT(null, Sound.ENTITY_BOAT_PADDLE_WATER, null, null, Sound.ENTITY_BOAT_PADDLE_LAND), + CHEST_BOAT(null, "ENTITY_BOAT_PADDLE_WATER", null, null, "ENTITY_BOAT_PADDLE_LAND"), - CHICKEN(Sound.ENTITY_CHICKEN_HURT, Sound.ENTITY_CHICKEN_STEP, Sound.ENTITY_CHICKEN_DEATH, Sound.ENTITY_CHICKEN_AMBIENT, - Sound.ENTITY_PLAYER_SMALL_FALL, Sound.ENTITY_CHICKEN_EGG, Sound.ENTITY_PLAYER_BIG_FALL), + CHICKEN("ENTITY_CHICKEN_HURT", "ENTITY_CHICKEN_STEP", "ENTITY_CHICKEN_DEATH", "ENTITY_CHICKEN_AMBIENT", "ENTITY_PLAYER_SMALL_FALL", + "ENTITY_CHICKEN_EGG", "ENTITY_PLAYER_BIG_FALL"), - COD(Sound.ENTITY_COD_HURT, null, Sound.ENTITY_COD_DEATH, Sound.ENTITY_COD_AMBIENT, Sound.ENTITY_COD_FLOP, Sound.ENTITY_FISH_SWIM), + COD("ENTITY_COD_HURT", null, "ENTITY_COD_DEATH", "ENTITY_COD_AMBIENT", "ENTITY_COD_FLOP", "ENTITY_FISH_SWIM"), - COW(Sound.ENTITY_COW_HURT, Sound.ENTITY_COW_STEP, Sound.ENTITY_COW_DEATH, Sound.ENTITY_COW_AMBIENT), + COW("ENTITY_COW_HURT", "ENTITY_COW_STEP", "ENTITY_COW_DEATH", "ENTITY_COW_AMBIENT"), - CREEPER(Sound.ENTITY_CREEPER_HURT, Sound.BLOCK_GRASS_STEP, Sound.ENTITY_CREEPER_DEATH, null, Sound.ENTITY_CREEPER_PRIMED), + CREAKING(null, "ENTITY_CREAKING_STEP", "ENTITY_CREAKING_DEATH", "ENTITY_CREAKING_AMBIENT", "ENTITY_CREAKING_SWAY", + "ENTITY_CREAKING_ACTIVATE", "ENTITY_CREAKING_DEACTIVATE", "ENTITY_CREAKING_SPAWN", "ENTITY_CREAKING_FREEZE", + "ENTITY_CREAKING_UNFREEZE", "ENTITY_CREAKING_ATTACK"), - DOLPHIN(Sound.ENTITY_DOLPHIN_HURT, Sound.ENTITY_DOLPHIN_SWIM, Sound.ENTITY_DOLPHIN_DEATH, - new Sound[]{Sound.ENTITY_DOLPHIN_AMBIENT, Sound.ENTITY_DOLPHIN_AMBIENT_WATER}, Sound.ENTITY_DOLPHIN_ATTACK, - Sound.ENTITY_DOLPHIN_EAT, Sound.ENTITY_DOLPHIN_SPLASH, Sound.ENTITY_DOLPHIN_PLAY, Sound.ENTITY_DOLPHIN_JUMP, - Sound.ENTITY_FISH_SWIM), + // They're the same as CREAKING, just different rules + CREAKING_TRANSIENT(null, "ENTITY_CREAKING_STEP", "ENTITY_CREAKING_DEATH", "ENTITY_CREAKING_AMBIENT", "ENTITY_CREAKING_SWAY", + "ENTITY_CREAKING_ACTIVATE", "ENTITY_CREAKING_DEACTIVATE", "ENTITY_CREAKING_SPAWN", "ENTITY_CREAKING_FREEZE", + "ENTITY_CREAKING_UNFREEZE", "ENTITY_CREAKING_ATTACK"), - DONKEY(Sound.ENTITY_DONKEY_HURT, new Sound[]{Sound.BLOCK_GRASS_STEP, Sound.ENTITY_HORSE_STEP_WOOD}, Sound.ENTITY_DONKEY_DEATH, - Sound.ENTITY_DONKEY_AMBIENT, Sound.ENTITY_HORSE_GALLOP, Sound.ENTITY_HORSE_SADDLE, Sound.ENTITY_DONKEY_ANGRY, - Sound.ENTITY_HORSE_ARMOR, Sound.ENTITY_HORSE_LAND, Sound.ENTITY_HORSE_JUMP, Sound.ENTITY_HORSE_ANGRY, Sound.ENTITY_DONKEY_CHEST), + CREEPER("ENTITY_CREEPER_HURT", "BLOCK_GRASS_STEP", "ENTITY_CREEPER_DEATH", null, "ENTITY_CREEPER_PRIMED"), - DROWNED(new Sound[]{Sound.ENTITY_DROWNED_HURT, Sound.ENTITY_DROWNED_HURT_WATER}, - new Sound[]{Sound.ENTITY_DROWNED_STEP, Sound.ENTITY_DROWNED_SWIM}, - new Sound[]{Sound.ENTITY_DROWNED_DEATH, Sound.ENTITY_DROWNED_DEATH_WATER}, - new Sound[]{Sound.ENTITY_DROWNED_AMBIENT, Sound.ENTITY_DROWNED_AMBIENT_WATER}, Sound.ENTITY_DROWNED_SHOOT), + DOLPHIN("ENTITY_DOLPHIN_HURT", "ENTITY_DOLPHIN_SWIM", "ENTITY_DOLPHIN_DEATH", + new String[]{"ENTITY_DOLPHIN_AMBIENT", "ENTITY_DOLPHIN_AMBIENT_WATER"}, "ENTITY_DOLPHIN_ATTACK", "ENTITY_DOLPHIN_EAT", + "ENTITY_DOLPHIN_SPLASH", "ENTITY_DOLPHIN_PLAY", "ENTITY_DOLPHIN_JUMP", "ENTITY_FISH_SWIM"), - ELDER_GUARDIAN(new Sound[]{Sound.ENTITY_ELDER_GUARDIAN_HURT, Sound.ENTITY_ELDER_GUARDIAN_HURT_LAND}, null, - new Sound[]{Sound.ENTITY_ELDER_GUARDIAN_DEATH, Sound.ENTITY_ELDER_GUARDIAN_DEATH_LAND}, - new Sound[]{Sound.ENTITY_ELDER_GUARDIAN_AMBIENT, Sound.ENTITY_ELDER_GUARDIAN_AMBIENT_LAND}, Sound.ENTITY_ELDER_GUARDIAN_FLOP), + DONKEY("ENTITY_DONKEY_HURT", new String[]{"BLOCK_GRASS_STEP", "ENTITY_HORSE_STEP_WOOD"}, "ENTITY_DONKEY_DEATH", "ENTITY_DONKEY_AMBIENT", + "ENTITY_HORSE_GALLOP", "ENTITY_HORSE_SADDLE", "ENTITY_DONKEY_ANGRY", "ENTITY_HORSE_ARMOR", "ENTITY_HORSE_LAND", "ENTITY_HORSE_JUMP", + "ENTITY_HORSE_ANGRY", "ENTITY_DONKEY_CHEST"), - ENDER_DRAGON(Sound.ENTITY_ENDER_DRAGON_HURT, null, Sound.ENTITY_ENDER_DRAGON_DEATH, Sound.ENTITY_ENDER_DRAGON_AMBIENT, - Sound.ENTITY_GENERIC_SMALL_FALL, Sound.ENTITY_GENERIC_BIG_FALL, Sound.ENTITY_ENDER_DRAGON_FLAP, Sound.ENTITY_ENDER_DRAGON_GROWL), + DROWNED(new String[]{"ENTITY_DROWNED_HURT", "ENTITY_DROWNED_HURT_WATER"}, new String[]{"ENTITY_DROWNED_STEP", "ENTITY_DROWNED_SWIM"}, + new String[]{"ENTITY_DROWNED_DEATH", "ENTITY_DROWNED_DEATH_WATER"}, + new String[]{"ENTITY_DROWNED_AMBIENT", "ENTITY_DROWNED_AMBIENT_WATER"}, "ENTITY_DROWNED_SHOOT"), - ENDERMAN(Sound.ENTITY_ENDERMAN_HURT, Sound.BLOCK_GRASS_STEP, Sound.ENTITY_ENDERMAN_DEATH, Sound.ENTITY_ENDERMAN_AMBIENT, - Sound.ENTITY_ENDERMAN_SCREAM, Sound.ENTITY_ENDERMAN_TELEPORT, Sound.ENTITY_ENDERMAN_STARE), + ELDER_GUARDIAN(new String[]{"ENTITY_ELDER_GUARDIAN_HURT", "ENTITY_ELDER_GUARDIAN_HURT_LAND"}, null, + new String[]{"ENTITY_ELDER_GUARDIAN_DEATH", "ENTITY_ELDER_GUARDIAN_DEATH_LAND"}, + new String[]{"ENTITY_ELDER_GUARDIAN_AMBIENT", "ENTITY_ELDER_GUARDIAN_AMBIENT_LAND"}, "ENTITY_ELDER_GUARDIAN_FLOP"), - ENDERMITE(Sound.ENTITY_ENDERMITE_HURT, Sound.ENTITY_ENDERMITE_STEP, Sound.ENTITY_ENDERMITE_DEATH, Sound.ENTITY_ENDERMITE_AMBIENT), + ENDER_DRAGON("ENTITY_ENDER_DRAGON_HURT", null, "ENTITY_ENDER_DRAGON_DEATH", "ENTITY_ENDER_DRAGON_AMBIENT", "ENTITY_GENERIC_SMALL_FALL", + "ENTITY_GENERIC_BIG_FALL", "ENTITY_ENDER_DRAGON_FLAP", "ENTITY_ENDER_DRAGON_GROWL"), - EVOKER(Sound.ENTITY_EVOKER_HURT, null, Sound.ENTITY_EVOKER_DEATH, Sound.ENTITY_EVOKER_AMBIENT, Sound.ENTITY_EVOKER_CAST_SPELL, - Sound.ENTITY_EVOKER_PREPARE_ATTACK, Sound.ENTITY_EVOKER_PREPARE_SUMMON, Sound.ENTITY_EVOKER_PREPARE_WOLOLO), + ENDERMAN("ENTITY_ENDERMAN_HURT", "BLOCK_GRASS_STEP", "ENTITY_ENDERMAN_DEATH", "ENTITY_ENDERMAN_AMBIENT", "ENTITY_ENDERMAN_SCREAM", + "ENTITY_ENDERMAN_TELEPORT", "ENTITY_ENDERMAN_STARE"), - EVOKER_FANGS(null, null, null, null, Sound.ENTITY_EVOKER_FANGS_ATTACK), + ENDERMITE("ENTITY_ENDERMITE_HURT", "ENTITY_ENDERMITE_STEP", "ENTITY_ENDERMITE_DEATH", "ENTITY_ENDERMITE_AMBIENT"), - FOX(Sound.ENTITY_FOX_HURT, null, Sound.ENTITY_FOX_DEATH, Sound.ENTITY_FOX_AMBIENT, Sound.ENTITY_FOX_AGGRO, Sound.ENTITY_FOX_BITE, - Sound.ENTITY_FOX_EAT, Sound.ENTITY_FOX_SCREECH, Sound.ENTITY_FOX_SLEEP, Sound.ENTITY_FOX_SPIT, Sound.ENTITY_FOX_SNIFF, - Sound.ENTITY_FOX_TELEPORT), + EVOKER("ENTITY_EVOKER_HURT", null, "ENTITY_EVOKER_DEATH", "ENTITY_EVOKER_AMBIENT", "ENTITY_EVOKER_CAST_SPELL", + "ENTITY_EVOKER_PREPARE_ATTACK", "ENTITY_EVOKER_PREPARE_SUMMON", "ENTITY_EVOKER_PREPARE_WOLOLO"), - FROG(Sound.ENTITY_FROG_HURT, Sound.ENTITY_FROG_STEP, Sound.ENTITY_FROG_DEATH, Sound.ENTITY_FROG_AMBIENT, Sound.ENTITY_FROG_EAT, - Sound.ENTITY_FROG_LAY_SPAWN, Sound.ENTITY_FROG_LONG_JUMP, Sound.ENTITY_FROG_TONGUE), + EVOKER_FANGS(null, null, null, null, "ENTITY_EVOKER_FANGS_ATTACK"), - GHAST(Sound.ENTITY_GHAST_HURT, null, Sound.ENTITY_GHAST_DEATH, Sound.ENTITY_GHAST_AMBIENT, Sound.ENTITY_PLAYER_SMALL_FALL, - Sound.ENTITY_GHAST_SHOOT, Sound.ENTITY_PLAYER_BIG_FALL, Sound.ENTITY_GHAST_SCREAM, Sound.ENTITY_GHAST_WARN), + FOX("ENTITY_FOX_HURT", null, "ENTITY_FOX_DEATH", "ENTITY_FOX_AMBIENT", "ENTITY_FOX_AGGRO", "ENTITY_FOX_BITE", "ENTITY_FOX_EAT", + "ENTITY_FOX_SCREECH", "ENTITY_FOX_SLEEP", "ENTITY_FOX_SPIT", "ENTITY_FOX_SNIFF", "ENTITY_FOX_TELEPORT"), - GIANT(Sound.ENTITY_PLAYER_HURT, Sound.BLOCK_GRASS_STEP, null, null), + FROG("ENTITY_FROG_HURT", "ENTITY_FROG_STEP", "ENTITY_FROG_DEATH", "ENTITY_FROG_AMBIENT", "ENTITY_FROG_EAT", "ENTITY_FROG_LAY_SPAWN", + "ENTITY_FROG_LONG_JUMP", "ENTITY_FROG_TONGUE"), - GLOW_SQUID(Sound.ENTITY_GLOW_SQUID_HURT, null, Sound.ENTITY_GLOW_SQUID_DEATH, Sound.ENTITY_GLOW_SQUID_AMBIENT, - Sound.ENTITY_GLOW_SQUID_SQUIRT, Sound.ENTITY_FISH_SWIM), + GHAST("ENTITY_GHAST_HURT", null, "ENTITY_GHAST_DEATH", "ENTITY_GHAST_AMBIENT", "ENTITY_PLAYER_SMALL_FALL", "ENTITY_GHAST_SHOOT", + "ENTITY_PLAYER_BIG_FALL", "ENTITY_GHAST_SCREAM", "ENTITY_GHAST_WARN"), - GOAT(Sound.ENTITY_GOAT_HURT, Sound.ENTITY_GOAT_STEP, Sound.ENTITY_GOAT_DEATH, Sound.ENTITY_GOAT_AMBIENT, Sound.ENTITY_GOAT_MILK, - Sound.ENTITY_GOAT_EAT, Sound.ENTITY_GOAT_LONG_JUMP, Sound.ENTITY_GOAT_PREPARE_RAM, Sound.ENTITY_GOAT_PREPARE_RAM, - Sound.ENTITY_GOAT_RAM_IMPACT, Sound.ENTITY_GOAT_SCREAMING_AMBIENT, Sound.ENTITY_GOAT_SCREAMING_DEATH, - Sound.ENTITY_GOAT_SCREAMING_EAT, Sound.ENTITY_GOAT_SCREAMING_MILK, Sound.ENTITY_GOAT_SCREAMING_RAM_IMPACT, - Sound.ENTITY_GOAT_SCREAMING_PREPARE_RAM, Sound.ENTITY_GOAT_SCREAMING_LONG_JUMP, Sound.ENTITY_GOAT_SCREAMING_HURT), + GIANT("ENTITY_PLAYER_HURT", "BLOCK_GRASS_STEP", null, null), - GUARDIAN(new Sound[]{Sound.ENTITY_GUARDIAN_HURT, Sound.ENTITY_GUARDIAN_HURT_LAND}, null, - new Sound[]{Sound.ENTITY_GUARDIAN_DEATH, Sound.ENTITY_GUARDIAN_DEATH_LAND}, - new Sound[]{Sound.ENTITY_GUARDIAN_AMBIENT, Sound.ENTITY_GUARDIAN_AMBIENT_LAND}, Sound.ENTITY_GUARDIAN_FLOP), + GLOW_SQUID("ENTITY_GLOW_SQUID_HURT", null, "ENTITY_GLOW_SQUID_DEATH", "ENTITY_GLOW_SQUID_AMBIENT", "ENTITY_GLOW_SQUID_SQUIRT", + "ENTITY_FISH_SWIM"), - HOGLIN(Sound.ENTITY_HOGLIN_HURT, Sound.ENTITY_HOGLIN_STEP, Sound.ENTITY_HOGLIN_DEATH, Sound.ENTITY_HOGLIN_AMBIENT, - Sound.ENTITY_HOGLIN_CONVERTED_TO_ZOMBIFIED, Sound.ENTITY_HOGLIN_ANGRY, Sound.ENTITY_HOGLIN_RETREAT), + GOAT("ENTITY_GOAT_HURT", "ENTITY_GOAT_STEP", "ENTITY_GOAT_DEATH", "ENTITY_GOAT_AMBIENT", "ENTITY_GOAT_MILK", "ENTITY_GOAT_EAT", + "ENTITY_GOAT_LONG_JUMP", "ENTITY_GOAT_PREPARE_RAM", "ENTITY_GOAT_PREPARE_RAM", "ENTITY_GOAT_RAM_IMPACT", + "ENTITY_GOAT_SCREAMING_AMBIENT", "ENTITY_GOAT_SCREAMING_DEATH", "ENTITY_GOAT_SCREAMING_EAT", "ENTITY_GOAT_SCREAMING_MILK", + "ENTITY_GOAT_SCREAMING_RAM_IMPACT", "ENTITY_GOAT_SCREAMING_PREPARE_RAM", "ENTITY_GOAT_SCREAMING_LONG_JUMP", + "ENTITY_GOAT_SCREAMING_HURT"), - HORSE(Sound.ENTITY_HORSE_HURT, new Sound[]{Sound.ENTITY_HORSE_STEP, Sound.ENTITY_HORSE_STEP_WOOD}, Sound.ENTITY_HORSE_DEATH, - Sound.ENTITY_HORSE_AMBIENT, Sound.ENTITY_HORSE_GALLOP, Sound.ENTITY_HORSE_SADDLE, Sound.ENTITY_DONKEY_ANGRY, - Sound.ENTITY_HORSE_ARMOR, Sound.ENTITY_HORSE_LAND, Sound.ENTITY_HORSE_JUMP, Sound.ENTITY_HORSE_ANGRY, Sound.ENTITY_HORSE_EAT, - Sound.ENTITY_HORSE_BREATHE), + GUARDIAN(new String[]{"ENTITY_GUARDIAN_HURT", "ENTITY_GUARDIAN_HURT_LAND"}, null, + new String[]{"ENTITY_GUARDIAN_DEATH", "ENTITY_GUARDIAN_DEATH_LAND"}, + new String[]{"ENTITY_GUARDIAN_AMBIENT", "ENTITY_GUARDIAN_AMBIENT_LAND"}, "ENTITY_GUARDIAN_FLOP"), - HUSK(Sound.ENTITY_HUSK_HURT, Sound.ENTITY_HUSK_STEP, Sound.ENTITY_HUSK_DEATH, Sound.ENTITY_HUSK_AMBIENT, - Sound.ENTITY_HUSK_CONVERTED_TO_ZOMBIE), + HOGLIN("ENTITY_HOGLIN_HURT", "ENTITY_HOGLIN_STEP", "ENTITY_HOGLIN_DEATH", "ENTITY_HOGLIN_AMBIENT", + "ENTITY_HOGLIN_CONVERTED_TO_ZOMBIFIED", "ENTITY_HOGLIN_ANGRY", "ENTITY_HOGLIN_RETREAT"), - ILLUSIONER(Sound.ENTITY_ILLUSIONER_HURT, null, Sound.ENTITY_ILLUSIONER_DEATH, Sound.ENTITY_ILLUSIONER_AMBIENT, - Sound.ENTITY_ILLUSIONER_CAST_SPELL, Sound.ENTITY_ILLUSIONER_PREPARE_BLINDNESS, Sound.ENTITY_ILLUSIONER_PREPARE_MIRROR, - Sound.ENTITY_ILLUSIONER_MIRROR_MOVE), + HORSE("ENTITY_HORSE_HURT", new String[]{"ENTITY_HORSE_STEP", "ENTITY_HORSE_STEP_WOOD"}, "ENTITY_HORSE_DEATH", "ENTITY_HORSE_AMBIENT", + "ENTITY_HORSE_GALLOP", "ENTITY_HORSE_SADDLE", "ENTITY_DONKEY_ANGRY", "ENTITY_HORSE_ARMOR", "ENTITY_HORSE_LAND", "ENTITY_HORSE_JUMP", + "ENTITY_HORSE_ANGRY", "ENTITY_HORSE_EAT", "ENTITY_HORSE_BREATHE"), + + HUSK("ENTITY_HUSK_HURT", "ENTITY_HUSK_STEP", "ENTITY_HUSK_DEATH", "ENTITY_HUSK_AMBIENT", "ENTITY_HUSK_CONVERTED_TO_ZOMBIE"), + + ILLUSIONER("ENTITY_ILLUSIONER_HURT", null, "ENTITY_ILLUSIONER_DEATH", "ENTITY_ILLUSIONER_AMBIENT", "ENTITY_ILLUSIONER_CAST_SPELL", + "ENTITY_ILLUSIONER_PREPARE_BLINDNESS", "ENTITY_ILLUSIONER_PREPARE_MIRROR", "ENTITY_ILLUSIONER_MIRROR_MOVE"), INTERACTION(null, null, null, null), - IRON_GOLEM(Sound.ENTITY_IRON_GOLEM_HURT, Sound.ENTITY_IRON_GOLEM_STEP, Sound.ENTITY_IRON_GOLEM_DEATH, Sound.ENTITY_IRON_GOLEM_ATTACK), + IRON_GOLEM("ENTITY_IRON_GOLEM_HURT", "ENTITY_IRON_GOLEM_STEP", "ENTITY_IRON_GOLEM_DEATH", "ENTITY_IRON_GOLEM_ATTACK"), ITEM_DISPLAY(null, null, null, null), - LLAMA(Sound.ENTITY_LLAMA_HURT, Sound.ENTITY_LLAMA_STEP, Sound.ENTITY_LLAMA_DEATH, Sound.ENTITY_LLAMA_AMBIENT, Sound.ENTITY_LLAMA_ANGRY, - Sound.ENTITY_LLAMA_CHEST, Sound.ENTITY_LLAMA_EAT, Sound.ENTITY_LLAMA_SWAG), + LLAMA("ENTITY_LLAMA_HURT", "ENTITY_LLAMA_STEP", "ENTITY_LLAMA_DEATH", "ENTITY_LLAMA_AMBIENT", "ENTITY_LLAMA_ANGRY", + "ENTITY_LLAMA_CHEST", "ENTITY_LLAMA_EAT", "ENTITY_LLAMA_SWAG"), - MAGMA_CUBE(Sound.ENTITY_MAGMA_CUBE_HURT, Sound.ENTITY_MAGMA_CUBE_JUMP, - new Sound[]{Sound.ENTITY_MAGMA_CUBE_DEATH, Sound.ENTITY_MAGMA_CUBE_DEATH_SMALL}, null, Sound.ENTITY_MAGMA_CUBE_SQUISH, - Sound.ENTITY_MAGMA_CUBE_SQUISH_SMALL), + MAGMA_CUBE("ENTITY_MAGMA_CUBE_HURT", "ENTITY_MAGMA_CUBE_JUMP", new String[]{"ENTITY_MAGMA_CUBE_DEATH", "ENTITY_MAGMA_CUBE_DEATH_SMALL"}, + null, "ENTITY_MAGMA_CUBE_SQUISH", "ENTITY_MAGMA_CUBE_SQUISH_SMALL"), - MINECART(null, Sound.ENTITY_MINECART_RIDING, null, null, Sound.ENTITY_MINECART_INSIDE, Sound.ENTITY_MINECART_INSIDE_UNDERWATER), + MINECART(null, "ENTITY_MINECART_RIDING", null, null, "ENTITY_MINECART_INSIDE", "ENTITY_MINECART_INSIDE_UNDERWATER"), - MINECART_CHEST(null, Sound.ENTITY_MINECART_RIDING, null, null, Sound.ENTITY_MINECART_INSIDE, Sound.ENTITY_MINECART_INSIDE_UNDERWATER), + MINECART_CHEST(null, "ENTITY_MINECART_RIDING", null, null, "ENTITY_MINECART_INSIDE", "ENTITY_MINECART_INSIDE_UNDERWATER"), - MINECART_COMMAND(null, Sound.ENTITY_MINECART_RIDING, null, null, Sound.ENTITY_MINECART_INSIDE, Sound.ENTITY_MINECART_INSIDE_UNDERWATER), + MINECART_COMMAND(null, "ENTITY_MINECART_RIDING", null, null, "ENTITY_MINECART_INSIDE", "ENTITY_MINECART_INSIDE_UNDERWATER"), - MINECART_FURNACE(null, Sound.ENTITY_MINECART_RIDING, null, null, Sound.ENTITY_MINECART_INSIDE, Sound.ENTITY_MINECART_INSIDE_UNDERWATER), + MINECART_FURNACE(null, "ENTITY_MINECART_RIDING", null, null, "ENTITY_MINECART_INSIDE", "ENTITY_MINECART_INSIDE_UNDERWATER"), - MINECART_HOPPER(null, Sound.ENTITY_MINECART_RIDING, null, null, Sound.ENTITY_MINECART_INSIDE, Sound.ENTITY_MINECART_INSIDE_UNDERWATER), + MINECART_HOPPER(null, "ENTITY_MINECART_RIDING", null, null, "ENTITY_MINECART_INSIDE", "ENTITY_MINECART_INSIDE_UNDERWATER"), - MINECART_MOB_SPAWNER(null, Sound.ENTITY_MINECART_RIDING, null, null, Sound.ENTITY_MINECART_INSIDE, - Sound.ENTITY_MINECART_INSIDE_UNDERWATER), + MINECART_MOB_SPAWNER(null, "ENTITY_MINECART_RIDING", null, null, "ENTITY_MINECART_INSIDE", "ENTITY_MINECART_INSIDE_UNDERWATER"), - MINECART_TNT(null, Sound.ENTITY_MINECART_RIDING, null, null, Sound.ENTITY_MINECART_INSIDE, Sound.ENTITY_MINECART_INSIDE_UNDERWATER), + MINECART_TNT(null, "ENTITY_MINECART_RIDING", null, null, "ENTITY_MINECART_INSIDE", "ENTITY_MINECART_INSIDE_UNDERWATER"), - MULE(Sound.ENTITY_MULE_HURT, Sound.BLOCK_GRASS_STEP, Sound.ENTITY_MULE_DEATH, Sound.ENTITY_MULE_AMBIENT, Sound.ENTITY_MULE_CHEST), + MULE("ENTITY_MULE_HURT", "BLOCK_GRASS_STEP", "ENTITY_MULE_DEATH", "ENTITY_MULE_AMBIENT", "ENTITY_MULE_CHEST"), - MUSHROOM_COW(Sound.ENTITY_COW_HURT, Sound.ENTITY_COW_STEP, Sound.ENTITY_COW_DEATH, Sound.ENTITY_COW_AMBIENT), + MUSHROOM_COW("ENTITY_COW_HURT", "ENTITY_COW_STEP", "ENTITY_COW_DEATH", "ENTITY_COW_AMBIENT"), - OCELOT(Sound.ENTITY_CAT_HURT, Sound.BLOCK_GRASS_STEP, Sound.ENTITY_CAT_DEATH, - new Sound[]{Sound.ENTITY_CAT_AMBIENT, Sound.ENTITY_CAT_PURR, Sound.ENTITY_CAT_PURREOW}, Sound.ENTITY_CAT_HISS), + OCELOT("ENTITY_CAT_HURT", "BLOCK_GRASS_STEP", "ENTITY_CAT_DEATH", + new String[]{"ENTITY_CAT_AMBIENT", "ENTITY_CAT_PURR", "ENTITY_CAT_PURREOW"}, "ENTITY_CAT_HISS"), - PANDA(Sound.ENTITY_PANDA_HURT, Sound.ENTITY_PANDA_STEP, Sound.ENTITY_PANDA_DEATH, - new Sound[]{Sound.ENTITY_PANDA_AMBIENT, Sound.ENTITY_PANDA_AGGRESSIVE_AMBIENT, Sound.ENTITY_PANDA_WORRIED_AMBIENT}, - Sound.ENTITY_PANDA_BITE, Sound.ENTITY_PANDA_CANT_BREED, Sound.ENTITY_PANDA_EAT, Sound.ENTITY_PANDA_PRE_SNEEZE, - Sound.ENTITY_PANDA_SNEEZE), + PANDA("ENTITY_PANDA_HURT", "ENTITY_PANDA_STEP", "ENTITY_PANDA_DEATH", + new String[]{"ENTITY_PANDA_AMBIENT", "ENTITY_PANDA_AGGRESSIVE_AMBIENT", "ENTITY_PANDA_WORRIED_AMBIENT"}, "ENTITY_PANDA_BITE", + "ENTITY_PANDA_CANT_BREED", "ENTITY_PANDA_EAT", "ENTITY_PANDA_PRE_SNEEZE", "ENTITY_PANDA_SNEEZE"), - PARROT(Sound.ENTITY_PARROT_HURT, Sound.ENTITY_PARROT_STEP, Sound.ENTITY_PARROT_DEATH, Sound.ENTITY_PARROT_AMBIENT, - (Object) Arrays.stream(Sound.values()).filter( - sound -> sound.name().contains("PARROT_IMITATE") || sound == Sound.ENTITY_PARROT_EAT || sound == Sound.ENTITY_PARROT_FLY) - .toArray(Sound[]::new)), + PARROT("ENTITY_PARROT_HURT", "ENTITY_PARROT_STEP", "ENTITY_PARROT_DEATH", "ENTITY_PARROT_AMBIENT", + (Object[]) new String[]{"ENTITY_PARROT_EAT", "ENTITY_PARROT_FLY", ".*PARROT_IMITATE.*"}), - PIG(Sound.ENTITY_PIG_HURT, Sound.ENTITY_PIG_STEP, Sound.ENTITY_PIG_DEATH, Sound.ENTITY_PIG_AMBIENT), + PIG("ENTITY_PIG_HURT", "ENTITY_PIG_STEP", "ENTITY_PIG_DEATH", "ENTITY_PIG_AMBIENT"), - PIGLIN(Sound.ENTITY_PIGLIN_HURT, Sound.ENTITY_PIGLIN_STEP, Sound.ENTITY_PIGLIN_DEATH, Sound.ENTITY_PIGLIN_AMBIENT, - Sound.ENTITY_PIGLIN_RETREAT, Sound.ENTITY_PIGLIN_JEALOUS, Sound.ENTITY_PIGLIN_ADMIRING_ITEM, Sound.ENTITY_PIGLIN_CELEBRATE, - Sound.ENTITY_PIGLIN_ANGRY), + PIGLIN("ENTITY_PIGLIN_HURT", "ENTITY_PIGLIN_STEP", "ENTITY_PIGLIN_DEATH", "ENTITY_PIGLIN_AMBIENT", "ENTITY_PIGLIN_RETREAT", + "ENTITY_PIGLIN_JEALOUS", "ENTITY_PIGLIN_ADMIRING_ITEM", "ENTITY_PIGLIN_CELEBRATE", "ENTITY_PIGLIN_ANGRY"), PIGLIN_BRUTE("ENTITY_PIGLIN_BRUTE_HURT", "ENTITY_PIGLIN_BRUTE_STEP", "ENTITY_PIGLIN_BRUTE_DEATH", "ENTITY_PIGLIN_BRUTE_AMBIENT", "ENTITY_PIGLIN_BRUTE_CONVERTED_TO_ZOMBIFIED", "ENTITY_PIGLIN_BRUTE_ANGRY"), @@ -201,133 +191,126 @@ public enum DisguiseSoundEnums { PIG_ZOMBIE("ENTITY_ZOMBIE_PIGMAN_HURT", null, "ENTITY_ZOMBIE_PIGMAN_DEATH", "ENTITY_ZOMBIE_PIGMAN_AMBIENT", "ENTITY_ZOMBIE_PIGMAN_ANGRY"), - PILLAGER(Sound.ENTITY_PILLAGER_HURT, Sound.BLOCK_GRASS_STEP, Sound.ENTITY_PILLAGER_DEATH, Sound.ENTITY_PILLAGER_AMBIENT, - Sound.ENTITY_PILLAGER_CELEBRATE), + PILLAGER("ENTITY_PILLAGER_HURT", "BLOCK_GRASS_STEP", "ENTITY_PILLAGER_DEATH", "ENTITY_PILLAGER_AMBIENT", "ENTITY_PILLAGER_CELEBRATE"), + + PLAYER("ENTITY_PLAYER_HURT", new String[]{"BLOCK_.*_STEP"}, "ENTITY_PLAYER_DEATH", null), + + PHANTOM("ENTITY_PHANTOM_HURT", new String[]{"ENTITY_PHANTOM_FLAP", "ENTITY_PHANTOM_SWOOP"}, "ENTITY_PHANTOM_DEATH", + "ENTITY_PHANTOM_AMBIENT", "ENTITY_PHANTOM_BITE"), - PLAYER(Sound.ENTITY_PLAYER_HURT, - Arrays.stream(Sound.values()).filter(sound -> sound.name().startsWith("BLOCK_") && sound.name().endsWith("_STEP")) - .toArray(Sound[]::new), Sound.ENTITY_PLAYER_DEATH, null), + POLAR_BEAR("ENTITY_POLAR_BEAR_HURT", "ENTITY_POLAR_BEAR_STEP", "ENTITY_POLAR_BEAR_DEATH", + new String[]{"ENTITY_POLAR_BEAR_AMBIENT", "ENTITY_POLAR_BEAR_AMBIENT_BABY"}, "ENTITY_POLAR_BEAR_WARNING"), - PHANTOM(Sound.ENTITY_PHANTOM_HURT, new Sound[]{Sound.ENTITY_PHANTOM_FLAP, Sound.ENTITY_PHANTOM_SWOOP}, Sound.ENTITY_PHANTOM_DEATH, - Sound.ENTITY_PHANTOM_AMBIENT, Sound.ENTITY_PHANTOM_BITE), + PUFFERFISH("ENTITY_PUFFER_FISH_HURT", null, "ENTITY_PUFFER_FISH_DEATH", "ENTITY_PUFFER_FISH_AMBIENT", "ENTITY_PUFFER_FISH_BLOW_OUT", + "ENTITY_PUFFER_FISH_BLOW_UP", "ENTITY_PUFFER_FISH_FLOP", "ENTITY_PUFFER_FISH_STING", "ENTITY_FISH_SWIM"), - POLAR_BEAR(Sound.ENTITY_POLAR_BEAR_HURT, Sound.ENTITY_POLAR_BEAR_STEP, Sound.ENTITY_POLAR_BEAR_DEATH, - new Sound[]{Sound.ENTITY_POLAR_BEAR_AMBIENT, Sound.ENTITY_POLAR_BEAR_AMBIENT_BABY}, Sound.ENTITY_POLAR_BEAR_WARNING), + RABBIT("ENTITY_RABBIT_HURT", "ENTITY_RABBIT_JUMP", "ENTITY_RABBIT_DEATH", "ENTITY_RABBIT_AMBIENT", "ENTITY_RABBIT_ATTACK"), - PUFFERFISH(Sound.ENTITY_PUFFER_FISH_HURT, null, Sound.ENTITY_PUFFER_FISH_DEATH, Sound.ENTITY_PUFFER_FISH_AMBIENT, - Sound.ENTITY_PUFFER_FISH_BLOW_OUT, Sound.ENTITY_PUFFER_FISH_BLOW_UP, Sound.ENTITY_PUFFER_FISH_FLOP, Sound.ENTITY_PUFFER_FISH_STING, - Sound.ENTITY_FISH_SWIM), + RAVAGER("ENTITY_RAVAGER_HURT", "ENTITY_RAVAGER_STEP", "ENTITY_RAVAGER_DEATH", "ENTITY_RAVAGER_AMBIENT", "ENTITY_RAVAGER_ATTACK", + "ENTITY_RAVAGER_CELEBRATE", "ENTITY_RAVAGER_ROAR", "ENTITY_RAVAGER_STUNNED"), - RABBIT(Sound.ENTITY_RABBIT_HURT, Sound.ENTITY_RABBIT_JUMP, Sound.ENTITY_RABBIT_DEATH, Sound.ENTITY_RABBIT_AMBIENT, - Sound.ENTITY_RABBIT_ATTACK), + SALMON("ENTITY_SALMON_HURT", null, "ENTITY_SALMON_DEATH", "ENTITY_SALMON_AMBIENT", "ENTITY_SALMON_FLOP", "ENTITY_FISH_SWIM"), - RAVAGER(Sound.ENTITY_RAVAGER_HURT, Sound.ENTITY_RAVAGER_STEP, Sound.ENTITY_RAVAGER_DEATH, Sound.ENTITY_RAVAGER_AMBIENT, - Sound.ENTITY_RAVAGER_ATTACK, Sound.ENTITY_RAVAGER_CELEBRATE, Sound.ENTITY_RAVAGER_ROAR, Sound.ENTITY_RAVAGER_STUNNED), + SHEEP("ENTITY_SHEEP_HURT", "ENTITY_SHEEP_STEP", "ENTITY_SHEEP_DEATH", "ENTITY_SHEEP_AMBIENT", "ENTITY_SHEEP_SHEAR"), - SALMON(Sound.ENTITY_SALMON_HURT, null, Sound.ENTITY_SALMON_DEATH, Sound.ENTITY_SALMON_AMBIENT, Sound.ENTITY_SALMON_FLOP, - Sound.ENTITY_FISH_SWIM), + SHULKER(new String[]{"ENTITY_SHULKER_HURT", "ENTITY_SHULKER_HURT_CLOSED"}, null, "ENTITY_SHULKER_DEATH", "ENTITY_SHULKER_AMBIENT", + "ENTITY_SHULKER_OPEN", "ENTITY_SHULKER_CLOSE", "ENTITY_SHULKER_TELEPORT"), - SHEEP(Sound.ENTITY_SHEEP_HURT, Sound.ENTITY_SHEEP_STEP, Sound.ENTITY_SHEEP_DEATH, Sound.ENTITY_SHEEP_AMBIENT, Sound.ENTITY_SHEEP_SHEAR), + SILVERFISH("ENTITY_SILVERFISH_HURT", "ENTITY_SILVERFISH_STEP", "ENTITY_SILVERFISH_DEATH", "ENTITY_SILVERFISH_AMBIENT"), - SHULKER(new Sound[]{Sound.ENTITY_SHULKER_HURT, Sound.ENTITY_SHULKER_HURT_CLOSED}, null, Sound.ENTITY_SHULKER_DEATH, - Sound.ENTITY_SHULKER_AMBIENT, Sound.ENTITY_SHULKER_OPEN, Sound.ENTITY_SHULKER_CLOSE, Sound.ENTITY_SHULKER_TELEPORT), + SKELETON("ENTITY_SKELETON_HURT", "ENTITY_SKELETON_STEP", "ENTITY_SKELETON_DEATH", "ENTITY_SKELETON_AMBIENT"), - SILVERFISH(Sound.ENTITY_SILVERFISH_HURT, Sound.ENTITY_SILVERFISH_STEP, Sound.ENTITY_SILVERFISH_DEATH, Sound.ENTITY_SILVERFISH_AMBIENT), + SKELETON_HORSE("ENTITY_SKELETON_HORSE_HURT", new String[]{"BLOCK_GRASS_STEP", "ENTITY_HORSE_STEP_WOOD"}, "ENTITY_SKELETON_HORSE_DEATH", + new String[] - SKELETON(Sound.ENTITY_SKELETON_HURT, Sound.ENTITY_SKELETON_STEP, Sound.ENTITY_SKELETON_DEATH, Sound.ENTITY_SKELETON_AMBIENT), + {"ENTITY_SKELETON_HORSE_AMBIENT", "ENTITY_SKELETON_HORSE_AMBIENT_WATER"}, "ENTITY_HORSE_GALLOP", "ENTITY_HORSE_SADDLE", + "ENTITY_HORSE_ARMOR", "ENTITY_HORSE_LAND", "ENTITY_HORSE_JUMP", "ENTITY_SKELETON_HORSE_GALLOP_WATER", + "ENTITY_SKELETON_HORSE_JUMP_WATER", "ENTITY_SKELETON_HORSE_SWIM", "ENTITY_SKELETON_HORSE_STEP_WATER"), - SKELETON_HORSE(Sound.ENTITY_SKELETON_HORSE_HURT, new Sound[]{Sound.BLOCK_GRASS_STEP, Sound.ENTITY_HORSE_STEP_WOOD}, - Sound.ENTITY_SKELETON_HORSE_DEATH, new Sound[]{Sound.ENTITY_SKELETON_HORSE_AMBIENT, Sound.ENTITY_SKELETON_HORSE_AMBIENT_WATER}, - Sound.ENTITY_HORSE_GALLOP, Sound.ENTITY_HORSE_SADDLE, Sound.ENTITY_HORSE_ARMOR, Sound.ENTITY_HORSE_LAND, Sound.ENTITY_HORSE_JUMP, - Sound.ENTITY_SKELETON_HORSE_GALLOP_WATER, Sound.ENTITY_SKELETON_HORSE_JUMP_WATER, Sound.ENTITY_SKELETON_HORSE_SWIM, - Sound.ENTITY_SKELETON_HORSE_STEP_WATER), + SLIME(new String[]{"ENTITY_SLIME_HURT", "ENTITY_SLIME_HURT_SMALL"}, new String[] - SLIME(new Sound[]{Sound.ENTITY_SLIME_HURT, Sound.ENTITY_SLIME_HURT_SMALL}, - new Sound[]{Sound.ENTITY_SLIME_JUMP, Sound.ENTITY_SLIME_JUMP_SMALL}, - new Sound[]{Sound.ENTITY_SLIME_DEATH, Sound.ENTITY_SLIME_DEATH_SMALL}, null, Sound.ENTITY_SLIME_ATTACK, Sound.ENTITY_SLIME_SQUISH, - Sound.ENTITY_SLIME_SQUISH_SMALL), + {"ENTITY_SLIME_JUMP", "ENTITY_SLIME_JUMP_SMALL"}, new String[] - SNIFFER(Sound.ENTITY_SNIFFER_HURT, Sound.ENTITY_SNIFFER_STEP, Sound.ENTITY_SNIFFER_DEATH, Sound.ENTITY_SNIFFER_IDLE, - Sound.ENTITY_SNIFFER_DIGGING, Sound.ENTITY_SNIFFER_DIGGING_STOP, Sound.ENTITY_SNIFFER_DROP_SEED, Sound.ENTITY_SNIFFER_EAT, - Sound.ENTITY_SNIFFER_SEARCHING, Sound.ENTITY_SNIFFER_SCENTING, Sound.ENTITY_SNIFFER_HAPPY, Sound.ENTITY_SNIFFER_SNIFFING), + {"ENTITY_SLIME_DEATH", "ENTITY_SLIME_DEATH_SMALL"}, null, "ENTITY_SLIME_ATTACK", "ENTITY_SLIME_SQUISH", + "ENTITY_SLIME_SQUISH_SMALL"), - SNOWMAN(Sound.ENTITY_SNOW_GOLEM_HURT, null, Sound.ENTITY_SNOW_GOLEM_DEATH, Sound.ENTITY_SNOW_GOLEM_AMBIENT, - Sound.ENTITY_SNOW_GOLEM_SHOOT), + SNIFFER("ENTITY_SNIFFER_HURT", "ENTITY_SNIFFER_STEP", "ENTITY_SNIFFER_DEATH", "ENTITY_SNIFFER_IDLE", "ENTITY_SNIFFER_DIGGING", + "ENTITY_SNIFFER_DIGGING_STOP", "ENTITY_SNIFFER_DROP_SEED", "ENTITY_SNIFFER_EAT", "ENTITY_SNIFFER_SEARCHING", + "ENTITY_SNIFFER_SCENTING", "ENTITY_SNIFFER_HAPPY", "ENTITY_SNIFFER_SNIFFING"), - SPIDER(Sound.ENTITY_SPIDER_HURT, Sound.ENTITY_SPIDER_STEP, Sound.ENTITY_SPIDER_DEATH, Sound.ENTITY_SPIDER_AMBIENT), + SNOWMAN("ENTITY_SNOW_GOLEM_HURT", null, "ENTITY_SNOW_GOLEM_DEATH", "ENTITY_SNOW_GOLEM_AMBIENT", "ENTITY_SNOW_GOLEM_SHOOT"), - STRAY(Sound.ENTITY_STRAY_HURT, Sound.ENTITY_STRAY_STEP, Sound.ENTITY_STRAY_DEATH, Sound.ENTITY_STRAY_AMBIENT), + SPIDER("ENTITY_SPIDER_HURT", "ENTITY_SPIDER_STEP", "ENTITY_SPIDER_DEATH", "ENTITY_SPIDER_AMBIENT"), - STRIDER(Sound.ENTITY_STRIDER_HURT, new Sound[]{Sound.ENTITY_STRIDER_STEP, Sound.ENTITY_STRIDER_STEP_LAVA}, Sound.ENTITY_STRIDER_DEATH, - Sound.ENTITY_STRIDER_AMBIENT, Sound.ENTITY_STRIDER_EAT, Sound.ENTITY_STRIDER_HAPPY, Sound.ENTITY_STRIDER_RETREAT, - Sound.ENTITY_STRIDER_SADDLE), + STRAY("ENTITY_STRAY_HURT", "ENTITY_STRAY_STEP", "ENTITY_STRAY_DEATH", "ENTITY_STRAY_AMBIENT"), - SQUID(Sound.ENTITY_SQUID_HURT, null, Sound.ENTITY_SQUID_DEATH, Sound.ENTITY_SQUID_AMBIENT, Sound.ENTITY_SQUID_SQUIRT, - Sound.ENTITY_FISH_SWIM), + STRIDER("ENTITY_STRIDER_HURT", new String[]{"ENTITY_STRIDER_STEP", "ENTITY_STRIDER_STEP_LAVA"}, "ENTITY_STRIDER_DEATH", + "ENTITY_STRIDER_AMBIENT", "ENTITY_STRIDER_EAT", "ENTITY_STRIDER_HAPPY", "ENTITY_STRIDER_RETREAT", "ENTITY_STRIDER_SADDLE"), - TADPOLE(Sound.ENTITY_TADPOLE_HURT, null, Sound.ENTITY_TADPOLE_DEATH, null, Sound.ENTITY_TADPOLE_FLOP, Sound.ITEM_BUCKET_EMPTY_TADPOLE, - Sound.ITEM_BUCKET_FILL_TADPOLE), + SQUID("ENTITY_SQUID_HURT", null, "ENTITY_SQUID_DEATH", "ENTITY_SQUID_AMBIENT", "ENTITY_SQUID_SQUIRT", "ENTITY_FISH_SWIM"), + + TADPOLE("ENTITY_TADPOLE_HURT", null, "ENTITY_TADPOLE_DEATH", null, "ENTITY_TADPOLE_FLOP", "ITEM_BUCKET_EMPTY_TADPOLE", + "ITEM_BUCKET_FILL_TADPOLE"), TEXT_DISPLAY(null, null, null, null), - TRADER_LLAMA(Sound.ENTITY_LLAMA_HURT, Sound.ENTITY_LLAMA_STEP, Sound.ENTITY_LLAMA_DEATH, Sound.ENTITY_LLAMA_AMBIENT, - Sound.ENTITY_LLAMA_ANGRY, Sound.ENTITY_LLAMA_CHEST, Sound.ENTITY_LLAMA_EAT, Sound.ENTITY_LLAMA_SWAG), + TRADER_LLAMA("ENTITY_LLAMA_HURT", "ENTITY_LLAMA_STEP", "ENTITY_LLAMA_DEATH", "ENTITY_LLAMA_AMBIENT", "ENTITY_LLAMA_ANGRY", + "ENTITY_LLAMA_CHEST", "ENTITY_LLAMA_EAT", "ENTITY_LLAMA_SWAG"), + + TROPICAL_FISH("ENTITY_TROPICAL_FISH_HURT", null, "ENTITY_TROPICAL_FISH_DEATH", "ENTITY_TROPICAL_FISH_AMBIENT", + "ENTITY_TROPICAL_FISH_FLOP", "ENTITY_FISH_SWIM"), - TROPICAL_FISH(Sound.ENTITY_TROPICAL_FISH_HURT, null, Sound.ENTITY_TROPICAL_FISH_DEATH, Sound.ENTITY_TROPICAL_FISH_AMBIENT, - Sound.ENTITY_TROPICAL_FISH_FLOP, Sound.ENTITY_FISH_SWIM), + TURTLE(new String[]{"ENTITY_TURTLE_HURT", "ENTITY_TURTLE_HURT_BABY"}, new String[] - TURTLE(new Sound[]{Sound.ENTITY_TURTLE_HURT, Sound.ENTITY_TURTLE_HURT_BABY}, - new Sound[]{Sound.ENTITY_TURTLE_SHAMBLE, Sound.ENTITY_TURTLE_SHAMBLE_BABY}, - new Sound[]{Sound.ENTITY_TURTLE_DEATH, Sound.ENTITY_TURTLE_DEATH_BABY}, Sound.ENTITY_TURTLE_AMBIENT_LAND, - Sound.ENTITY_TURTLE_LAY_EGG), + {"ENTITY_TURTLE_SHAMBLE", "ENTITY_TURTLE_SHAMBLE_BABY"}, new String[] - VEX(Sound.ENTITY_VEX_HURT, null, Sound.ENTITY_VEX_DEATH, Sound.ENTITY_VEX_AMBIENT, Sound.ENTITY_VEX_CHARGE), + {"ENTITY_TURTLE_DEATH", "ENTITY_TURTLE_DEATH_BABY"}, "ENTITY_TURTLE_AMBIENT_LAND", "ENTITY_TURTLE_LAY_EGG"), - VILLAGER(Sound.ENTITY_VILLAGER_HURT, null, Sound.ENTITY_VILLAGER_DEATH, Sound.ENTITY_VILLAGER_AMBIENT, Sound.ENTITY_VILLAGER_TRADE, - Sound.ENTITY_VILLAGER_NO, Sound.ENTITY_VILLAGER_YES), + VEX("ENTITY_VEX_HURT", null, "ENTITY_VEX_DEATH", "ENTITY_VEX_AMBIENT", "ENTITY_VEX_CHARGE"), - VINDICATOR(Sound.ENTITY_VINDICATOR_HURT, null, Sound.ENTITY_VINDICATOR_DEATH, Sound.ENTITY_VINDICATOR_AMBIENT), + VILLAGER("ENTITY_VILLAGER_HURT", null, "ENTITY_VILLAGER_DEATH", "ENTITY_VILLAGER_AMBIENT", "ENTITY_VILLAGER_TRADE", + "ENTITY_VILLAGER_NO", "ENTITY_VILLAGER_YES"), - WANDERING_TRADER(Sound.ENTITY_WANDERING_TRADER_HURT, null, Sound.ENTITY_WANDERING_TRADER_DEATH, Sound.ENTITY_WANDERING_TRADER_AMBIENT, - Sound.ENTITY_WANDERING_TRADER_NO, Sound.ENTITY_WANDERING_TRADER_YES, Sound.ENTITY_WANDERING_TRADER_TRADE, - Sound.ENTITY_WANDERING_TRADER_TRADE, Sound.ENTITY_WANDERING_TRADER_REAPPEARED, Sound.ENTITY_WANDERING_TRADER_DRINK_POTION, - Sound.ENTITY_WANDERING_TRADER_DRINK_MILK, Sound.ENTITY_WANDERING_TRADER_DISAPPEARED), + VINDICATOR("ENTITY_VINDICATOR_HURT", null, "ENTITY_VINDICATOR_DEATH", "ENTITY_VINDICATOR_AMBIENT"), - WARDEN(Sound.ENTITY_WARDEN_HURT, Sound.ENTITY_WARDEN_STEP, Sound.ENTITY_WARDEN_DEATH, Sound.ENTITY_WARDEN_AMBIENT, - Sound.ENTITY_WARDEN_AGITATED, Sound.ENTITY_WARDEN_ANGRY, Sound.ENTITY_WARDEN_ATTACK_IMPACT, Sound.ENTITY_WARDEN_DIG, - Sound.ENTITY_WARDEN_EMERGE, Sound.ENTITY_WARDEN_HEARTBEAT, Sound.ENTITY_WARDEN_TENDRIL_CLICKS, Sound.ENTITY_WARDEN_LISTENING, - Sound.ENTITY_WARDEN_LISTENING_ANGRY, Sound.ENTITY_WARDEN_NEARBY_CLOSE, Sound.ENTITY_WARDEN_NEARBY_CLOSER, - Sound.ENTITY_WARDEN_NEARBY_CLOSEST, Sound.ENTITY_WARDEN_SONIC_BOOM, Sound.ENTITY_WARDEN_SONIC_CHARGE, Sound.ENTITY_WARDEN_ROAR, - Sound.ENTITY_WARDEN_SNIFF), + WANDERING_TRADER("ENTITY_WANDERING_TRADER_HURT", null, "ENTITY_WANDERING_TRADER_DEATH", "ENTITY_WANDERING_TRADER_AMBIENT", + "ENTITY_WANDERING_TRADER_NO", "ENTITY_WANDERING_TRADER_YES", "ENTITY_WANDERING_TRADER_TRADE", "ENTITY_WANDERING_TRADER_TRADE", + "ENTITY_WANDERING_TRADER_REAPPEARED", "ENTITY_WANDERING_TRADER_DRINK_POTION", "ENTITY_WANDERING_TRADER_DRINK_MILK", + "ENTITY_WANDERING_TRADER_DISAPPEARED"), - WITCH(Sound.ENTITY_WITCH_HURT, null, Sound.ENTITY_WITCH_DEATH, Sound.ENTITY_WITCH_AMBIENT), + WARDEN("ENTITY_WARDEN_HURT", "ENTITY_WARDEN_STEP", "ENTITY_WARDEN_DEATH", "ENTITY_WARDEN_AMBIENT", "ENTITY_WARDEN_AGITATED", + "ENTITY_WARDEN_ANGRY", "ENTITY_WARDEN_ATTACK_IMPACT", "ENTITY_WARDEN_DIG", "ENTITY_WARDEN_EMERGE", "ENTITY_WARDEN_HEARTBEAT", + "ENTITY_WARDEN_TENDRIL_CLICKS", "ENTITY_WARDEN_LISTENING", "ENTITY_WARDEN_LISTENING_ANGRY", "ENTITY_WARDEN_NEARBY_CLOSE", + "ENTITY_WARDEN_NEARBY_CLOSER", "ENTITY_WARDEN_NEARBY_CLOSEST", "ENTITY_WARDEN_SONIC_BOOM", "ENTITY_WARDEN_SONIC_CHARGE", + "ENTITY_WARDEN_ROAR", "ENTITY_WARDEN_SNIFF"), - WITHER(Sound.ENTITY_WITHER_HURT, null, Sound.ENTITY_WITHER_DEATH, Sound.ENTITY_WITHER_AMBIENT, Sound.ENTITY_PLAYER_SMALL_FALL, - Sound.ENTITY_WITHER_SPAWN, Sound.ENTITY_PLAYER_BIG_FALL, Sound.ENTITY_WITHER_SHOOT), + WITCH("ENTITY_WITCH_HURT", null, "ENTITY_WITCH_DEATH", "ENTITY_WITCH_AMBIENT"), - WITHER_SKELETON(Sound.ENTITY_WITHER_SKELETON_HURT, Sound.ENTITY_WITHER_SKELETON_STEP, Sound.ENTITY_WITHER_SKELETON_DEATH, - Sound.ENTITY_WITHER_SKELETON_AMBIENT), + WITHER("ENTITY_WITHER_HURT", null, "ENTITY_WITHER_DEATH", "ENTITY_WITHER_AMBIENT", "ENTITY_PLAYER_SMALL_FALL", "ENTITY_WITHER_SPAWN", + "ENTITY_PLAYER_BIG_FALL", "ENTITY_WITHER_SHOOT"), - WOLF(Sound.ENTITY_WOLF_HURT, Sound.ENTITY_WOLF_STEP, Sound.ENTITY_WOLF_DEATH, Sound.ENTITY_WOLF_AMBIENT, Sound.ENTITY_WOLF_GROWL, - Sound.ENTITY_WOLF_PANT, Sound.ENTITY_WOLF_HOWL, Sound.ENTITY_WOLF_SHAKE, Sound.ENTITY_WOLF_WHINE), + WITHER_SKELETON("ENTITY_WITHER_SKELETON_HURT", "ENTITY_WITHER_SKELETON_STEP", "ENTITY_WITHER_SKELETON_DEATH", + "ENTITY_WITHER_SKELETON_AMBIENT"), - ZOGLIN(Sound.ENTITY_ZOGLIN_HURT, Sound.ENTITY_ZOGLIN_STEP, Sound.ENTITY_ZOGLIN_DEATH, Sound.ENTITY_ZOGLIN_AMBIENT, - Sound.ENTITY_ZOGLIN_ANGRY, Sound.ENTITY_ZOGLIN_ATTACK), + WOLF("ENTITY_WOLF_HURT", "ENTITY_WOLF_STEP", "ENTITY_WOLF_DEATH", "ENTITY_WOLF_AMBIENT", "ENTITY_WOLF_GROWL", "ENTITY_WOLF_PANT", + "ENTITY_WOLF_HOWL", "ENTITY_WOLF_SHAKE", "ENTITY_WOLF_WHINE"), - ZOMBIE(Sound.ENTITY_ZOMBIE_HURT, Sound.ENTITY_ZOMBIE_STEP, Sound.ENTITY_ZOMBIE_DEATH, Sound.ENTITY_ZOMBIE_AMBIENT, - Sound.ENTITY_ZOMBIE_INFECT, Sound.ENTITY_ZOMBIE_ATTACK_WOODEN_DOOR, Sound.ENTITY_ZOMBIE_BREAK_WOODEN_DOOR, - Sound.ENTITY_ZOMBIE_ATTACK_IRON_DOOR), + ZOGLIN("ENTITY_ZOGLIN_HURT", "ENTITY_ZOGLIN_STEP", "ENTITY_ZOGLIN_DEATH", "ENTITY_ZOGLIN_AMBIENT", "ENTITY_ZOGLIN_ANGRY", + "ENTITY_ZOGLIN_ATTACK"), - ZOMBIE_HORSE(Sound.ENTITY_ZOMBIE_HORSE_HURT, new Sound[]{Sound.BLOCK_GRASS_STEP, Sound.ENTITY_HORSE_STEP_WOOD}, - Sound.ENTITY_ZOMBIE_HORSE_DEATH, Sound.ENTITY_ZOMBIE_HORSE_AMBIENT, Sound.ENTITY_HORSE_GALLOP, Sound.ENTITY_HORSE_SADDLE, - Sound.ENTITY_HORSE_ARMOR, Sound.ENTITY_HORSE_LAND, Sound.ENTITY_HORSE_JUMP, Sound.ENTITY_HORSE_ANGRY), + ZOMBIE("ENTITY_ZOMBIE_HURT", "ENTITY_ZOMBIE_STEP", "ENTITY_ZOMBIE_DEATH", "ENTITY_ZOMBIE_AMBIENT", "ENTITY_ZOMBIE_INFECT", + "ENTITY_ZOMBIE_ATTACK_WOODEN_DOOR", "ENTITY_ZOMBIE_BREAK_WOODEN_DOOR", "ENTITY_ZOMBIE_ATTACK_IRON_DOOR"), - ZOMBIE_VILLAGER(Sound.ENTITY_ZOMBIE_VILLAGER_HURT, Sound.ENTITY_ZOMBIE_VILLAGER_STEP, Sound.ENTITY_ZOMBIE_VILLAGER_DEATH, - Sound.ENTITY_ZOMBIE_VILLAGER_AMBIENT, Sound.ENTITY_ZOMBIE_INFECT, Sound.ENTITY_ZOMBIE_ATTACK_WOODEN_DOOR, - Sound.ENTITY_ZOMBIE_BREAK_WOODEN_DOOR, Sound.ENTITY_ZOMBIE_ATTACK_IRON_DOOR), + ZOMBIE_HORSE("ENTITY_ZOMBIE_HORSE_HURT", new String[]{"BLOCK_GRASS_STEP", "ENTITY_HORSE_STEP_WOOD"}, "ENTITY_ZOMBIE_HORSE_DEATH", + "ENTITY_ZOMBIE_HORSE_AMBIENT", "ENTITY_HORSE_GALLOP", "ENTITY_HORSE_SADDLE", "ENTITY_HORSE_ARMOR", "ENTITY_HORSE_LAND", + "ENTITY_HORSE_JUMP", "ENTITY_HORSE_ANGRY"), - ZOMBIFIED_PIGLIN(Sound.ENTITY_ZOMBIFIED_PIGLIN_HURT, null, Sound.ENTITY_ZOMBIFIED_PIGLIN_DEATH, Sound.ENTITY_ZOMBIFIED_PIGLIN_AMBIENT, - Sound.ENTITY_ZOMBIFIED_PIGLIN_ANGRY, Sound.ENTITY_PIGLIN_CONVERTED_TO_ZOMBIFIED); + ZOMBIE_VILLAGER("ENTITY_ZOMBIE_VILLAGER_HURT", "ENTITY_ZOMBIE_VILLAGER_STEP", "ENTITY_ZOMBIE_VILLAGER_DEATH", + "ENTITY_ZOMBIE_VILLAGER_AMBIENT", "ENTITY_ZOMBIE_INFECT", "ENTITY_ZOMBIE_ATTACK_WOODEN_DOOR", "ENTITY_ZOMBIE_BREAK_WOODEN_DOOR", + "ENTITY_ZOMBIE_ATTACK_IRON_DOOR"), + + ZOMBIFIED_PIGLIN("ENTITY_ZOMBIFIED_PIGLIN_HURT", null, "ENTITY_ZOMBIFIED_PIGLIN_DEATH", "ENTITY_ZOMBIFIED_PIGLIN_AMBIENT", + "ENTITY_ZOMBIFIED_PIGLIN_ANGRY", "ENTITY_PIGLIN_CONVERTED_TO_ZOMBIFIED"); private final HashMap sounds = new HashMap<>(); @@ -351,17 +334,7 @@ private void addSound(Object sound, SoundType type) { return; } - if (sound instanceof Sound[]) { - for (Sound s : (Sound[]) sound) { - if (s == null) { - continue; - } - - addSound(s, type); - } - } else if (sound instanceof Sound) { - addSound((Sound) sound, type); - } else if (sound instanceof String[]) { + if (sound instanceof String[]) { for (String s : (String[]) sound) { if (s == null) { continue; @@ -376,10 +349,6 @@ private void addSound(Object sound, SoundType type) { } } - private void addSound(Sound sound, SoundType type) { - addSound(sound.name(), type); - } - private void addSound(String sound, SoundType type) { sounds.put(sound, type); } diff --git a/plugin/src/main/java/me/libraryaddict/disguise/utilities/sounds/SoundManager.java b/plugin/src/main/java/me/libraryaddict/disguise/utilities/sounds/SoundManager.java index 15cb4b621c7..ce46fee4c6c 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/utilities/sounds/SoundManager.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/utilities/sounds/SoundManager.java @@ -112,11 +112,11 @@ private void loadSounds() { continue; } - String[] sounds = s.split(","); + String[] sounds = s.split(",", -1); for (String sound : sounds) { try { - Sound actualSound = Sound.valueOf(sound); + Sound actualSound = ReflectionManager.fromEnum(Sound.class,sound); group.addSound(actualSound, type); } catch (Exception ignored) { diff --git a/plugin/src/main/java/me/libraryaddict/disguise/utilities/translations/LibsMsg.java b/plugin/src/main/java/me/libraryaddict/disguise/utilities/translations/LibsMsg.java index 2a1d253369f..973dd5b3d49 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/utilities/translations/LibsMsg.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/utilities/translations/LibsMsg.java @@ -175,6 +175,8 @@ public enum LibsMsg { PARSE_PARTICLE_ITEM("Expected %s:Material,Amount?,Glow?, received %s instead"), PARSE_PARTICLE_SHULK_CHARGE("Expected %s:Roll(number.0), received %s instead"), PARSE_PARTICLE_SHRIEK("Expected %s:Delay(number.0), received %s instead"), + PARSE_PARTICLE_TRAIL( + "Expected %s:Target(3 numbers),Color(3 numbers or red/blue/etc) eg X,Y,Z:RED, received %s instead"), PARSE_PARTICLE_DUST( "Expected %s:Size(Optional Number),Color(3 numbers or red/blue/etc), received %s instead"), PARSE_PARTICLE_DUST_TRANSITION( diff --git a/plugin/src/main/java/me/libraryaddict/disguise/utilities/watchers/DisguiseMethods.java b/plugin/src/main/java/me/libraryaddict/disguise/utilities/watchers/DisguiseMethods.java index 857bc624e6d..65cee8984da 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/utilities/watchers/DisguiseMethods.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/utilities/watchers/DisguiseMethods.java @@ -159,7 +159,7 @@ private void loadMethods() { WatcherMethod m = new WatcherMethod(watcher, method, info.getMappedAs(), info.getMethod(), returnType, param, info.isRandomDefault(), info.isDeprecated() && info.getAdded() == 0, unusableBy, hiddenFor, info.getDescription(), - info.isNoVisibleDifference()); + info.isNoVisibleDifference(), info.getAdded(), info.getRemoved()); methods.add(m); @@ -225,7 +225,7 @@ private void loadMethods() { WatcherMethod method = new WatcherMethod(disguiseClass, MethodHandles.publicLookup().findVirtual(disguiseClass, methodName, MethodType.methodType(returnType, cl)), methodName, methodName, null, cl, randomDefault, false, new boolean[DisguiseType.values().length], - new boolean[DisguiseType.values().length], null, false); + new boolean[DisguiseType.values().length], null, false, 0, 0); methods.add(method); @@ -242,7 +242,8 @@ private void loadMethods() { WatcherMethod getMethod = new WatcherMethod(disguiseClass, MethodHandles.publicLookup().findVirtual(disguiseClass, getName, MethodType.methodType(cl)), getName, - getName, cl, null, randomDefault, false, new boolean[DisguiseType.values().length], hiddenFor, null, false); + getName, cl, null, randomDefault, false, new boolean[DisguiseType.values().length], hiddenFor, null, false, + 0, 0); methods.add(getMethod); break; diff --git a/shaded/src/main/java/me/libraryaddict/disguise/utilities/watchers/CompileMethods.java b/shaded/src/main/java/me/libraryaddict/disguise/utilities/watchers/CompileMethods.java index 4f0f8404640..03583f1a398 100644 --- a/shaded/src/main/java/me/libraryaddict/disguise/utilities/watchers/CompileMethods.java +++ b/shaded/src/main/java/me/libraryaddict/disguise/utilities/watchers/CompileMethods.java @@ -16,9 +16,11 @@ import me.libraryaddict.disguise.utilities.reflection.annotations.NmsRemovedIn; import me.libraryaddict.disguise.utilities.sounds.DisguiseSoundEnums; import me.libraryaddict.disguise.utilities.sounds.SoundGroup; +import org.bukkit.Sound; import java.io.File; import java.io.IOException; +import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.nio.charset.StandardCharsets; @@ -106,6 +108,24 @@ private static byte[] doSounds() { return String.join("\n", list).getBytes(StandardCharsets.UTF_8); } + private static List getMatchingFields(String pattern) { + List matches = new ArrayList<>(); + + for (Field field : Sound.class.getFields()) { + if (!Modifier.isStatic(field.getModifiers()) || field.getType() != Sound.class) { + continue; + } + + if (!field.getName().matches(pattern)) { + continue; + } + + matches.add(field.getName()); + } + + return matches; + } + private static StringBuilder getSoundAsString(DisguiseSoundEnums e) { StringBuilder sound = new StringBuilder(e.name()); @@ -119,11 +139,17 @@ private static StringBuilder getSoundAsString(DisguiseSoundEnums e) { continue; } + String soundValue = entry.getKey(); + + if (soundValue.contains("*")) { + soundValue = String.join(",", getMatchingFields(soundValue)); + } + if (i++ > 0) { sound.append(","); } - sound.append(entry.getKey()); + sound.append(soundValue); } } return sound; diff --git a/shaded/src/main/resources/configs/dangerous.yml b/shaded/src/main/resources/configs/dangerous.yml index 7944e67750c..27dba0bee9f 100644 --- a/shaded/src/main/resources/configs/dangerous.yml +++ b/shaded/src/main/resources/configs/dangerous.yml @@ -29,7 +29,7 @@ DisabledDisguises: - INTERACTION # These disguise methods are also limited to OP only, because they're open to abuse -# setInvisible has overlap with the config option for disabled invsibility, if either is used, it will be disabled. +# setInvisible has overlap with the config option for disabled invisibility, if either is used, it will be disabled. # Thankfully, only trusted people are OP. So this doesn't need further configuration. # Command users who has the permission return true for "libsdisguises.*.*.*" will also have access. DisabledMethods: diff --git a/shaded/src/test/java/me/libraryaddict/disguise/utilities/parser/params/DisguiseParamParticleTest.java b/shaded/src/test/java/me/libraryaddict/disguise/utilities/parser/params/DisguiseParamParticleTest.java index cc829066775..7be83e629f4 100644 --- a/shaded/src/test/java/me/libraryaddict/disguise/utilities/parser/params/DisguiseParamParticleTest.java +++ b/shaded/src/test/java/me/libraryaddict/disguise/utilities/parser/params/DisguiseParamParticleTest.java @@ -3,6 +3,8 @@ import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerManager; import com.github.retrooper.packetevents.manager.server.ServerVersion; +import com.github.retrooper.packetevents.protocol.color.AlphaColor; +import com.github.retrooper.packetevents.protocol.color.Color; import com.github.retrooper.packetevents.protocol.item.ItemStack; import com.github.retrooper.packetevents.protocol.item.type.ItemTypes; import com.github.retrooper.packetevents.protocol.particle.Particle; @@ -14,10 +16,13 @@ import com.github.retrooper.packetevents.protocol.particle.data.ParticleItemStackData; import com.github.retrooper.packetevents.protocol.particle.data.ParticleSculkChargeData; import com.github.retrooper.packetevents.protocol.particle.data.ParticleShriekData; +import com.github.retrooper.packetevents.protocol.particle.data.ParticleTrailData; import com.github.retrooper.packetevents.protocol.particle.data.ParticleVibrationData; +import com.github.retrooper.packetevents.protocol.particle.type.ParticleType; import com.github.retrooper.packetevents.protocol.particle.type.ParticleTypes; import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState; import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes; +import com.github.retrooper.packetevents.util.Vector3d; import com.github.retrooper.packetevents.util.Vector3i; import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder; import io.github.retrooper.packetevents.manager.server.ServerManagerImpl; @@ -29,12 +34,13 @@ import me.libraryaddict.disguise.utilities.params.types.custom.ParamInfoParticle; import me.libraryaddict.disguise.utilities.parser.DisguiseParseException; import me.libraryaddict.disguise.utilities.translations.LibsMsg; -import org.bukkit.Color; import org.bukkit.Material; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.ArgumentMatchers; import org.mockito.MockedStatic; import org.mockito.Mockito; @@ -94,32 +100,28 @@ private void testEquality(Particle expected, Particle parsed) { ParticleData data = expected.getData(); - if (data instanceof ParticleDustData) { - ParticleDustData p1 = (ParticleDustData) data; + if (data instanceof ParticleDustData p1) { ParticleDustData p2 = (ParticleDustData) parsed.getData(); assertEquals(p1.getScale(), p2.getScale()); assertEquals(p1.getRed(), p2.getRed()); assertEquals(p1.getBlue(), p2.getBlue()); assertEquals(p1.getGreen(), p2.getGreen()); - } else if (data instanceof ParticleDustColorTransitionData) { - ParticleDustColorTransitionData p1 = (ParticleDustColorTransitionData) data; + } else if (data instanceof ParticleDustColorTransitionData p1) { ParticleDustColorTransitionData p2 = (ParticleDustColorTransitionData) parsed.getData(); - assertEquals(p1.getScale(), p2.getScale()); - assertEquals(p1.getStartRed(), p2.getStartRed()); - assertEquals(p1.getStartGreen(), p2.getStartGreen()); - assertEquals(p1.getStartBlue(), p2.getStartBlue()); - assertEquals(p1.getEndRed(), p2.getEndRed()); - assertEquals(p1.getEndGreen(), p2.getEndGreen()); - assertEquals(p1.getEndBlue(), p2.getEndBlue()); - } else if (data instanceof ParticleColorData) { - ParticleColorData p1 = (ParticleColorData) data; + assertEquals(p1.getScale(), p2.getScale(), "Particle Scale"); + assertEquals(p1.getStartRed(), p2.getStartRed(), "Particle Start Red"); + assertEquals(p1.getStartGreen(), p2.getStartGreen(), "Particle Start Green"); + assertEquals(p1.getStartBlue(), p2.getStartBlue(), "Particle Start Blue"); + assertEquals(p1.getEndRed(), p2.getEndRed(), "Particle End Red"); + assertEquals(p1.getEndGreen(), p2.getEndGreen(), "Particle End Green"); + assertEquals(p1.getEndBlue(), p2.getEndBlue(), "Particle End Blue"); + } else if (data instanceof ParticleColorData p1) { ParticleColorData p2 = (ParticleColorData) parsed.getData(); assertEquals(p1.getColor(), p2.getColor()); - } else if (data instanceof ParticleVibrationData) { - ParticleVibrationData p1 = (ParticleVibrationData) data; + } else if (data instanceof ParticleVibrationData p1) { ParticleVibrationData p2 = (ParticleVibrationData) parsed.getData(); assertEquals(p1.getTicks(), p2.getTicks()); @@ -143,24 +145,19 @@ private void testEquality(Particle expected, Particle parsed) { assertEquals(v1.getY(), v2.getY()); assertEquals(v1.getZ(), v2.getZ()); } - } else if (data instanceof ParticleShriekData) { - ParticleShriekData p1 = (ParticleShriekData) data; + } else if (data instanceof ParticleShriekData p1) { ParticleShriekData p2 = (ParticleShriekData) parsed.getData(); assertEquals(p1.getDelay(), p2.getDelay()); - } else if (data instanceof ParticleSculkChargeData) { - ParticleSculkChargeData p1 = (ParticleSculkChargeData) data; + } else if (data instanceof ParticleSculkChargeData p1) { ParticleSculkChargeData p2 = (ParticleSculkChargeData) parsed.getData(); assertEquals(p1.getRoll(), p2.getRoll()); - } else if (data instanceof ParticleBlockStateData) { - ParticleBlockStateData p1 = (ParticleBlockStateData) data; + } else if (data instanceof ParticleBlockStateData p1) { ParticleBlockStateData p2 = (ParticleBlockStateData) parsed.getData(); assertEquals(p1.getBlockState(), p2.getBlockState()); - } else if (data instanceof ParticleItemStackData) { - - ParticleItemStackData p1 = (ParticleItemStackData) data; + } else if (data instanceof ParticleItemStackData p1) { ParticleItemStackData p2 = (ParticleItemStackData) parsed.getData(); assertNotNull(p1.getItemStack()); @@ -168,45 +165,93 @@ private void testEquality(Particle expected, Particle parsed) { assertEquals(p1.getItemStack().getType(), p2.getItemStack().getType()); assertEquals(p1.getItemStack().getAmount(), p2.getItemStack().getAmount()); assertEquals(p1.getItemStack().getDamageValue(), p2.getItemStack().getDamageValue()); + } else if (data instanceof ParticleTrailData p1) { + ParticleTrailData p2 = (ParticleTrailData) parsed.getData(); + + assertEquals(p1.getTarget().getX(), p2.getTarget().getX()); + assertEquals(p1.getTarget().getY(), p2.getTarget().getY()); + assertEquals(p1.getTarget().getZ(), p2.getTarget().getZ()); + + assertEquals(p1.getColor().red(), p2.getColor().red()); + assertEquals(p1.getColor().green(), p2.getColor().green()); + assertEquals(p1.getColor().blue(), p2.getColor().blue()); } else { throw new IllegalArgumentException("Unrecognized class " + data.getClass() + " when testing particle equality"); } } - @Test + private static ParticleType[] blockStateParticles() { + return new ParticleType[]{ParticleTypes.BLOCK, ParticleTypes.BLOCK_CRUMBLE, ParticleTypes.BLOCK_MARKER}; + } + + @ParameterizedTest @SneakyThrows - public void testParticleBlockStateData() { + @MethodSource("blockStateParticles") + public void testParticleBlockStateData(ParticleType particleType) { WrappedBlockState openGate = WrappedBlockState.getDefaultState(StateTypes.ACACIA_FENCE_GATE).clone(); openGate.setOpen(true); - Particle asParticle = new Particle<>(ParticleTypes.BLOCK, new ParticleBlockStateData(openGate)); + Particle asParticle = new Particle<>(particleType, new ParticleBlockStateData(openGate)); + String particleName = particleType.getName().getKey().toUpperCase(Locale.ENGLISH); - runTest("BLOCK:ACACIA_FENCE_GATE[open=true]", "BLOCK:ACACIA_FENCE_GATE[open=true]", asParticle); - runTest("BLOCK:ACACIA_FENCE_GATE[facing=north,in_wall=false,open=true,powered=false]", "BLOCK:ACACIA_FENCE_GATE[open=true]", - asParticle); + runTest(particleName + ":ACACIA_FENCE_GATE[open=true]", particleName + ":ACACIA_FENCE_GATE[open=true]", asParticle); + runTest(particleName + ":ACACIA_FENCE_GATE[facing=north,in_wall=false,open=true,powered=false]", + particleName + ":ACACIA_FENCE_GATE[open=true]", asParticle); // Default of stone - runTest("BLOCK", "block:stone", - new Particle<>(ParticleTypes.BLOCK, new ParticleBlockStateData(WrappedBlockState.getDefaultState(StateTypes.STONE)))); + runTest(particleName, particleName.toLowerCase(Locale.ENGLISH) + ":stone", + new Particle<>(particleType, new ParticleBlockStateData(WrappedBlockState.getDefaultState(StateTypes.STONE)))); // Invalid block - runThrowTest(LibsMsg.PARSE_BLOCK_STATE_UNKNOWN_BLOCK, "BLOCK:libraryaddict"); - runThrowTest(LibsMsg.PARSE_BLOCK_STATE_UNKNOWN_BLOCK, "BLOCK:1"); - runThrowTest(LibsMsg.PARSE_BLOCK_STATE_UNKNOWN_BLOCK_SYNTAX, "BLOCK:STONE:STONE"); - runThrowTest(LibsMsg.PARSE_BLOCK_STATE_UNKNOWN_BLOCK_SYNTAX, "BLOCK:1:1"); - runThrowTest(LibsMsg.PARSE_PARTICLE_BLOCK, "BLOCK:"); + runThrowTest(LibsMsg.PARSE_BLOCK_STATE_UNKNOWN_BLOCK, particleName + ":libraryaddict"); + runThrowTest(LibsMsg.PARSE_BLOCK_STATE_UNKNOWN_BLOCK, particleName + ":1"); + runThrowTest(LibsMsg.PARSE_BLOCK_STATE_UNKNOWN_BLOCK_SYNTAX, particleName + ":STONE:STONE"); + runThrowTest(LibsMsg.PARSE_BLOCK_STATE_UNKNOWN_BLOCK_SYNTAX, particleName + ":1:1"); + runThrowTest(LibsMsg.PARSE_PARTICLE_BLOCK, particleName + ":"); + } + + @Test + @SneakyThrows + public void testParticleTrailData() { + Color red = new Color(org.bukkit.Color.RED.asRGB()); + + // We allow no params, no vector, no color + runTest("TRAIL:0.5,0,0", "trail:0.5,0.0,0.0:95,95,255", + new Particle<>(ParticleTypes.TRAIL, new ParticleTrailData(new Vector3d(0.5, 0, 0), new Color(95, 95, 255)))); + runTest("TRAIL:12,15,5", "trail:12.0,15.0,5.0:95,95,255", + new Particle<>(ParticleTypes.TRAIL, new ParticleTrailData(new Vector3d(12, 15, 5), new Color(95, 95, 255)))); + runTest("TRAIL:12,15,5,RED", "trail:12.0,15.0,5.0:red", + new Particle<>(ParticleTypes.TRAIL, new ParticleTrailData(new Vector3d(12, 15, 5), red))); + runTest("TRAIL:12,15,5:red", "trail:12.0,15.0,5.0:red", + new Particle<>(ParticleTypes.TRAIL, new ParticleTrailData(new Vector3d(12, 15, 5), red))); + runTest("TRAIL:12,15,5:black", "trail:12.0,15.0,5.0:black", + new Particle<>(ParticleTypes.TRAIL, new ParticleTrailData(new Vector3d(12, 15, 5), new Color(0, 0, 0)))); + runTest("TRAIL:12,15,5:0,0,0", "trail:12.0,15.0,5.0:black", + new Particle<>(ParticleTypes.TRAIL, new ParticleTrailData(new Vector3d(12, 15, 5), new Color(0, 0, 0)))); + + runThrowTest(LibsMsg.PARSE_PARTICLE_TRAIL, "TRAIL:RED,RED,RED,RED"); + runThrowTest(LibsMsg.PARSE_PARTICLE_TRAIL, "TRAIL:RED"); + runThrowTest(LibsMsg.PARSE_PARTICLE_TRAIL, "TRAIL:RED:12,15,5"); + runThrowTest(LibsMsg.PARSE_PARTICLE_TRAIL, "TRAIL:RED:12,15,5,5"); + runThrowTest(LibsMsg.PARSE_PARTICLE_TRAIL, "TRAIL:12,15,5,5:RED"); + runThrowTest(LibsMsg.PARSE_PARTICLE_TRAIL, "TRAIL:12,15,5:0,0"); + runThrowTest(LibsMsg.PARSE_PARTICLE_TRAIL, "TRAIL:12,15,5:0,0,0,0"); + runThrowTest(LibsMsg.PARSE_PARTICLE_TRAIL, "TRAIL:12,15,5:0,0,0:RED"); + runThrowTest(LibsMsg.PARSE_PARTICLE_TRAIL, "TRAIL:12,15,5:0,0,0,0,0"); } @Test @SneakyThrows public void testParticleDustData() { + org.bukkit.Color bRed = org.bukkit.Color.RED; // No args runTest("DUST", "dust:black", new Particle<>(ParticleTypes.DUST, new ParticleDustData(1, 0, 0, 0))); // With args - runTest("DUST:-1,-1,-1", new Particle<>(ParticleTypes.DUST, new ParticleDustData(1, -1, -1, -1))); + runTest("DUST:black", new Particle<>(ParticleTypes.DUST, new ParticleDustData(1, 0, 0, 0))); runTest("DUST:RED", new Particle<>(ParticleTypes.DUST, - new ParticleDustData(1, Color.RED.getRed() / 255f, Color.RED.getGreen() / 255f, Color.RED.getBlue() / 255f))); + new ParticleDustData(1, bRed.getRed() / 255f, bRed.getGreen() / 255f, bRed.getBlue() / 255f))); runTest("DUST:7.5:RED", new Particle<>(ParticleTypes.DUST, - new ParticleDustData(7.5f, Color.RED.getRed() / 255f, Color.RED.getGreen() / 255f, Color.RED.getBlue() / 255f))); - runTest("DUST:12,32,23", new Particle<>(ParticleTypes.DUST, new ParticleDustData(1, 12, 32, 23))); + new ParticleDustData(7.5f, bRed.getRed() / 255f, bRed.getGreen() / 255f, bRed.getBlue() / 255f))); + // That it can drop the scale + runTest("DUST:12,32,23", new Particle<>(ParticleTypes.DUST, new ParticleDustData(1, new Color(12, 32, 23)))); runTest("DUST:7.5:12,32,23", new Particle<>(ParticleTypes.DUST, new ParticleDustData(7.5f, 12, 32, 23))); runThrowTest(LibsMsg.PARSE_PARTICLE_DUST, "DUST:RandomString"); @@ -219,47 +264,45 @@ public void testParticleDustData() { runThrowTest(LibsMsg.PARSE_PARTICLE_DUST, "DUST:0,0,0,0,0"); } - private ParticleDustColorTransitionData constructTransiton(float scale, com.github.retrooper.packetevents.protocol.color.Color c1, - com.github.retrooper.packetevents.protocol.color.Color c2) { - return new ParticleDustColorTransitionData(scale, c1.red() / 255f, c1.green() / 255f, c1.blue() / 255f, c2.red() / 255f, - c2.green() / 255f, c2.blue() / 255f); - } - @Test @SneakyThrows public void testParticleDustColorTransitionData() { - com.github.retrooper.packetevents.protocol.color.Color c1 = - new com.github.retrooper.packetevents.protocol.color.Color(Color.RED.asRGB()); - com.github.retrooper.packetevents.protocol.color.Color c2 = - new com.github.retrooper.packetevents.protocol.color.Color(Color.BLUE.asRGB()); + Color c1 = new Color(org.bukkit.Color.RED.asRGB()); + Color c2 = new Color(org.bukkit.Color.BLUE.asRGB()); // Test a simple - runTest("DUST_COLOR_TRANSITION:RED:BLUE", new Particle(ParticleTypes.DUST_COLOR_TRANSITION, constructTransiton(1, c1, c2))); + runTest("DUST_COLOR_TRANSITION:RED:BLUE", + new Particle(ParticleTypes.DUST_COLOR_TRANSITION, new ParticleDustColorTransitionData(1, c1, c2))); // With a scale - runTest("DUST_COLOR_TRANSITION:1.6:RED:BLUE", new Particle(ParticleTypes.DUST_COLOR_TRANSITION, constructTransiton(1.6f, c1, c2))); + runTest("DUST_COLOR_TRANSITION:1.6:RED:BLUE", + new Particle(ParticleTypes.DUST_COLOR_TRANSITION, new ParticleDustColorTransitionData(1.6f, c1, c2))); // Without scale, the first is 3 numbers - runTest("DUST_COLOR_TRANSITION:1,0,0:BLUE", "DUST_COLOR_TRANSITION:RED:BLUE", - new Particle(ParticleTypes.DUST_COLOR_TRANSITION, constructTransiton(1, c1, c2))); + runTest("DUST_COLOR_TRANSITION:255,0,0:BLUE", "DUST_COLOR_TRANSITION:RED:BLUE", + new Particle(ParticleTypes.DUST_COLOR_TRANSITION, new ParticleDustColorTransitionData(1, c1, c2))); + runTest("DUST_COLOR_TRANSITION:1.0,0,0:BLUE", "DUST_COLOR_TRANSITION:RED:BLUE", + new Particle(ParticleTypes.DUST_COLOR_TRANSITION, new ParticleDustColorTransitionData(1, c1, c2))); // With scale, the first is 3 numbers - runTest("DUST_COLOR_TRANSITION:1.6:1,0,0:BLUE", "DUST_COLOR_TRANSITION:1.6:RED:BLUE", - new Particle(ParticleTypes.DUST_COLOR_TRANSITION, constructTransiton(1.6f, c1, c2))); + runTest("DUST_COLOR_TRANSITION:1.6:255,0,0:BLUE", "DUST_COLOR_TRANSITION:1.6:RED:BLUE", + new Particle(ParticleTypes.DUST_COLOR_TRANSITION, new ParticleDustColorTransitionData(1.6f, c1, c2))); + runTest("DUST_COLOR_TRANSITION:1.6:1.0,0,0:BLUE", "DUST_COLOR_TRANSITION:1.6:RED:BLUE", + new Particle(ParticleTypes.DUST_COLOR_TRANSITION, new ParticleDustColorTransitionData(1.6f, c1, c2))); // Without scale, the last is 3 numbers - runTest("DUST_COLOR_TRANSITION:RED:0,0,1", "DUST_COLOR_TRANSITION:RED:BLUE", - new Particle(ParticleTypes.DUST_COLOR_TRANSITION, constructTransiton(1, c1, c2))); + runTest("DUST_COLOR_TRANSITION:RED:0,0,255", "DUST_COLOR_TRANSITION:RED:BLUE", + new Particle(ParticleTypes.DUST_COLOR_TRANSITION, new ParticleDustColorTransitionData(1, c1, c2))); // With scale - runTest("DUST_COLOR_TRANSITION:1.6:RED:0,0,1", "DUST_COLOR_TRANSITION:1.6:RED:BLUE", - new Particle(ParticleTypes.DUST_COLOR_TRANSITION, constructTransiton(1.6f, c1, c2))); + runTest("DUST_COLOR_TRANSITION:1.6:RED:0,0,255", "DUST_COLOR_TRANSITION:1.6:RED:BLUE", + new Particle(ParticleTypes.DUST_COLOR_TRANSITION, new ParticleDustColorTransitionData(1.6f, c1, c2))); // Without scale, only number colors - runTest("DUST_COLOR_TRANSITION:1,0,0:0,0,1", "DUST_COLOR_TRANSITION:RED:BLUE", - new Particle(ParticleTypes.DUST_COLOR_TRANSITION, constructTransiton(1, c1, c2))); + runTest("DUST_COLOR_TRANSITION:255,0,0:0,0,255", "DUST_COLOR_TRANSITION:RED:BLUE", + new Particle(ParticleTypes.DUST_COLOR_TRANSITION, new ParticleDustColorTransitionData(1, c1, c2))); // With scale - runTest("DUST_COLOR_TRANSITION:1.6:1,0,0:0,0,1", "DUST_COLOR_TRANSITION:1.6:RED:BLUE", - new Particle(ParticleTypes.DUST_COLOR_TRANSITION, constructTransiton(1.6f, c1, c2))); + runTest("DUST_COLOR_TRANSITION:1.6:255,0,0:0,0,255", "DUST_COLOR_TRANSITION:1.6:RED:BLUE", + new Particle(ParticleTypes.DUST_COLOR_TRANSITION, new ParticleDustColorTransitionData(1.6f, c1, c2))); // Negatives - runTest("DUST_COLOR_TRANSITION:-1,-1,-1:-1,-1,-1", - new Particle(ParticleTypes.DUST_COLOR_TRANSITION, new ParticleDustColorTransitionData(1f, -1, -1, -1, -1, -1, -1))); - runTest("DUST_COLOR_TRANSITION:1.6:-1,-1,-1:-1,-1,-1", - new Particle(ParticleTypes.DUST_COLOR_TRANSITION, new ParticleDustColorTransitionData(1.6f, -1, -1, -1, -1, -1, -1))); + runTest("DUST_COLOR_TRANSITION:black:black", + new Particle(ParticleTypes.DUST_COLOR_TRANSITION, new ParticleDustColorTransitionData(1f, 0, 0, 0, 0, 0, 0))); + runTest("DUST_COLOR_TRANSITION:1.6:black:black", + new Particle(ParticleTypes.DUST_COLOR_TRANSITION, new ParticleDustColorTransitionData(1.6f, 0, 0, 0, 0, 0, 0))); // Invalid args runThrowTest(LibsMsg.PARSE_PARTICLE_DUST_TRANSITION, "DUST_COLOR_TRANSITION"); @@ -288,11 +331,23 @@ public void testParticleDustColorTransitionData() { @Test @SneakyThrows public void testParticleColorData() { + org.bukkit.Color bRed = org.bukkit.Color.RED; + org.bukkit.Color bPurple = org.bukkit.Color.PURPLE; // Will default to black - runTest("entity_effect", "entity_effect:black", new Particle<>(ParticleTypes.ENTITY_EFFECT, new ParticleColorData(0))); - runTest("entity_effect:-1", new Particle<>(ParticleTypes.ENTITY_EFFECT, new ParticleColorData(-1))); - runTest("entity_effect:RED", new Particle<>(ParticleTypes.ENTITY_EFFECT, new ParticleColorData(Color.RED.asRGB()))); - runTest("entity_effect:16711620", new Particle<>(ParticleTypes.ENTITY_EFFECT, new ParticleColorData(16711620))); + runTest("entity_effect", "entity_effect:-1", new Particle<>(ParticleTypes.ENTITY_EFFECT, new ParticleColorData(-1))); + runTest("entity_effect:black", "entity_effect:255:black", + new Particle<>(ParticleTypes.ENTITY_EFFECT, new ParticleColorData(new AlphaColor(255, 0, 0, 0)))); + runTest("entity_effect:RED", "entity_effect:255:RED", new Particle<>(ParticleTypes.ENTITY_EFFECT, + new ParticleColorData(new AlphaColor(255, bRed.getRed(), bRed.getGreen(), bRed.getBlue())))); + runTest("entity_effect:0.5,RED", "entity_effect:127:RED", new Particle<>(ParticleTypes.ENTITY_EFFECT, + new ParticleColorData(new AlphaColor(127, bRed.getRed(), bRed.getGreen(), bRed.getBlue())))); + // Test with a color that's not known by name + runTest("entity_effect:127:239,251,196", + new Particle<>(ParticleTypes.ENTITY_EFFECT, new ParticleColorData(new AlphaColor(0.5f, 20, 40, 60)))); + runTest("entity_effect:PURPLE", "entity_effect:255:PURPLE", new Particle<>(ParticleTypes.ENTITY_EFFECT, + new ParticleColorData(new AlphaColor(255, bPurple.getRed(), bPurple.getGreen(), bPurple.getBlue())))); + runTest("entity_effect:16711620", "entity_effect:0:254,255,196", + new Particle<>(ParticleTypes.ENTITY_EFFECT, new ParticleColorData(16711620))); runThrowTest(LibsMsg.PARSE_PARTICLE_COLOR, "entity_effect:WHITE:1"); runThrowTest(LibsMsg.PARSE_PARTICLE_COLOR, "entity_effect:Cat");