A lot of tweaks to the chunkloading for entity behaviour. Entities are now bound by a new

persistent id they *all* have, on the server side.
This commit is contained in:
Christian 2012-09-22 12:27:14 -04:00
parent c684360f51
commit 9640c5dcf9
3 changed files with 99 additions and 56 deletions

View file

@ -9,9 +9,14 @@ import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.ListMultimap;
@ -27,6 +32,7 @@ import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.ModContainer;
import net.minecraft.src.Chunk;
import net.minecraft.src.ChunkCoordIntPair;
import net.minecraft.src.CompressedStreamTools;
import net.minecraft.src.Entity;
@ -68,6 +74,7 @@ public class ForgeChunkManager
private static Map<String, LoadingCallback> callbacks = Maps.newHashMap();
private static Map<World, SetMultimap<ChunkCoordIntPair,Ticket>> forcedChunks = Maps.newHashMap();
private static BiMap<UUID,Ticket> pendingEntities = HashBiMap.create();
/**
* All mods requiring chunkloading need to implement this to handle the
@ -108,9 +115,8 @@ public class ForgeChunkManager
private World world;
private int maxDepth;
private String entityClazz;
private int entityX;
private int entityY;
private int entityZ;
private int entityChunkX;
private int entityChunkZ;
private Entity entity;
Ticket(String modId, Type type, World world)
@ -122,14 +128,6 @@ public class ForgeChunkManager
this.requestedChunks = Sets.newLinkedHashSet();
}
void bindEntityData(int x, int y, int z, String clazz)
{
this.entityX = x;
this.entityY = y;
this.entityZ = z;
this.entityClazz = clazz;
}
/**
* The chunk list depth can be manipulated up to the maximal grant allowed for the mod. This value is configurable. Once the maximum is reached,
* the least recently forced chunk, by original registration time, is removed from the forced chunk list.
@ -189,37 +187,12 @@ public class ForgeChunkManager
}
/**
* Get the entity class associated with this ticket. Only valid for callbacks.
* Get the entity associated with this {@link Type#ENTITY} type ticket
* @return
*/
public String getEntityClass()
public Entity getEntity()
{
return this.entityClazz;
}
/**
* Get the last known entity X coordinate for this ticket. Only valid for callbacks.
* @return
*/
public int getEntityX()
{
return entityX;
}
/**
* Get the last known entity Y coordinate for this ticket. Only valid for callbacks.
* @return
*/
public int getEntityY()
{
return entityY;
}
/**
* Get the last known entity Z coordinate for this ticket. Only valid for callbacks.
* @return
*/
public int getEntityZ()
{
return entityZ;
return entity;
}
}
@ -287,16 +260,35 @@ public class ForgeChunkManager
tick.modData = modData;
if (type == Type.ENTITY)
{
int entX = ticket.getInteger("entityX");
int entY = ticket.getInteger("entityY");
int entZ = ticket.getInteger("entityZ");
String entClass = ticket.getString("entityClass");
tick.bindEntityData(entX, entY, entZ, entClass);
tick.entityChunkX = ticket.getInteger("chunkX");
tick.entityChunkZ = ticket.getInteger("chunkZ");
UUID uuid = new UUID(ticket.getLong("PersistentIDMSB"), ticket.getLong("PersistentIDLSB"));
// add the ticket to the "pending entity" list
pendingEntities.put(uuid, tick);
}
loadedTickets.put(modId, tick);
}
}
for (Ticket tick : ImmutableSet.copyOf(pendingEntities.values()))
{
if (tick.ticketType == Type.ENTITY && tick.entity == null)
{
// force the world to load the entity's chunk
// the load will come back through the loadEntity method and attach the entity
// to the ticket
world.getChunkFromChunkCoords(tick.entityChunkX, tick.entityChunkZ);
}
}
for (Ticket tick : ImmutableSet.copyOf(pendingEntities.values()))
{
if (tick.ticketType == Type.ENTITY && tick.entity == null)
{
FMLLog.warning("Failed to load persistent chunkloading entity %s from store.", pendingEntities.inverse().get(tick));
loadedTickets.remove(tick.modId, tick);
}
}
pendingEntities.clear();
// send callbacks
for (String modId : loadedTickets.keySet())
{
@ -537,10 +529,10 @@ public class ForgeChunkManager
ticket.setCompoundTag("ModData", tick.modData);
if (tick.ticketType == Type.ENTITY)
{
ticket.setInteger("entityX", MathHelper.floor_double(tick.entity.posX));
ticket.setInteger("entityY", MathHelper.floor_double(tick.entity.posY));
ticket.setInteger("entityZ", MathHelper.floor_double(tick.entity.posZ));
ticket.setString("entityClass", tick.entity.getClass().getName());
ticket.setInteger("chunkX", MathHelper.floor_double(tick.entity.chunkCoordX));
ticket.setInteger("chunkZ", MathHelper.floor_double(tick.entity.chunkCoordZ));
ticket.setLong("persistentIDMSB", tick.entity.getPersistentID().getMostSignificantBits());
ticket.setLong("persistentIDLSB", tick.entity.getPersistentID().getLeastSignificantBits());
}
}
}
@ -554,4 +546,15 @@ public class ForgeChunkManager
return;
}
}
static void loadEntity(Entity entity)
{
UUID id = entity.getPersistentID();
Ticket tick = pendingEntities.get(id);
if (tick != null)
{
tick.bindEntity(entity);
pendingEntities.remove(id);
}
}
}

View file

@ -1,5 +1,7 @@
package net.minecraftforge.common;
import java.util.UUID;
import net.minecraft.src.*;
import net.minecraftforge.event.*;
import net.minecraftforge.event.entity.*;
@ -10,6 +12,17 @@ public class ForgeInternalHandler
@ForgeSubscribe(priority = EventPriority.HIGHEST)
public void onEntityJoinWorld(EntityJoinWorldEvent event)
{
if (!event.world.isRemote)
{
if (event.entity.getPersistentID() == null)
{
event.entity.generatePersistentID();
}
else
{
ForgeChunkManager.loadEntity(event.entity);
}
}
Entity entity = event.entity;
if (entity instanceof EntityItem)
{

View file

@ -1,6 +1,6 @@
--- ../src_base/common/net/minecraft/src/Entity.java
+++ ../src_work/common/net/minecraft/src/Entity.java
@@ -2,6 +2,8 @@
@@ -2,9 +2,12 @@
import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.asm.SideOnly;
@ -9,7 +9,11 @@
import java.util.Iterator;
import java.util.List;
import java.util.Random;
@@ -186,6 +188,10 @@
+import java.util.UUID;
public abstract class Entity
{
@@ -186,6 +189,11 @@
public boolean ignoreFrustumCheck;
public boolean isAirBorne;
public EnumEntitySize myEntitySize;
@ -17,13 +21,19 @@
+ private NBTTagCompound customEntityData;
+ public boolean captureDrops = false;
+ public ArrayList<EntityItem> capturedDrops = new ArrayList<EntityItem>();
+ private UUID persistentID;
public Entity(World par1World)
{
@@ -1382,6 +1388,10 @@
@@ -1382,6 +1390,15 @@
par1NBTTagCompound.setShort("Fire", (short)this.fire);
par1NBTTagCompound.setShort("Air", (short)this.getAir());
par1NBTTagCompound.setBoolean("OnGround", this.onGround);
+ if (persistentID != null)
+ {
+ par1NBTTagCompound.setLong("PersistentIDMSB", persistentID.getMostSignificantBits());
+ par1NBTTagCompound.setLong("PersistentIDLSB", persistentID.getLeastSignificantBits());
+ }
+ if (customEntityData != null)
+ {
+ par1NBTTagCompound.setCompoundTag("ForgeData", customEntityData);
@ -31,18 +41,22 @@
this.writeEntityToNBT(par1NBTTagCompound);
}
@@ -1423,6 +1433,10 @@
@@ -1423,6 +1440,14 @@
this.onGround = par1NBTTagCompound.getBoolean("OnGround");
this.setPosition(this.posX, this.posY, this.posZ);
this.setRotation(this.rotationYaw, this.rotationPitch);
+ if (par1NBTTagCompound.hasKey("ForgeData"))
+ {
+ customEntityData = par1NBTTagCompound.getCompoundTag("ForgeData");
+ }
+ if (par1NBTTagCompound.hasKey("PersistentIDMSB") && par1NBTTagCompound.hasKey("PersistentIDLSB"))
+ {
+ persistentID = new UUID(par1NBTTagCompound.getLong("PersistentIDMSB"), par1NBTTagCompound.getLong("PersistentIDLSB"));
+ }
this.readEntityFromNBT(par1NBTTagCompound);
}
@@ -1509,7 +1523,14 @@
@@ -1509,7 +1534,14 @@
{
EntityItem var3 = new EntityItem(this.worldObj, this.posX, this.posY + (double)par2, this.posZ, par1ItemStack);
var3.delayBeforeCanPickup = 10;
@ -58,7 +72,7 @@
return var3;
}
@@ -1843,7 +1864,7 @@
@@ -1843,7 +1875,7 @@
*/
public boolean isRiding()
{
@ -67,7 +81,7 @@
}
/**
@@ -2107,4 +2128,59 @@
@@ -2107,4 +2139,72 @@
{
return String.format("%s[\'%s\'/%d, l=\'%s\', x=%.2f, y=%.2f, z=%.2f]", new Object[] {this.getClass().getSimpleName(), this.getEntityName(), Integer.valueOf(this.entityId), this.worldObj == null ? "~NULL~" : this.worldObj.getWorldInfo().getWorldName(), Double.valueOf(this.posX), Double.valueOf(this.posY), Double.valueOf(this.posZ)});
}
@ -98,7 +112,7 @@
+
+ /**
+ * Called when a user uses the creative pick block button on this entity.
+ *
+ *
+ * @param target The full target the player is looking at
+ * @return A ItemStack to add to the player's inventory, Null if nothing should be added.
+ */
@ -125,5 +139,18 @@
+ }
+ }
+ return null;
+ }
+
+ public UUID getPersistentID()
+ {
+ return persistentID;
+ }
+
+ public synchronized void generatePersistentID()
+ {
+ if (persistentID == null)
+ {
+ persistentID = UUID.randomUUID();
+ }
+ }
}