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:
parent
c684360f51
commit
9640c5dcf9
3 changed files with 99 additions and 56 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue