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:
parent
269363753c
commit
f0448e6afc
@ -67,6 +67,8 @@ public class LibsDisguises extends JavaPlugin {
|
||||
|
||||
instance = this;
|
||||
|
||||
WatcherSanitizer.init();
|
||||
|
||||
Plugin plugin = Bukkit.getPluginManager().getPlugin("ProtocolLib");
|
||||
|
||||
if (plugin == null || DisguiseUtilities.isOlderThan(DisguiseUtilities.getProtocolLibRequiredVersion(), plugin.getDescription().getVersion())) {
|
||||
@ -105,8 +107,6 @@ public class LibsDisguises extends JavaPlugin {
|
||||
if (!reloaded) {
|
||||
commandConfig.load();
|
||||
}
|
||||
|
||||
WatcherSanitizer.init();
|
||||
} catch (Throwable throwable) {
|
||||
getUpdateChecker().doUpdate();
|
||||
|
||||
|
@ -4,7 +4,6 @@ import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.PacketType.Play.Server;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
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.PlayerInfoAction;
|
||||
import com.comphenix.protocol.wrappers.PlayerInfoData;
|
||||
@ -16,7 +15,10 @@ import me.libraryaddict.disguise.DisguiseAPI;
|
||||
import me.libraryaddict.disguise.DisguiseConfig;
|
||||
import me.libraryaddict.disguise.LibsDisguises;
|
||||
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.UndisguiseEvent;
|
||||
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 net.md_5.bungee.api.ChatMessageType;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.boss.BarColor;
|
||||
import org.bukkit.boss.BarStyle;
|
||||
@ -38,7 +39,6 @@ import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.metadata.FixedMetadataValue;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.*;
|
||||
@ -71,7 +71,7 @@ public abstract class Disguise {
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
@ -370,7 +370,7 @@ public abstract class Disguise {
|
||||
return this;
|
||||
}
|
||||
|
||||
private void doActionBar() {
|
||||
protected void doActionBar() {
|
||||
if (getNotifyBar() == DisguiseConfig.NotifyBar.ACTION_BAR && getEntity() instanceof Player && !getEntity().hasPermission("libsdisguises.noactionbar") &&
|
||||
DisguiseAPI.getDisguise(getEntity()) == Disguise.this) {
|
||||
((Player) getEntity()).spigot().sendMessage(ChatMessageType.ACTION_BAR, LibsMsg.ACTION_BAR_MESSAGE.getChat(getDisguiseName()));
|
||||
@ -394,227 +394,18 @@ public abstract class Disguise {
|
||||
}
|
||||
|
||||
private void createRunnable() {
|
||||
if (runnable != null) {
|
||||
if (runnable != null && !runnable.isCancelled()) {
|
||||
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;
|
||||
|
||||
// A scheduler to clean up any unused disguises.
|
||||
runnable = new BukkitRunnable() {
|
||||
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 = new DisguiseRunnable(this);
|
||||
|
||||
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
|
||||
*
|
||||
@ -1189,13 +980,12 @@ public abstract class Disguise {
|
||||
DisguiseUtilities.refreshTrackers((TargetedDisguise) this);
|
||||
|
||||
// If he is a player, then self disguise himself
|
||||
Bukkit.getScheduler().
|
||||
scheduleSyncDelayedTask(LibsDisguises.getInstance(), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
DisguiseUtilities.setupFakeDisguise(Disguise.this);
|
||||
}
|
||||
}, 2);
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(LibsDisguises.getInstance(), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
DisguiseUtilities.setupFakeDisguise(Disguise.this);
|
||||
}
|
||||
}, 2);
|
||||
|
||||
if (isHidePlayer() && getEntity() instanceof Player) {
|
||||
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 java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
@ -11,8 +10,7 @@ import java.util.Map;
|
||||
* Created by libraryaddict on 17/02/2020.
|
||||
*/
|
||||
public class Asm13 {
|
||||
public byte[] createClassWithoutMethods(String className, ArrayList<Map.Entry<String, String>> illegalMethods)
|
||||
throws IOException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {
|
||||
public byte[] createClassWithoutMethods(String className, ArrayList<Map.Entry<String, String>> illegalMethods) throws IOException {
|
||||
className = className.replace(".", "/") + ".class";
|
||||
|
||||
ClassReader cr = new ClassReader(getClass().getClassLoader().getResourceAsStream(className));
|
||||
@ -20,7 +18,6 @@ public class Asm13 {
|
||||
|
||||
cr.accept(new ClassVisitor(Opcodes.ASM5, writer) {
|
||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
|
||||
|
||||
Map.Entry<String, String> entry =
|
||||
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.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
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 boolean asmExists;
|
||||
private URLClassLoader classLoader;
|
||||
private LibsJarFile libsJarFile;
|
||||
|
||||
public AsmLoader() {
|
||||
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() {
|
||||
try {
|
||||
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 me.libraryaddict.disguise.LibsDisguises;
|
||||
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.java.JavaPluginLoader;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
@ -69,11 +72,29 @@ public class WatcherSanitizer {
|
||||
} 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<>();
|
||||
|
||||
try (InputStream stream = LibsDisguises.getInstance().getResource("ANTI_PIRACY_ENCRYPTION")) {
|
||||
AsmLoader loader = new AsmLoader();
|
||||
loader.load();
|
||||
|
||||
Object obj;
|
||||
Method getBytes;
|
||||
@ -109,15 +130,18 @@ public class WatcherSanitizer {
|
||||
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()) {
|
||||
byte[] bytes = (byte[]) getBytes.invoke(obj, entry.getKey(), entry.getValue());
|
||||
mapped.add(entry.getKey());
|
||||
|
||||
String name = entry.getKey().replace(".", "/") + ".class";
|
||||
|
||||
loader.getLibsJarFile().addClass(name, bytes);
|
||||
classes.put(entry.getKey().replace(".", "/") + ".class", bytes);
|
||||
}
|
||||
|
||||
fakePluginCreator.createJar(ourVers, classes);
|
||||
loadPlugin(fakePluginCreator);
|
||||
|
||||
if (!loader.isAsmExists()) {
|
||||
loader.unload();
|
||||
}
|
||||
@ -126,4 +150,32 @@ public class WatcherSanitizer {
|
||||
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.NmsAddedIn;
|
||||
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.SoundGroup;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
@ -34,6 +35,14 @@ public class CompileMethods {
|
||||
public static void main(String[] args) {
|
||||
doMethods();
|
||||
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() {
|
||||
@ -91,8 +100,7 @@ public class CompileMethods {
|
||||
}
|
||||
|
||||
private static void doMethods() {
|
||||
ArrayList<Class<?>> classes =
|
||||
ClassGetter.getClassesForPackage(FlagWatcher.class, "me.libraryaddict.disguise.disguisetypes.watchers");
|
||||
ArrayList<Class<?>> classes = ClassGetter.getClassesForPackage(FlagWatcher.class, "me.libraryaddict.disguise.disguisetypes.watchers");
|
||||
|
||||
ArrayList<Class> sorted = new ArrayList<>();
|
||||
|
||||
@ -106,12 +114,10 @@ public class CompileMethods {
|
||||
for (Method method : c.getMethods()) {
|
||||
if (!FlagWatcher.class.isAssignableFrom(method.getDeclaringClass())) {
|
||||
continue;
|
||||
} else if (method.getParameterCount() > 1 && !method.isAnnotationPresent(NmsAddedIn.class) &&
|
||||
!method.isAnnotationPresent(NmsRemovedIn.class)) {
|
||||
} else if (method.getParameterCount() > 1 && !method.isAnnotationPresent(NmsAddedIn.class) && !method.isAnnotationPresent(NmsRemovedIn.class)) {
|
||||
continue;
|
||||
} else if (!(method.getName().startsWith("set") && method.getParameterCount() == 1) &&
|
||||
!method.getName().startsWith("get") && !method.getName().startsWith("has") &&
|
||||
!method.getName().startsWith("is")) {
|
||||
} else if (!(method.getName().startsWith("set") && method.getParameterCount() == 1) && !method.getName().startsWith("get") &&
|
||||
!method.getName().startsWith("has") && !method.getName().startsWith("is")) {
|
||||
continue;
|
||||
} else if (method.getName().equals("removePotionEffect")) {
|
||||
continue;
|
||||
@ -141,8 +147,7 @@ public class CompileMethods {
|
||||
descriptor = ":" + getMethodDescriptor(method) + ":" + added + ":" + removed;
|
||||
}
|
||||
|
||||
String s =
|
||||
method.getDeclaringClass().getSimpleName() + ":" + method.getName() + ":" + param + descriptor;
|
||||
String s = method.getDeclaringClass().getSimpleName() + ":" + method.getName() + ":" + param + descriptor;
|
||||
|
||||
if (methods.contains(s)) {
|
||||
continue;
|
||||
|
@ -6,7 +6,7 @@ build-date: ${timestamp}
|
||||
build-number: ${build.number}
|
||||
author: libraryaddict
|
||||
authors: [Byteflux, Navid K.]
|
||||
softdepend: [ProtocolLib]
|
||||
softdepend: [ProtocolLib, LibsDisguisesVersioning]
|
||||
api-version: '1.13'
|
||||
commands:
|
||||
libsdisguises:
|
||||
|
Loading…
Reference in New Issue
Block a user