I was going to submit a pull request, but my branch continually failed to download at around 70%.
Basically a fake world that can be used for pre built world scenerios, ai, and the likes of that
FakeWorld.class
package net.minecraftforge.common;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EnumCreatureType;
import net.minecraft.logging.ILogAgent;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.profiler.Profiler;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.util.IProgressUpdate;
import net.minecraft.village.VillageCollection;
import net.minecraft.world.ChunkPosition;
import net.minecraft.world.EnumGameType;
import net.minecraft.world.MinecraftException;
import net.minecraft.world.World;
import net.minecraft.world.WorldProvider;
import net.minecraft.world.WorldSettings;
import net.minecraft.world.WorldType;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.chunk.storage.IChunkLoader;
import net.minecraft.world.storage.IPlayerFileData;
import net.minecraft.world.storage.ISaveHandler;
import net.minecraft.world.storage.WorldInfo;
/**Built to synthesize a running world for usage in test AI, external rendering,
* and other scenarios which may occur before a loaded world is available, or where
* utilization of a running world is undesirable*/
public class FakeWorld extends World{
private int[][][] idArray;
private int[][][] metaArray;
private int factor = 3;
private boolean replace = false;
private final List<Entity> spawnOrder = new ArrayList(5);
private static final Profiler dummyProfiler = new Profiler();
private static final ILogAgent dummyLogger = new dudLog();
public FakeWorld(EnumGameType type) {
super(new dudSave(), "pseudo", new dudProvider(), new WorldSettings(0, type, false, false, WorldType.DEFAULT), dummyProfiler, dummyLogger);
this.setBlockArray(this.getDefaultIdArray());
this.chunkProvider = new dudCP(this);
this.villageCollectionObj = new VillageCollection(this);
this.provider.registerWorld(this);
this.chunkProvider = this.createChunkProvider();
this.calculateInitialSkylight();
this.provider.calculateInitialWeather();
}
private static final class dudProvider extends WorldProvider{
@Override
public String getDimensionName() {
return "pseudo";
}
}
private static final class dudSave implements ISaveHandler{
@Override
public WorldInfo loadWorldInfo() {return null;}
@Override
public void checkSessionLock() throws MinecraftException {}
@Override
public IChunkLoader getChunkLoader(WorldProvider worldprovider) {return null;}
@Override
public void saveWorldInfoWithPlayer(WorldInfo worldinfo, NBTTagCompound nbttagcompound) {}
@Override
public void saveWorldInfo(WorldInfo worldinfo) {}
@Override
public IPlayerFileData getSaveHandler(){return null;}
@Override
public void flush() {}
@Override
public File getMapFileFromName(String s) {return null;}
@Override
public String getWorldDirectoryName() {
return "";
}
}
private static final class dudLog implements ILogAgent{
@Override
public void logInfo(String s) {
}
@Override
@SideOnly(Side.SERVER)
public Logger getServerLogger() {
return FMLCommonHandler.instance().getFMLLogger();
}
@Override
public void logWarning(String s) {
}
@Override
public void logWarningFormatted(String s, Object... var2) {
}
@Override
public void logWarningException(String s, Throwable throwable) {
}
@Override
public void logSevere(String s) {
}
@Override
public void logSevereException(String s, Throwable throwable) {
}
@Override
@SideOnly(Side.CLIENT)
public void logFine(String s) {
}
}
private static final class dudCP implements IChunkProvider{
private final FakeWorld theWorld;
public dudCP(FakeWorld w){theWorld = w;}
@Override
public boolean chunkExists(int i, int j) {
return true;
}
@Override
public Chunk provideChunk(int i, int j) {
return new Chunk(theWorld,0,0);
}
@Override
public Chunk loadChunk(int i, int j) {
return new Chunk(theWorld, 0, 0);
}
@Override
public void populate(IChunkProvider ichunkprovider, int i, int j) {}
@Override
public boolean saveChunks(boolean flag, IProgressUpdate iprogressupdate) {
return false;
}
@Override
public boolean unloadQueuedChunks() {
return true;
}
@Override
public boolean canSave() {
return false;
}
@Override
public String makeString() {
return "fake world";
}
@Override
public List getPossibleCreatures(EnumCreatureType enumcreaturetype,
int i, int j, int k) {
return null;
}
@Override
public ChunkPosition findClosestStructure(World world, String s, int i,
int j, int k) {
return new ChunkPosition(0,0,0);
}
@Override
public int getLoadedChunkCount() {
return 1;
}
@Override
public void recreateStructures(int i, int j) {}
@Override
public void func_104112_b() {}
}
//Fake World specific usage features
/**returns the default array of a layer of air above a layer of grass
* above a layer of dirt*/
public int[] getDefaultIdArray(){
int[] r = new int[27];
for(int i = 0; i < r.length; i++)
if(i < 18)
r[i] = 0;
else if( i < 9)
r[i] = Block.grass.blockID;
else
r[i] = Block.dirt.blockID;
return r;
}
/**Builds layers (x & z) of the given int values. Can be used for block and meta array building*/
public int[] buildHorizontalLayers(int...i){
int[] builder = new int[(int) Math.pow(i.length, 3)];
int a = -1;
for(int y: i)
for(int z = 0; z < i.length; z++)
for(int x = 0; x < i.length; x++)
builder[a++] = i[y];
return builder;
}
/**sets whether or not external calls can replace the values in the meta and id arrays*/
public void setCanBlockValuesBeReplaced(boolean b){
replace = b;
}
/**Sets up a blockID array to return during World.getBlockId && World.getBlockMetadata via
* Integer arrays. Integer array must be a cubic (^3) factor. the getBlock methods then return
* a block/meta depending on relative position read in the array set up in Y,X,Z format. The
* The arrays are checked to make sure the lengths are equivalent, the meta ids are not greater
* than 15, the blocks are logical value, and the array is a round cubic factor
* @param ids The block ID array
* @param metas The block metadata array
* */
public void setBlockArrays(int[] ids, int[] metas){
try{
if(ids.length != metas.length)
throw new Throwable("Id and meta arrays must be equivalent in length");
for(int i = 0; i < ids.length; i++){
if(ids[i] < 0 || i >= Block.blocksList.length)
throw new Throwable("All Id values must be within range of 0 to " + Block.blocksList.length);
else if(metas[i] > 16 || i < 0)
throw new Throwable("All meta values must be within the range of 0 to 15");
}
double fact = Math.cbrt(ids.length);
int a = this.factor;
this.factor = (int)fact;
if(fact != this.factor)
if(fact != this.factor || this.factor == 0){
this.factor = a;
throw new Throwable("Block Return arrays must be a round, cubic this.factor");
}
int i = 0;
this.idArray = new int[this.factor][this.factor][this.factor];
this.metaArray = new int[this.factor][this.factor][this.factor];
for(int x = 0; x < this.factor; x++)
for(int z = 0; z < this.factor; z++)
for(int y = 0; y < this.factor; y++){
this.idArray[x]
[y]
[z]
= ids[i];
this.metaArray[x][y][z] = metas[i];
i++;
}
}catch(Throwable t){
t.printStackTrace();
}
}
/**Sets up a blockID array to return during World.getBlockId && World.getBlockMetadata
* @param ids blockId array. the meta array will be built as an array of the same length
* but with all metadata values at 0*/
public void setBlockArray(int[] ids){
int[] metas = new int[ids.length];
for(int i = 0; i < ids.length; i++)
metas[0] = 0;
this.setBlockArrays(ids, metas);
}
/**Empties the spawn order list*/
public void flushSpawnRetention(){
spawnOrder.clear();
}
/**Retrieves the entity spawn order list, empties it*/
public List<Entity> getSpawnOrder(){
List l = spawnOrder;
this.flushSpawnRetention();
return l;
}
/**Gets the latest spawned entity, Removes from spawn order, Be sure to catch null returns*/
public Entity getLastSpawned(){
Entity e = null;
if(!spawnOrder.isEmpty()){
e = spawnOrder.get(0);
spawnOrder.remove(0);
}
return e;
}
/*Begin pseudo world overrides*/
@Override
public void tickBlocksAndAmbiance(){
for(int x = 0; x < this.factor; x++)
for(int z = 0; z < this.factor; z++)
for(int y = 0; y < this.factor; y++)
Block.blocksList[this.idArray[y][x][z]].updateTick(this, x, y, z, this.rand);
}
@Override
public boolean setBlock(int x, int y, int z, int id){
if(replace)
this.idArray[y >= this.factor ? this.factor : y < 0 ? 0 : y][x % this.factor][z % this.factor] = id;
return replace;
}
@Override
public boolean setBlock(int x, int y, int z, int id, int meta, int flag){
if(replace){
this.idArray[y > this.factor ? this.factor : y < 0 ? 0 : y][x % this.factor][z % this.factor] = id;
this.metaArray[y > this.factor ? this.factor : y < 0 ? 0 : y][x % this.factor][z % this.factor] = meta;
}
return replace;
}
@Override
public boolean setBlockMetadataWithNotify(int x, int y, int z, int meta, int flag){
if(replace)
this.metaArray[y > this.factor ? this.factor : y < 0 ? 0 : y][x % this.factor][z % this.factor] = meta;
return replace;
}
@Override
public void tick(){
this.tickBlocksAndAmbiance();
this.tickUpdates(true);
this.updateWeather();
this.updateEntities();
}
@Override
public boolean setBlockToAir(int x, int y, int z){
if(replace)
this.idArray[y > this.factor ? this.factor : y < 0 ? 0 : y][x % this.factor][z % this.factor] = 0;
return replace;
}
@Override
public boolean blockExists(int x, int y, int z){
return getBlockId(x,y,z) != 0;
}
@Override
public int getBlockId(int x, int y, int z){
return this.idArray[y > this.factor ? this.factor : y < 0 ? 0 : y][x % this.factor][z % this.factor];
}
@Override
public int getBlockMetadata(int x, int y, int z){
return this.idArray[y > this.factor ? this.factor : y < 0 ? 0 : y][x % this.factor][z % this.factor];
}
@Override
protected IChunkProvider createChunkProvider() {
return new dudCP(this);
}
@Override
public Entity getEntityByID(int i) {
for(Entity e : (List<Entity>)this.loadedEntityList)
if(e.entityId == i)
return e;
return null;
}
@Override
public boolean spawnEntityInWorld(Entity e){
this.spawnOrder.add(e);
return super.spawnEntityInWorld(e);
}
@Override
public ChunkCoordinates getSpawnPoint(){
return new ChunkCoordinates(0,0,0);
}
}
FakeWorldFactory.class
package net.minecraftforge.common;
import net.minecraft.world.EnumGameType;
/**Holds a constant fake world*/
public final class FakeWorldFactory {
private static final FakeWorld instance = new FakeWorld(EnumGameType.SURVIVAL);
private static final FakePlayer psuedo = new FakePlayer(instance, "Psuedo");
/**NOTE: Treat this world as a volatile platform. You should always update the Block array
* as a precaution for array edits done by other mods
* @return the constant {@link FakeWorld} value*/
public static FakeWorld getDefault(){
return instance;
}
/**This gives access to a world safe player instance. Safe for various edits and such
* @return returns a constant {@link FakePlayer} which has a worldObj set to the constant FakeWorld*/
public static FakePlayer getPseudoPlayer(){
return psuedo;
}
}