From b52670c4b3e6137571084a1734f5585ce59aa905 Mon Sep 17 00:00:00 2001 From: "Kristian S. Stangeland" Date: Tue, 16 Oct 2012 07:58:30 +0200 Subject: [PATCH] Switching to overriding an ArrayList directly. This makes the injection code compatible with earlier versions of Minecraft (even 1.0.0). --- .../comphenix/protocol/ProtocolLibrary.java | 2 +- .../protocol/events/MonitorAdapter.java | 20 ++- .../player/InjectedServerConnection.java | 5 + .../injector/player/ReplacedArrayList.java | 124 ++++++++++++++++-- 4 files changed, 138 insertions(+), 13 deletions(-) diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/ProtocolLibrary.java b/ProtocolLib/src/main/java/com/comphenix/protocol/ProtocolLibrary.java index 10887aa9..74b2108e 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/ProtocolLibrary.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/ProtocolLibrary.java @@ -101,7 +101,7 @@ public class ProtocolLibrary extends JavaPlugin { private void addDebugListener() { // DEBUG DEBUG - protocolManager.addPacketListener(new MonitorAdapter(this, ConnectionSide.BOTH) { + protocolManager.addPacketListener(new MonitorAdapter(this, ConnectionSide.BOTH, logger) { @Override public void onPacketReceiving(PacketEvent event) { System.out.println("RECEIVING " + event.getPacketID() + " from " + event.getPlayer().getName()); diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/events/MonitorAdapter.java b/ProtocolLib/src/main/java/com/comphenix/protocol/events/MonitorAdapter.java index e3e4e81a..9036971a 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/events/MonitorAdapter.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/events/MonitorAdapter.java @@ -25,11 +25,14 @@ public abstract class MonitorAdapter implements PacketListener { private ListeningWhitelist receiving = ListeningWhitelist.EMPTY_WHITELIST; public MonitorAdapter(Plugin plugin, ConnectionSide side) { - this(plugin, side, plugin.getLogger()); + initialize(plugin, side, getLogger(plugin)); } public MonitorAdapter(Plugin plugin, ConnectionSide side, Logger logger) { - super(); + initialize(plugin, side, logger); + } + + private void initialize(Plugin plugin, ConnectionSide side, Logger logger) { this.plugin = plugin; // Recover in case something goes wrong @@ -47,6 +50,19 @@ public abstract class MonitorAdapter implements PacketListener { } } + /** + * Retrieve a logger, even if we're running in a CraftBukkit version that doesn't support it. + * @param plugin - the plugin to retrieve. + * @return The logger. + */ + private Logger getLogger(Plugin plugin) { + try { + return plugin.getLogger(); + } catch (NoSuchMethodError e) { + return Logger.getLogger("Minecraft"); + } + } + @Override public void onPacketReceiving(PacketEvent event) { // Empty for now diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/InjectedServerConnection.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/InjectedServerConnection.java index 680e5248..d65fd405 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/InjectedServerConnection.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/InjectedServerConnection.java @@ -210,6 +210,11 @@ class InjectedServerConnection { // Hack to avoid the "moved to quickly" error private ReplacedArrayList createReplacement(List list) { return new ReplacedArrayList(list) { + /** + * Shut up Eclipse! + */ + private static final long serialVersionUID = 2070481080950500367L; + @Override protected void onReplacing(Object inserting, Object replacement) { // Is this a normal Minecraft object? diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/ReplacedArrayList.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/ReplacedArrayList.java index 7fe17fdb..2ee75461 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/ReplacedArrayList.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/ReplacedArrayList.java @@ -17,12 +17,14 @@ package com.comphenix.protocol.injector.player; +import java.util.ArrayList; import java.util.Collection; +import java.util.Iterator; import java.util.List; +import java.util.ListIterator; import com.google.common.base.Objects; import com.google.common.collect.BiMap; -import com.google.common.collect.ForwardingList; import com.google.common.collect.HashBiMap; /** @@ -33,7 +35,12 @@ import com.google.common.collect.HashBiMap; * @author Kristian * @param - type of the elements we're replacing. */ -class ReplacedArrayList extends ForwardingList { +class ReplacedArrayList extends ArrayList { + /** + * Generated by Eclipse. + */ + private static final long serialVersionUID = 1008492765999744804L; + private BiMap replaceMap = HashBiMap.create(); private List underlyingList; @@ -75,9 +82,9 @@ class ReplacedArrayList extends ForwardingList { if (replaceMap.containsKey(element)) { TKey replacement = replaceMap.get(element); onReplacing(element, replacement); - return super.add(replacement); + return delegate().add(replacement); } else { - return super.add(element); + return delegate().add(element); } } @@ -88,9 +95,9 @@ class ReplacedArrayList extends ForwardingList { if (replaceMap.containsKey(element)) { TKey replacement = replaceMap.get(element); onReplacing(element, replacement); - super.add(index, replacement); + delegate().add(index, replacement); } else { - super.add(index, element); + delegate().add(index, element); } } @@ -115,7 +122,7 @@ class ReplacedArrayList extends ForwardingList { @SuppressWarnings("unchecked") @Override public boolean remove(Object object) { - boolean success = super.remove(object); + boolean success = delegate().remove(object); if (success) onRemoved((TKey) object); @@ -124,7 +131,7 @@ class ReplacedArrayList extends ForwardingList { @Override public TKey remove(int index) { - TKey removed = super.remove(index); + TKey removed = delegate().remove(index); if (removed != null) onRemoved(removed); @@ -140,12 +147,109 @@ class ReplacedArrayList extends ForwardingList { remove(element); return size() != oldSize; } - - @Override + protected List delegate() { return underlyingList; } + @Override + public void clear() { + delegate().clear(); + } + + @Override + public boolean contains(Object o) { + return delegate().contains(o); + } + + @Override + public boolean containsAll(Collection c) { + return delegate().containsAll(c); + } + + @Override + public TKey get(int index) { + return delegate().get(index); + } + + @Override + public int indexOf(Object o) { + return delegate().indexOf(o); + } + + @Override + public boolean isEmpty() { + return delegate().isEmpty(); + } + + @Override + public Iterator iterator() { + return delegate().iterator(); + } + + @Override + public int lastIndexOf(Object o) { + return delegate().lastIndexOf(o); + } + + @Override + public ListIterator listIterator() { + return delegate().listIterator(); + } + + @Override + public ListIterator listIterator(int index) { + return delegate().listIterator(index); + } + + @Override + public boolean retainAll(Collection c) { + int oldSize = size(); + + for (Iterator it = delegate().iterator(); it.hasNext(); ) { + TKey current = it.next(); + + // Remove elements that are not in the list + if (!c.contains(current)) { + it.remove(); + onRemoved(current); + } + } + return size() != oldSize; + } + + @Override + public TKey set(int index, TKey element) { + // Make sure to replace the element + if (replaceMap.containsKey(element)) { + TKey replacement = replaceMap.get(element); + onReplacing(element, replacement); + return delegate().set(index, replacement); + } else { + return delegate().set(index, element); + } + } + + @Override + public int size() { + return delegate().size(); + } + + @Override + public List subList(int fromIndex, int toIndex) { + return delegate().subList(fromIndex, toIndex); + } + + @Override + public Object[] toArray() { + return delegate().toArray(); + } + + @Override + public T[] toArray(T[] a) { + return delegate().toArray(a); + } + /** * Add a replace rule. *