Java 16 support, some dodgy code hmm. Has errors with "class loaded by another plugin" which needs to be resolved
This commit is contained in:
		| @@ -67,6 +67,8 @@ public class LibsDisguises extends JavaPlugin { | |||||||
|  |  | ||||||
|             instance = this; |             instance = this; | ||||||
|  |  | ||||||
|  |             WatcherSanitizer.init(); | ||||||
|  |  | ||||||
|             Plugin plugin = Bukkit.getPluginManager().getPlugin("ProtocolLib"); |             Plugin plugin = Bukkit.getPluginManager().getPlugin("ProtocolLib"); | ||||||
|  |  | ||||||
|             if (plugin == null || DisguiseUtilities.isOlderThan(DisguiseUtilities.getProtocolLibRequiredVersion(), plugin.getDescription().getVersion())) { |             if (plugin == null || DisguiseUtilities.isOlderThan(DisguiseUtilities.getProtocolLibRequiredVersion(), plugin.getDescription().getVersion())) { | ||||||
| @@ -105,8 +107,6 @@ public class LibsDisguises extends JavaPlugin { | |||||||
|             if (!reloaded) { |             if (!reloaded) { | ||||||
|                 commandConfig.load(); |                 commandConfig.load(); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             WatcherSanitizer.init(); |  | ||||||
|         } catch (Throwable throwable) { |         } catch (Throwable throwable) { | ||||||
|             getUpdateChecker().doUpdate(); |             getUpdateChecker().doUpdate(); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,7 +4,6 @@ import com.comphenix.protocol.PacketType; | |||||||
| import com.comphenix.protocol.PacketType.Play.Server; | import com.comphenix.protocol.PacketType.Play.Server; | ||||||
| import com.comphenix.protocol.ProtocolLibrary; | import com.comphenix.protocol.ProtocolLibrary; | ||||||
| import com.comphenix.protocol.events.PacketContainer; | import com.comphenix.protocol.events.PacketContainer; | ||||||
| import com.comphenix.protocol.reflect.StructureModifier; |  | ||||||
| import com.comphenix.protocol.wrappers.EnumWrappers.NativeGameMode; | import com.comphenix.protocol.wrappers.EnumWrappers.NativeGameMode; | ||||||
| import com.comphenix.protocol.wrappers.EnumWrappers.PlayerInfoAction; | import com.comphenix.protocol.wrappers.EnumWrappers.PlayerInfoAction; | ||||||
| import com.comphenix.protocol.wrappers.PlayerInfoData; | import com.comphenix.protocol.wrappers.PlayerInfoData; | ||||||
| @@ -16,7 +15,10 @@ import me.libraryaddict.disguise.DisguiseAPI; | |||||||
| import me.libraryaddict.disguise.DisguiseConfig; | import me.libraryaddict.disguise.DisguiseConfig; | ||||||
| import me.libraryaddict.disguise.LibsDisguises; | import me.libraryaddict.disguise.LibsDisguises; | ||||||
| import me.libraryaddict.disguise.disguisetypes.TargetedDisguise.TargetType; | import me.libraryaddict.disguise.disguisetypes.TargetedDisguise.TargetType; | ||||||
| import me.libraryaddict.disguise.disguisetypes.watchers.*; | import me.libraryaddict.disguise.disguisetypes.watchers.AbstractHorseWatcher; | ||||||
|  | import me.libraryaddict.disguise.disguisetypes.watchers.AgeableWatcher; | ||||||
|  | import me.libraryaddict.disguise.disguisetypes.watchers.BoatWatcher; | ||||||
|  | import me.libraryaddict.disguise.disguisetypes.watchers.ZombieWatcher; | ||||||
| import me.libraryaddict.disguise.events.DisguiseEvent; | import me.libraryaddict.disguise.events.DisguiseEvent; | ||||||
| import me.libraryaddict.disguise.events.UndisguiseEvent; | import me.libraryaddict.disguise.events.UndisguiseEvent; | ||||||
| import me.libraryaddict.disguise.utilities.DisguiseUtilities; | import me.libraryaddict.disguise.utilities.DisguiseUtilities; | ||||||
| @@ -29,7 +31,6 @@ import me.libraryaddict.disguise.utilities.reflection.ReflectionManager; | |||||||
| import me.libraryaddict.disguise.utilities.translations.LibsMsg; | import me.libraryaddict.disguise.utilities.translations.LibsMsg; | ||||||
| import net.md_5.bungee.api.ChatMessageType; | import net.md_5.bungee.api.ChatMessageType; | ||||||
| import org.bukkit.Bukkit; | import org.bukkit.Bukkit; | ||||||
| import org.bukkit.Location; |  | ||||||
| import org.bukkit.NamespacedKey; | import org.bukkit.NamespacedKey; | ||||||
| import org.bukkit.boss.BarColor; | import org.bukkit.boss.BarColor; | ||||||
| import org.bukkit.boss.BarStyle; | import org.bukkit.boss.BarStyle; | ||||||
| @@ -38,7 +39,6 @@ import org.bukkit.command.CommandSender; | |||||||
| import org.bukkit.entity.*; | import org.bukkit.entity.*; | ||||||
| import org.bukkit.metadata.FixedMetadataValue; | import org.bukkit.metadata.FixedMetadataValue; | ||||||
| import org.bukkit.scheduler.BukkitRunnable; | import org.bukkit.scheduler.BukkitRunnable; | ||||||
| import org.bukkit.util.Vector; |  | ||||||
|  |  | ||||||
| import java.lang.reflect.InvocationTargetException; | import java.lang.reflect.InvocationTargetException; | ||||||
| import java.util.*; | import java.util.*; | ||||||
| @@ -71,7 +71,7 @@ public abstract class Disguise { | |||||||
|     /** |     /** | ||||||
|      * If set, how long before disguise expires |      * If set, how long before disguise expires | ||||||
|      */ |      */ | ||||||
|     private long disguiseExpires; |     protected long disguiseExpires; | ||||||
|     /** |     /** | ||||||
|      * For when plugins may want to assign custom data to a disguise, such as who owns it |      * For when plugins may want to assign custom data to a disguise, such as who owns it | ||||||
|      */ |      */ | ||||||
| @@ -370,7 +370,7 @@ public abstract class Disguise { | |||||||
|         return this; |         return this; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void doActionBar() { |     protected void doActionBar() { | ||||||
|         if (getNotifyBar() == DisguiseConfig.NotifyBar.ACTION_BAR && getEntity() instanceof Player && !getEntity().hasPermission("libsdisguises.noactionbar") && |         if (getNotifyBar() == DisguiseConfig.NotifyBar.ACTION_BAR && getEntity() instanceof Player && !getEntity().hasPermission("libsdisguises.noactionbar") && | ||||||
|                 DisguiseAPI.getDisguise(getEntity()) == Disguise.this) { |                 DisguiseAPI.getDisguise(getEntity()) == Disguise.this) { | ||||||
|             ((Player) getEntity()).spigot().sendMessage(ChatMessageType.ACTION_BAR, LibsMsg.ACTION_BAR_MESSAGE.getChat(getDisguiseName())); |             ((Player) getEntity()).spigot().sendMessage(ChatMessageType.ACTION_BAR, LibsMsg.ACTION_BAR_MESSAGE.getChat(getDisguiseName())); | ||||||
| @@ -394,227 +394,18 @@ public abstract class Disguise { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void createRunnable() { |     private void createRunnable() { | ||||||
|         if (runnable != null) { |         if (runnable != null && !runnable.isCancelled()) { | ||||||
|             runnable.cancel(); |             runnable.cancel(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         final boolean alwaysSendVelocity; |  | ||||||
|  |  | ||||||
|         switch (getType()) { |  | ||||||
|             case EXPERIENCE_ORB: |  | ||||||
|             case WITHER_SKULL: |  | ||||||
|             case FIREWORK: |  | ||||||
|                 alwaysSendVelocity = true; |  | ||||||
|                 break; |  | ||||||
|             default: |  | ||||||
|                 alwaysSendVelocity = false; |  | ||||||
|                 break; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         final Double vectorY; |  | ||||||
|  |  | ||||||
|         switch (getType()) { |  | ||||||
|             case FIREWORK: |  | ||||||
|             case WITHER_SKULL: |  | ||||||
|                 vectorY = 0.000001D; |  | ||||||
|                 break; |  | ||||||
|             case EXPERIENCE_ORB: |  | ||||||
|                 vectorY = 0.0221; |  | ||||||
|                 break; |  | ||||||
|             default: |  | ||||||
|                 vectorY = null; |  | ||||||
|                 break; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         final TargetedDisguise disguise = (TargetedDisguise) this; |         final TargetedDisguise disguise = (TargetedDisguise) this; | ||||||
|  |  | ||||||
|         // A scheduler to clean up any unused disguises. |         // A scheduler to clean up any unused disguises. | ||||||
|         runnable = new BukkitRunnable() { |         runnable = new DisguiseRunnable(this); | ||||||
|             private int blockX, blockY, blockZ, facing; |  | ||||||
|             private int deadTicks = 0; |  | ||||||
|             private int actionBarTicks = -1; |  | ||||||
|             private long lastRefreshed = System.currentTimeMillis(); |  | ||||||
|  |  | ||||||
|             @Override |  | ||||||
|             public void run() { |  | ||||||
|                 if (!isDisguiseInUse() || getEntity() == null) { |  | ||||||
|                     cancel(); |  | ||||||
|                     runnable = null; |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 if (++actionBarTicks % 15 == 0) { |  | ||||||
|                     actionBarTicks = 0; |  | ||||||
|  |  | ||||||
|                     doActionBar(); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 // If entity is no longer valid. Remove it. |  | ||||||
|                 if (getEntity() instanceof Player && !((Player) getEntity()).isOnline()) { |  | ||||||
|                     removeDisguise(); |  | ||||||
|                 } else if (disguiseExpires > 0 && |  | ||||||
|                         (DisguiseConfig.isDynamicExpiry() ? disguiseExpires-- == 1 : disguiseExpires < System.currentTimeMillis())) { // If disguise expired |  | ||||||
|                     removeDisguise(); |  | ||||||
|  |  | ||||||
|                     if (getEntity() instanceof Player) { |  | ||||||
|                         LibsMsg.EXPIRED_DISGUISE.send(getEntity()); |  | ||||||
|                     } |  | ||||||
|  |  | ||||||
|                     return; |  | ||||||
|                 } else if (!getEntity().isValid()) { |  | ||||||
|                     // If it has been dead for 30+ ticks |  | ||||||
|                     // This is to ensure that this disguise isn't removed while clients think its the real entity |  | ||||||
|                     // The delay is because if it sends the destroy entity packets straight away, then it means no |  | ||||||
|                     // death animation |  | ||||||
|                     // This is probably still a problem for wither and enderdragon deaths. |  | ||||||
|                     if (deadTicks++ > (getType() == DisguiseType.ENDER_DRAGON ? 200 : 20)) { |  | ||||||
|                         if (isRemoveDisguiseOnDeath()) { |  | ||||||
|                             removeDisguise(); |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|  |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 deadTicks = 0; |  | ||||||
|  |  | ||||||
|                 // If the disguise type is tnt, we need to resend the entity packet else it will turn invisible |  | ||||||
|                 if (getType() == DisguiseType.FIREWORK || getType() == DisguiseType.EVOKER_FANGS) { |  | ||||||
|                     if (lastRefreshed + ((getType() == DisguiseType.FIREWORK ? 40 : 23) * 50) < System.currentTimeMillis()) { |  | ||||||
|                         lastRefreshed = System.currentTimeMillis(); |  | ||||||
|  |  | ||||||
|                         DisguiseUtilities.refreshTrackers(disguise); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 if (isModifyBoundingBox()) { |  | ||||||
|                     DisguiseUtilities.doBoundingBox(disguise); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 if (getType() == DisguiseType.BAT && !((BatWatcher) getWatcher()).isHanging()) { |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 doVelocity(vectorY, alwaysSendVelocity); |  | ||||||
|  |  | ||||||
|                 if (getType() == DisguiseType.EXPERIENCE_ORB) { |  | ||||||
|                     PacketContainer packet = new PacketContainer(Server.REL_ENTITY_MOVE); |  | ||||||
|  |  | ||||||
|                     packet.getIntegers().write(0, getEntity().getEntityId()); |  | ||||||
|  |  | ||||||
|                     try { |  | ||||||
|                         for (Player player : DisguiseUtilities.getPerverts(disguise)) { |  | ||||||
|                             if (getEntity() != player) { |  | ||||||
|                                 ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet, false); |  | ||||||
|                                 continue; |  | ||||||
|                             } else if (!isSelfDisguiseVisible() || !(getEntity() instanceof Player)) { |  | ||||||
|                                 continue; |  | ||||||
|                             } |  | ||||||
|  |  | ||||||
|                             PacketContainer selfPacket = packet.shallowClone(); |  | ||||||
|  |  | ||||||
|                             selfPacket.getModifier().write(0, DisguiseAPI.getSelfDisguiseId()); |  | ||||||
|  |  | ||||||
|                             try { |  | ||||||
|                                 ProtocolLibrary.getProtocolManager().sendServerPacket((Player) getEntity(), selfPacket, false); |  | ||||||
|                             } catch (InvocationTargetException e) { |  | ||||||
|                                 e.printStackTrace(); |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                     } catch (InvocationTargetException e) { |  | ||||||
|                         e.printStackTrace(); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         }; |  | ||||||
|  |  | ||||||
|         runnable.runTaskTimer(LibsDisguises.getInstance(), 1, 1); |         runnable.runTaskTimer(LibsDisguises.getInstance(), 1, 1); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void doVelocity(Double vectorY, boolean alwaysSendVelocity) { |  | ||||||
|         // If the vectorY isn't 0. Cos if it is. Then it doesn't want to send any vectors. |  | ||||||
|         // If this disguise has velocity sending enabled and the entity is flying. |  | ||||||
|         if (isVelocitySent() && vectorY != null && (alwaysSendVelocity || !getEntity().isOnGround())) { |  | ||||||
|             Vector vector = getEntity().getVelocity(); |  | ||||||
|  |  | ||||||
|             // If the entity doesn't have velocity changes already - You know. I really can't wrap my |  | ||||||
|             // head about the |  | ||||||
|             // if statement. |  | ||||||
|             // But it doesn't seem to do anything wrong.. |  | ||||||
|             if (vector.getY() != 0 && !(vector.getY() < 0 && alwaysSendVelocity && getEntity().isOnGround())) { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             // If disguise isn't a experience orb, or the entity isn't standing on the ground |  | ||||||
|             if (getType() != DisguiseType.EXPERIENCE_ORB || !getEntity().isOnGround()) { |  | ||||||
|                 PacketContainer lookPacket = null; |  | ||||||
|  |  | ||||||
|                 if (getType() == DisguiseType.WITHER_SKULL && DisguiseConfig.isWitherSkullPacketsEnabled()) { |  | ||||||
|                     lookPacket = new PacketContainer(Server.ENTITY_LOOK); |  | ||||||
|  |  | ||||||
|                     StructureModifier<Object> mods = lookPacket.getModifier(); |  | ||||||
|                     lookPacket.getIntegers().write(0, getEntity().getEntityId()); |  | ||||||
|                     Location loc = getEntity().getLocation(); |  | ||||||
|  |  | ||||||
|                     mods.write(4, DisguiseUtilities.getYaw(getType(), getEntity().getType(), (byte) Math.floor(loc.getYaw() * 256.0F / 360.0F))); |  | ||||||
|                     mods.write(5, DisguiseUtilities.getPitch(getType(), getEntity().getType(), (byte) Math.floor(loc.getPitch() * 256.0F / 360.0F))); |  | ||||||
|  |  | ||||||
|                     if (isSelfDisguiseVisible() && getEntity() instanceof Player) { |  | ||||||
|                         PacketContainer selfLookPacket = lookPacket.shallowClone(); |  | ||||||
|  |  | ||||||
|                         selfLookPacket.getIntegers().write(0, DisguiseAPI.getSelfDisguiseId()); |  | ||||||
|  |  | ||||||
|                         try { |  | ||||||
|                             ProtocolLibrary.getProtocolManager().sendServerPacket((Player) getEntity(), selfLookPacket, false); |  | ||||||
|                         } catch (InvocationTargetException e) { |  | ||||||
|                             e.printStackTrace(); |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 try { |  | ||||||
|                     PacketContainer velocityPacket = new PacketContainer(Server.ENTITY_VELOCITY); |  | ||||||
|  |  | ||||||
|                     StructureModifier<Integer> mods = velocityPacket.getIntegers(); |  | ||||||
|  |  | ||||||
|                     // Write entity ID |  | ||||||
|                     mods.write(0, getEntity().getEntityId()); |  | ||||||
|                     mods.write(1, (int) (vector.getX() * 8000)); |  | ||||||
|                     mods.write(3, (int) (vector.getZ() * 8000)); |  | ||||||
|  |  | ||||||
|                     for (Player player : DisguiseUtilities.getPerverts(this)) { |  | ||||||
|                         PacketContainer tempVelocityPacket = velocityPacket.shallowClone(); |  | ||||||
|                         mods = tempVelocityPacket.getIntegers(); |  | ||||||
|  |  | ||||||
|                         // If the viewing player is the disguised player |  | ||||||
|                         if (getEntity() == player) { |  | ||||||
|                             // If not using self disguise, continue |  | ||||||
|                             if (!isSelfDisguiseVisible()) { |  | ||||||
|                                 continue; |  | ||||||
|                             } |  | ||||||
|  |  | ||||||
|                             // Write self disguise ID |  | ||||||
|                             mods.write(0, DisguiseAPI.getSelfDisguiseId()); |  | ||||||
|                         } |  | ||||||
|  |  | ||||||
|                         mods.write(2, (int) (8000D * (vectorY * ReflectionManager.getPing(player)) * 0.069D)); |  | ||||||
|  |  | ||||||
|                         if (lookPacket != null && player != getEntity()) { |  | ||||||
|                             ProtocolLibrary.getProtocolManager().sendServerPacket(player, lookPacket, false); |  | ||||||
|                         } |  | ||||||
|  |  | ||||||
|                         ProtocolLibrary.getProtocolManager().sendServerPacket(player, tempVelocityPacket, false); |  | ||||||
|                     } |  | ||||||
|                 } catch (Exception e) { |  | ||||||
|                     e.printStackTrace(); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             // If we need to send a packet to update the exp position as it likes to gravitate client |  | ||||||
|             // sided to |  | ||||||
|             // players. |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Get the disguised entity |      * Get the disguised entity | ||||||
|      * |      * | ||||||
| @@ -1189,13 +980,12 @@ public abstract class Disguise { | |||||||
|         DisguiseUtilities.refreshTrackers((TargetedDisguise) this); |         DisguiseUtilities.refreshTrackers((TargetedDisguise) this); | ||||||
|  |  | ||||||
|         // If he is a player, then self disguise himself |         // If he is a player, then self disguise himself | ||||||
|         Bukkit.getScheduler(). |         Bukkit.getScheduler().scheduleSyncDelayedTask(LibsDisguises.getInstance(), new Runnable() { | ||||||
|                 scheduleSyncDelayedTask(LibsDisguises.getInstance(), new Runnable() { |             @Override | ||||||
|                     @Override |             public void run() { | ||||||
|                     public void run() { |                 DisguiseUtilities.setupFakeDisguise(Disguise.this); | ||||||
|                         DisguiseUtilities.setupFakeDisguise(Disguise.this); |             } | ||||||
|                     } |         }, 2); | ||||||
|                 }, 2); |  | ||||||
|  |  | ||||||
|         if (isHidePlayer() && getEntity() instanceof Player) { |         if (isHidePlayer() && getEntity() instanceof Player) { | ||||||
|             PacketContainer removeTab = new PacketContainer(PacketType.Play.Server.PLAYER_INFO); |             PacketContainer removeTab = new PacketContainer(PacketType.Play.Server.PLAYER_INFO); | ||||||
|   | |||||||
| @@ -0,0 +1,227 @@ | |||||||
|  | package me.libraryaddict.disguise.disguisetypes; | ||||||
|  |  | ||||||
|  | import com.comphenix.protocol.PacketType; | ||||||
|  | import com.comphenix.protocol.ProtocolLibrary; | ||||||
|  | import com.comphenix.protocol.events.PacketContainer; | ||||||
|  | import com.comphenix.protocol.reflect.StructureModifier; | ||||||
|  | import me.libraryaddict.disguise.DisguiseAPI; | ||||||
|  | import me.libraryaddict.disguise.DisguiseConfig; | ||||||
|  | import me.libraryaddict.disguise.disguisetypes.watchers.BatWatcher; | ||||||
|  | import me.libraryaddict.disguise.utilities.DisguiseUtilities; | ||||||
|  | import me.libraryaddict.disguise.utilities.reflection.ReflectionManager; | ||||||
|  | import me.libraryaddict.disguise.utilities.translations.LibsMsg; | ||||||
|  | import org.bukkit.Location; | ||||||
|  | import org.bukkit.entity.Player; | ||||||
|  | import org.bukkit.scheduler.BukkitRunnable; | ||||||
|  | import org.bukkit.util.Vector; | ||||||
|  |  | ||||||
|  | import java.lang.reflect.InvocationTargetException; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Created by libraryaddict on 20/05/2021. | ||||||
|  |  */ | ||||||
|  | class DisguiseRunnable extends BukkitRunnable { | ||||||
|  |     private int blockX, blockY, blockZ, facing; | ||||||
|  |     private int deadTicks = 0; | ||||||
|  |     private int actionBarTicks = -1; | ||||||
|  |     private long lastRefreshed = System.currentTimeMillis(); | ||||||
|  |     private Disguise disguise; | ||||||
|  |     final Double vectorY; | ||||||
|  |     final boolean alwaysSendVelocity; | ||||||
|  |  | ||||||
|  |     public DisguiseRunnable(Disguise disguise) { | ||||||
|  |         switch (disguise.getType()) { | ||||||
|  |             case FIREWORK: | ||||||
|  |             case WITHER_SKULL: | ||||||
|  |                 vectorY = 0.000001D; | ||||||
|  |                 alwaysSendVelocity = true; | ||||||
|  |                 break; | ||||||
|  |             case EXPERIENCE_ORB: | ||||||
|  |                 vectorY = 0.0221; | ||||||
|  |                 alwaysSendVelocity = true; | ||||||
|  |                 break; | ||||||
|  |             default: | ||||||
|  |                 vectorY = null; | ||||||
|  |                 alwaysSendVelocity = false; | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void run() { | ||||||
|  |         if (!disguise.isDisguiseInUse() || disguise.getEntity() == null) { | ||||||
|  |             cancel(); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (++actionBarTicks % 15 == 0) { | ||||||
|  |             actionBarTicks = 0; | ||||||
|  |  | ||||||
|  |             disguise.doActionBar(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // If entity is no longer valid. Remove it. | ||||||
|  |         if (disguise.getEntity() instanceof Player && !((Player) disguise.getEntity()).isOnline()) { | ||||||
|  |             disguise.removeDisguise(); | ||||||
|  |         } else if (disguise.disguiseExpires > 0 && (DisguiseConfig.isDynamicExpiry() ? disguise.disguiseExpires-- == 1 : | ||||||
|  |                 disguise.disguiseExpires < System.currentTimeMillis())) { // If disguise expired | ||||||
|  |             disguise.removeDisguise(); | ||||||
|  |  | ||||||
|  |             if (disguise.getEntity() instanceof Player) { | ||||||
|  |                 LibsMsg.EXPIRED_DISGUISE.send(disguise.getEntity()); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return; | ||||||
|  |         } else if (!disguise.getEntity().isValid()) { | ||||||
|  |             // If it has been dead for 30+ ticks | ||||||
|  |             // This is to ensure that this disguise isn't removed while clients think its the real entity | ||||||
|  |             // The delay is because if it sends the destroy entity packets straight away, then it means no | ||||||
|  |             // death animation | ||||||
|  |             // This is probably still a problem for wither and enderdragon deaths. | ||||||
|  |             if (deadTicks++ > (disguise.getType() == DisguiseType.ENDER_DRAGON ? 200 : 20)) { | ||||||
|  |                 if (disguise.isRemoveDisguiseOnDeath()) { | ||||||
|  |                     disguise.removeDisguise(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         deadTicks = 0; | ||||||
|  |  | ||||||
|  |         // If the disguise type is tnt, we need to resend the entity packet else it will turn invisible | ||||||
|  |         if (disguise.getType() == DisguiseType.FIREWORK || disguise.getType() == DisguiseType.EVOKER_FANGS) { | ||||||
|  |             if (lastRefreshed + ((disguise.getType() == DisguiseType.FIREWORK ? 40 : 23) * 50) < System.currentTimeMillis()) { | ||||||
|  |                 lastRefreshed = System.currentTimeMillis(); | ||||||
|  |  | ||||||
|  |                 DisguiseUtilities.refreshTrackers((TargetedDisguise) disguise); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (disguise.isModifyBoundingBox()) { | ||||||
|  |             DisguiseUtilities.doBoundingBox((TargetedDisguise) disguise); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (disguise.getType() == DisguiseType.BAT && !((BatWatcher) disguise.getWatcher()).isHanging()) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         doVelocity(vectorY, alwaysSendVelocity); | ||||||
|  |  | ||||||
|  |         if (disguise.getType() == DisguiseType.EXPERIENCE_ORB) { | ||||||
|  |             PacketContainer packet = new PacketContainer(PacketType.Play.Server.REL_ENTITY_MOVE); | ||||||
|  |  | ||||||
|  |             packet.getIntegers().write(0, disguise.getEntity().getEntityId()); | ||||||
|  |  | ||||||
|  |             try { | ||||||
|  |                 for (Player player : DisguiseUtilities.getPerverts(disguise)) { | ||||||
|  |                     if (disguise.getEntity() != player) { | ||||||
|  |                         ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet, false); | ||||||
|  |                         continue; | ||||||
|  |                     } else if (!disguise.isSelfDisguiseVisible() || !(disguise.getEntity() instanceof Player)) { | ||||||
|  |                         continue; | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     PacketContainer selfPacket = packet.shallowClone(); | ||||||
|  |  | ||||||
|  |                     selfPacket.getModifier().write(0, DisguiseAPI.getSelfDisguiseId()); | ||||||
|  |  | ||||||
|  |                     try { | ||||||
|  |                         ProtocolLibrary.getProtocolManager().sendServerPacket((Player) disguise.getEntity(), selfPacket, false); | ||||||
|  |                     } catch (InvocationTargetException e) { | ||||||
|  |                         e.printStackTrace(); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } catch (InvocationTargetException e) { | ||||||
|  |                 e.printStackTrace(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private void doVelocity(Double vectorY, boolean alwaysSendVelocity) { | ||||||
|  |         // If the vectorY isn't 0. Cos if it is. Then it doesn't want to send any vectors. | ||||||
|  |         // If this disguise has velocity sending enabled and the entity is flying. | ||||||
|  |         if (disguise.isVelocitySent() && vectorY != null && (alwaysSendVelocity || !disguise.getEntity().isOnGround())) { | ||||||
|  |             Vector vector = disguise.getEntity().getVelocity(); | ||||||
|  |  | ||||||
|  |             // If the entity doesn't have velocity changes already - You know. I really can't wrap my | ||||||
|  |             // head about the | ||||||
|  |             // if statement. | ||||||
|  |             // But it doesn't seem to do anything wrong.. | ||||||
|  |             if (vector.getY() != 0 && !(vector.getY() < 0 && alwaysSendVelocity && disguise.getEntity().isOnGround())) { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // If disguise isn't a experience orb, or the entity isn't standing on the ground | ||||||
|  |             if (disguise.getType() != DisguiseType.EXPERIENCE_ORB || !disguise.getEntity().isOnGround()) { | ||||||
|  |                 PacketContainer lookPacket = null; | ||||||
|  |  | ||||||
|  |                 if (disguise.getType() == DisguiseType.WITHER_SKULL && DisguiseConfig.isWitherSkullPacketsEnabled()) { | ||||||
|  |                     lookPacket = new PacketContainer(PacketType.Play.Server.ENTITY_LOOK); | ||||||
|  |  | ||||||
|  |                     StructureModifier<Object> mods = lookPacket.getModifier(); | ||||||
|  |                     lookPacket.getIntegers().write(0, disguise.getEntity().getEntityId()); | ||||||
|  |                     Location loc = disguise.getEntity().getLocation(); | ||||||
|  |  | ||||||
|  |                     mods.write(4, | ||||||
|  |                             DisguiseUtilities.getYaw(disguise.getType(), disguise.getEntity().getType(), (byte) Math.floor(loc.getYaw() * 256.0F / 360.0F))); | ||||||
|  |                     mods.write(5, DisguiseUtilities | ||||||
|  |                             .getPitch(disguise.getType(), disguise.getEntity().getType(), (byte) Math.floor(loc.getPitch() * 256.0F / 360.0F))); | ||||||
|  |  | ||||||
|  |                     if (disguise.isSelfDisguiseVisible() && disguise.getEntity() instanceof Player) { | ||||||
|  |                         PacketContainer selfLookPacket = lookPacket.shallowClone(); | ||||||
|  |  | ||||||
|  |                         selfLookPacket.getIntegers().write(0, DisguiseAPI.getSelfDisguiseId()); | ||||||
|  |  | ||||||
|  |                         try { | ||||||
|  |                             ProtocolLibrary.getProtocolManager().sendServerPacket((Player) disguise.getEntity(), selfLookPacket, false); | ||||||
|  |                         } catch (InvocationTargetException e) { | ||||||
|  |                             e.printStackTrace(); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 try { | ||||||
|  |                     PacketContainer velocityPacket = new PacketContainer(PacketType.Play.Server.ENTITY_VELOCITY); | ||||||
|  |  | ||||||
|  |                     StructureModifier<Integer> mods = velocityPacket.getIntegers(); | ||||||
|  |  | ||||||
|  |                     // Write entity ID | ||||||
|  |                     mods.write(0, disguise.getEntity().getEntityId()); | ||||||
|  |                     mods.write(1, (int) (vector.getX() * 8000)); | ||||||
|  |                     mods.write(3, (int) (vector.getZ() * 8000)); | ||||||
|  |  | ||||||
|  |                     for (Player player : DisguiseUtilities.getPerverts(disguise)) { | ||||||
|  |                         PacketContainer tempVelocityPacket = velocityPacket.shallowClone(); | ||||||
|  |                         mods = tempVelocityPacket.getIntegers(); | ||||||
|  |  | ||||||
|  |                         // If the viewing player is the disguised player | ||||||
|  |                         if (disguise.getEntity() == player) { | ||||||
|  |                             // If not using self disguise, continue | ||||||
|  |                             if (!disguise.isSelfDisguiseVisible()) { | ||||||
|  |                                 continue; | ||||||
|  |                             } | ||||||
|  |  | ||||||
|  |                             // Write self disguise ID | ||||||
|  |                             mods.write(0, DisguiseAPI.getSelfDisguiseId()); | ||||||
|  |                         } | ||||||
|  |  | ||||||
|  |                         mods.write(2, (int) (8000D * (vectorY * ReflectionManager.getPing(player)) * 0.069D)); | ||||||
|  |  | ||||||
|  |                         if (lookPacket != null && player != disguise.getEntity()) { | ||||||
|  |                             ProtocolLibrary.getProtocolManager().sendServerPacket(player, lookPacket, false); | ||||||
|  |                         } | ||||||
|  |  | ||||||
|  |                         ProtocolLibrary.getProtocolManager().sendServerPacket(player, tempVelocityPacket, false); | ||||||
|  |                     } | ||||||
|  |                 } catch (Exception e) { | ||||||
|  |                     e.printStackTrace(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             // If we need to send a packet to update the exp position as it likes to gravitate client | ||||||
|  |             // sided to | ||||||
|  |             // players. | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -3,7 +3,6 @@ package me.libraryaddict.disguise.utilities.reflection.asm; | |||||||
| import org.objectweb.asm.*; | import org.objectweb.asm.*; | ||||||
|  |  | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.lang.reflect.InvocationTargetException; |  | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
|  |  | ||||||
| @@ -11,8 +10,7 @@ import java.util.Map; | |||||||
|  * Created by libraryaddict on 17/02/2020. |  * Created by libraryaddict on 17/02/2020. | ||||||
|  */ |  */ | ||||||
| public class Asm13 { | public class Asm13 { | ||||||
|     public byte[] createClassWithoutMethods(String className, ArrayList<Map.Entry<String, String>> illegalMethods) |     public byte[] createClassWithoutMethods(String className, ArrayList<Map.Entry<String, String>> illegalMethods) throws IOException { | ||||||
|             throws IOException, InvocationTargetException, IllegalAccessException, NoSuchFieldException { |  | ||||||
|         className = className.replace(".", "/") + ".class"; |         className = className.replace(".", "/") + ".class"; | ||||||
|  |  | ||||||
|         ClassReader cr = new ClassReader(getClass().getClassLoader().getResourceAsStream(className)); |         ClassReader cr = new ClassReader(getClass().getClassLoader().getResourceAsStream(className)); | ||||||
| @@ -20,7 +18,6 @@ public class Asm13 { | |||||||
|  |  | ||||||
|         cr.accept(new ClassVisitor(Opcodes.ASM5, writer) { |         cr.accept(new ClassVisitor(Opcodes.ASM5, writer) { | ||||||
|             public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { |             public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { | ||||||
|  |  | ||||||
|                 Map.Entry<String, String> entry = |                 Map.Entry<String, String> entry = | ||||||
|                         illegalMethods.stream().filter(e -> e.getKey().equals(name) && e.getValue().equals(desc)).findFirst().orElse(null); |                         illegalMethods.stream().filter(e -> e.getKey().equals(name) && e.getValue().equals(desc)).findFirst().orElse(null); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -7,8 +7,6 @@ import java.io.BufferedInputStream; | |||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.FileOutputStream; | import java.io.FileOutputStream; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.lang.reflect.Field; |  | ||||||
| import java.lang.reflect.Modifier; |  | ||||||
| import java.net.MalformedURLException; | import java.net.MalformedURLException; | ||||||
| import java.net.URL; | import java.net.URL; | ||||||
| import java.net.URLClassLoader; | import java.net.URLClassLoader; | ||||||
| @@ -28,7 +26,6 @@ public class AsmLoader { | |||||||
|     private final File filePath = new File(LibsDisguises.getInstance().getDataFolder(), "libs/org-ow2-asm-9.1.jar"); |     private final File filePath = new File(LibsDisguises.getInstance().getDataFolder(), "libs/org-ow2-asm-9.1.jar"); | ||||||
|     private boolean asmExists; |     private boolean asmExists; | ||||||
|     private URLClassLoader classLoader; |     private URLClassLoader classLoader; | ||||||
|     private LibsJarFile libsJarFile; |  | ||||||
|  |  | ||||||
|     public AsmLoader() { |     public AsmLoader() { | ||||||
|         try { |         try { | ||||||
| @@ -47,28 +44,6 @@ public class AsmLoader { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void load() { |  | ||||||
|         try { |  | ||||||
|             ClassLoader pluginClassLoader = getClass().getClassLoader(); |  | ||||||
|             Class c = Class.forName("org.bukkit.plugin.java.PluginClassLoader"); |  | ||||||
|             Field file = c.getDeclaredField("file"); |  | ||||||
|             file.setAccessible(true); |  | ||||||
|  |  | ||||||
|             libsJarFile = new LibsJarFile((File) file.get(pluginClassLoader)); |  | ||||||
|  |  | ||||||
|             Field field = c.getDeclaredField("jar"); |  | ||||||
|             field.setAccessible(true); |  | ||||||
|  |  | ||||||
|             Field modifiersField = Field.class.getDeclaredField("modifiers"); |  | ||||||
|             modifiersField.setAccessible(true); |  | ||||||
|             modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); |  | ||||||
|  |  | ||||||
|             field.set(pluginClassLoader, libsJarFile); |  | ||||||
|         } catch (Throwable e) { |  | ||||||
|             e.printStackTrace(); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public void unload() { |     public void unload() { | ||||||
|         try { |         try { | ||||||
|             classLoader.close(); |             classLoader.close(); | ||||||
|   | |||||||
| @@ -0,0 +1,120 @@ | |||||||
|  | package me.libraryaddict.disguise.utilities.reflection.asm; | ||||||
|  |  | ||||||
|  | import me.libraryaddict.disguise.LibsDisguises; | ||||||
|  | import me.libraryaddict.disguise.utilities.reflection.ReflectionManager; | ||||||
|  | import org.apache.commons.lang.StringUtils; | ||||||
|  | import org.bukkit.configuration.file.YamlConfiguration; | ||||||
|  |  | ||||||
|  | import java.io.*; | ||||||
|  | import java.nio.charset.StandardCharsets; | ||||||
|  | import java.util.Enumeration; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.jar.JarEntry; | ||||||
|  | import java.util.jar.JarFile; | ||||||
|  | import java.util.jar.JarOutputStream; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  | import java.util.zip.ZipEntry; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Created by libraryaddict on 20/05/2021. | ||||||
|  |  */ | ||||||
|  | public class FakePluginCreator { | ||||||
|  |     public String getPluginYAML() { | ||||||
|  |         return "name: LibsDisguisesVersioning\nmain: " + getPluginClassPath().replace(".class", "").replace("/", ".") + | ||||||
|  |                 "\ndescription: Plugin created by Libs Disguises for " + | ||||||
|  |                 "compatibility with different versions\nversion: 1.0.0\nauthor: libraryaddict\napi-version: '1.13'\nsoftdepend: [ProtocolLib, LibsDisguises]"; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public File getDestination() { | ||||||
|  |         return new File(LibsDisguises.getInstance().getDataFolder(), "libs/LibsDisguisesCompat.jar"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public String getPluginClassPath() { | ||||||
|  |         return "me/libraryaddict/disguise/utilities/reflection/asm/LibsDisguisesCompat.class"; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public String getVersion() throws Exception { | ||||||
|  |         File dest = getDestination(); | ||||||
|  |  | ||||||
|  |         if (!dest.exists()) { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         JarFile jarFile = new JarFile(dest); | ||||||
|  |  | ||||||
|  |         try (InputStream stream = jarFile.getInputStream(jarFile.getEntry("version.txt"))) { | ||||||
|  |             return new BufferedReader(new InputStreamReader(stream)).lines().collect(Collectors.joining("\n")); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public String getOurVersion() { | ||||||
|  |         YamlConfiguration pluginYml = ReflectionManager.getPluginYAML(LibsDisguises.getInstance().getFile()); | ||||||
|  |  | ||||||
|  |         String buildNo = StringUtils.stripToNull(pluginYml.getString("build-number")); | ||||||
|  |  | ||||||
|  |         return buildNo != null && buildNo.matches("[0-9]+") ? ReflectionManager.getBukkitVersion() + " " + Integer.parseInt(buildNo) : | ||||||
|  |                 ReflectionManager.getBukkitVersion() + " CUSTOM"; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void createJar(String ourVersion, Map<String, byte[]> classes) throws Exception { | ||||||
|  |         File dest = getDestination(); | ||||||
|  |  | ||||||
|  |         if (!dest.getParentFile().exists()) { | ||||||
|  |             dest.getParentFile().mkdirs(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (dest.exists()) { | ||||||
|  |             dest.delete(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         JarOutputStream out = new JarOutputStream(new FileOutputStream(dest)); | ||||||
|  |  | ||||||
|  |         out.putNextEntry(new ZipEntry("plugin.yml")); | ||||||
|  |         out.write(getPluginYAML().getBytes(StandardCharsets.UTF_8)); | ||||||
|  |         out.closeEntry(); | ||||||
|  |  | ||||||
|  |         // Write our main plugin class | ||||||
|  |         try (JarFile jar = new JarFile(LibsDisguises.getInstance().getFile())) { | ||||||
|  |             Enumeration<JarEntry> entries = jar.entries(); | ||||||
|  |             String mainPath = getPluginClassPath().replace(".class", ""); | ||||||
|  |  | ||||||
|  |             while (entries.hasMoreElements()) { | ||||||
|  |                 JarEntry entry = entries.nextElement(); | ||||||
|  |  | ||||||
|  |                 if (!entry.getName().equals(mainPath) && !entry.getName().startsWith("me/libraryaddict/disguise/disguisetypes/")) { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if (classes.containsKey(entry.getName())) { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 out.putNextEntry(new ZipEntry(entry.getName().equals(mainPath) ? getPluginClassPath() : entry.getName())); | ||||||
|  |  | ||||||
|  |                 try (InputStream stream = jar.getInputStream(entry)) { | ||||||
|  |                     int nRead; | ||||||
|  |                     byte[] data = new byte[1024]; | ||||||
|  |                     while ((nRead = stream.read(data, 0, data.length)) != -1) { | ||||||
|  |                         out.write(data, 0, nRead); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 out.closeEntry(); | ||||||
|  |             } | ||||||
|  |         } catch (Exception ex) { | ||||||
|  |             ex.printStackTrace(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         for (Map.Entry<String, byte[]> entry : classes.entrySet()) { | ||||||
|  |             out.putNextEntry(new ZipEntry(entry.getKey())); | ||||||
|  |             out.write(entry.getValue()); | ||||||
|  |             out.closeEntry(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         out.putNextEntry(new ZipEntry("version.txt")); | ||||||
|  |         out.write(ourVersion.getBytes(StandardCharsets.UTF_8)); | ||||||
|  |         out.closeEntry(); | ||||||
|  |  | ||||||
|  |         out.close(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,9 @@ | |||||||
|  | package me.libraryaddict.disguise.utilities.reflection.asm; | ||||||
|  |  | ||||||
|  | import org.bukkit.plugin.java.JavaPlugin; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Created by libraryaddict on 20/05/2021. | ||||||
|  |  */ | ||||||
|  | public class LibsDisguisesCompat extends JavaPlugin { | ||||||
|  | } | ||||||
| @@ -1,39 +0,0 @@ | |||||||
| package me.libraryaddict.disguise.utilities.reflection.asm; |  | ||||||
|  |  | ||||||
| import java.io.ByteArrayInputStream; |  | ||||||
| import java.io.File; |  | ||||||
| import java.io.IOException; |  | ||||||
| import java.io.InputStream; |  | ||||||
| import java.util.HashMap; |  | ||||||
| import java.util.jar.JarFile; |  | ||||||
| import java.util.zip.ZipEntry; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Created by libraryaddict on 15/05/2021. |  | ||||||
|  */ |  | ||||||
| public class LibsJarFile extends JarFile { |  | ||||||
|     private final HashMap<String, byte[]> customFiles = new HashMap<>(); |  | ||||||
|  |  | ||||||
|     public LibsJarFile(File file) throws IOException { |  | ||||||
|         super(file); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public synchronized InputStream getInputStream(ZipEntry ze) throws IOException { |  | ||||||
|         if (customFiles.containsKey(ze.getName())) { |  | ||||||
|             return new ByteArrayInputStream(customFiles.get(ze.getName())); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         return super.getInputStream(ze); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public void addClass(String name, byte[] bytes) { |  | ||||||
|         customFiles.put(name, bytes); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public void close() throws IOException { |  | ||||||
|         customFiles.clear(); |  | ||||||
|         super.close(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -3,9 +3,12 @@ package me.libraryaddict.disguise.utilities.reflection.asm; | |||||||
| import com.google.gson.Gson; | import com.google.gson.Gson; | ||||||
| import me.libraryaddict.disguise.LibsDisguises; | import me.libraryaddict.disguise.LibsDisguises; | ||||||
| import me.libraryaddict.disguise.utilities.reflection.ReflectionManager; | import me.libraryaddict.disguise.utilities.reflection.ReflectionManager; | ||||||
|  | import org.bukkit.Bukkit; | ||||||
|  | import org.bukkit.plugin.Plugin; | ||||||
| import org.bukkit.plugin.PluginDescriptionFile; | import org.bukkit.plugin.PluginDescriptionFile; | ||||||
| import org.bukkit.plugin.java.JavaPluginLoader; | import org.bukkit.plugin.java.JavaPluginLoader; | ||||||
|  |  | ||||||
|  | import java.io.File; | ||||||
| import java.io.InputStream; | import java.io.InputStream; | ||||||
| import java.lang.reflect.Field; | import java.lang.reflect.Field; | ||||||
| import java.lang.reflect.Method; | import java.lang.reflect.Method; | ||||||
| @@ -69,11 +72,29 @@ public class WatcherSanitizer { | |||||||
|         } catch (NoSuchFieldException | IllegalAccessException ignored) { |         } catch (NoSuchFieldException | IllegalAccessException ignored) { | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         if (Bukkit.getPluginManager().getPlugin("LibsDisguisesVersioning") != null) { | ||||||
|  |             throw new IllegalStateException("Why is LibsDisguisesVersioning already active? Did the server owner do something.. Weird?"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         FakePluginCreator fakePluginCreator = new FakePluginCreator(); | ||||||
|  |  | ||||||
|  |         String ourVers = fakePluginCreator.getOurVersion(); | ||||||
|  |  | ||||||
|  |         try { | ||||||
|  |             if (ourVers != null && ourVers.equals(fakePluginCreator.getVersion()) && !ourVers.contains(" CUSTOM")) { | ||||||
|  |                 loadPlugin(fakePluginCreator); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             e.printStackTrace(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         LibsDisguises.getInstance().getLogger().info("Creating a new version compatibility jar"); | ||||||
|  |  | ||||||
|         ArrayList<String> mapped = new ArrayList<>(); |         ArrayList<String> mapped = new ArrayList<>(); | ||||||
|  |  | ||||||
|         try (InputStream stream = LibsDisguises.getInstance().getResource("ANTI_PIRACY_ENCRYPTION")) { |         try (InputStream stream = LibsDisguises.getInstance().getResource("ANTI_PIRACY_ENCRYPTION")) { | ||||||
|             AsmLoader loader = new AsmLoader(); |             AsmLoader loader = new AsmLoader(); | ||||||
|             loader.load(); |  | ||||||
|  |  | ||||||
|             Object obj; |             Object obj; | ||||||
|             Method getBytes; |             Method getBytes; | ||||||
| @@ -109,15 +130,18 @@ public class WatcherSanitizer { | |||||||
|                 list.add(new HashMap.SimpleEntry(info.getMethod(), info.getDescriptor())); |                 list.add(new HashMap.SimpleEntry(info.getMethod(), info.getDescriptor())); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             Map<String, byte[]> classes = new HashMap<>(); | ||||||
|  |  | ||||||
|             for (Map.Entry<String, ArrayList<Map.Entry<String, String>>> entry : toRemove.entrySet()) { |             for (Map.Entry<String, ArrayList<Map.Entry<String, String>>> entry : toRemove.entrySet()) { | ||||||
|                 byte[] bytes = (byte[]) getBytes.invoke(obj, entry.getKey(), entry.getValue()); |                 byte[] bytes = (byte[]) getBytes.invoke(obj, entry.getKey(), entry.getValue()); | ||||||
|                 mapped.add(entry.getKey()); |                 mapped.add(entry.getKey()); | ||||||
|  |  | ||||||
|                 String name = entry.getKey().replace(".", "/") + ".class"; |                 classes.put(entry.getKey().replace(".", "/") + ".class", bytes); | ||||||
|  |  | ||||||
|                 loader.getLibsJarFile().addClass(name, bytes); |  | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             fakePluginCreator.createJar(ourVers, classes); | ||||||
|  |             loadPlugin(fakePluginCreator); | ||||||
|  |  | ||||||
|             if (!loader.isAsmExists()) { |             if (!loader.isAsmExists()) { | ||||||
|                 loader.unload(); |                 loader.unload(); | ||||||
|             } |             } | ||||||
| @@ -126,4 +150,32 @@ public class WatcherSanitizer { | |||||||
|             LibsDisguises.getInstance().getLogger().severe("Registered: " + new Gson().toJson(mapped)); |             LibsDisguises.getInstance().getLogger().severe("Registered: " + new Gson().toJson(mapped)); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     private static void loadPlugin(FakePluginCreator fakePluginCreator) throws Exception { | ||||||
|  |         LibsDisguises.getInstance().getLogger().info("Starting version support plugin: LibsDisguisesVersioning"); | ||||||
|  |         Method method = Class.forName("org.bukkit.plugin.PluginManager", false, WatcherSanitizer.class.getClassLoader().getParent()) | ||||||
|  |                 .getMethod("loadPlugin", File.class); | ||||||
|  |  | ||||||
|  |         Plugin plugin = (Plugin) method.invoke(Bukkit.getPluginManager(), fakePluginCreator.getDestination()); | ||||||
|  |  | ||||||
|  |         Class pluginClassLoader = Class.forName("org.bukkit.plugin.java.PluginClassLoader"); | ||||||
|  |  | ||||||
|  |         Field loaderField = JavaPluginLoader.class.getDeclaredField("loaders"); | ||||||
|  |         loaderField.setAccessible(true); | ||||||
|  |         List loaderList = (List) loaderField.get(LibsDisguises.getInstance().getPluginLoader()); | ||||||
|  |  | ||||||
|  |         Field pluginOwner = pluginClassLoader.getDeclaredField("plugin"); | ||||||
|  |         pluginOwner.setAccessible(true); | ||||||
|  |  | ||||||
|  |         // Move Lib's Disguises to load its classes after the new plugin | ||||||
|  |         for (Object o : loaderList) { | ||||||
|  |             if (pluginOwner.get(o) != LibsDisguises.getInstance()) { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             loaderList.remove(o); | ||||||
|  |             loaderList.add(o); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ import me.libraryaddict.disguise.utilities.LibsPremium; | |||||||
| import me.libraryaddict.disguise.utilities.reflection.ClassGetter; | import me.libraryaddict.disguise.utilities.reflection.ClassGetter; | ||||||
| import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn; | import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn; | ||||||
| import me.libraryaddict.disguise.utilities.reflection.NmsRemovedIn; | import me.libraryaddict.disguise.utilities.reflection.NmsRemovedIn; | ||||||
|  | import me.libraryaddict.disguise.utilities.reflection.asm.FakePluginCreator; | ||||||
| import me.libraryaddict.disguise.utilities.sounds.DisguiseSoundEnums; | import me.libraryaddict.disguise.utilities.sounds.DisguiseSoundEnums; | ||||||
| import me.libraryaddict.disguise.utilities.sounds.SoundGroup; | import me.libraryaddict.disguise.utilities.sounds.SoundGroup; | ||||||
| import org.apache.commons.lang.StringUtils; | import org.apache.commons.lang.StringUtils; | ||||||
| @@ -34,6 +35,14 @@ public class CompileMethods { | |||||||
|     public static void main(String[] args) { |     public static void main(String[] args) { | ||||||
|         doMethods(); |         doMethods(); | ||||||
|         doSounds(); |         doSounds(); | ||||||
|  |         moveCompat(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private static void moveCompat() { | ||||||
|  |         FakePluginCreator creator = new FakePluginCreator(); | ||||||
|  |  | ||||||
|  |         File compatFile = new File("target/classes/" + creator.getPluginClassPath()); | ||||||
|  |         compatFile.renameTo(new File(compatFile.getParentFile(), compatFile.getName().replace(".class", ""))); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private static void doSounds() { |     private static void doSounds() { | ||||||
| @@ -91,8 +100,7 @@ public class CompileMethods { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     private static void doMethods() { |     private static void doMethods() { | ||||||
|         ArrayList<Class<?>> classes = |         ArrayList<Class<?>> classes = ClassGetter.getClassesForPackage(FlagWatcher.class, "me.libraryaddict.disguise.disguisetypes.watchers"); | ||||||
|                 ClassGetter.getClassesForPackage(FlagWatcher.class, "me.libraryaddict.disguise.disguisetypes.watchers"); |  | ||||||
|  |  | ||||||
|         ArrayList<Class> sorted = new ArrayList<>(); |         ArrayList<Class> sorted = new ArrayList<>(); | ||||||
|  |  | ||||||
| @@ -106,12 +114,10 @@ public class CompileMethods { | |||||||
|             for (Method method : c.getMethods()) { |             for (Method method : c.getMethods()) { | ||||||
|                 if (!FlagWatcher.class.isAssignableFrom(method.getDeclaringClass())) { |                 if (!FlagWatcher.class.isAssignableFrom(method.getDeclaringClass())) { | ||||||
|                     continue; |                     continue; | ||||||
|                 } else if (method.getParameterCount() > 1 && !method.isAnnotationPresent(NmsAddedIn.class) && |                 } else if (method.getParameterCount() > 1 && !method.isAnnotationPresent(NmsAddedIn.class) && !method.isAnnotationPresent(NmsRemovedIn.class)) { | ||||||
|                         !method.isAnnotationPresent(NmsRemovedIn.class)) { |  | ||||||
|                     continue; |                     continue; | ||||||
|                 } else if (!(method.getName().startsWith("set") && method.getParameterCount() == 1) && |                 } else if (!(method.getName().startsWith("set") && method.getParameterCount() == 1) && !method.getName().startsWith("get") && | ||||||
|                         !method.getName().startsWith("get") && !method.getName().startsWith("has") && |                         !method.getName().startsWith("has") && !method.getName().startsWith("is")) { | ||||||
|                         !method.getName().startsWith("is")) { |  | ||||||
|                     continue; |                     continue; | ||||||
|                 } else if (method.getName().equals("removePotionEffect")) { |                 } else if (method.getName().equals("removePotionEffect")) { | ||||||
|                     continue; |                     continue; | ||||||
| @@ -141,8 +147,7 @@ public class CompileMethods { | |||||||
|                     descriptor = ":" + getMethodDescriptor(method) + ":" + added + ":" + removed; |                     descriptor = ":" + getMethodDescriptor(method) + ":" + added + ":" + removed; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 String s = |                 String s = method.getDeclaringClass().getSimpleName() + ":" + method.getName() + ":" + param + descriptor; | ||||||
|                         method.getDeclaringClass().getSimpleName() + ":" + method.getName() + ":" + param + descriptor; |  | ||||||
|  |  | ||||||
|                 if (methods.contains(s)) { |                 if (methods.contains(s)) { | ||||||
|                     continue; |                     continue; | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ build-date: ${timestamp} | |||||||
| build-number: ${build.number} | build-number: ${build.number} | ||||||
| author: libraryaddict | author: libraryaddict | ||||||
| authors: [Byteflux, Navid K.] | authors: [Byteflux, Navid K.] | ||||||
| softdepend: [ProtocolLib] | softdepend: [ProtocolLib, LibsDisguisesVersioning] | ||||||
| api-version: '1.13' | api-version: '1.13' | ||||||
| commands: | commands: | ||||||
|   libsdisguises: |   libsdisguises: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user