mirror of
https://github.com/amalthea-mc/ShopChest.git
synced 2024-11-26 04:12:22 +00:00
Link plugin to nms sub modules
This commit is contained in:
parent
7410f2088d
commit
b46bd953c3
@ -18,6 +18,9 @@ import java.util.stream.Stream;
|
|||||||
import com.palmergames.bukkit.towny.Towny;
|
import com.palmergames.bukkit.towny.Towny;
|
||||||
import com.wasteofplastic.askyblock.ASkyBlock;
|
import com.wasteofplastic.askyblock.ASkyBlock;
|
||||||
|
|
||||||
|
import de.epiceric.shopchest.nms.Platform;
|
||||||
|
import de.epiceric.shopchest.nms.reflection.PlatformImpl;
|
||||||
|
import de.epiceric.shopchest.nms.reflection.ShopChestDebug;
|
||||||
import org.bstats.bukkit.Metrics;
|
import org.bstats.bukkit.Metrics;
|
||||||
import org.bstats.charts.AdvancedPie;
|
import org.bstats.charts.AdvancedPie;
|
||||||
import org.bstats.charts.SimplePie;
|
import org.bstats.charts.SimplePie;
|
||||||
@ -82,6 +85,7 @@ public class ShopChest extends JavaPlugin {
|
|||||||
private static ShopChest instance;
|
private static ShopChest instance;
|
||||||
|
|
||||||
private Config config;
|
private Config config;
|
||||||
|
private Platform platform;
|
||||||
private HologramFormat hologramFormat;
|
private HologramFormat hologramFormat;
|
||||||
private ShopCommand shopCommand;
|
private ShopCommand shopCommand;
|
||||||
private Economy econ = null;
|
private Economy econ = null;
|
||||||
@ -188,12 +192,17 @@ public class ShopChest extends JavaPlugin {
|
|||||||
case "v1_16_R1":
|
case "v1_16_R1":
|
||||||
case "v1_16_R2":
|
case "v1_16_R2":
|
||||||
case "v1_16_R3":
|
case "v1_16_R3":
|
||||||
|
platform = new PlatformImpl(new ShopChestDebug(getLogger(), this::debug, this::debug));
|
||||||
|
break;
|
||||||
|
case "v1_17_R1":
|
||||||
|
platform = new de.epiceric.shopchest.nms.v1_17_R1.PlatformImpl();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
debug("Server version not officially supported: " + Utils.getServerVersion() + "!");
|
debug("Server version not officially supported: " + Utils.getServerVersion() + "!");
|
||||||
debug("Plugin may still work, but more errors are expected!");
|
//debug("Plugin may still work, but more errors are expected!");
|
||||||
getLogger().warning("Server version not officially supported: " + Utils.getServerVersion() + "!");
|
getLogger().warning("Server version not officially supported: " + Utils.getServerVersion() + "!");
|
||||||
getLogger().warning("Plugin may still work, but more errors are expected!");
|
//getLogger().warning("Plugin may still work, but more errors are expected!");
|
||||||
|
getServer().getPluginManager().disablePlugin(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
shopUtils = new ShopUtils(this);
|
shopUtils = new ShopUtils(this);
|
||||||
@ -559,6 +568,10 @@ public class ShopChest extends JavaPlugin {
|
|||||||
return shopCreationThreadPool;
|
return shopCreationThreadPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Platform getPlatform() {
|
||||||
|
return platform;
|
||||||
|
}
|
||||||
|
|
||||||
public HologramFormat getHologramFormat() {
|
public HologramFormat getHologramFormat() {
|
||||||
return hologramFormat;
|
return hologramFormat;
|
||||||
}
|
}
|
||||||
|
@ -1,148 +1,57 @@
|
|||||||
package de.epiceric.shopchest.nms;
|
package de.epiceric.shopchest.nms;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import de.epiceric.shopchest.ShopChest;
|
||||||
import java.lang.reflect.Method;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.entity.EntityType;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.inventivetalent.reflection.resolver.minecraft.NMSClassResolver;
|
|
||||||
|
|
||||||
import de.epiceric.shopchest.ShopChest;
|
|
||||||
import de.epiceric.shopchest.utils.Utils;
|
|
||||||
|
|
||||||
public class ArmorStandWrapper {
|
public class ArmorStandWrapper {
|
||||||
private final NMSClassResolver nmsClassResolver = new NMSClassResolver();
|
|
||||||
private final Class<?> packetDataSerializerClass = nmsClassResolver.resolveSilent("network.PacketDataSerializer");
|
|
||||||
private final Class<?> packetPlayOutEntityDestroyClass = nmsClassResolver.resolveSilent("network.protocol.game.PacketPlayOutEntityDestroy");
|
|
||||||
private final Class<?> packetPlayOutEntityMetadataClass = nmsClassResolver.resolveSilent("network.protocol.game.PacketPlayOutEntityMetadata");
|
|
||||||
private final Class<?> packetPlayOutEntityTeleportClass = nmsClassResolver.resolveSilent("network.protocol.game.PacketPlayOutEntityTeleport");
|
|
||||||
private final Class<?> dataWatcherClass = nmsClassResolver.resolveSilent("network.syncher.DataWatcher");
|
|
||||||
|
|
||||||
private final UUID uuid = UUID.randomUUID();
|
private final UUID uuid = UUID.randomUUID();
|
||||||
private final int entityId;
|
private final FakeArmorStand fakeArmorStand;
|
||||||
|
|
||||||
private ShopChest plugin;
|
|
||||||
private Location location;
|
private Location location;
|
||||||
private String customName;
|
private String customName;
|
||||||
|
|
||||||
public ArmorStandWrapper(ShopChest plugin, Location location, String customName) {
|
public ArmorStandWrapper(ShopChest plugin, Location location, String customName) {
|
||||||
this.plugin = plugin;
|
|
||||||
this.location = location;
|
this.location = location;
|
||||||
this.customName = customName;
|
this.customName = customName;
|
||||||
this.entityId = Utils.getFreeEntityId();
|
this.fakeArmorStand = plugin.getPlatform().createFakeArmorStand();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVisible(Player player, boolean visible) {
|
public void setVisible(Player player, boolean visible) {
|
||||||
try {
|
final List<Player> receiver = Collections.singletonList(player);
|
||||||
if(visible){
|
if(visible){
|
||||||
Object dataWatcher = Utils.createDataWatcher(customName, null);
|
fakeArmorStand.spawn(uuid, location, receiver);
|
||||||
Utils.sendPacket(plugin, Utils.createPacketSpawnEntity(plugin, entityId, uuid, location, EntityType.ARMOR_STAND), player);
|
fakeArmorStand.sendData(customName, receiver);
|
||||||
Utils.sendPacket(plugin, packetPlayOutEntityMetadataClass.getConstructor(int.class, dataWatcherClass, boolean.class)
|
|
||||||
.newInstance(entityId, dataWatcher, true), player);
|
|
||||||
} else if (entityId != -1) {
|
|
||||||
Utils.sendPacket(plugin, packetPlayOutEntityDestroyClass.getConstructor(int[].class).newInstance((Object) new int[]{entityId}), player);
|
|
||||||
}
|
}
|
||||||
} catch (ReflectiveOperationException e) {
|
else if(fakeArmorStand.getEntityId() != -1){
|
||||||
plugin.getLogger().severe("Could not change hologram visibility");
|
fakeArmorStand.remove(receiver);
|
||||||
plugin.debug("Could not change armor stand visibility");
|
|
||||||
plugin.debug(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLocation(Location location) {
|
public void setLocation(Location location) {
|
||||||
this.location = location;
|
this.location = location;
|
||||||
double y = location.getY() + (Utils.getServerVersion().equals("v1_8_R1") ? 0 : 1.975);
|
fakeArmorStand.setLocation(location, Objects.requireNonNull(location.getWorld()).getPlayers());
|
||||||
Object packet;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (Utils.getMajorVersion() >= 17) {
|
|
||||||
// Empty constructor does not exist anymore in 1.17+ so create packet via serializer
|
|
||||||
Class<?> byteBufClass = Class.forName("io.netty.buffer.ByteBuf");
|
|
||||||
Class<?> unpooledClass = Class.forName("io.netty.buffer.Unpooled");
|
|
||||||
Object buffer = unpooledClass.getMethod("buffer").invoke(null);
|
|
||||||
Object serializer = packetDataSerializerClass.getConstructor(byteBufClass).newInstance(buffer);
|
|
||||||
|
|
||||||
Method d = packetDataSerializerClass.getMethod("d", int.class);
|
|
||||||
Method writeDouble = packetDataSerializerClass.getMethod("writeDouble", double.class);
|
|
||||||
Method writeByte = packetDataSerializerClass.getMethod("writeByte", int.class);
|
|
||||||
Method writeBoolean = packetDataSerializerClass.getMethod("writeBoolean", boolean.class);
|
|
||||||
|
|
||||||
d.invoke(serializer, getEntityId());
|
|
||||||
writeDouble.invoke(serializer, location.getX());
|
|
||||||
writeDouble.invoke(serializer, y);
|
|
||||||
writeDouble.invoke(serializer, location.getZ());
|
|
||||||
writeByte.invoke(serializer, 0);
|
|
||||||
writeByte.invoke(serializer, 0);
|
|
||||||
writeBoolean.invoke(serializer, false);
|
|
||||||
|
|
||||||
packet = packetPlayOutEntityTeleportClass.getConstructor(packetDataSerializerClass).newInstance(serializer);
|
|
||||||
} else {
|
|
||||||
packet = packetPlayOutEntityTeleportClass.getConstructor().newInstance();
|
|
||||||
Field[] fields = packetPlayOutEntityTeleportClass.getDeclaredFields();
|
|
||||||
for (Field field : fields) {
|
|
||||||
field.setAccessible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isPre9 = Utils.getMajorVersion() < 9;
|
|
||||||
fields[0].set(packet, entityId);
|
|
||||||
|
|
||||||
if (isPre9) {
|
|
||||||
fields[1].set(packet, (int)(location.getX() * 32));
|
|
||||||
fields[2].set(packet, (int)(y * 32));
|
|
||||||
fields[3].set(packet, (int)(location.getZ() * 32));
|
|
||||||
} else {
|
|
||||||
fields[1].set(packet, location.getX());
|
|
||||||
fields[2].set(packet, y);
|
|
||||||
fields[3].set(packet, location.getZ());
|
|
||||||
}
|
|
||||||
fields[4].set(packet, (byte) 0);
|
|
||||||
fields[5].set(packet, (byte) 0);
|
|
||||||
fields[6].set(packet, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packet == null) {
|
|
||||||
plugin.getLogger().severe("Could not set hologram location");
|
|
||||||
plugin.debug("Could not set armor stand location: Packet is null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Player player : location.getWorld().getPlayers()) {
|
|
||||||
Utils.sendPacket(plugin, packet, player);
|
|
||||||
}
|
|
||||||
} catch (ReflectiveOperationException e) {
|
|
||||||
plugin.getLogger().severe("Could not set hologram location");
|
|
||||||
plugin.debug("Could not set armor stand location");
|
|
||||||
plugin.debug(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCustomName(String customName) {
|
public void setCustomName(String customName) {
|
||||||
this.customName = customName;
|
this.customName = customName;
|
||||||
Object dataWatcher = Utils.createDataWatcher(customName, null);
|
fakeArmorStand.sendData(customName, Objects.requireNonNull(location.getWorld()).getPlayers());
|
||||||
try {
|
|
||||||
Object packet = packetPlayOutEntityMetadataClass.getConstructor(int.class, dataWatcherClass, boolean.class)
|
|
||||||
.newInstance(entityId, dataWatcher, true);
|
|
||||||
|
|
||||||
for (Player player : location.getWorld().getPlayers()) {
|
|
||||||
Utils.sendPacket(plugin, packet, player);
|
|
||||||
}
|
|
||||||
} catch (ReflectiveOperationException e) {
|
|
||||||
plugin.getLogger().severe("Could not set hologram text");
|
|
||||||
plugin.debug("Could not set armor stand custom name");
|
|
||||||
plugin.debug(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove() {
|
public void remove() {
|
||||||
for (Player player : location.getWorld().getPlayers()) {
|
for (Player player : Objects.requireNonNull(location.getWorld()).getPlayers()) {
|
||||||
setVisible(player, false);
|
setVisible(player, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getEntityId() {
|
public int getEntityId() {
|
||||||
return entityId;
|
return fakeArmorStand.getEntityId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID getUuid() {
|
public UUID getUuid() {
|
||||||
|
@ -1,59 +1,28 @@
|
|||||||
package de.epiceric.shopchest.shop;
|
package de.epiceric.shopchest.shop;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import de.epiceric.shopchest.ShopChest;
|
||||||
import java.util.ArrayList;
|
import de.epiceric.shopchest.nms.FakeItem;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.EntityType;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.inventivetalent.reflection.resolver.minecraft.NMSClassResolver;
|
|
||||||
import org.inventivetalent.reflection.resolver.minecraft.OBCClassResolver;
|
|
||||||
|
|
||||||
import de.epiceric.shopchest.ShopChest;
|
import java.util.*;
|
||||||
import de.epiceric.shopchest.utils.Utils;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
public class ShopItem {
|
public class ShopItem {
|
||||||
private final ShopChest plugin;
|
|
||||||
|
|
||||||
// concurrent since update task is in async thread
|
// concurrent since update task is in async thread
|
||||||
private final Set<UUID> viewers = ConcurrentHashMap.newKeySet();
|
private final Set<UUID> viewers = ConcurrentHashMap.newKeySet();
|
||||||
private final ItemStack itemStack;
|
private final ItemStack itemStack;
|
||||||
private final Location location;
|
private final Location location;
|
||||||
private final UUID uuid = UUID.randomUUID();
|
private final UUID uuid = UUID.randomUUID();
|
||||||
private final int entityId;
|
private final FakeItem fakeItem;
|
||||||
|
|
||||||
private final NMSClassResolver nmsClassResolver = new NMSClassResolver();
|
|
||||||
private final OBCClassResolver obcClassResolver = new OBCClassResolver();
|
|
||||||
private final Class<?> packetPlayOutEntityDestroyClass = nmsClassResolver.resolveSilent("network.protocol.game.PacketPlayOutEntityDestroy");
|
|
||||||
private final Class<?> packetPlayOutEntityVelocityClass = nmsClassResolver.resolveSilent("network.protocol.game.PacketPlayOutEntityVelocity");
|
|
||||||
private final Class<?> packetPlayOutEntityMetadataClass = nmsClassResolver.resolveSilent("network.protocol.game.PacketPlayOutEntityMetadata");
|
|
||||||
private final Class<?> dataWatcherClass = nmsClassResolver.resolveSilent("network.syncher.DataWatcher");
|
|
||||||
private final Class<?> vec3dClass = nmsClassResolver.resolveSilent("world.phys.Vec3D");
|
|
||||||
private final Class<?> craftItemStackClass = obcClassResolver.resolveSilent("inventory.CraftItemStack");
|
|
||||||
private final Class<?> nmsItemStackClass = nmsClassResolver.resolveSilent("world.item.ItemStack");
|
|
||||||
|
|
||||||
public ShopItem(ShopChest plugin, ItemStack itemStack, Location location) {
|
public ShopItem(ShopChest plugin, ItemStack itemStack, Location location) {
|
||||||
this.plugin = plugin;
|
|
||||||
this.itemStack = itemStack;
|
this.itemStack = itemStack;
|
||||||
this.location = location;
|
this.location = location;
|
||||||
this.entityId = Utils.getFreeEntityId();
|
this.fakeItem = plugin.getPlatform().createFakeItem();
|
||||||
|
|
||||||
Class<?>[] requiredClasses = new Class<?>[] {
|
|
||||||
nmsItemStackClass, craftItemStackClass, packetPlayOutEntityMetadataClass, dataWatcherClass,
|
|
||||||
packetPlayOutEntityDestroyClass, packetPlayOutEntityVelocityClass,
|
|
||||||
};
|
|
||||||
|
|
||||||
for (Class<?> c : requiredClasses) {
|
|
||||||
if (c == null) {
|
|
||||||
plugin.debug("Failed to create shop item: Could not find all required classes");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -91,22 +60,10 @@ public class ShopItem {
|
|||||||
*/
|
*/
|
||||||
public void showPlayer(Player p, boolean force) {
|
public void showPlayer(Player p, boolean force) {
|
||||||
if (viewers.add(p.getUniqueId()) || force) {
|
if (viewers.add(p.getUniqueId()) || force) {
|
||||||
try {
|
final List<Player> receiver = Collections.singletonList(p);
|
||||||
Object nmsItemStack = craftItemStackClass.getMethod("asNMSCopy", ItemStack.class).invoke(null, itemStack);
|
fakeItem.spawn(uuid, location, receiver);
|
||||||
Object dataWatcher = Utils.createDataWatcher(null, nmsItemStack);
|
fakeItem.sendData(itemStack, receiver);
|
||||||
Utils.sendPacket(plugin, Utils.createPacketSpawnEntity(plugin, entityId, uuid, location, EntityType.DROPPED_ITEM), p);
|
fakeItem.resetVelocity(receiver);
|
||||||
Utils.sendPacket(plugin, packetPlayOutEntityMetadataClass.getConstructor(int.class, dataWatcherClass, boolean.class).newInstance(entityId, dataWatcher, true), p);
|
|
||||||
if (Utils.getMajorVersion() < 14) {
|
|
||||||
Utils.sendPacket(plugin, packetPlayOutEntityVelocityClass.getConstructor(int.class, double.class, double.class, double.class).newInstance(entityId, 0D, 0D, 0D), p);
|
|
||||||
} else {
|
|
||||||
Object vec3d = vec3dClass.getConstructor(double.class, double.class, double.class).newInstance(0D, 0D, 0D);
|
|
||||||
Utils.sendPacket(plugin, packetPlayOutEntityVelocityClass.getConstructor(int.class, vec3dClass).newInstance(entityId, vec3d), p);
|
|
||||||
}
|
|
||||||
} catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | SecurityException | InstantiationException e) {
|
|
||||||
plugin.getLogger().severe("Failed to create item!");
|
|
||||||
plugin.debug("Failed to create item!");
|
|
||||||
plugin.debug(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,15 +80,8 @@ public class ShopItem {
|
|||||||
*/
|
*/
|
||||||
public void hidePlayer(Player p, boolean force) {
|
public void hidePlayer(Player p, boolean force) {
|
||||||
if (viewers.remove(p.getUniqueId()) || force) {
|
if (viewers.remove(p.getUniqueId()) || force) {
|
||||||
try {
|
|
||||||
if (p.isOnline()) {
|
if (p.isOnline()) {
|
||||||
Object packetPlayOutEntityDestroy = packetPlayOutEntityDestroyClass.getConstructor(int[].class).newInstance((Object) new int[]{entityId});
|
fakeItem.remove(Collections.singletonList(p));
|
||||||
Utils.sendPacket(plugin, packetPlayOutEntityDestroy, p);
|
|
||||||
}
|
|
||||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) {
|
|
||||||
plugin.getLogger().severe("Failed to destroy shop item");
|
|
||||||
plugin.debug("Failed to destroy shop item with reflection");
|
|
||||||
plugin.debug(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user