Merge pull request #57 from psxlover/PathMarkersOptimization
Path markers optimization
This commit is contained in:
commit
e1d4cf14a8
6 changed files with 112 additions and 151 deletions
|
@ -40,6 +40,7 @@ import net.minecraft.src.buildcraft.builders.BlockFiller;
|
|||
import net.minecraft.src.buildcraft.builders.BlockMarker;
|
||||
import net.minecraft.src.buildcraft.builders.BlockPathMarker;
|
||||
import net.minecraft.src.buildcraft.builders.BptBlockFiller;
|
||||
import net.minecraft.src.buildcraft.builders.BuildersSaveManager;
|
||||
import net.minecraft.src.buildcraft.builders.FillerFillAll;
|
||||
import net.minecraft.src.buildcraft.builders.FillerFillPyramid;
|
||||
import net.minecraft.src.buildcraft.builders.FillerFillStairs;
|
||||
|
@ -61,7 +62,6 @@ import net.minecraft.src.buildcraft.core.BptPlayerIndex;
|
|||
import net.minecraft.src.buildcraft.core.BptRootIndex;
|
||||
import net.minecraft.src.buildcraft.core.CoreProxy;
|
||||
import net.minecraft.src.buildcraft.core.DefaultProps;
|
||||
import net.minecraft.src.buildcraft.core.WorldIteratorRadius;
|
||||
import net.minecraft.src.forge.Configuration;
|
||||
import net.minecraft.src.forge.MinecraftForge;
|
||||
import net.minecraft.src.forge.Property;
|
||||
|
@ -96,6 +96,9 @@ public class BuildCraftBuilders {
|
|||
|
||||
// Register gui handler
|
||||
MinecraftForge.setGuiHandler(mod_BuildCraftBuilders.instance, new GuiHandler());
|
||||
|
||||
// Register save handler
|
||||
MinecraftForge.registerSaveHandler(new BuildersSaveManager());
|
||||
}
|
||||
|
||||
public static void initialize() {
|
||||
|
@ -277,9 +280,6 @@ public class BuildCraftBuilders {
|
|||
new BptBlockWallSide(pathMarkerBlock.blockID);
|
||||
new BptBlockFiller(fillerBlock.blockID);
|
||||
|
||||
// Optimization
|
||||
WorldIteratorRadius.createPrecomputedList(TilePathMarker.searchSize);
|
||||
|
||||
if (BuildCraftCore.loadDefaultRecipes)
|
||||
loadRecipes();
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ public class BlockPathMarker extends BlockMarker {
|
|||
public int getBlockTexture(IBlockAccess iblockaccess, int i, int j, int k, int l) {
|
||||
TilePathMarker marker = (TilePathMarker) iblockaccess.getBlockTileEntity(i, j, k);
|
||||
|
||||
if (l == 1 || (marker != null && marker.currentWorldIterator != null)) {
|
||||
if (l == 1 || (marker != null && marker.tryingToConnect)) {
|
||||
return 3 * 16 + 11;
|
||||
} else {
|
||||
return 3 * 16 + 10;
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* Copyright (c) SpaceToad, 2011 http://www.mod-buildcraft.com
|
||||
*
|
||||
* BuildCraft is distributed under the terms of the Minecraft Mod Public License
|
||||
* 1.0, or MMPL. Please check the contents of the license located in
|
||||
* http://www.mod-buildcraft.com/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.minecraft.src.buildcraft.builders;
|
||||
|
||||
import net.minecraft.src.Chunk;
|
||||
import net.minecraft.src.NBTTagCompound;
|
||||
import net.minecraft.src.World;
|
||||
import net.minecraft.src.forge.ISaveEventHandler;
|
||||
|
||||
public class BuildersSaveManager implements ISaveEventHandler {
|
||||
|
||||
@Override
|
||||
public void onWorldLoad(World world) {
|
||||
//When a world loads clean the list of available markers
|
||||
TilePathMarker.clearAvailableMarkersList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWorldSave(World world) {}
|
||||
|
||||
@Override
|
||||
public void onChunkLoad(World world, Chunk chunk) {}
|
||||
|
||||
@Override
|
||||
public void onChunkUnload(World world, Chunk chunk) {}
|
||||
|
||||
@Override
|
||||
public void onChunkSaveData(World world, Chunk chunk, NBTTagCompound data) {}
|
||||
|
||||
@Override
|
||||
public void onChunkLoadData(World world, Chunk chunk, NBTTagCompound data) {}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
package net.minecraft.src.buildcraft.builders;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
@ -10,8 +11,6 @@ import net.minecraft.src.buildcraft.api.Position;
|
|||
import net.minecraft.src.buildcraft.core.BlockIndex;
|
||||
import net.minecraft.src.buildcraft.core.DefaultProps;
|
||||
import net.minecraft.src.buildcraft.core.EntityLaser;
|
||||
import net.minecraft.src.buildcraft.core.WorldIterator;
|
||||
import net.minecraft.src.buildcraft.core.WorldIteratorRadius;
|
||||
|
||||
public class TilePathMarker extends TileMarker {
|
||||
|
||||
|
@ -19,10 +18,18 @@ public class TilePathMarker extends TileMarker {
|
|||
|
||||
public int x0, y0, z0, x1, y1, z1;
|
||||
public boolean loadLink0 = false, loadLink1 = false;
|
||||
public boolean tryingToConnect = false;
|
||||
|
||||
public TilePathMarker links[] = new TilePathMarker[2];
|
||||
public static int searchSize = 64; //TODO: this should be moved to default props
|
||||
|
||||
//A list with the pathMarkers that aren't fully connected
|
||||
//It only contains markers within the loaded chunks
|
||||
private static LinkedList<TilePathMarker> availableMarkers = new LinkedList<TilePathMarker>();
|
||||
|
||||
public static int searchSize = 64;
|
||||
public TilePathMarker() {
|
||||
availableMarkers.add(this);
|
||||
}
|
||||
|
||||
public boolean isFullyConnected() {
|
||||
return lasers[0] != null && lasers[1] != null;
|
||||
|
@ -40,18 +47,19 @@ public class TilePathMarker extends TileMarker {
|
|||
lasers[1] = laser;
|
||||
links[1] = marker;
|
||||
}
|
||||
|
||||
if (isFullyConnected())
|
||||
availableMarkers.remove(this);
|
||||
}
|
||||
|
||||
public void createLaserAndConnect (TilePathMarker pathMarker) {
|
||||
|
||||
|
||||
public void createLaserAndConnect(TilePathMarker pathMarker) {
|
||||
|
||||
if (APIProxy.isClient(worldObj))
|
||||
return;
|
||||
|
||||
EntityLaser laser = new EntityLaser(worldObj,
|
||||
new Position(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5),
|
||||
new Position(pathMarker.xCoord + 0.5, pathMarker.yCoord + 0.5, pathMarker.zCoord + 0.5));
|
||||
|
||||
EntityLaser laser = new EntityLaser(worldObj, new Position(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5), new Position(pathMarker.xCoord + 0.5, pathMarker.yCoord + 0.5, pathMarker.zCoord + 0.5));
|
||||
laser.show();
|
||||
|
||||
|
||||
laser.setTexture(DefaultProps.TEXTURE_PATH_ENTITIES + "/laser_1.png");
|
||||
worldObj.spawnEntityInWorld(laser);
|
||||
|
||||
|
@ -59,7 +67,28 @@ public class TilePathMarker extends TileMarker {
|
|||
pathMarker.connect(this, laser);
|
||||
}
|
||||
|
||||
WorldIterator currentWorldIterator;
|
||||
//Searches the availableMarkers list for the nearest available that is within searchSize
|
||||
private TilePathMarker findNearestAvailablePathMarker() {
|
||||
TilePathMarker nearestAvailable = null;
|
||||
double nearestDistance = 0, distance; //The initialization of nearestDistance is only to make the compiler shut up
|
||||
|
||||
for (TilePathMarker t : availableMarkers) {
|
||||
if (t == this || t == this.links[0] || t == this.links[1])
|
||||
continue;
|
||||
|
||||
distance = Math.sqrt(Math.pow(this.xCoord - t.xCoord, 2) + Math.pow(this.yCoord - t.yCoord, 2) + Math.pow(this.zCoord - t.zCoord, 2));
|
||||
|
||||
if (distance > searchSize)
|
||||
continue;
|
||||
|
||||
if (nearestAvailable == null || distance < nearestDistance) {
|
||||
nearestAvailable = t;
|
||||
nearestDistance = distance;
|
||||
}
|
||||
}
|
||||
|
||||
return nearestAvailable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tryConnection() {
|
||||
|
@ -67,50 +96,21 @@ public class TilePathMarker extends TileMarker {
|
|||
return;
|
||||
}
|
||||
|
||||
if (currentWorldIterator == null) {
|
||||
currentWorldIterator = new WorldIteratorRadius(worldObj, xCoord, yCoord, zCoord, searchSize);
|
||||
worldObj.markBlockNeedsUpdate(xCoord, yCoord, zCoord);
|
||||
}
|
||||
tryingToConnect = !tryingToConnect; //Allow the user to stop the path marker from searching for new path markers to connect
|
||||
worldObj.markBlockNeedsUpdate(xCoord, yCoord, zCoord);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateEntity() {
|
||||
super.updateEntity();
|
||||
|
||||
if (currentWorldIterator != null) {
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
BlockIndex b = currentWorldIterator.iterate();
|
||||
if (tryingToConnect) {
|
||||
TilePathMarker nearestPathMarker = findNearestAvailablePathMarker();
|
||||
|
||||
if (b == null) {
|
||||
currentWorldIterator = null;
|
||||
worldObj.markBlockNeedsUpdate(xCoord, yCoord, zCoord);
|
||||
break;
|
||||
}
|
||||
|
||||
if (b.i == xCoord && b.j == yCoord && b.k == zCoord) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TileEntity tile = null;
|
||||
|
||||
try {
|
||||
tile = worldObj.getBlockTileEntity(b.i, b.j, b.k);
|
||||
} catch (Throwable t) {
|
||||
// sometimes, tile can't be loaded. Just carry on the
|
||||
// analysis. We don't even need to log these
|
||||
}
|
||||
|
||||
if (tile instanceof TilePathMarker) {
|
||||
TilePathMarker pathMarker = (TilePathMarker) tile;
|
||||
|
||||
if (!pathMarker.isFullyConnected() && !isLinkedTo(pathMarker)) {
|
||||
createLaserAndConnect(pathMarker);
|
||||
|
||||
worldObj.markBlockNeedsUpdate(xCoord, yCoord, zCoord);
|
||||
currentWorldIterator = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (nearestPathMarker != null) {
|
||||
createLaserAndConnect(nearestPathMarker);
|
||||
tryingToConnect = false;
|
||||
worldObj.markBlockNeedsUpdate(xCoord, yCoord, zCoord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -127,13 +127,9 @@ public class TilePathMarker extends TileMarker {
|
|||
visitedPaths.add(b);
|
||||
res.add(b);
|
||||
|
||||
if (nextTile.links[0] != null
|
||||
&& !visitedPaths.contains(new BlockIndex(nextTile.links[0].xCoord, nextTile.links[0].yCoord,
|
||||
nextTile.links[0].zCoord))) {
|
||||
if (nextTile.links[0] != null && !visitedPaths.contains(new BlockIndex(nextTile.links[0].xCoord, nextTile.links[0].yCoord, nextTile.links[0].zCoord))) {
|
||||
nextTile = nextTile.links[0];
|
||||
} else if (nextTile.links[1] != null
|
||||
&& !visitedPaths.contains(new BlockIndex(nextTile.links[1].xCoord, nextTile.links[1].yCoord,
|
||||
nextTile.links[1].zCoord))) {
|
||||
} else if (nextTile.links[1] != null && !visitedPaths.contains(new BlockIndex(nextTile.links[1].xCoord, nextTile.links[1].yCoord, nextTile.links[1].zCoord))) {
|
||||
nextTile = nextTile.links[1];
|
||||
} else {
|
||||
nextTile = null;
|
||||
|
@ -160,6 +156,9 @@ public class TilePathMarker extends TileMarker {
|
|||
|
||||
lasers = new EntityLaser[2];
|
||||
links = new TilePathMarker[2];
|
||||
|
||||
availableMarkers.remove(this);
|
||||
tryingToConnect = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -197,6 +196,9 @@ public class TilePathMarker extends TileMarker {
|
|||
lasers[1] = null;
|
||||
links[1] = null;
|
||||
}
|
||||
|
||||
if (!isFullyConnected() && !availableMarkers.contains(this))
|
||||
availableMarkers.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -231,9 +233,18 @@ public class TilePathMarker extends TileMarker {
|
|||
}
|
||||
|
||||
if (links[1] != null) {
|
||||
nbttagcompound.setInteger("x0", links[1].xCoord);
|
||||
nbttagcompound.setInteger("y0", links[1].yCoord);
|
||||
nbttagcompound.setInteger("z0", links[1].zCoord);
|
||||
nbttagcompound.setInteger("x1", links[1].xCoord);
|
||||
nbttagcompound.setInteger("y1", links[1].yCoord);
|
||||
nbttagcompound.setInteger("z1", links[1].zCoord);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkUnload() {
|
||||
availableMarkers.remove(this);
|
||||
}
|
||||
|
||||
public static void clearAvailableMarkersList() {
|
||||
availableMarkers.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
package net.minecraft.src.buildcraft.core;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import net.minecraft.src.World;
|
||||
|
||||
public abstract class WorldIterator {
|
||||
|
||||
protected World world;
|
||||
protected int x;
|
||||
protected int y;
|
||||
protected int z;
|
||||
|
||||
protected Iterator<BlockIndex> iterator;
|
||||
|
||||
public WorldIterator(World world, int x, int y, int z) {
|
||||
this.world = world;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public BlockIndex iterate() {
|
||||
if (iterator.hasNext())
|
||||
return iterator.next();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
package net.minecraft.src.buildcraft.core;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import net.minecraft.src.World;
|
||||
|
||||
public class WorldIteratorRadius extends WorldIterator {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static LinkedList<BlockIndex>[] lists = new LinkedList[65];
|
||||
|
||||
public WorldIteratorRadius(World world, int px, int py, int pz, int radius) {
|
||||
super(world, px, py, pz);
|
||||
|
||||
createPrecomputedList(radius);
|
||||
|
||||
iterator = lists[radius].iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockIndex iterate() {
|
||||
if (iterator.hasNext()) {
|
||||
BlockIndex b = iterator.next();
|
||||
|
||||
return new BlockIndex(b.i + x, b.j + y, b.k + z);
|
||||
} else
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void createPrecomputedList(int radius) {
|
||||
if (lists[radius] == null) {
|
||||
lists[radius] = new LinkedList<BlockIndex>();
|
||||
|
||||
for (int i = -radius; i <= radius; ++i)
|
||||
for (int j = -radius; j <= radius; ++j)
|
||||
for (int k = -radius; k <= radius; ++k)
|
||||
lists[radius].add(new BlockIndex(i, j, k));
|
||||
|
||||
Collections.sort(lists[radius], new Comparator<BlockIndex>() {
|
||||
|
||||
@Override
|
||||
public int compare(BlockIndex o1, BlockIndex o2) {
|
||||
double d1 = o1.i * o1.i + o1.j * o1.j + o1.k * o1.k;
|
||||
double d2 = o2.i * o2.i + o2.j * o2.j + o2.k * o2.k;
|
||||
|
||||
if (d1 < d2)
|
||||
return -1;
|
||||
else if (d1 > d2)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue