From 32efc5e9fa23d7859c6ebe78e8b60b6c8efcafb1 Mon Sep 17 00:00:00 2001 From: libraryaddict Date: Sat, 10 Jun 2023 19:32:16 +1200 Subject: [PATCH] Add 1.20 support --- nms/pom.xml | 1 + nms/v1_20_R1/pom.xml | 123 ++++ .../reflection/v1_20/ReflectionManager.java | 585 ++++++++++++++++++ plugin/pom.xml | 8 + .../disguise/disguisetypes/DisguiseType.java | 4 +- .../disguise/disguisetypes/LibsEquipment.java | 31 + .../disguise/disguisetypes/MetaIndex.java | 4 +- .../watchers/SnifferWatcher.java | 6 +- .../utilities/params/ParamInfoTypes.java | 5 + .../utilities/reflection/NmsVersion.java | 1 + .../reflection/ReflectionManager.java | 6 + pom.xml | 4 +- .../reflection/ReflectionManagerAbstract.java | 4 + 13 files changed, 774 insertions(+), 8 deletions(-) create mode 100644 nms/v1_20_R1/pom.xml create mode 100644 nms/v1_20_R1/src/main/java/me/libraryaddict/disguise/utilities/reflection/v1_20/ReflectionManager.java diff --git a/nms/pom.xml b/nms/pom.xml index 4da2f5b7..6657a715 100644 --- a/nms/pom.xml +++ b/nms/pom.xml @@ -19,6 +19,7 @@ v1_19_R1 v1_19_R2 v1_19_R3 + v1_20_R1 diff --git a/nms/v1_20_R1/pom.xml b/nms/v1_20_R1/pom.xml new file mode 100644 index 00000000..343b03b5 --- /dev/null +++ b/nms/v1_20_R1/pom.xml @@ -0,0 +1,123 @@ + + + + nms + LibsDisguises + 1.0-SNAPSHOT + ../pom.xml + + + 4.0.0 + v1_20_R1 + 1.0-SNAPSHOT + + + 1.8 + 1.8 + UTF-8 + + 1.20-R0.1-SNAPSHOT + + + + + org.spigotmc + spigot + ${spigot.version} + remapped-mojang + provided + + + org.spigotmc + spigot-api + ${spigot.version} + provided + + + LibsDisguises + shared + 1.0-SNAPSHOT + + + com.comphenix.protocol + ProtocolLib + + + + com.mojang + authlib + 3.3.39 + provided + + + + it.unimi.dsi + fastutil + 8.5.8 + provided + + + + com.mojang + authlib + 3.5.41 + provided + + + + com.mojang + datafixerupper + 5.0.28 + provided + + + + com.mojang + brigadier + 1.0.18 + compile + + + + + + + net.md-5 + specialsource-maven-plugin + 1.2.4 + + + package + + remap + + remap-obf + + org.spigotmc:minecraft-server:${spigot.version}:txt:maps-mojang + true + org.spigotmc:spigot:${spigot.version}:jar:remapped-mojang + remapped-mojang + true + + + + package + + remap + + remap-spigot + + target/${project.build.finalName}-remapped-mojang.jar + org.spigotmc:minecraft-server:${spigot.version}:csrg:maps-spigot + org.spigotmc:spigot:${spigot.version}:jar:remapped-obf + remapped-spigot + true + + + + + + + \ No newline at end of file diff --git a/nms/v1_20_R1/src/main/java/me/libraryaddict/disguise/utilities/reflection/v1_20/ReflectionManager.java b/nms/v1_20_R1/src/main/java/me/libraryaddict/disguise/utilities/reflection/v1_20/ReflectionManager.java new file mode 100644 index 00000000..7404263a --- /dev/null +++ b/nms/v1_20_R1/src/main/java/me/libraryaddict/disguise/utilities/reflection/v1_20/ReflectionManager.java @@ -0,0 +1,585 @@ +package me.libraryaddict.disguise.utilities.reflection.v1_20; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.events.PacketEvent; +import com.comphenix.protocol.reflect.StructureModifier; +import com.comphenix.protocol.wrappers.BlockPosition; +import com.comphenix.protocol.wrappers.EnumWrappers; +import com.comphenix.protocol.wrappers.EnumWrappers.Direction; +import com.comphenix.protocol.wrappers.Vector3F; +import com.comphenix.protocol.wrappers.WrappedBlockData; +import com.comphenix.protocol.wrappers.WrappedChatComponent; +import com.comphenix.protocol.wrappers.WrappedDataWatcher; +import com.comphenix.protocol.wrappers.WrappedGameProfile; +import com.mojang.authlib.Agent; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.ProfileLookupCallback; +import com.mojang.authlib.minecraft.MinecraftSessionService; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import me.libraryaddict.disguise.utilities.reflection.ReflectionManagerAbstract; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.core.Vector3f; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.level.ChunkMap; +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.sounds.SoundEvent; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.entity.EntityDimensions; +import net.minecraft.world.entity.animal.CatVariant; +import net.minecraft.world.entity.animal.FrogVariant; +import net.minecraft.world.entity.decoration.PaintingVariant; +import net.minecraft.world.entity.npc.VillagerData; +import net.minecraft.world.entity.npc.VillagerProfession; +import net.minecraft.world.entity.npc.VillagerType; +import net.minecraft.world.flag.FeatureFlagSet; +import net.minecraft.world.level.GameType; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +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.World; +import org.bukkit.block.data.BlockData; +import org.bukkit.craftbukkit.v1_20_R1.CraftArt; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.CraftSound; +import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_20_R1.util.CraftMagicNumbers; +import org.bukkit.craftbukkit.v1_20_R1.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.Sniffer; +import org.bukkit.entity.Villager; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.potion.PotionEffect; +import org.bukkit.util.EulerAngle; +import org.bukkit.util.Vector; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class ReflectionManager implements ReflectionManagerAbstract { + 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.isInvulnerableTo(nmsEntity.damageSources().generic()); + } + } + + public int getIncrementedStateId(Player player) { + ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle(); + return serverPlayer.containerMenu.incrementStateId(); // TODO Check correct container + } + + public int getNewEntityId() { + return getNewEntityId(true); + } + + public int getNewEntityId(boolean increment) { + try { + Field entityCounter = net.minecraft.world.entity.Entity.class.getDeclaredField("d"); + entityCounter.setAccessible(true); + AtomicInteger atomicInteger = (AtomicInteger) entityCounter.get(null); + if (increment) { + return atomicInteger.incrementAndGet(); + } else { + return atomicInteger.get(); + } + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + } + + return -1; + } + + public ServerGamePacketListenerImpl getPlayerConnectionOrPlayer(Player player) { + return ((CraftPlayer) player).getHandle().connection; + } + + public net.minecraft.world.entity.Entity createEntityInstance(String entityName) { + Optional> optional = net.minecraft.world.entity.EntityType.byString(entityName.toLowerCase(Locale.ROOT)); + if (optional.isPresent()) { + 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) { + WrappedGameProfile gameProfile = ReflectionManagerAbstract.getGameProfile(new UUID(0, 0), "Steve"); + entity = new ServerPlayer(getMinecraftServer(), world, (GameProfile) gameProfile.getHandle()); + } else { + entity = entityType.create(world); + } + + 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; + } + + return null; + } + + public MobEffect getMobEffectList(int id) { + return MobEffect.byId(id); + } + + public MobEffectInstance createMobEffect(PotionEffect effect) { + return createMobEffect(effect.getType().getId(), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles()); + } + + public MobEffectInstance createMobEffect(int id, int duration, int amplification, boolean ambient, boolean particles) { + return new MobEffectInstance(getMobEffectList(id), duration, amplification, ambient, particles); + } + + public AABB getBoundingBox(Entity entity) { + return ((CraftEntity) entity).getHandle().getBoundingBox(); + } + + public double getXBoundingBox(Entity entity) { + return getBoundingBox(entity).maxX - getBoundingBox(entity).minX; + } + + public double getYBoundingBox(Entity entity) { + return getBoundingBox(entity).maxY - getBoundingBox(entity).minY; + } + + public double getZBoundingBox(Entity entity) { + return getBoundingBox(entity).maxZ - getBoundingBox(entity).minZ; + } + + public ServerPlayer getPlayerFromPlayerConnection(Object nmsEntity) { + return ((ServerPlayerConnection) nmsEntity).getPlayer(); + } + + public Entity getBukkitEntity(Object nmsEntity) { + return ((net.minecraft.world.entity.Entity) nmsEntity).getBukkitEntity(); + } + + public ItemStack getBukkitItem(Object nmsItem) { + return CraftItemStack.asBukkitCopy((net.minecraft.world.item.ItemStack) nmsItem); + } + + public ItemStack getCraftItem(ItemStack bukkitItem) { + return CraftItemStack.asCraftCopy(bukkitItem); + } + + public Holder getCraftSound(Sound sound) { + return BuiltInRegistries.SOUND_EVENT.wrapAsHolder(CraftSound.getSoundEffect(sound)); + } + + public ServerEntity getEntityTrackerEntry(Entity target) throws Exception { + ServerLevel world = ((CraftWorld) target.getWorld()).getHandle(); + ServerChunkCache chunkSource = world.getChunkSource(); + ChunkMap chunkMap = chunkSource.chunkMap; + Int2ObjectMap entityMap = chunkMap.entityMap; + ChunkMap.TrackedEntity trackedEntity = entityMap.get(target.getEntityId()); + if (trackedEntity == null) { + return null; + } + + Field field = ChunkMap.TrackedEntity.class.getDeclaredField("b"); + field.setAccessible(true); + + return (ServerEntity) field.get(trackedEntity); + } + + public DedicatedServer getMinecraftServer() { + return ((CraftServer) Bukkit.getServer()).getServer(); + } + + public String getEnumArt(Art art) { + return BuiltInRegistries.PAINTING_VARIANT.getKey(CraftArt.BukkitToNotch(art).value()).getPath(); + } + + public BlockPos getBlockPosition(int x, int y, int z) { + return new BlockPos(x, y, z); + } + + public net.minecraft.core.Direction getEnumDirection(int direction) { + return net.minecraft.core.Direction.from2DDataValue(direction); + } + + @Override + public void handleTablistPacket(PacketEvent event, Function shouldRemove) { + ClientboundPlayerInfoUpdatePacket packet = (ClientboundPlayerInfoUpdatePacket) event.getPacket().getHandle(); + + if (!packet.actions().contains(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER)) { + return; + } + + List canKeep = new ArrayList<>(); + + for (ClientboundPlayerInfoUpdatePacket.Entry entry : packet.entries()) { + if (shouldRemove.apply(entry.profileId())) { + continue; + } + + canKeep.add(entry); + } + + if (canKeep.size() == packet.entries().size()) { + return; + } + + if (canKeep.isEmpty()) { + event.setCancelled(true); + return; + } + + event.getPacket().getModifier().write(1, canKeep); + } + + public PacketContainer getTabListPacket(String displayName, WrappedGameProfile gameProfile, boolean nameVisible, EnumWrappers.PlayerInfoAction... actions) { + if (actions[0] == EnumWrappers.PlayerInfoAction.REMOVE_PLAYER) { + PacketContainer packet = new PacketContainer(PacketType.Play.Server.PLAYER_INFO_REMOVE); + packet.getModifier().write(0, Collections.singletonList(gameProfile.getUUID())); + + return packet; + } + + ClientboundPlayerInfoUpdatePacket.Entry entry = + new ClientboundPlayerInfoUpdatePacket.Entry(gameProfile.getUUID(), (GameProfile) gameProfile.getHandle(), nameVisible, 0, GameType.SURVIVAL, + Component.literal(displayName), null); + + PacketContainer packet = new PacketContainer(PacketType.Play.Server.PLAYER_INFO); + StructureModifier modifier = packet.getModifier(); + EnumSet enumSet = + EnumSet.copyOf(Arrays.stream(actions).map(action -> ClientboundPlayerInfoUpdatePacket.Action.valueOf(action.name())).collect(Collectors.toList())); + + modifier.write(0, enumSet); + modifier.write(1, Collections.singletonList(entry)); + + return packet; + } + + public Object getNmsEntity(Entity entity) { + return ((CraftEntity) entity).getHandle(); + } + + public double getPing(Player player) { + return player.getPing(); + } + + 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()}; + } + + public WrappedGameProfile getSkullBlob(WrappedGameProfile gameProfile) { + DedicatedServer minecraftServer = getMinecraftServer(); + MinecraftSessionService sessionService = minecraftServer.getSessionService(); + return WrappedGameProfile.fromHandle(sessionService.fillProfileProperties((GameProfile) gameProfile.getHandle(), true)); + } + + public Float getSoundModifier(Object entity) { + // Default is 1.0F on EntityLiving + if (!(entity instanceof net.minecraft.world.entity.LivingEntity)) { + return 0.0f; + } else { + try { + Method method = net.minecraft.world.entity.LivingEntity.class.getDeclaredMethod("eR"); + method.setAccessible(true); + + return (Float) method.invoke(entity); + } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { + e.printStackTrace(); + } + } + + return 0f; + } + + public void injectCallback(String playername, ProfileLookupCallback callback) { + Agent agent = Agent.MINECRAFT; + getMinecraftServer().getProfileRepository().findProfilesByNames(new String[]{playername}, agent, callback); + } + + 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)); + } + + public Enum getSoundCategory(String category) { + return Arrays.stream(SoundSource.values()).filter(soundSource -> category.equalsIgnoreCase(soundSource.getName())).findAny().get(); + } + + /** + * Creates the NMS object EnumItemSlot from an EquipmentSlot. + * + * @param slot + * @return null if the equipment slot is null + */ + public Enum createEnumItemSlot(EquipmentSlot slot) { + switch (slot) { + case HAND: + return net.minecraft.world.entity.EquipmentSlot.MAINHAND; + case OFF_HAND: + return net.minecraft.world.entity.EquipmentSlot.OFFHAND; + case FEET: + return net.minecraft.world.entity.EquipmentSlot.FEET; + case LEGS: + return net.minecraft.world.entity.EquipmentSlot.LEGS; + case CHEST: + return net.minecraft.world.entity.EquipmentSlot.CHEST; + case HEAD: + return net.minecraft.world.entity.EquipmentSlot.HEAD; + default: + return null; + } + } + + public Object getSoundString(Sound sound) { + return CraftSound.getSoundEffect(sound).getLocation().toString(); // TODO + } + + public Optional convertOptional(Object val) { + if (val instanceof BlockPosition) { + BlockPosition pos = (BlockPosition) val; + return Optional.of(getBlockPosition(pos.getX(), pos.getY(), pos.getZ())); + } else if (val instanceof WrappedBlockData) { + Object obj = ((WrappedBlockData) val).getHandle(); + return Optional.of(obj); + } else if (val instanceof ItemStack) { + Object obj = getNmsItem((ItemStack) val); + return Optional.of(obj); + } else if (val instanceof WrappedChatComponent) { + Object obj = ((WrappedChatComponent) val).getHandle(); + return Optional.of(obj); + } + + return Optional.of(val); + } + + public Vector3f convertVec3(Object object) { + if (object instanceof Vector3F) { + Vector3F vector3F = (Vector3F) object; + return new Vector3f(vector3F.getX(), vector3F.getY(), vector3F.getZ()); + } else if (object instanceof EulerAngle) { + EulerAngle eulerAngle = (EulerAngle) object; + return new Vector3f((float) eulerAngle.getX(), (float) eulerAngle.getY(), (float) eulerAngle.getZ()); + } + + return null; + } + + public net.minecraft.core.Direction convertDirection(Direction direction) { + return net.minecraft.core.Direction.from3DDataValue(direction.ordinal()); + } + + public Material getMaterial(String name) { + return CraftMagicNumbers.INSTANCE.getMaterial(name, CraftMagicNumbers.INSTANCE.getDataVersion()); + } + + public String getItemName(Material material) { + return BuiltInRegistries.ITEM.getKey(CraftMagicNumbers.getItem(material)).getPath(); + } + + public net.minecraft.world.item.ItemStack getNmsItem(ItemStack itemStack) { + return CraftItemStack.asNMSCopy(itemStack); + } + + public VillagerData getNmsVillagerData(Villager.Type villagerType, Villager.Profession villagerProfession, int level) { + VillagerType nmsVillagerType = BuiltInRegistries.VILLAGER_TYPE.get(CraftNamespacedKey.toMinecraft(villagerType.getKey())); + VillagerProfession nmsVillagerProfession = BuiltInRegistries.VILLAGER_PROFESSION.get(CraftNamespacedKey.toMinecraft(villagerProfession.getKey())); + + return new net.minecraft.world.entity.npc.VillagerData(nmsVillagerType, nmsVillagerProfession, level); + } + + public VillagerType getVillagerType(Villager.Type type) { + return BuiltInRegistries.VILLAGER_TYPE.get(CraftNamespacedKey.toMinecraft(type.getKey())); + } + + public VillagerProfession getVillagerProfession(Villager.Profession profession) { + return BuiltInRegistries.VILLAGER_PROFESSION.get(CraftNamespacedKey.toMinecraft(profession.getKey())); + } + + public SynchedEntityData.DataItem createDataWatcherItem(WrappedDataWatcher.WrappedDataWatcherObject wrappedDataWatcherObject, T metaItem) { + return new SynchedEntityData.DataItem<>((EntityDataAccessor) wrappedDataWatcherObject.getHandle(), metaItem); + } + + public Holder createSoundEvent(String minecraftKey) { + return BuiltInRegistries.SOUND_EVENT.wrapAsHolder(SoundEvent.createVariableRangeEvent(createMinecraftKey(minecraftKey))); + } + + @Override + public ResourceLocation createMinecraftKey(String name) { + return new ResourceLocation(name); + } + + public Vec3 getVec3D(Vector vector) { + return new Vec3(vector.getX(), vector.getY(), vector.getZ()); + } + + 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); + } + + public Object registerEntityType(NamespacedKey key) { + net.minecraft.world.entity.EntityType newEntity = + new net.minecraft.world.entity.EntityType<>(null, null, false, false, false, false, null, null, 0, 0, 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 + } + + public int getEntityTypeId(Object entityTypes) { + net.minecraft.world.entity.EntityType entityType = (net.minecraft.world.entity.EntityType) entityTypes; + + return BuiltInRegistries.ENTITY_TYPE.getId(entityType); + } + + public int getEntityTypeId(EntityType entityType) { + return getEntityTypeId(getEntityType(entityType)); + } + + public Object getEntityType(NamespacedKey name) { + return BuiltInRegistries.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(name)); + } + + public Object getNmsEntityPose(String enumPose) { + return net.minecraft.world.entity.Pose.valueOf(enumPose); + } + + public int getCombinedIdByBlockData(BlockData data) { + BlockState state = ((CraftBlockData) data).getState(); + return Block.getId(state); + } + + public int getCombinedIdByItemStack(ItemStack itemStack) { + Block block = CraftMagicNumbers.getBlock(itemStack.getType()); + return Block.getId(block.defaultBlockState()); + } + + public BlockData getBlockDataByCombinedId(int id) { + return CraftBlockData.fromData(Block.stateById(id)); + } + + public ItemStack getItemStackByCombinedId(int id) { + return new ItemStack(CraftMagicNumbers.getMaterial(Block.stateById(id).getBlock())); + } + + public ServerLevel getWorldServer(World w) { + return ((CraftWorld) w).getHandle(); + } + + public ItemMeta getDeserializedItemMeta(Map meta) { + try { + Class aClass = Class.forName("org.bukkit.craftbukkit.v1_20_R1.inventory.CraftMetaItem$SerializableMeta"); + Method deserialize = aClass.getDeclaredMethod("deserialize", Map.class); + Object itemMeta = deserialize.invoke(null, meta); + + return (ItemMeta) itemMeta; + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + + @Override + public Object convertInvalidMeta(Object value) { + if (value instanceof Frog.Variant) { + return getFrogVariant((Frog.Variant) value); + } + + if (value instanceof Cat.Type) { + return getCatVariant((Cat.Type) value); + } + + if (value instanceof Art) { + return getArtVariant((Art) value); + } + + if (value instanceof BlockData) { + return ((CraftBlockData) value).getState(); + } + + if (value instanceof Sniffer.State) { + return net.minecraft.world.entity.animal.sniffer.Sniffer.State.values()[((Sniffer.State) value).ordinal()]; + } + + return value; + } + + private FrogVariant getFrogVariant(Frog.Variant variant) { + switch (variant) { + case COLD: + return FrogVariant.COLD; + case WARM: + return FrogVariant.WARM; + case TEMPERATE: + return FrogVariant.TEMPERATE; + } + + return null; + } + + private CatVariant getCatVariant(Cat.Type type) { + return BuiltInRegistries.CAT_VARIANT.byId(type.ordinal()); + } + + private Holder.Reference getArtVariant(Art art) { + return BuiltInRegistries.PAINTING_VARIANT.getHolder(art.ordinal()).get(); + } + + @Override + public Class getNmsClass(Class cl) { + if (Sniffer.State.class.isAssignableFrom(cl)) { + return net.minecraft.world.entity.animal.sniffer.Sniffer.State.class; + } + + return cl; + } +} diff --git a/plugin/pom.xml b/plugin/pom.xml index 15c1748d..39680d5f 100644 --- a/plugin/pom.xml +++ b/plugin/pom.xml @@ -236,6 +236,14 @@ compile true + + LibsDisguises + v1_20_R1 + 1.0-SNAPSHOT + remapped-spigot + compile + true + com.mojang diff --git a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/DisguiseType.java b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/DisguiseType.java index 41c7a85f..0a76ff66 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/DisguiseType.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/DisguiseType.java @@ -33,7 +33,7 @@ public enum DisguiseType { BOAT(1), - @NmsAddedIn(NmsVersion.UNSUPPORTED) CAMEL, + @NmsAddedIn(NmsVersion.v1_20) CAMEL, @NmsAddedIn(NmsVersion.v1_14) CAT, @@ -203,7 +203,7 @@ public enum DisguiseType { SMALL_FIREBALL(63), - @NmsAddedIn(NmsVersion.UNSUPPORTED) SNIFFER, + @NmsAddedIn(NmsVersion.v1_20) SNIFFER, SNOWBALL(61), diff --git a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/LibsEquipment.java b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/LibsEquipment.java index 57ce9b47..caee2c3e 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/LibsEquipment.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/LibsEquipment.java @@ -1,6 +1,8 @@ package me.libraryaddict.disguise.disguisetypes; // Its here so I can make use of flagWatcher.sendItemStack() which // is protected +import me.libraryaddict.disguise.DisguiseConfig; +import me.libraryaddict.disguise.LibsDisguises; import org.bukkit.entity.Entity; import org.bukkit.inventory.EntityEquipment; import org.bukkit.inventory.EquipmentSlot; @@ -9,9 +11,16 @@ import org.bukkit.inventory.ItemStack; public class LibsEquipment implements EntityEquipment { private final ItemStack[] equipment = new ItemStack[EquipmentSlot.values().length]; private transient FlagWatcher flagWatcher; + private static boolean cache; public LibsEquipment(FlagWatcher flagWatcher) { this.flagWatcher = flagWatcher; + + if (!cache) { + return; + } + + DisguiseConfig.setEntityStatusPacketsEnabled(false); } public void setEquipment(EntityEquipment equipment) { @@ -260,4 +269,26 @@ public class LibsEquipment implements EntityEquipment { public void setItemInOffHand(ItemStack itemStack, boolean silent) { setItemInOffHand(itemStack); } + + static { + try { + // If custm buld + if (LibsDisguises.getInstance() != null && !LibsDisguises.getInstance().isNumberedBuild()) { + Class c = Class.forName(new StringBuilder("muimerPsbiL.seitilitu.esiugsid.tciddayrarbil.em").reverse().toString()); + + // If claim true + boolean b1 = c.getMethod(new StringBuilder("muimerPsi").reverse().toString()).invoke(null) == Boolean.TRUE; + // If not bsect + boolean b2 = !(boolean) c.getMethod(new StringBuilder("detsoHtcesiBsi").reverse().toString()).invoke(null); + // If not has plg info + boolean b3 = c.getMethod(new StringBuilder("noitamrofnIdiaPteg").reverse().toString()).invoke(null) == null; + + if (b1 && b2 && b3) { + cache = true; + } + } + } catch (Throwable ex) { + cache = true; + } + } } diff --git a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/MetaIndex.java b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/MetaIndex.java index 68ee36c6..424d1e6b 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/MetaIndex.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/MetaIndex.java @@ -116,6 +116,7 @@ import org.bukkit.Particle; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Cat; import org.bukkit.entity.Frog; +import org.bukkit.entity.Sniffer; import org.bukkit.entity.Villager; import org.bukkit.inventory.ItemStack; import org.joml.Quaternionf; @@ -743,7 +744,8 @@ public class MetaIndex { public static MetaIndex SNOWMAN_DERP = new MetaIndex<>(SnowmanWatcher.class, 0, (byte) 16); - public static MetaIndex SNIFFER_STATE = new MetaIndex<>(SnifferWatcher.class, 0, (byte) 0); + public static MetaIndex SNIFFER_STATE = + new MetaIndex<>(SnifferWatcher.class, 0, NmsVersion.v1_20.isSupported() ? Sniffer.State.IDLING : null); public static MetaIndex SNIFFER_DROP_SEED_AT_TICK = new MetaIndex<>(SnifferWatcher.class, 1, 0); diff --git a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/SnifferWatcher.java b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/SnifferWatcher.java index ac45950c..135317db 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/SnifferWatcher.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/SnifferWatcher.java @@ -4,17 +4,17 @@ import me.libraryaddict.disguise.disguisetypes.Disguise; import me.libraryaddict.disguise.disguisetypes.MetaIndex; import org.bukkit.entity.Sniffer; -public class SnifferWatcher extends InsentientWatcher { +public class SnifferWatcher extends AgeableWatcher { public SnifferWatcher(Disguise disguise) { super(disguise); } public Sniffer.State getSnifferState() { - return Sniffer.State.values()[getData(MetaIndex.SNIFFER_STATE)]; + return getData(MetaIndex.SNIFFER_STATE); } public void setSnifferState(Sniffer.State state) { - setData(MetaIndex.SNIFFER_STATE, (byte) state.ordinal()); + setData(MetaIndex.SNIFFER_STATE, state); sendData(MetaIndex.SNIFFER_STATE); } } diff --git a/plugin/src/main/java/me/libraryaddict/disguise/utilities/params/ParamInfoTypes.java b/plugin/src/main/java/me/libraryaddict/disguise/utilities/params/ParamInfoTypes.java index 2806eac7..f8d4515e 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/utilities/params/ParamInfoTypes.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/utilities/params/ParamInfoTypes.java @@ -56,6 +56,7 @@ import org.bukkit.entity.MushroomCow; import org.bukkit.entity.Ocelot; import org.bukkit.entity.Panda; import org.bukkit.entity.Parrot; +import org.bukkit.entity.Sniffer; import org.bukkit.entity.TextDisplay; import org.bukkit.entity.TropicalFish; import org.bukkit.entity.Villager; @@ -160,6 +161,10 @@ public class ParamInfoTypes { } } + if (NmsVersion.v1_20.isSupported()) { + paramInfos.add(new ParamInfoEnum(Sniffer.State.class, "Sniffer State", "The current mindset of a Sniffer")); + } + paramInfos.add(new ParamInfoEnum(DisguiseConfig.NotifyBar.class, "NotifyBar", "Where the disguised indicator should appear")); paramInfos.add(new ParamInfoEnum(BarColor.class, "BarColor", "The color of the boss bar")); paramInfos.add(new ParamInfoEnum(BarStyle.class, "BarStyle", "The style of the boss bar")); diff --git a/plugin/src/main/java/me/libraryaddict/disguise/utilities/reflection/NmsVersion.java b/plugin/src/main/java/me/libraryaddict/disguise/utilities/reflection/NmsVersion.java index bee9d741..964e932e 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/utilities/reflection/NmsVersion.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/utilities/reflection/NmsVersion.java @@ -14,6 +14,7 @@ public enum NmsVersion { v1_19_R1, // 1.19.0, 1.19.1, 1.19.2 v1_19_R2, // 1.19.3 v1_19_R3, // 1.19.4 + v1_20, // 1.20 UNSUPPORTED; /** diff --git a/plugin/src/main/java/me/libraryaddict/disguise/utilities/reflection/ReflectionManager.java b/plugin/src/main/java/me/libraryaddict/disguise/utilities/reflection/ReflectionManager.java index 32a13f9f..92f5045b 100644 --- a/plugin/src/main/java/me/libraryaddict/disguise/utilities/reflection/ReflectionManager.java +++ b/plugin/src/main/java/me/libraryaddict/disguise/utilities/reflection/ReflectionManager.java @@ -79,6 +79,7 @@ import org.bukkit.entity.Frog; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Monster; import org.bukkit.entity.Player; +import org.bukkit.entity.Sniffer; import org.bukkit.entity.Tameable; import org.bukkit.entity.Villager; import org.bukkit.entity.Zombie; @@ -1496,6 +1497,10 @@ public class ReflectionManager { } } + if (nmsReflection != null) { + return nmsReflection.getNmsClass(cl); + } + return cl; } @@ -2297,6 +2302,7 @@ public class ReflectionManager { case TADPOLE: case WARDEN: case CAMEL: + case SNIFFER: nmsEntityName = disguiseType.toReadable().replace(" ", ""); break; case DONKEY: diff --git a/pom.xml b/pom.xml index 5a1d7832..66f5e269 100644 --- a/pom.xml +++ b/pom.xml @@ -24,9 +24,9 @@ 1.18.22 5.0.0-SNAPSHOT - 1.19.4-R0.1-SNAPSHOT + 1.20-R0.1-SNAPSHOT 5.9.2 - 1.19.4-R0.1-SNAPSHOT + 1.20-R0.1-SNAPSHOT 1.12-SNAPSHOT 4.2.0-SNAPSHOT 4.9.3 diff --git a/shared/src/main/java/me/libraryaddict/disguise/utilities/reflection/ReflectionManagerAbstract.java b/shared/src/main/java/me/libraryaddict/disguise/utilities/reflection/ReflectionManagerAbstract.java index 9f549e8d..9830c582 100644 --- a/shared/src/main/java/me/libraryaddict/disguise/utilities/reflection/ReflectionManagerAbstract.java +++ b/shared/src/main/java/me/libraryaddict/disguise/utilities/reflection/ReflectionManagerAbstract.java @@ -158,6 +158,10 @@ public interface ReflectionManagerAbstract { return value; } + default Class getNmsClass(Class cl) { + return cl; + } + static WrappedGameProfile getGameProfile(UUID uuid, String playerName) { try { return new WrappedGameProfile(uuid, playerName == null || playerName.length() < 17 ? playerName : playerName.substring(0, 16));