Handle 1.21.3 update

This commit is contained in:
libraryaddict 2024-11-10 21:58:12 +13:00
parent 2d9e16ae67
commit 292ce911c2
33 changed files with 1385 additions and 425 deletions

View File

@ -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]

View File

@ -81,7 +81,7 @@ import java.util.concurrent.atomic.AtomicInteger;
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 class ReflectionManager implements ReflectionManagerAbstract {
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 class ReflectionManager implements ReflectionManagerAbstract {
Optional<net.minecraft.world.entity.EntityType<?>> optional =
net.minecraft.world.entity.EntityType.byString(entityName.toLowerCase(Locale.ENGLISH));
if (!optional.isPresent()) {
if (optional.isEmpty()) {
return null;
}
@ -235,7 +236,7 @@ public class ReflectionManager implements ReflectionManagerAbstract {
return null;
}
return (ServerEntity) trackedEntityField.get(trackedEntity);
return (ServerEntity) entityTrackerField.get(trackedEntity);
}
@Override

View File

@ -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
}

View File

@ -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<net.minecraft.world.entity.EntityType<?>> 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<ChunkMap.TrackedEntity> 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<net.minecraft.world.entity.Entity> 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<String, Object> 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<CatVariant> registry = MinecraftServer.getDefaultRegistryAccess().lookupOrThrow(Registries.CAT_VARIANT);
return CraftCat.CraftType.minecraftHolderToBukkit(registry.get(catType).get());
}
@Override
public int getCatVariantAsInt(Cat.Type type) {
Registry<CatVariant> registry = MinecraftServer.getDefaultRegistryAccess().lookupOrThrow(Registries.CAT_VARIANT);
return registry.getIdOrThrow(CraftCat.CraftType.bukkitToMinecraft(type));
}
@Override
public Frog.Variant getFrogVariantFromInt(int frogType) {
Registry<FrogVariant> registry = MinecraftServer.getDefaultRegistryAccess().lookupOrThrow(Registries.FROG_VARIANT);
return CraftFrog.CraftVariant.minecraftHolderToBukkit(registry.get(frogType).get());
}
@Override
public int getFrogVariantAsInt(Frog.Variant type) {
Registry<FrogVariant> registry = MinecraftServer.getDefaultRegistryAccess().lookupOrThrow(Registries.FROG_VARIANT);
return registry.getIdOrThrow(CraftFrog.CraftVariant.bukkitToMinecraft(type));
}
@Override
public Art getPaintingFromInt(int paintingId) {
Registry<PaintingVariant> registry = MinecraftServer.getDefaultRegistryAccess().lookupOrThrow(Registries.PAINTING_VARIANT);
return CraftArt.minecraftHolderToBukkit(registry.get(paintingId - 1).get());
}
@Override
public int getPaintingAsInt(Art type) {
Registry<PaintingVariant> registry = MinecraftServer.getDefaultRegistryAccess().lookupOrThrow(Registries.PAINTING_VARIANT);
return registry.getIdOrThrow(CraftArt.bukkitToMinecraft(type)) + 1;
}
@Override
public Wolf.Variant getWolfVariantFromInt(int wolfVariant) {
Registry<WolfVariant> registry = MinecraftServer.getDefaultRegistryAccess().lookupOrThrow(Registries.WOLF_VARIANT);
return CraftWolf.CraftVariant.minecraftHolderToBukkit(registry.get(wolfVariant - 1).get());
}
@Override
public int getWolfVariantAsInt(Wolf.Variant type) {
Registry<WolfVariant> 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<Object> cond = DataComponentPatch.CODEC.encodeStart(JavaOps.INSTANCE, comps);
return cond.result().orElse(null);
}
}

View File

@ -28,7 +28,6 @@ import me.libraryaddict.disguise.utilities.translations.LibsMsg;
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 @@ public abstract class Disguise {
}
// 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);

View File

@ -37,7 +37,7 @@ import java.util.UUID;
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() {

View File

@ -18,6 +18,10 @@ import org.bukkit.entity.EntityType;
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),
@NmsAddedIn(NmsVersion.v1_21_R2) JUNGLE_BOAT,
@NmsAddedIn(NmsVersion.v1_21_R2) JUNGLE_CHEST_BOAT,
LEASH_HITCH(77, "leash_knot"),
LLAMA,
LLAMA_SPIT(68),
LEASH_HITCH(77, "leash_knot"),
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,

View File

@ -1021,6 +1021,7 @@ public class FlagWatcher {
}
}
@NmsAddedIn(NmsVersion.v1_17)
public int getTicksFrozen() {
return getData(MetaIndex.ENTITY_TICKS_FROZEN);
}

View File

@ -87,6 +87,7 @@ import me.libraryaddict.disguise.disguisetypes.watchers.PolarBearWatcher;
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.Ocelot;
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<Y> {
@NmsAddedIn(NmsVersion.v1_14)
public static MetaIndex<Byte> ARROW_PIERCE_LEVEL = new MetaIndex<>(ArrowWatcher.class, 2, (byte) 0);
@NmsAddedIn(NmsVersion.v1_21_R2)
public static MetaIndex<Boolean> ARROW_IN_GROUND = new MetaIndex<>(ArrowWatcher.class, 3, false);
@NmsAddedIn(NmsVersion.v1_17)
public static MetaIndex<Axolotl.Variant> AXOLOTL_VARIANT =
new MetaIndex<>(AxolotlWatcher.class, 0, NmsVersion.v1_17.isSupported() ? Axolotl.Variant.LUCY : null);
@ -277,15 +282,15 @@ public class MetaIndex<Y> {
public static MetaIndex<WrappedBlockState> BLOCK_DISPLAY_BLOCK_STATE =
new MetaIndex<>(BlockDisplayWatcher.class, 0, WrappedBlockState.getDefaultState(StateTypes.AIR));
public static MetaIndex<Integer> BOAT_LAST_HIT = new MetaIndex<>(BoatWatcher.class, 0, 0);
public static MetaIndex<Integer> BOAT_DIRECTION = new MetaIndex<>(BoatWatcher.class, 1, 1);
/**
* How damaged the boat is
*/
public static MetaIndex<Float> BOAT_DAMAGE = new MetaIndex<>(BoatWatcher.class, 2, 0F);
public static MetaIndex<Integer> BOAT_DIRECTION = new MetaIndex<>(BoatWatcher.class, 1, 1);
public static MetaIndex<Integer> BOAT_LAST_HIT = new MetaIndex<>(BoatWatcher.class, 0, 0);
public static MetaIndex<Boolean> BOAT_LEFT_PADDLING = new MetaIndex<>(BoatWatcher.class, 5, false);
public static MetaIndex<Boolean> BOAT_RIGHT_PADDLING = new MetaIndex<>(BoatWatcher.class, 4, false);
@ -297,6 +302,7 @@ public class MetaIndex<Y> {
public static MetaIndex<TreeSpecies> 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> BOAT_TYPE_NEW =
new MetaIndex<>(BoatWatcher.class, 3, NmsVersion.v1_19_R1.isSupported() ? Boat.Type.OAK : null);
@ -763,6 +769,10 @@ public class MetaIndex<Y> {
@NmsAddedIn(NmsVersion.v1_14)
public static MetaIndex<Boolean> RAIDER_CASTING_SPELL = new MetaIndex<>(RaiderWatcher.class, 0, false);
@NmsAddedIn(NmsVersion.v1_21_R2)
public static MetaIndex<Salmon.Variant> 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 @@ public class MetaIndex<Y> {
public static void validateMetadata() {
HashMap<Class, Integer> 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 class MetaIndex<Y> {
for (Entry<Class, Integer> 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 class MetaIndex<Y> {
continue;
}
if (!ReflectionManager.isAssignableFrom(watcherClass, type.getFlagWatcher())) {
if (!ReflectionManager.isAssignableFrom(type.getFlagWatcher(), watcherClass)) {
continue;
}
@ -1073,7 +1088,7 @@ public class MetaIndex<Y> {
ArrayList<MetaIndex> list = new ArrayList<>();
for (MetaIndex type : values()) {
if (type == null || !ReflectionManager.isAssignableFrom(watcherClass, type.getFlagWatcher())) {
if (type == null || !ReflectionManager.isAssignableFrom(type.getFlagWatcher(), watcherClass)) {
continue;
}

View File

@ -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();
}
}

View File

@ -12,6 +12,7 @@ public class AllayWatcher extends InsentientWatcher {
super(disguise);
}
@NmsAddedIn(NmsVersion.v1_19_R1)
public boolean isDancing() {
return getData(MetaIndex.ALLAY_DANCING);
}
@ -22,6 +23,7 @@ public class AllayWatcher extends InsentientWatcher {
sendData(MetaIndex.ALLAY_DANCING, dancing);
}
@NmsAddedIn(NmsVersion.v1_19_R1)
public boolean isCanDuplicate() {
return getData(MetaIndex.ALLAY_CAN_DUPLICATE);
}

View File

@ -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 class BoatWatcher extends FlagWatcher {
}
@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) {

View File

@ -2,7 +2,7 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
import me.libraryaddict.disguise.disguisetypes.Disguise;
public class DolphinWatcher extends InsentientWatcher {
public class DolphinWatcher extends AgeableAquaWatcher {
public DolphinWatcher(Disguise disguise) {
super(disguise);
}

View File

@ -18,6 +18,7 @@ public class GoatWatcher extends AgeableWatcher {
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 class GoatWatcher extends AgeableWatcher {
sendData(MetaIndex.GOAT_HAS_LEFT_HORN, hasHorn);
}
@NmsAddedIn(NmsVersion.v1_19_R1)
public boolean hasRightHorn() {
return getData(MetaIndex.GOAT_HAS_RIGHT_HORN);
}

View File

@ -2,6 +2,10 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
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.ArrayList;
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,16 +250,49 @@ public class LivingWatcher extends FlagWatcher {
sendData(MetaIndex.LIVING_POTION_AMBIENT, particles);
}
@NmsAddedIn(NmsVersion.v1_20_R4)
public void addParticle(Particle<? extends ParticleData> particle) {
getData(MetaIndex.LIVING_PARTICLES).add(particle);
sendData(MetaIndex.LIVING_PARTICLES);
}
@SafeVarargs
@NmsAddedIn(NmsVersion.v1_20_R4)
public final void removeParticles(Particle<? extends ParticleData>... particles) {
for (Particle<? extends ParticleData> particle : particles) {
getData(MetaIndex.LIVING_PARTICLES).remove(particle);
}
sendData(MetaIndex.LIVING_PARTICLES);
}
@NmsAddedIn(NmsVersion.v1_20_R4)
public List<Particle<? extends ParticleData>> 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();
if (NmsVersion.v1_20_R4.isSupported()) {
List<Particle<?>> 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() {
if (potionEffects.isEmpty()) {
@ -289,19 +326,19 @@ public class LivingWatcher extends FlagWatcher {
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<String> 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 class LivingWatcher extends FlagWatcher {
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 class LivingWatcher extends FlagWatcher {
sendPotionEffects();
}
@Deprecated
@NmsRemovedIn(NmsVersion.v1_20_R4)
public void removePotionEffect(PotionEffectType potionEffect) {
if (hasPotionEffect(potionEffect)) {
potionEffects.remove(potionEffect.getId());

View File

@ -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);
}
}

View File

@ -2,7 +2,7 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
import me.libraryaddict.disguise.disguisetypes.Disguise;
public class SquidWatcher extends InsentientWatcher {
public class SquidWatcher extends AgeableAquaWatcher {
public SquidWatcher(Disguise disguise) {
super(disguise);
}

View File

@ -73,6 +73,7 @@ public class WolfWatcher extends TameableWatcher {
}
}
@NmsAddedIn(NmsVersion.v1_16)
public int getAnger() {
return getData(MetaIndex.WOLF_ANGER);
}

View File

@ -9,6 +9,7 @@ import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher;
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 class ParamInfoManager {
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;
}

View File

@ -64,6 +64,7 @@ import org.bukkit.entity.Panda;
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 class ParamInfoTypes {
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"));

View File

@ -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.ParticleDustData
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 @@ public class ParamInfoParticle extends ParamInfoEnum {
private final Class<? extends ParticleData> 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 class ParamInfoParticle extends ParamInfoEnum {
}
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 class ParamInfoParticle extends ParamInfoEnum {
return enums;
}
private String colorToString(int color) {
for (Map.Entry<String, Color> entry : ParamInfoColor.getStaticColors().entrySet()) {
Color c = entry.getValue();
if (c.asRGB() != color) {
continue;
}
return entry.getKey();
}
private String alphaColorToString(int color) {
if (color == -1) {
return String.valueOf(color);
}
private String colorToString(float red, float green, float blue) {
int r = (int) red * 255;
int g = (int) green * 255;
int b = (int) blue * 255;
AlphaColor alphaColor = new AlphaColor(color);
for (Map.Entry<String, Color> entry : ParamInfoColor.getStaticColors().entrySet()) {
Color c = entry.getValue();
for (Map.Entry<String, org.bukkit.Color> entry : ParamInfoColor.getStaticColors().entrySet()) {
org.bukkit.Color c = entry.getValue();
if (r != c.getRed() || g != c.getGreen() || b != c.getBlue()) {
if (c.getRed() != alphaColor.red() || c.getGreen() != alphaColor.green() || c.getBlue() != alphaColor.blue()) {
continue;
}
// Always include the alpha to show usage
return alphaColor.alpha() + ":" + entry.getKey();
}
// Return in Alpha:Red,Green,Blue format to be more readable
return alphaColor.alpha() + ":" + alphaColor.red() + "," + alphaColor.green() + "," + alphaColor.blue();
}
private String colorToString(int red, int green, int blue) {
for (Map.Entry<String, org.bukkit.Color> entry : ParamInfoColor.getStaticColors().entrySet()) {
org.bukkit.Color c = entry.getValue();
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 class ParamInfoParticle extends ParamInfoEnum {
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 class ParamInfoParticle extends ParamInfoEnum {
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 class ParamInfoParticle extends ParamInfoEnum {
}
} 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 class ParamInfoParticle extends ParamInfoEnum {
}
}
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 class ParamInfoParticle extends ParamInfoEnum {
// 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 class ParamInfoParticle extends ParamInfoEnum {
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 class ParamInfoParticle extends ParamInfoEnum {
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 class ParamInfoParticle extends ParamInfoEnum {
}
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 class ParamInfoParticle extends ParamInfoEnum {
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 @@ public class ParamInfoParticle extends ParamInfoEnum {
throw new DisguiseParseException(LibsMsg.PARSE_PARTICLE_COLOR, name, string);
}
}
return color;
}

View File

@ -187,13 +187,19 @@ public class DisguiseParser {
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 class DisguiseParser {
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);

View File

@ -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()];

View File

@ -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

View File

@ -31,8 +31,11 @@ import me.libraryaddict.disguise.disguisetypes.DisguiseType;
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.Panda;
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 class ReflectionManager {
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 class ReflectionManager {
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 class ReflectionManager {
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 class ReflectionManager {
return null;
}
if (!NmsVersion.v1_14.isSupported()) {
if (cl == OcelotWatcher.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 @@ public class ReflectionManager {
watcherClass = ModdedWatcher.class;
break;
case COD:
case SALMON:
watcherClass = FishWatcher.class;
break;
case SPECTRAL_ARROW:
@ -1960,7 +1988,6 @@ public class ReflectionManager {
case MINECART_TNT:
watcherClass = MinecartWatcher.class;
break;
case SPIDER:
case CAVE_SPIDER:
watcherClass = SpiderWatcher.class;
break;
@ -1983,6 +2010,30 @@ public class ReflectionManager {
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<? extends FlagWatcher>) Class.forName(
"me.libraryaddict.disguise.disguisetypes.watchers." + toReadable(disguiseType.name()) + "Watcher");
@ -2480,6 +2531,11 @@ public class ReflectionManager {
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];

View File

@ -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]
* <br>
* Eg, FishWatcher only supported AgeableWatcher in 1.21.3
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface NmsSupported {
NmsVersion version();
Class<? extends FlagWatcher> watcher();
}

View File

@ -3,9 +3,7 @@ package me.libraryaddict.disguise.utilities.sounds;
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 @@ import java.util.HashMap;
*/
@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(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),
PLAYER("ENTITY_PLAYER_HURT", new String[]{"BLOCK_.*_STEP"}, "ENTITY_PLAYER_DEATH", null),
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),
PHANTOM("ENTITY_PHANTOM_HURT", new String[]{"ENTITY_PHANTOM_FLAP", "ENTITY_PHANTOM_SWOOP"}, "ENTITY_PHANTOM_DEATH",
"ENTITY_PHANTOM_AMBIENT", "ENTITY_PHANTOM_BITE"),
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),
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"),
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),
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"),
RABBIT(Sound.ENTITY_RABBIT_HURT, Sound.ENTITY_RABBIT_JUMP, Sound.ENTITY_RABBIT_DEATH, Sound.ENTITY_RABBIT_AMBIENT,
Sound.ENTITY_RABBIT_ATTACK),
RABBIT("ENTITY_RABBIT_HURT", "ENTITY_RABBIT_JUMP", "ENTITY_RABBIT_DEATH", "ENTITY_RABBIT_AMBIENT", "ENTITY_RABBIT_ATTACK"),
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),
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"),
SALMON(Sound.ENTITY_SALMON_HURT, null, Sound.ENTITY_SALMON_DEATH, Sound.ENTITY_SALMON_AMBIENT, Sound.ENTITY_SALMON_FLOP,
Sound.ENTITY_FISH_SWIM),
SALMON("ENTITY_SALMON_HURT", null, "ENTITY_SALMON_DEATH", "ENTITY_SALMON_AMBIENT", "ENTITY_SALMON_FLOP", "ENTITY_FISH_SWIM"),
SHEEP(Sound.ENTITY_SHEEP_HURT, Sound.ENTITY_SHEEP_STEP, Sound.ENTITY_SHEEP_DEATH, Sound.ENTITY_SHEEP_AMBIENT, Sound.ENTITY_SHEEP_SHEAR),
SHEEP("ENTITY_SHEEP_HURT", "ENTITY_SHEEP_STEP", "ENTITY_SHEEP_DEATH", "ENTITY_SHEEP_AMBIENT", "ENTITY_SHEEP_SHEAR"),
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),
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"),
SILVERFISH(Sound.ENTITY_SILVERFISH_HURT, Sound.ENTITY_SILVERFISH_STEP, Sound.ENTITY_SILVERFISH_DEATH, Sound.ENTITY_SILVERFISH_AMBIENT),
SILVERFISH("ENTITY_SILVERFISH_HURT", "ENTITY_SILVERFISH_STEP", "ENTITY_SILVERFISH_DEATH", "ENTITY_SILVERFISH_AMBIENT"),
SKELETON(Sound.ENTITY_SKELETON_HURT, Sound.ENTITY_SKELETON_STEP, Sound.ENTITY_SKELETON_DEATH, Sound.ENTITY_SKELETON_AMBIENT),
SKELETON("ENTITY_SKELETON_HURT", "ENTITY_SKELETON_STEP", "ENTITY_SKELETON_DEATH", "ENTITY_SKELETON_AMBIENT"),
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),
SKELETON_HORSE("ENTITY_SKELETON_HORSE_HURT", new String[]{"BLOCK_GRASS_STEP", "ENTITY_HORSE_STEP_WOOD"}, "ENTITY_SKELETON_HORSE_DEATH",
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_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"),
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),
SLIME(new String[]{"ENTITY_SLIME_HURT", "ENTITY_SLIME_HURT_SMALL"}, new String[]
SNOWMAN(Sound.ENTITY_SNOW_GOLEM_HURT, null, Sound.ENTITY_SNOW_GOLEM_DEATH, Sound.ENTITY_SNOW_GOLEM_AMBIENT,
Sound.ENTITY_SNOW_GOLEM_SHOOT),
{"ENTITY_SLIME_JUMP", "ENTITY_SLIME_JUMP_SMALL"}, new String[]
SPIDER(Sound.ENTITY_SPIDER_HURT, Sound.ENTITY_SPIDER_STEP, Sound.ENTITY_SPIDER_DEATH, Sound.ENTITY_SPIDER_AMBIENT),
{"ENTITY_SLIME_DEATH", "ENTITY_SLIME_DEATH_SMALL"}, null, "ENTITY_SLIME_ATTACK", "ENTITY_SLIME_SQUISH",
"ENTITY_SLIME_SQUISH_SMALL"),
STRAY(Sound.ENTITY_STRAY_HURT, Sound.ENTITY_STRAY_STEP, Sound.ENTITY_STRAY_DEATH, Sound.ENTITY_STRAY_AMBIENT),
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"),
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),
SNOWMAN("ENTITY_SNOW_GOLEM_HURT", null, "ENTITY_SNOW_GOLEM_DEATH", "ENTITY_SNOW_GOLEM_AMBIENT", "ENTITY_SNOW_GOLEM_SHOOT"),
SQUID(Sound.ENTITY_SQUID_HURT, null, Sound.ENTITY_SQUID_DEATH, Sound.ENTITY_SQUID_AMBIENT, Sound.ENTITY_SQUID_SQUIRT,
Sound.ENTITY_FISH_SWIM),
SPIDER("ENTITY_SPIDER_HURT", "ENTITY_SPIDER_STEP", "ENTITY_SPIDER_DEATH", "ENTITY_SPIDER_AMBIENT"),
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),
STRAY("ENTITY_STRAY_HURT", "ENTITY_STRAY_STEP", "ENTITY_STRAY_DEATH", "ENTITY_STRAY_AMBIENT"),
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"),
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(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),
TROPICAL_FISH("ENTITY_TROPICAL_FISH_HURT", null, "ENTITY_TROPICAL_FISH_DEATH", "ENTITY_TROPICAL_FISH_AMBIENT",
"ENTITY_TROPICAL_FISH_FLOP", "ENTITY_FISH_SWIM"),
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),
TURTLE(new String[]{"ENTITY_TURTLE_HURT", "ENTITY_TURTLE_HURT_BABY"}, new String[]
VEX(Sound.ENTITY_VEX_HURT, null, Sound.ENTITY_VEX_DEATH, Sound.ENTITY_VEX_AMBIENT, Sound.ENTITY_VEX_CHARGE),
{"ENTITY_TURTLE_SHAMBLE", "ENTITY_TURTLE_SHAMBLE_BABY"}, new String[]
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),
{"ENTITY_TURTLE_DEATH", "ENTITY_TURTLE_DEATH_BABY"}, "ENTITY_TURTLE_AMBIENT_LAND", "ENTITY_TURTLE_LAY_EGG"),
VINDICATOR(Sound.ENTITY_VINDICATOR_HURT, null, Sound.ENTITY_VINDICATOR_DEATH, Sound.ENTITY_VINDICATOR_AMBIENT),
VEX("ENTITY_VEX_HURT", null, "ENTITY_VEX_DEATH", "ENTITY_VEX_AMBIENT", "ENTITY_VEX_CHARGE"),
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),
VILLAGER("ENTITY_VILLAGER_HURT", null, "ENTITY_VILLAGER_DEATH", "ENTITY_VILLAGER_AMBIENT", "ENTITY_VILLAGER_TRADE",
"ENTITY_VILLAGER_NO", "ENTITY_VILLAGER_YES"),
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),
VINDICATOR("ENTITY_VINDICATOR_HURT", null, "ENTITY_VINDICATOR_DEATH", "ENTITY_VINDICATOR_AMBIENT"),
WITCH(Sound.ENTITY_WITCH_HURT, null, Sound.ENTITY_WITCH_DEATH, Sound.ENTITY_WITCH_AMBIENT),
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"),
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),
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_SKELETON(Sound.ENTITY_WITHER_SKELETON_HURT, Sound.ENTITY_WITHER_SKELETON_STEP, Sound.ENTITY_WITHER_SKELETON_DEATH,
Sound.ENTITY_WITHER_SKELETON_AMBIENT),
WITCH("ENTITY_WITCH_HURT", null, "ENTITY_WITCH_DEATH", "ENTITY_WITCH_AMBIENT"),
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("ENTITY_WITHER_HURT", null, "ENTITY_WITHER_DEATH", "ENTITY_WITHER_AMBIENT", "ENTITY_PLAYER_SMALL_FALL", "ENTITY_WITHER_SPAWN",
"ENTITY_PLAYER_BIG_FALL", "ENTITY_WITHER_SHOOT"),
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),
WITHER_SKELETON("ENTITY_WITHER_SKELETON_HURT", "ENTITY_WITHER_SKELETON_STEP", "ENTITY_WITHER_SKELETON_DEATH",
"ENTITY_WITHER_SKELETON_AMBIENT"),
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),
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_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),
ZOGLIN("ENTITY_ZOGLIN_HURT", "ENTITY_ZOGLIN_STEP", "ENTITY_ZOGLIN_DEATH", "ENTITY_ZOGLIN_AMBIENT", "ENTITY_ZOGLIN_ANGRY",
"ENTITY_ZOGLIN_ATTACK"),
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("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"),
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_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"),
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<String, SoundType> sounds = new HashMap<>();
@ -351,17 +334,7 @@ public enum DisguiseSoundEnums {
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 @@ public enum DisguiseSoundEnums {
}
}
private void addSound(Sound sound, SoundType type) {
addSound(sound.name(), type);
}
private void addSound(String sound, SoundType type) {
sounds.put(sound, type);
}

View File

@ -112,11 +112,11 @@ public class SoundManager {
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) {

View File

@ -175,6 +175,8 @@ public enum LibsMsg {
PARSE_PARTICLE_ITEM("<red>Expected <green>%s:Material,Amount?,Glow?<red>, received <green>%s</green> instead"),
PARSE_PARTICLE_SHULK_CHARGE("<red>Expected <green>%s:Roll(number.0)</green>, received <green>%s</green> instead"),
PARSE_PARTICLE_SHRIEK("<red>Expected <green>%s:Delay(number.0)</green>, received <green>%s</green> instead"),
PARSE_PARTICLE_TRAIL(
"<red>Expected <green>%s:Target(3 numbers),Color(3 numbers or red/blue/etc)</green> eg <green>X,Y,Z:RED</green>, received <green>%s</green> instead"),
PARSE_PARTICLE_DUST(
"<red>Expected <green>%s:Size(Optional Number),Color(3 numbers or red/blue/etc)</green>, received <green>%s</green> instead"),
PARSE_PARTICLE_DUST_TRANSITION(

View File

@ -159,7 +159,7 @@ public class DisguiseMethods {
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 @@ public class DisguiseMethods {
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 @@ public class DisguiseMethods {
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;

View File

@ -16,9 +16,11 @@ import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
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 @@ public class CompileMethods {
return String.join("\n", list).getBytes(StandardCharsets.UTF_8);
}
private static List<String> getMatchingFields(String pattern) {
List<String> 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 @@ public class CompileMethods {
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;

View File

@ -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:

View File

@ -3,6 +3,8 @@ package me.libraryaddict.disguise.utilities.parser.params;
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.ParticleDustData
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.ParamInfoItemStac
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 @@ public class DisguiseParamParticleTest {
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 @@ public class DisguiseParamParticleTest {
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 @@ public class DisguiseParamParticleTest {
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<ParticleBlockStateData>[] blockStateParticles() {
return new ParticleType[]{ParticleTypes.BLOCK, ParticleTypes.BLOCK_CRUMBLE, ParticleTypes.BLOCK_MARKER};
}
@ParameterizedTest
@SneakyThrows
public void testParticleBlockStateData() {
@MethodSource("blockStateParticles")
public void testParticleBlockStateData(ParticleType<ParticleBlockStateData> 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 class DisguiseParamParticleTest {
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 <Color1> <Color2>
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 class DisguiseParamParticleTest {
@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");