From 305f6b7ce23c03d2d3226b8e226fdcc1e758236e Mon Sep 17 00:00:00 2001 From: Myles Date: Fri, 30 Sep 2016 20:48:02 +0100 Subject: [PATCH] Implement Hand Item Cache for Sponge --- .../myles/ViaVersion/util/PipelineUtil.java | 1 - .../protocol1_9to1_8/HandItemCache.java | 78 +++++++++++++++++++ .../sponge/platform/SpongeViaLoader.java | 61 ++++++--------- 3 files changed, 100 insertions(+), 40 deletions(-) create mode 100644 sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/HandItemCache.java diff --git a/common/src/main/java/us/myles/ViaVersion/util/PipelineUtil.java b/common/src/main/java/us/myles/ViaVersion/util/PipelineUtil.java index fca66ada5..05b92e9d5 100644 --- a/common/src/main/java/us/myles/ViaVersion/util/PipelineUtil.java +++ b/common/src/main/java/us/myles/ViaVersion/util/PipelineUtil.java @@ -95,7 +95,6 @@ public class PipelineUtil { boolean mark = false; for (String s : pipeline.names()) { if (mark) { - System.out.println("Context before: " + s); return pipeline.context(pipeline.get(s)); } if (s.equalsIgnoreCase(name)) diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/HandItemCache.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/HandItemCache.java new file mode 100644 index 000000000..2a60aadcc --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/HandItemCache.java @@ -0,0 +1,78 @@ +package us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8; + +import org.spongepowered.api.Sponge; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.item.inventory.ItemStack; +import us.myles.ViaVersion.api.minecraft.item.Item; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class HandItemCache implements Runnable { + public static boolean CACHE = false; + private static ConcurrentHashMap handCache = new ConcurrentHashMap<>(); + private static Field GET_DAMAGE; + private static Method GET_ID; + + public static Item getHandItem(UUID player) { + if (!handCache.containsKey(player)) + return null; + return handCache.get(player); + } + + @Override + public void run() { + List players = new ArrayList<>(handCache.keySet()); + + for (Player p : Sponge.getServer().getOnlinePlayers()) { + handCache.put(p.getUniqueId(), convert(p.getItemInHand().orElse(null))); + players.remove(p.getUniqueId()); + } + // Remove offline players + for (UUID uuid : players) { + handCache.remove(uuid); + } + } + + public static Item convert(ItemStack itemInHand) { + if (itemInHand == null) return new Item((short) 0, (byte) 0, (short) 0, null); + if (GET_DAMAGE == null) { + try { + GET_DAMAGE = itemInHand.getClass().getDeclaredField("field_77991_e"); + GET_DAMAGE.setAccessible(true); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } + } + if (GET_ID == null) { + try { + GET_ID = Class.forName("net.minecraft.item.Item").getDeclaredMethod("func_150891_b", Class.forName("net.minecraft.item.Item")); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } + int id = 0; + try { + id = (int) GET_ID.invoke(null, itemInHand.getItem()); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + int damage = 0; + try { + damage = (int) GET_DAMAGE.get(itemInHand); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return new Item((short) id, (byte) itemInHand.getQuantity(), (short) damage, null); + } +} + diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaLoader.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaLoader.java index ae6e123cd..98f1d39d5 100644 --- a/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaLoader.java +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaLoader.java @@ -4,15 +4,16 @@ import lombok.AllArgsConstructor; import org.spongepowered.api.Sponge; import us.myles.ViaVersion.SpongePlugin; import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.minecraft.item.Item; import us.myles.ViaVersion.api.platform.ViaPlatformLoader; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BulkChunkTranslatorProvider; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.HandItemProvider; import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider; import us.myles.ViaVersion.sponge.listeners.ClientLeaveListener; import us.myles.ViaVersion.sponge.listeners.UpdateListener; -import us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8.ArmorListener; -import us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8.BlockListener; -import us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8.CommandBlockListener; -import us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8.DeathListener; +import us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8.*; import us.myles.ViaVersion.sponge.providers.SpongeViaBulkChunkTranslator; import us.myles.ViaVersion.sponge.providers.SpongeViaMovementTransmitter; @@ -24,49 +25,31 @@ public class SpongeViaLoader implements ViaPlatformLoader { public void load() { // Update Listener Sponge.getEventManager().registerListeners(plugin, new UpdateListener()); -// /* Base Protocol */ Sponge.getEventManager().registerListeners(plugin, new ClientLeaveListener()); -// /* 1.9 client to 1.8 server */ -// + /* 1.9 client to 1.8 server */ new ArmorListener(plugin).register(); new CommandBlockListener(plugin).register(); new DeathListener(plugin).register(); new BlockListener(plugin).register(); -// if (plugin.getConf().isItemCache()) { -// new HandItemCache().runTaskTimerAsynchronously(plugin, 2L, 2L); // Updates player's items :) -// HandItemCache.CACHE = true; -// } -// -// /* Providers */ + if (plugin.getConf().isItemCache()) { + Via.getPlatform().runRepeatingSync(new HandItemCache(), 2L); // Updates player's items :) + HandItemCache.CACHE = true; + } + + /* Providers */ Via.getManager().getProviders().use(BulkChunkTranslatorProvider.class, new SpongeViaBulkChunkTranslator()); Via.getManager().getProviders().use(MovementTransmitterProvider.class, new SpongeViaMovementTransmitter()); -// Via.getManager().getProviders().use(HandItemProvider.class, new HandItemProvider() { -// @Override -// public Item getHandItem(final UserConnection info) { -// if (HandItemCache.CACHE) { -// return HandItemCache.getHandItem(info.get(ProtocolInfo.class).getUuid()); -// } else { -// try { -// return Bukkit.getScheduler().callSyncMethod(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Callable() { -// @Override -// public Item call() throws Exception { -// UUID playerUUID = info.get(ProtocolInfo.class).getUuid(); -// if (Bukkit.getPlayer(playerUUID) != null) { -// return HandItemCache.convert(Bukkit.getPlayer(playerUUID).getItemInHand()); -// } -// return null; -// } -// }).get(10, TimeUnit.SECONDS); -// } catch (Exception e) { -// System.out.println("Error fetching hand item: " + e.getClass().getName()); -// if (Via.getManager().isDebug()) -// e.printStackTrace(); -// return null; -// } -// } -// } -// }); + Via.getManager().getProviders().use(HandItemProvider.class, new HandItemProvider() { + @Override + public Item getHandItem(final UserConnection info) { + if (HandItemCache.CACHE) { + return HandItemCache.getHandItem(info.get(ProtocolInfo.class).getUuid()); + } else { + return super.getHandItem(info); // TODO: On API Docs write about this + } + } + }); } }