getByteArrays() {
+ return structureModifier.withType(byte[].class);
+ }
+
/**
* Retrieves a read/write structure for ItemStack.
*
@@ -145,22 +203,8 @@ public class PacketContainer implements Serializable {
*/
public StructureModifier getItemModifier() {
// Convert to and from the Bukkit wrapper
- return structureModifier.withType(net.minecraft.server.ItemStack.class,
- getIgnoreNull(new EquivalentConverter() {
- public Object getGeneric(ItemStack specific) {
- return toStackNMS(specific);
- }
-
- @Override
- public ItemStack getSpecific(Object generic) {
- return new CraftItemStack((net.minecraft.server.ItemStack) generic);
- }
-
- @Override
- public Class getSpecificType() {
- return ItemStack.class;
- }
- }));
+ return structureModifier.withType(
+ net.minecraft.server.ItemStack.class, BukkitConverters.getItemStackConverter());
}
/**
@@ -171,17 +215,21 @@ public class PacketContainer implements Serializable {
* @return A modifier for ItemStack array fields.
*/
public StructureModifier getItemArrayModifier() {
+
+ final EquivalentConverter stackConverter = BukkitConverters.getItemStackConverter();
+
// Convert to and from the Bukkit wrapper
return structureModifier.withType(
net.minecraft.server.ItemStack[].class,
- getIgnoreNull(new EquivalentConverter() {
+ BukkitConverters.getIgnoreNull(new EquivalentConverter() {
- public Object getGeneric(ItemStack[] specific) {
+ public Object getGeneric(Class>genericType, ItemStack[] specific) {
net.minecraft.server.ItemStack[] result = new net.minecraft.server.ItemStack[specific.length];
// Unwrap every item
for (int i = 0; i < result.length; i++) {
- result[i] = toStackNMS(specific[i]);
+ result[i] = (net.minecraft.server.ItemStack) stackConverter.getGeneric(
+ net.minecraft.server.ItemStack.class, specific[i]);
}
return result;
}
@@ -193,7 +241,7 @@ public class PacketContainer implements Serializable {
// Add the wrapper
for (int i = 0; i < result.length; i++) {
- result[i] = new CraftItemStack(input[i]);
+ result[i] = stackConverter.getSpecific(input[i]);
}
return result;
}
@@ -205,20 +253,6 @@ public class PacketContainer implements Serializable {
}));
}
- /**
- * Convert an item stack to the NMS equivalent.
- * @param stack - Bukkit stack to convert.
- * @return A bukkit stack.
- */
- private net.minecraft.server.ItemStack toStackNMS(ItemStack stack) {
- // We must be prepared for an object that simply implements ItemStcak
- if (stack instanceof CraftItemStack) {
- return ((CraftItemStack) stack).getHandle();
- } else {
- return (new CraftItemStack(stack)).getHandle();
- }
- }
-
/**
* Retrieves a read/write structure for the world type enum.
*
@@ -227,33 +261,21 @@ public class PacketContainer implements Serializable {
* @return A modifier for world type fields.
*/
public StructureModifier getWorldTypeModifier() {
-
- if (!hasWorldType) {
- // We couldn't find the Minecraft equivalent
- return structureModifier.withType(null);
- }
-
// Convert to and from the Bukkit wrapper
return structureModifier.withType(
net.minecraft.server.WorldType.class,
- getIgnoreNull(new EquivalentConverter() {
-
- @Override
- public Object getGeneric(WorldType specific) {
- return net.minecraft.server.WorldType.getType(specific.getName());
- }
-
- @Override
- public WorldType getSpecific(Object generic) {
- net.minecraft.server.WorldType type = (net.minecraft.server.WorldType) generic;
- return WorldType.getByName(type.name());
- }
-
- @Override
- public Class getSpecificType() {
- return WorldType.class;
- }
- }));
+ BukkitConverters.getWorldTypeConverter());
+ }
+
+ /**
+ * Retrieves a read/write structure for data watchers.
+ * @return A modifier for data watchers.
+ */
+ public StructureModifier getDataWatcherModifier() {
+ // Convert to and from the Bukkit wrapper
+ return structureModifier.withType(
+ net.minecraft.server.DataWatcher.class,
+ BukkitConverters.getDataWatcherConverter());
}
/**
@@ -267,91 +289,56 @@ public class PacketContainer implements Serializable {
* @return A modifier entity types.
*/
public StructureModifier getEntityModifier(World world) {
-
- final Object worldServer = ((CraftWorld) world).getHandle();
- final Class> nmsEntityClass = net.minecraft.server.Entity.class;
-
- if (getEntity == null)
- getEntity = FuzzyReflection.fromObject(worldServer).getMethodByParameters(
- "getEntity", nmsEntityClass, new Class[] { int.class });
-
// Convert to and from the Bukkit wrapper
return structureModifier.withType(
- int.class,
- getIgnoreNull(new EquivalentConverter() {
-
- @Override
- public Object getGeneric(Entity specific) {
- // Simple enough
- return specific.getEntityId();
- }
-
- @Override
- public Entity getSpecific(Object generic) {
- try {
- net.minecraft.server.Entity nmsEntity = (net.minecraft.server.Entity)
- getEntity.invoke(worldServer, generic);
- Integer id = (Integer) generic;
-
- // Attempt to get the Bukkit entity
- if (nmsEntity != null) {
- return nmsEntity.getBukkitEntity();
- } else {
- Server server = Bukkit.getServer();
-
- // Maybe it's a player that has just logged in? Try a search
- if (server != null) {
- for (Player player : server.getOnlinePlayers()) {
- if (player.getEntityId() == id) {
- return player;
- }
- }
- }
-
- return null;
- }
-
- } catch (IllegalArgumentException e) {
- throw new RuntimeException("Incorrect arguments detected.", e);
- } catch (IllegalAccessException e) {
- throw new RuntimeException("Cannot read field due to a security limitation.", e);
- } catch (InvocationTargetException e) {
- throw new RuntimeException("Error occured in Minecraft method.", e.getCause());
- }
- }
-
- @Override
- public Class getSpecificType() {
- return Entity.class;
- }
- }));
+ int.class, BukkitConverters.getEntityConverter(world));
}
- private EquivalentConverter getIgnoreNull(final EquivalentConverter delegate) {
- // Automatically wrap all parameters to the delegate with a NULL check
- return new EquivalentConverter() {
- public Object getGeneric(TType specific) {
- if (specific != null)
- return delegate.getGeneric(specific);
- else
- return null;
- }
-
- @Override
- public TType getSpecific(Object generic) {
- if (generic != null)
- return delegate.getSpecific(generic);
- else
- return null;
- }
-
- @Override
- public Class getSpecificType() {
- return delegate.getSpecificType();
- }
- };
+ /**
+ * Retrieves a read/write structure for chunk positions.
+ * @return A modifier for a ChunkPosition.
+ */
+ public StructureModifier getPositionModifier() {
+ // Convert to and from the Bukkit wrapper
+ return structureModifier.withType(
+ net.minecraft.server.ChunkPosition.class,
+ ChunkPosition.getConverter());
}
-
+
+ /**
+ * Retrieves a read/write structure for collections of chunk positions.
+ *
+ * This modifier will automatically marshall between the visible ProtocolLib ChunkPosition and the
+ * internal Minecraft ChunkPosition.
+ * @return A modifier for ChunkPosition list fields.
+ */
+ public StructureModifier> getPositionCollectionModifier() {
+ // Convert to and from the ProtocolLib wrapper
+ return structureModifier.withType(
+ Collection.class,
+ BukkitConverters.getListConverter(
+ net.minecraft.server.ChunkPosition.class,
+ ChunkPosition.getConverter())
+ );
+ }
+
+ /**
+ * Retrieves a read/write structure for collections of watchable objects.
+ *
+ * This modifier will automatically marshall between the visible WrappedWatchableObject and the
+ * internal Minecraft WatchableObject.
+ * @return A modifier for watchable object list fields.
+ */
+ public StructureModifier> getWatchableCollectionModifier() {
+ // Convert to and from the ProtocolLib wrapper
+ return structureModifier.withType(
+ Collection.class,
+ BukkitConverters.getListConverter(
+ net.minecraft.server.WatchableObject.class,
+ BukkitConverters.getWatchableObjectConverter())
+ );
+ }
+
/**
* Retrieves the ID of this packet.
* @return Packet ID.
diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/EntityUtilities.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/EntityUtilities.java
index 8dbd1567..9671c6ce 100644
--- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/EntityUtilities.java
+++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/EntityUtilities.java
@@ -27,6 +27,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import net.minecraft.server.EntityTrackerEntry;
+
import org.bukkit.World;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.entity.Entity;
@@ -83,8 +85,51 @@ class EntityUtilities {
*
*/
public static void updateEntity(Entity entity, List observers) throws FieldAccessException {
-
- World world = entity.getWorld();
+ try {
+ //EntityTrackerEntry trackEntity = (EntityTrackerEntry) tracker.trackedEntities.get(entity.getEntityId());
+ Object trackerEntry = getEntityTrackerEntry(entity.getWorld(), entity.getEntityId());
+
+ if (trackedPlayersField == null) {
+ // This one is fairly easy
+ trackedPlayersField = FuzzyReflection.fromObject(trackerEntry).getFieldByType("java\\.util\\..*");
+ }
+
+ // Phew, finally there.
+ Collection> trackedPlayers = (Collection>) FieldUtils.readField(trackedPlayersField, trackerEntry, false);
+ List