Simple chunkloading implementation

This commit is contained in:
Christian 2012-09-09 23:47:07 -04:00
parent a9e3a4dbb9
commit d21e3ae218
6 changed files with 199 additions and 1 deletions

View file

@ -1,8 +1,13 @@
package net.minecraftforge.common;
import java.util.*;
import java.util.Map.Entry;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Loader;
import net.minecraft.src.*;
import net.minecraftforge.event.entity.item.ItemTossEvent;
@ -354,4 +359,55 @@ public class ForgeHooks
player.joinEntityItemWithWorld(event.entityItem);
return event.entityItem;
}
public static void dumpPersistentChunks(WorldInfo worldInfo, ListMultimap<ChunkCoordIntPair, String> persistentChunks)
{
worldInfo.forgeWorldData = new NBTTagCompound();
NBTTagList chunkDataList = new NBTTagList();
for (Entry<ChunkCoordIntPair, Collection<String>> entry : persistentChunks.asMap().entrySet())
{
NBTTagCompound dataList = new NBTTagCompound();
dataList.setIntArray("Chunk", new int[] { entry.getKey().chunkXPos, entry.getKey().chunkZPos });
NBTTagList modList = new NBTTagList();
for (String modId : entry.getValue())
{
modList.appendTag(new NBTTagString(modId, ""));
}
dataList.setTag("Mods", modList);
chunkDataList.appendTag(dataList);
}
worldInfo.forgeWorldData.setTag("PersistentChunks", chunkDataList);
}
public static ListMultimap<ChunkCoordIntPair, String> loadPersistentChunkData(WorldInfo worldInfo)
{
ArrayListMultimap<ChunkCoordIntPair, String> chunkList = ArrayListMultimap.<ChunkCoordIntPair, String>create();
if (worldInfo == null || worldInfo.forgeWorldData == null)
{
return chunkList;
}
NBTTagList chunkDataList = worldInfo.forgeWorldData.getTagList("PersistentChunks");
for (int i = 0; i < chunkDataList.tagCount(); i++)
{
NBTTagCompound dataList = (NBTTagCompound) chunkDataList.tagAt(i);
int[] ccpairint = dataList.getIntArray("Chunk");
ChunkCoordIntPair ccpair = new ChunkCoordIntPair(ccpairint[0], ccpairint[1]);
NBTTagList modList = dataList.getTagList("Mods");
for (int j = 0; j < modList.tagCount(); j++)
{
String modId = modList.tagAt(j).getName();
if (Loader.isModLoaded(modId))
{
chunkList.put(ccpair, modId);
}
else
{
FMLLog.warning("The mod %s is not present - it's chunks will not be persisted any longer", modId);
}
}
}
return chunkList;
}
}

View file

@ -3,7 +3,10 @@ package net.minecraftforge.common;
import java.lang.reflect.Constructor;
import java.util.*;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.ModContainer;
import net.minecraft.src.*;
import net.minecraftforge.common.ForgeHooks.GrassEntry;
@ -199,4 +202,42 @@ public class MinecraftForge
{
return "Minecraft Forge "+ ForgeVersion.getVersion();
}
/**
* Force a chunk to remain loaded by the supplied mod
*
* @param chunk the chunk to keep loaded
* @param world the world holding the chunk
* @param mod the mod (either {@link Mod} or {@link BaseMod}) that wishes to force the load
*/
public static void forceChunkLoaded(ChunkCoordIntPair chunk, World world, Object mod)
{
ModContainer mc = FMLCommonHandler.instance().findContainerFor(mod);
if (mc == null)
{
FMLLog.warning("Attempt to force chunk load for a non-existent mod %s", mod.getClass().getName());
return;
}
String modId = mc.getModId();
world.getPersistentChunks().put(chunk, modId);
}
/**
* Stop forcing the chunk to remain loaded by the supplied mod (other mods may still
* keep the chunk loaded, however)
* @param chunk the chunk to keep loaded
* @param world the world holding the chunk
* @param mod the mod (either {@link Mod} or {@link BaseMod}) that wishes to unforce the load
*/
public static void unforceChunkLoaded(ChunkCoordIntPair chunk, World world, Object mod)
{
ModContainer mc = FMLCommonHandler.instance().findContainerFor(mod);
if (mc == null)
{
FMLLog.warning("Attempt to unforce chunk load for a non-existent mod %s", mod.getClass().getName());
return;
}
String modId = mc.getModId();
world.getPersistentChunks().remove(chunk, modId);
}
}

View file

@ -0,0 +1,14 @@
--- ../src_base/common/net/minecraft/src/ChunkProviderServer.java
+++ ../src_work/common/net/minecraft/src/ChunkProviderServer.java
@@ -274,6 +274,11 @@
{
if (!this.currentServer.canNotSave)
{
+ for (ChunkCoordIntPair forced : currentServer.persistentChunks.keySet())
+ {
+ this.chunksToUnload.remove(ChunkCoordIntPair.chunkXZ2Int(forced.chunkXPos, forced.chunkZPos));
+ }
+
for (int var1 = 0; var1 < 100; ++var1)
{
if (!this.chunksToUnload.isEmpty())

View file

@ -4,6 +4,10 @@
import java.util.Random;
import java.util.Set;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ListMultimap;
+
+import net.minecraftforge.common.ForgeHooks;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.common.ForgeDirection;
+import net.minecraftforge.event.entity.EntityEvent;
@ -23,6 +27,12 @@
/**
* boolean; if true updates scheduled by scheduleBlockUpdate happen immediately
*/
@@ -128,6 +145,7 @@
*/
public boolean isRemote;
+ protected ListMultimap<ChunkCoordIntPair, String> persistentChunks;
/**
@@ -132,6 +146,11 @@
* Gets the biome for a given set of x/z coordinates
*/
@ -47,6 +57,9 @@
this.calculateInitialSkylight();
this.calculateInitialWeather();
+
+ persistentChunks = ForgeHooks.loadPersistentChunkData(this.worldInfo);
+
+ MinecraftForge.EVENT_BUS.post(new WorldEvent.Load(this));
}
@ -226,9 +239,11 @@
@@ -1974,8 +2030,14 @@
int var3 = MathHelper.floor_double(par1Entity.posX);
int var4 = MathHelper.floor_double(par1Entity.posZ);
byte var5 = 32;
- byte var5 = 32;
-
- if (!par2 || this.checkChunksExist(var3 - var5, 0, var4 - var5, var3 + var5, 0, var4 + var5))
+ boolean isForced = persistentChunks.containsKey(new ChunkCoordIntPair(var3 >> 4, var4 >> 4));
+ byte var5 = isForced ? (byte)0 : 32;
+ boolean canUpdate = !par2 || this.checkChunksExist(var3 - var5, 0, var4 - var5, var3 + var5, 0, var4 + var5);
+ if (!canUpdate)
+ {
@ -658,5 +673,10 @@
+ }
+
+ return block.isBlockSolidOnSide(this, X, Y, Z, side);
+ }
+
+ public ListMultimap<ChunkCoordIntPair, String> getPersistentChunks()
+ {
+ return persistentChunks;
+ }
}

View file

@ -0,0 +1,38 @@
--- ../src_base/common/net/minecraft/src/WorldInfo.java
+++ ../src_work/common/net/minecraft/src/WorldInfo.java
@@ -1,5 +1,6 @@
package net.minecraft.src;
+import net.minecraftforge.common.ForgeHooks;
import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.asm.SideOnly;
@@ -59,6 +60,8 @@
private boolean hardcore;
private boolean allowCommands;
private boolean initialized;
+
+ public NBTTagCompound forgeWorldData;
protected WorldInfo()
{
@@ -139,6 +142,10 @@
{
this.playerTag = par1NBTTagCompound.getCompoundTag("Player");
this.dimension = this.playerTag.getInteger("Dimension");
+ }
+ if (par1NBTTagCompound.hasKey("ForgeData"))
+ {
+ this.forgeWorldData = par1NBTTagCompound.getCompoundTag("ForgeData");
}
}
@@ -228,6 +235,8 @@
{
par1NBTTagCompound.setCompoundTag("Player", par2NBTTagCompound);
}
+
+ par1NBTTagCompound.setCompoundTag("ForgeData", forgeWorldData);
}
/**

View file

@ -50,6 +50,26 @@
{
this.updateLCG = this.updateLCG * 3 + 1013904223;
var8 = this.updateLCG >> 2;
@@ -362,7 +367,8 @@
public void scheduleBlockUpdate(int par1, int par2, int par3, int par4, int par5)
{
NextTickListEntry var6 = new NextTickListEntry(par1, par2, par3, par4);
- byte var7 = 8;
+ boolean isForced = persistentChunks.containsKey(new ChunkCoordIntPair(var6.xCoord >> 4, var6.zCoord >> 4));
+ byte var7 = isForced ? (byte)0 : 8;
if (this.scheduledUpdatesAreImmediate)
{
@@ -462,7 +468,8 @@
this.pendingTickListEntries.remove(var4);
this.field_73064_N.remove(var4);
- byte var5 = 8;
+ boolean isForced = persistentChunks.containsKey(new ChunkCoordIntPair(var4.xCoord >> 4, var4.zCoord >> 4));
+ byte var5 = isForced ? (byte)0 : 8;
if (this.checkChunksExist(var4.xCoord - var5, var4.yCoord - var5, var4.zCoord - var5, var4.xCoord + var5, var4.yCoord + var5, var4.zCoord + var5))
{
@@ -559,15 +562,27 @@
public List getAllTileEntityInBox(int par1, int par2, int par3, int par4, int par5, int par6)
{
@ -117,6 +137,15 @@
for (int var2 = 0; var2 < 10; ++var2)
{
@@ -702,6 +721,8 @@
par2IProgressUpdate.displayProgressMessage("Saving level");
}
+ ForgeHooks.dumpPersistentChunks(worldInfo, persistentChunks);
+
this.saveLevel();
if (par2IProgressUpdate != null)
@@ -713,6 +733,7 @@
}