I might gone overboard with how deep I went this time.
This commit is contained in:
parent
1b87445f8a
commit
09eb9ab48d
37 changed files with 859 additions and 1541 deletions
|
@ -175,11 +175,11 @@ public class BlockRift extends Block implements ITileEntityProvider {
|
|||
private void destroyNearbyBlocks(World world, int x, int y, int z, Random random)
|
||||
{
|
||||
// Find reachable blocks that are vulnerable to rift damage (ignoring air, of course)
|
||||
ArrayList<Point3D> targets = findReachableBlocks(world, x, y, z, BLOCK_DESTRUCTION_RANGE, false);
|
||||
ArrayList<BlockPos> targets = findReachableBlocks(world, x, y, z, BLOCK_DESTRUCTION_RANGE, false);
|
||||
|
||||
// For each block, randomly decide whether to destroy it.
|
||||
// The randomness makes it so the destroyed area appears "noisy" if the rift is exposed to a large surface.
|
||||
for (Point3D target : targets)
|
||||
for (BlockPos target : targets)
|
||||
{
|
||||
if (random.nextInt(MAX_BLOCK_DESTRUCTION_CHANCE) < BLOCK_DESTRUCTION_CHANCE)
|
||||
{
|
||||
|
@ -189,20 +189,20 @@ public class BlockRift extends Block implements ITileEntityProvider {
|
|||
}
|
||||
}
|
||||
|
||||
private ArrayList<Point3D> findReachableBlocks(World world, int x, int y, int z, int range, boolean includeAir)
|
||||
private ArrayList<BlockPos> findReachableBlocks(World world, int x, int y, int z, int range, boolean includeAir)
|
||||
{
|
||||
int searchVolume = (int) Math.pow(2 * range + 1, 3);
|
||||
HashMap<Point3D, Integer> pointDistances = new HashMap<Point3D, Integer>(searchVolume);
|
||||
Queue<Point3D> points = new LinkedList<Point3D>();
|
||||
ArrayList<Point3D> targets = new ArrayList<Point3D>();
|
||||
HashMap<BlockPos, Integer> pointDistances = new HashMap<BlockPos, Integer>(searchVolume);
|
||||
Queue<BlockPos> points = new LinkedList<BlockPos>();
|
||||
ArrayList<BlockPos> targets = new ArrayList<BlockPos>();
|
||||
|
||||
// Perform a breadth-first search outwards from the point at which the rift is located.
|
||||
// Record the distances of the points we visit to stop the search at its maximum range.
|
||||
pointDistances.put(new Point3D(x, y, z), 0);
|
||||
pointDistances.put(new BlockPos(x, y, z), 0);
|
||||
addAdjacentBlocks(x, y, z, 0, pointDistances, points);
|
||||
while (!points.isEmpty())
|
||||
{
|
||||
Point3D current = points.remove();
|
||||
BlockPos current = points.remove();
|
||||
int distance = pointDistances.get(current);
|
||||
|
||||
// If the current block is air, continue searching. Otherwise, add the block to our list.
|
||||
|
@ -241,15 +241,15 @@ public class BlockRift extends Block implements ITileEntityProvider {
|
|||
}
|
||||
}
|
||||
|
||||
private static void addAdjacentBlocks(int x, int y, int z, int distance, HashMap<Point3D, Integer> pointDistances, Queue<Point3D> points)
|
||||
private static void addAdjacentBlocks(int x, int y, int z, int distance, HashMap<BlockPos, Integer> pointDistances, Queue<BlockPos> points)
|
||||
{
|
||||
Point3D[] neighbors = new Point3D[] {
|
||||
new Point3D(x - 1, y, z),
|
||||
new Point3D(x + 1, y, z),
|
||||
new Point3D(x, y - 1, z),
|
||||
new Point3D(x, y + 1, z),
|
||||
new Point3D(x, y, z - 1),
|
||||
new Point3D(x, y, z + 1)
|
||||
BlockPos[] neighbors = new BlockPos[] {
|
||||
new BlockPos(x - 1, y, z),
|
||||
new BlockPos(x + 1, y, z),
|
||||
new BlockPos(x, y - 1, z),
|
||||
new BlockPos(x, y + 1, z),
|
||||
new BlockPos(x, y, z - 1),
|
||||
new BlockPos(x, y, z + 1)
|
||||
};
|
||||
for (int index = 0; index < neighbors.length; index++)
|
||||
{
|
||||
|
@ -268,13 +268,13 @@ public class BlockRift extends Block implements ITileEntityProvider {
|
|||
Point4D source = parent.source();
|
||||
|
||||
// Find reachable blocks that are vulnerable to rift damage and include air
|
||||
ArrayList<Point3D> targets = findReachableBlocks(world, source.getX(), source.getY(), source.getZ(),
|
||||
ArrayList<BlockPos> targets = findReachableBlocks(world, source.getX(), source.getY(), source.getZ(),
|
||||
RIFT_SPREAD_RANGE, true);
|
||||
|
||||
if (!targets.isEmpty())
|
||||
{
|
||||
// Choose randomly from among the possible locations where we can spawn a new rift
|
||||
Point3D target = targets.get( random.nextInt(targets.size()) );
|
||||
BlockPos target = targets.get( random.nextInt(targets.size()) );
|
||||
x = target.getX();
|
||||
y = target.getY();
|
||||
z = target.getZ();
|
||||
|
@ -310,7 +310,7 @@ public class BlockRift extends Block implements ITileEntityProvider {
|
|||
{
|
||||
|
||||
|
||||
ArrayList<Point3D> targets=findReachableBlocks(world, x, y, z, 2, false);
|
||||
ArrayList<BlockPos> targets=findReachableBlocks(world, x, y, z, 2, false);
|
||||
|
||||
|
||||
TileEntityRift tile = (TileEntityRift)world.getTileEntity(x, y, z);
|
||||
|
|
|
@ -4,8 +4,10 @@ import com.zixiken.dimdoors.core.DimLink;
|
|||
import com.zixiken.dimdoors.core.LinkType;
|
||||
import com.zixiken.dimdoors.core.PocketManager;
|
||||
import com.zixiken.dimdoors.DimDoors;
|
||||
import net.minecraft.block.BlockDoor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import com.zixiken.dimdoors.core.NewDimData;
|
||||
|
||||
|
@ -19,15 +21,12 @@ public class WarpDoor extends BaseDimDoor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void placeLink(World world, int x, int y, int z)
|
||||
{
|
||||
if (!world.isRemote && world.getBlock(x, y - 1, z) == this)
|
||||
{
|
||||
public void placeLink(World world, BlockPos pos) {
|
||||
if (!world.isRemote && world.getBlockState(pos.down()) == this) {
|
||||
NewDimData dimension = PocketManager.createDimensionData(world);
|
||||
DimLink link = dimension.getLink(x, y, z);
|
||||
if (link == null && dimension.isPocketDimension())
|
||||
{
|
||||
dimension.createLink(x, y, z, LinkType.SAFE_EXIT,world.getBlockMetadata(x, y - 1, z));
|
||||
DimLink link = dimension.getLink(pos);
|
||||
if (link == null && dimension.isPocketDimension()) {
|
||||
dimension.createLink(pos, LinkType.SAFE_EXIT,world. getBlockState(pos.down()).getValue(BlockDoor.FACING));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,16 +42,12 @@ public class DDLock
|
|||
|
||||
/**
|
||||
* see if we could unlock this door if it where locked.
|
||||
* @param link
|
||||
* @param itemStack
|
||||
* @return
|
||||
*/
|
||||
public boolean doesKeyUnlock(ItemStack itemStack)
|
||||
{
|
||||
for(int key :getKeys(itemStack))
|
||||
{
|
||||
if(this.lockKey == key)
|
||||
{
|
||||
public boolean doesKeyUnlock(ItemStack itemStack) {
|
||||
for(int key :getKeys(itemStack)) {
|
||||
if(this.lockKey == key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -60,11 +56,10 @@ public class DDLock
|
|||
|
||||
/**
|
||||
* Tries to open this lock
|
||||
* @param item
|
||||
* @param itemStack
|
||||
* @return
|
||||
*/
|
||||
public boolean tryToOpen(ItemStack itemStack)
|
||||
{
|
||||
public boolean tryToOpen(ItemStack itemStack) {
|
||||
return (!this.lockState)||this.doesKeyUnlock(itemStack);
|
||||
}
|
||||
|
||||
|
@ -78,10 +73,8 @@ public class DDLock
|
|||
* gets all the keys stored on a single key item
|
||||
* @return
|
||||
*/
|
||||
public static int[] getKeys(ItemStack itemStack)
|
||||
{
|
||||
if (!itemStack.hasTagCompound())
|
||||
{
|
||||
public static int[] getKeys(ItemStack itemStack) {
|
||||
if (!itemStack.hasTagCompound()) {
|
||||
initNBTTags(itemStack);
|
||||
}
|
||||
return itemStack.getTagCompound().getIntArray("DDKeys");
|
||||
|
@ -92,8 +85,7 @@ public class DDLock
|
|||
* @return
|
||||
* @return
|
||||
*/
|
||||
public static void addKeys(ItemStack itemStack, int[] keysToAdd)
|
||||
{
|
||||
public static void addKeys(ItemStack itemStack, int[] keysToAdd) {
|
||||
int[] oldKeys = DDLock.getKeys(itemStack);
|
||||
int[] newKeys = new int[keysToAdd.length+oldKeys.length];
|
||||
System.arraycopy(oldKeys, 0, newKeys, 0, oldKeys.length);
|
||||
|
@ -107,10 +99,8 @@ public class DDLock
|
|||
* @return
|
||||
* @return
|
||||
*/
|
||||
public static void setKeys(ItemStack itemStack, int[] keys)
|
||||
{
|
||||
if (!itemStack.hasTagCompound())
|
||||
{
|
||||
public static void setKeys(ItemStack itemStack, int[] keys) {
|
||||
if (!itemStack.hasTagCompound()) {
|
||||
initNBTTags(itemStack);
|
||||
}
|
||||
NBTTagCompound tag = itemStack.getTagCompound();
|
||||
|
@ -122,8 +112,7 @@ public class DDLock
|
|||
* Gives the key a new NBTTag
|
||||
* @param itemStack
|
||||
*/
|
||||
public static void initNBTTags(ItemStack itemStack)
|
||||
{
|
||||
public static void initNBTTags(ItemStack itemStack) {
|
||||
itemStack.setTagCompound(new NBTTagCompound());
|
||||
NBTTagCompound tag = itemStack.getTagCompound();
|
||||
tag.setIntArray("DDKeys", new int[0]);
|
||||
|
@ -144,20 +133,16 @@ public class DDLock
|
|||
return false;
|
||||
}
|
||||
|
||||
public static boolean isItemKey(ItemStack key)
|
||||
{
|
||||
public static boolean isItemKey(ItemStack key) {
|
||||
return key.getItem() instanceof ItemDDKey;
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected static DDLock generateLockKeyPair(ItemStack itemStack, int lockKey2)
|
||||
{
|
||||
protected static DDLock generateLockKeyPair(ItemStack itemStack, int lockKey2) {
|
||||
itemStack.getTagCompound().setBoolean("HasCreatedLock", true);
|
||||
DDLock.setKeys(itemStack, new int[]{lockKey2});
|
||||
return new DDLock(true, lockKey2);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ import com.zixiken.dimdoors.world.PocketBuilder;
|
|||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.gameevent.PlayerEvent;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockDoor;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.entity.item.EntityMinecart;
|
||||
|
@ -30,6 +32,8 @@ import net.minecraft.network.play.server.S1DPacketEntityEffect;
|
|||
import net.minecraft.network.play.server.S1FPacketSetExperience;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
|
@ -37,8 +41,7 @@ import net.minecraftforge.common.DimensionManager;
|
|||
import com.zixiken.dimdoors.watcher.ClientDimData;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
|
||||
public class DDTeleporter
|
||||
{
|
||||
public class DDTeleporter {
|
||||
private static final Random random = new Random();
|
||||
private static final int NETHER_DIMENSION_ID = -1;
|
||||
private static final int OVERWORLD_DIMENSION_ID = 0;
|
||||
|
@ -59,50 +62,45 @@ public class DDTeleporter
|
|||
/**
|
||||
* Checks if the destination supplied is safe (i.e. filled by any replaceable or non-opaque blocks)
|
||||
*/
|
||||
private static boolean checkDestination(WorldServer world, Point4D destination, int orientation)
|
||||
{
|
||||
private static boolean checkDestination(WorldServer world, Point4D destination, EnumFacing orientation) {
|
||||
int x = destination.getX();
|
||||
int y = destination.getY();
|
||||
int z = destination.getZ();
|
||||
Block blockTop;
|
||||
Block blockBottom;
|
||||
Point3D point;
|
||||
BlockPos point;
|
||||
|
||||
switch (orientation)
|
||||
{
|
||||
case 0:
|
||||
point = new Point3D(x - 1, y - 1, z);
|
||||
switch (orientation) {
|
||||
case SOUTH:
|
||||
point = new BlockPos(x - 1, y - 1, z);
|
||||
break;
|
||||
case 1:
|
||||
point = new Point3D(x, y - 1, z - 1);
|
||||
case WEST:
|
||||
point = new BlockPos(x, y - 1, z - 1);
|
||||
break;
|
||||
case 2:
|
||||
point = new Point3D(x + 1, y - 1, z);
|
||||
case NORTH:
|
||||
point = new BlockPos(x + 1, y - 1, z);
|
||||
break;
|
||||
case 3:
|
||||
point = new Point3D(x, y - 1, z + 1);
|
||||
case EAST:
|
||||
point = new BlockPos(x, y - 1, z + 1);
|
||||
break;
|
||||
default:
|
||||
point = new Point3D(x, y - 1, z);
|
||||
point = new BlockPos(x, y - 1, z);
|
||||
break;
|
||||
}
|
||||
blockBottom = world.getBlock(point.getX(), point.getY(), point.getZ());
|
||||
blockTop = world.getBlock(point.getX(), point.getY() + 1, point.getZ());
|
||||
|
||||
if (blockBottom != null)
|
||||
{
|
||||
if (!blockBottom.isReplaceable(world, point.getX(), point.getY(), point.getZ()) && world.isBlockNormalCubeDefault(point.getX(), point.getY(), point.getZ(), false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (blockTop != null)
|
||||
{
|
||||
if (!blockTop.isReplaceable(world, point.getX(), point.getY() + 1, point.getZ()))
|
||||
{
|
||||
blockBottom = world.getBlockState(point).getBlock();
|
||||
blockTop = world.getBlockState(point.up()).getBlock();
|
||||
|
||||
if (blockBottom != null) {
|
||||
if (!blockBottom.isReplaceable(world, point) && world.isBlockNormalCube(point, false)) {
|
||||
return false;
|
||||
}
|
||||
} if (blockTop != null) {
|
||||
if (!blockTop.isReplaceable(world, point.up())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -112,16 +110,16 @@ public class DDTeleporter
|
|||
int y = destination.getY();
|
||||
int z = destination.getZ();
|
||||
|
||||
int orientation;
|
||||
EnumFacing orientation;
|
||||
if (checkOrientation)
|
||||
{
|
||||
orientation = getDestinationOrientation(destination, properties);
|
||||
entity.rotationYaw = (orientation * 90) + 90;
|
||||
entity.rotationYaw = (orientation.getIndex() * 90) + 90;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Teleport the entity to the precise destination point
|
||||
orientation = -1;
|
||||
orientation = EnumFacing.SOUTH;
|
||||
}
|
||||
|
||||
if (entity instanceof EntityPlayer)
|
||||
|
@ -148,8 +146,7 @@ public class DDTeleporter
|
|||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
player.setPositionAndUpdate(x + 0.5, y - 1, z + 0.5);
|
||||
}
|
||||
}
|
||||
|
@ -217,29 +214,25 @@ public class DDTeleporter
|
|||
entity.setPosition(x, y, z);
|
||||
}
|
||||
|
||||
private static int getDestinationOrientation(Point4D door, DDProperties properties)
|
||||
{
|
||||
private static EnumFacing getDestinationOrientation(Point4D door, DDProperties properties) {
|
||||
World world = DimensionManager.getWorld(door.getDimension());
|
||||
if (world == null)
|
||||
{
|
||||
if (world == null) {
|
||||
throw new IllegalStateException("The destination world should be loaded!");
|
||||
}
|
||||
|
||||
//Check if the block below that point is actually a door
|
||||
Block block = world.getBlock(door.getX(), door.getY() - 1, door.getZ());
|
||||
if (block==null || !(block instanceof IDimDoor))
|
||||
{
|
||||
IBlockState block = world.getBlockState(door.toBlockPos().down());
|
||||
if (block==null || !(block instanceof IDimDoor)) {
|
||||
//Return the pocket's orientation instead
|
||||
return PocketManager.createDimensionData(world).orientation();
|
||||
}
|
||||
|
||||
|
||||
//Return the orientation portion of its metadata
|
||||
return world.getBlockMetadata(door.getX(), door.getY() - 1, door.getZ()) & 3;
|
||||
return world.getBlockState(door.toBlockPos().down()).getValue(BlockDoor.FACING);
|
||||
}
|
||||
|
||||
public static Entity teleportEntity(Entity entity, Point4D destination, boolean checkOrientation)
|
||||
{
|
||||
public static Entity teleportEntity(Entity entity, Point4D destination, boolean checkOrientation) {
|
||||
if (entity == null)
|
||||
{
|
||||
throw new IllegalArgumentException("entity cannot be null.");
|
||||
|
@ -390,6 +383,7 @@ public class DDTeleporter
|
|||
// Let's try doing this down here in case this is what's killing NEI.
|
||||
FMLCommonHandler.instance().firePlayerChangedDimensionEvent((EntityPlayer) entity, oldWorld.provider.dimensionId, newWorld.provider.dimensionId);
|
||||
}
|
||||
|
||||
DDTeleporter.placeInPortal(entity, newWorld, destination, properties, checkOrientation);
|
||||
return entity;
|
||||
}
|
||||
|
@ -591,7 +585,7 @@ public class DDTeleporter
|
|||
return false;
|
||||
}
|
||||
|
||||
Point3D destination = yCoordHelper.findDropPoint(world, source.getX(), source.getY() + 1, source.getZ());
|
||||
BlockPos destination = yCoordHelper.findDropPoint(world, source.getX(), source.getY() + 1, source.getZ());
|
||||
if (destination != null)
|
||||
{
|
||||
current.root().setLinkDestination(link, destination.getX(), destination.getY(), destination.getZ());
|
||||
|
@ -707,9 +701,9 @@ public class DDTeleporter
|
|||
}
|
||||
|
||||
int startY = source.getY() - 2;
|
||||
Point3D destination;
|
||||
Point3D locationUp = yCoordHelper.findSafeCubeUp(world, source.getX(), startY, source.getZ());
|
||||
Point3D locationDown = yCoordHelper.findSafeCubeDown(world, source.getX(), startY, source.getZ());
|
||||
BlockPos destination;
|
||||
BlockPos locationUp = yCoordHelper.findSafeCubeUp(world, source.getX(), startY, source.getZ());
|
||||
BlockPos locationDown = yCoordHelper.findSafeCubeDown(world, source.getX(), startY, source.getZ());
|
||||
|
||||
if (locationUp == null)
|
||||
{
|
||||
|
|
|
@ -3,23 +3,22 @@ package com.zixiken.dimdoors.core;
|
|||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.world.ChunkCoordIntPair;
|
||||
import com.zixiken.dimdoors.util.Point4D;
|
||||
|
||||
public abstract class DimLink
|
||||
{
|
||||
protected Point4D point;
|
||||
protected int orientation;
|
||||
protected EnumFacing orientation;
|
||||
protected DDLock lock;
|
||||
protected DimLink parent;
|
||||
protected LinkTail tail;
|
||||
protected List<DimLink> children;
|
||||
|
||||
protected DimLink(Point4D point, int orientation, DDLock lock, DimLink parent)
|
||||
{
|
||||
protected DimLink(Point4D point, EnumFacing orientation, DDLock lock, DimLink parent) {
|
||||
|
||||
if (parent.point.getDimension() != point.getDimension())
|
||||
{
|
||||
if (parent.point.getDimension() != point.getDimension()) {
|
||||
// Ban having children in other dimensions to avoid serialization issues with cross-dimensional tails
|
||||
throw new IllegalArgumentException("source and parent.source must have the same dimension.");
|
||||
}
|
||||
|
@ -32,8 +31,7 @@ public abstract class DimLink
|
|||
parent.children.add(this);
|
||||
}
|
||||
|
||||
protected DimLink(Point4D point, int orientation, DDLock lock, LinkType linkType)
|
||||
{
|
||||
protected DimLink(Point4D point, EnumFacing orientation, DDLock lock, LinkType linkType) {
|
||||
/**This really cant happen anymore, I guess.
|
||||
*
|
||||
if ((linkType < LinkTypes.ENUM_MIN || linkType > LinkTypes.ENUM_MAX) && linkType != LinkTypes.CLIENT_SIDE)
|
||||
|
@ -50,23 +48,19 @@ public abstract class DimLink
|
|||
this.children = new LinkedList<DimLink>();
|
||||
}
|
||||
|
||||
public Point4D source()
|
||||
{
|
||||
public Point4D source() {
|
||||
return point;
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
public void clear() {
|
||||
//Release children
|
||||
for (DimLink child : children)
|
||||
{
|
||||
for (DimLink child : children) {
|
||||
child.parent = null;
|
||||
}
|
||||
children.clear();
|
||||
|
||||
//Release parent
|
||||
if (parent != null)
|
||||
{
|
||||
if (parent != null) {
|
||||
parent.children.remove(this);
|
||||
}
|
||||
|
||||
|
@ -75,48 +69,39 @@ public abstract class DimLink
|
|||
tail = new LinkTail(LinkType.NORMAL, null);
|
||||
}
|
||||
|
||||
public int orientation()
|
||||
{
|
||||
public EnumFacing orientation() {
|
||||
return orientation;
|
||||
}
|
||||
|
||||
public Point4D destination()
|
||||
{
|
||||
public Point4D destination() {
|
||||
return tail.getDestination();
|
||||
}
|
||||
|
||||
public int getDestinationOrientation()
|
||||
{
|
||||
public EnumFacing getDestinationOrientation() {
|
||||
DimLink destinationLink = PocketManager.getLink(tail.getDestination());
|
||||
if (destinationLink != null)
|
||||
{
|
||||
if (destinationLink != null) {
|
||||
return destinationLink.orientation();
|
||||
}
|
||||
return (orientation + 2) % 4;
|
||||
return orientation.rotateY().rotateY();
|
||||
}
|
||||
|
||||
public boolean hasDestination()
|
||||
{
|
||||
return (tail.getDestination() != null);
|
||||
public boolean hasDestination() {
|
||||
return tail.getDestination() != null;
|
||||
}
|
||||
|
||||
public Iterable<DimLink> children()
|
||||
{
|
||||
public Iterable<DimLink> children() {
|
||||
return children;
|
||||
}
|
||||
|
||||
public int childCount()
|
||||
{
|
||||
public int childCount() {
|
||||
return children.size();
|
||||
}
|
||||
|
||||
public DimLink parent()
|
||||
{
|
||||
public DimLink parent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public LinkType linkType()
|
||||
{
|
||||
public LinkType linkType() {
|
||||
return tail.getLinkType();
|
||||
}
|
||||
|
||||
|
@ -125,8 +110,7 @@ public abstract class DimLink
|
|||
* Tries to open this lock. Returns true if the lock is open or if the key can open it
|
||||
* @return
|
||||
*/
|
||||
public boolean tryToOpen(ItemStack item)
|
||||
{
|
||||
public boolean tryToOpen(ItemStack item) {
|
||||
return lock.tryToOpen(item);
|
||||
}
|
||||
|
||||
|
@ -134,8 +118,7 @@ public abstract class DimLink
|
|||
* Tests if the given key item fits this lock
|
||||
* @return
|
||||
*/
|
||||
public boolean doesKeyUnlock(ItemStack item)
|
||||
{
|
||||
public boolean doesKeyUnlock(ItemStack item) {
|
||||
return lock.doesKeyUnlock(item);
|
||||
}
|
||||
|
||||
|
@ -143,8 +126,7 @@ public abstract class DimLink
|
|||
* test if there is a lock, regardless if it is locked or not.
|
||||
* @return
|
||||
*/
|
||||
public boolean hasLock()
|
||||
{
|
||||
public boolean hasLock() {
|
||||
return this.lock!=null;
|
||||
}
|
||||
|
||||
|
@ -152,8 +134,7 @@ public abstract class DimLink
|
|||
* Tests if the lock is open or not
|
||||
*
|
||||
*/
|
||||
public boolean getLockState()
|
||||
{
|
||||
public boolean getLockState() {
|
||||
return this.hasLock()&&this.lock.getLockState();
|
||||
}
|
||||
|
||||
|
@ -161,19 +142,16 @@ public abstract class DimLink
|
|||
* gets the actual lock object
|
||||
* @return
|
||||
*/
|
||||
public DDLock getLock()
|
||||
{
|
||||
public DDLock getLock() {
|
||||
return this.lock;
|
||||
}
|
||||
|
||||
public ChunkCoordIntPair getChunkCoordinates()
|
||||
{
|
||||
public ChunkCoordIntPair getChunkCoordinates() {
|
||||
return new ChunkCoordIntPair(point.getX() >> 4, point.getZ() >> 4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
public String toString() {
|
||||
return point + " -> " + (hasDestination() ? destination() : "()");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ import com.zixiken.dimdoors.dungeon.pack.DungeonPack;
|
|||
import com.zixiken.dimdoors.util.Point4D;
|
||||
import com.zixiken.dimdoors.watcher.IUpdateWatcher;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.world.ChunkCoordIntPair;
|
||||
import net.minecraft.world.World;
|
||||
import com.zixiken.dimdoors.saving.IPackable;
|
||||
|
@ -25,52 +27,39 @@ import com.zixiken.dimdoors.saving.PackedDungeonData;
|
|||
import com.zixiken.dimdoors.saving.PackedLinkData;
|
||||
import com.zixiken.dimdoors.saving.PackedLinkTail;
|
||||
|
||||
public abstract class NewDimData implements IPackable<PackedDimData>
|
||||
{
|
||||
private static class InnerDimLink extends DimLink
|
||||
{
|
||||
public InnerDimLink(Point4D source, DimLink parent, int orientation, DDLock lock)
|
||||
{
|
||||
public abstract class NewDimData implements IPackable<PackedDimData> {
|
||||
private static class InnerDimLink extends DimLink {
|
||||
public InnerDimLink(Point4D source, DimLink parent, EnumFacing orientation, DDLock lock) {
|
||||
super(source, orientation, lock, parent);
|
||||
}
|
||||
|
||||
public InnerDimLink(Point4D source, LinkType linkType, int orientation, DDLock lock)
|
||||
{
|
||||
public InnerDimLink(Point4D source, LinkType linkType, EnumFacing orientation, DDLock lock) {
|
||||
super(source, orientation, lock, linkType);
|
||||
}
|
||||
|
||||
public void setDestination(int x, int y, int z, NewDimData dimension)
|
||||
{
|
||||
tail.setDestination(new Point4D(x, y, z, dimension.id()));
|
||||
public void setDestination(BlockPos pos, NewDimData dimension) {
|
||||
tail.setDestination(new Point4D(pos, dimension.id()));
|
||||
}
|
||||
|
||||
public boolean overwrite(InnerDimLink nextParent,int orientation)
|
||||
{
|
||||
if (nextParent == null)
|
||||
{
|
||||
public boolean overwrite(InnerDimLink nextParent, EnumFacing orientation) {
|
||||
if (nextParent == null) {
|
||||
throw new IllegalArgumentException("nextParent cannot be null.");
|
||||
}
|
||||
if (this == nextParent)
|
||||
{
|
||||
} if (this == nextParent) {
|
||||
//Ignore this request silently
|
||||
return false;
|
||||
}
|
||||
if (nextParent.point.getDimension() != point.getDimension())
|
||||
{
|
||||
} if (nextParent.point.getDimension() != point.getDimension()) {
|
||||
// Ban having children in other dimensions to avoid serialization issues with cross-dimensional tails
|
||||
throw new IllegalArgumentException("source and parent.source must have the same dimension.");
|
||||
}
|
||||
|
||||
//Release children
|
||||
for (DimLink child : children)
|
||||
{
|
||||
for (DimLink child : children) {
|
||||
((InnerDimLink) child).parent = null;
|
||||
}
|
||||
children.clear();
|
||||
|
||||
//Release parent
|
||||
if (parent != null)
|
||||
{
|
||||
if (parent != null) {
|
||||
parent.children.remove(this);
|
||||
}
|
||||
|
||||
|
@ -82,18 +71,15 @@ public abstract class NewDimData implements IPackable<PackedDimData>
|
|||
return true;
|
||||
}
|
||||
|
||||
public void overwrite(LinkType linkType, int orientation)
|
||||
{
|
||||
public void overwrite(LinkType linkType, EnumFacing orientation) {
|
||||
//Release children
|
||||
for (DimLink child : children)
|
||||
{
|
||||
for (DimLink child : children) {
|
||||
((InnerDimLink) child).parent = null;
|
||||
}
|
||||
children.clear();
|
||||
|
||||
//Release parent
|
||||
if (parent != null)
|
||||
{
|
||||
if (parent != null) {
|
||||
parent.children.remove(this);
|
||||
}
|
||||
|
||||
|
@ -108,8 +94,7 @@ public abstract class NewDimData implements IPackable<PackedDimData>
|
|||
* only use this on the client to update errything
|
||||
* @param lock
|
||||
*/
|
||||
public void setLock(DDLock lock)
|
||||
{
|
||||
public void setLock(DDLock lock) {
|
||||
this.lock = lock;
|
||||
}
|
||||
|
||||
|
@ -118,20 +103,16 @@ public abstract class NewDimData implements IPackable<PackedDimData>
|
|||
* @param itemStack
|
||||
* @return
|
||||
*/
|
||||
public boolean createLock(ItemStack itemStack, int lockKey)
|
||||
{
|
||||
if(this.hasLock()||DDLock.hasCreatedLock(itemStack))
|
||||
{
|
||||
public boolean createLock(ItemStack itemStack, int lockKey) {
|
||||
if(this.hasLock()||DDLock.hasCreatedLock(itemStack)) {
|
||||
return false;
|
||||
}
|
||||
this.lock = DDLock.generateLockKeyPair(itemStack, lockKey);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void removeLock(ItemStack itemStack, InnerDimLink link)
|
||||
{
|
||||
if(link.doesKeyUnlock(itemStack))
|
||||
{
|
||||
public void removeLock(ItemStack itemStack, InnerDimLink link) {
|
||||
if(link.doesKeyUnlock(itemStack)) {
|
||||
link.lock = null;
|
||||
}
|
||||
}
|
||||
|
@ -153,7 +134,7 @@ public abstract class NewDimData implements IPackable<PackedDimData>
|
|||
protected NewDimData root;
|
||||
protected List<NewDimData> children;
|
||||
protected Point4D origin;
|
||||
protected int orientation;
|
||||
protected EnumFacing orientation;
|
||||
protected DungeonData dungeon;
|
||||
protected boolean modified;
|
||||
public IUpdateWatcher<ClientLinkData> linkWatcher;
|
||||
|
@ -162,10 +143,8 @@ public abstract class NewDimData implements IPackable<PackedDimData>
|
|||
// Don't write this field to a file - it should be recreated on startup
|
||||
private Map<ChunkCoordIntPair, List<InnerDimLink>> chunkMapping;
|
||||
|
||||
protected NewDimData(int id, NewDimData parent, DimensionType type, IUpdateWatcher<ClientLinkData> linkWatcher)
|
||||
{
|
||||
if (type != DimensionType.ROOT && (parent == null))
|
||||
{
|
||||
protected NewDimData(int id, NewDimData parent, DimensionType type, IUpdateWatcher<ClientLinkData> linkWatcher) {
|
||||
if (type != DimensionType.ROOT && (parent == null)) {
|
||||
throw new NullPointerException("Dimensions can be pocket dimensions if and only if they have a parent dimension.");
|
||||
}
|
||||
|
||||
|
@ -177,7 +156,7 @@ public abstract class NewDimData implements IPackable<PackedDimData>
|
|||
this.packDepth = 0;
|
||||
this.type = type;
|
||||
this.isFilled = false;
|
||||
this.orientation = 0;
|
||||
this.orientation = EnumFacing.SOUTH;
|
||||
this.origin = null;
|
||||
this.dungeon = null;
|
||||
this.linkWatcher = linkWatcher;
|
||||
|
@ -185,26 +164,21 @@ public abstract class NewDimData implements IPackable<PackedDimData>
|
|||
this.modified = true;
|
||||
|
||||
//Register with parent
|
||||
if (parent != null)
|
||||
{
|
||||
if (parent != null) {
|
||||
//We don't need to raise an update event for adding a child because the child's creation will be signaled.
|
||||
this.root = parent.root;
|
||||
this.depth = parent.depth + 1;
|
||||
parent.children.add(this);
|
||||
parent.modified = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
this.root = this;
|
||||
this.depth = 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected NewDimData(int id, NewDimData root, DimensionType type)
|
||||
{
|
||||
protected NewDimData(int id, NewDimData root, DimensionType type) {
|
||||
// This constructor is meant for client-side code only
|
||||
if (root == null)
|
||||
{
|
||||
if (root == null) {
|
||||
throw new IllegalArgumentException("root cannot be null.");
|
||||
}
|
||||
|
||||
|
@ -216,7 +190,7 @@ public abstract class NewDimData implements IPackable<PackedDimData>
|
|||
this.packDepth = 0;
|
||||
this.type = type;
|
||||
this.isFilled = false;
|
||||
this.orientation = 0;
|
||||
this.orientation = EnumFacing.SOUTH;
|
||||
this.origin = null;
|
||||
this.dungeon = null;
|
||||
this.linkWatcher = null;
|
||||
|
@ -226,11 +200,9 @@ public abstract class NewDimData implements IPackable<PackedDimData>
|
|||
}
|
||||
|
||||
|
||||
public DimLink findNearestRift(World world, int range, int x, int y, int z)
|
||||
{
|
||||
public DimLink findNearestRift(World world, int range, BlockPos pos) {
|
||||
// Sanity check...
|
||||
if (world.provider.dimensionId != id)
|
||||
{
|
||||
if (world.provider.getDimensionId() != id) {
|
||||
throw new IllegalArgumentException("Attempted to search for links in a World instance for a different dimension!");
|
||||
}
|
||||
|
||||
|
@ -244,18 +216,13 @@ public abstract class NewDimData implements IPackable<PackedDimData>
|
|||
int minDistance = Integer.MAX_VALUE;
|
||||
DDProperties properties = DDProperties.instance();
|
||||
|
||||
for (i = -range; i <= range; i++)
|
||||
{
|
||||
for (j = -range; j <= range; j++)
|
||||
{
|
||||
for (k = -range; k <= range; k++)
|
||||
{
|
||||
for (i = -range; i <= range; i++) {
|
||||
for (j = -range; j <= range; j++) {
|
||||
for (k = -range; k <= range; k++) {
|
||||
distance = getAbsoluteSum(i, j, k);
|
||||
if (distance > 0 && distance < minDistance && world.getBlock(x + i, y + j, z + k) == DimDoors.blockRift)
|
||||
{
|
||||
link = getLink(x + i, y + j, z + k);
|
||||
if (link != null)
|
||||
{
|
||||
if (distance > 0 && distance < minDistance && world.getBlockState(pos.add(i, j, k)) == DimDoors.blockRift) {
|
||||
link = getLink(pos.add(i, j, k));
|
||||
if (link != null) {
|
||||
nearest = link;
|
||||
minDistance = distance;
|
||||
}
|
||||
|
@ -267,11 +234,9 @@ public abstract class NewDimData implements IPackable<PackedDimData>
|
|||
return nearest;
|
||||
}
|
||||
|
||||
public ArrayList<DimLink> findRiftsInRange(World world, int range, int x, int y, int z)
|
||||
{
|
||||
public ArrayList<DimLink> findRiftsInRange(World world, int range, BlockPos pos) {
|
||||
// Sanity check...
|
||||
if (world.provider.dimensionId != id)
|
||||
{
|
||||
if (world.provider.getDimensionId() != id) {
|
||||
throw new IllegalArgumentException("Attempted to search for links in a World instance for a different dimension!");
|
||||
}
|
||||
|
||||
|
@ -283,18 +248,13 @@ public abstract class NewDimData implements IPackable<PackedDimData>
|
|||
DDProperties properties = DDProperties.instance();
|
||||
ArrayList<DimLink> links = new ArrayList<DimLink>();
|
||||
|
||||
for (i = -range; i <= range; i++)
|
||||
{
|
||||
for (j = -range; j <= range; j++)
|
||||
{
|
||||
for (k = -range; k <= range; k++)
|
||||
{
|
||||
for (i = -range; i <= range; i++) {
|
||||
for (j = -range; j <= range; j++) {
|
||||
for (k = -range; k <= range; k++) {
|
||||
distance = getAbsoluteSum(i, j, k);
|
||||
if (distance > 0 && world.getBlock(x + i, y + j, z + k) == DimDoors.blockRift)
|
||||
{
|
||||
link = getLink(x + i, y + j, z + k);
|
||||
if (link != null)
|
||||
{
|
||||
if (distance > 0 && world.getBlockState(pos.add(i, j, k)) == DimDoors.blockRift) {
|
||||
link = getLink(pos.add(i, j, k));
|
||||
if (link != null) {
|
||||
links.add(link);
|
||||
}
|
||||
}
|
||||
|
@ -310,66 +270,53 @@ public abstract class NewDimData implements IPackable<PackedDimData>
|
|||
return Math.abs(i) + Math.abs(j) + Math.abs(k);
|
||||
}
|
||||
|
||||
public DimLink createLink(int x, int y, int z, LinkType linkType, int orientation)
|
||||
{
|
||||
return createLink(new Point4D(x, y, z, id), linkType, orientation, null);
|
||||
public DimLink createLink(BlockPos pos, LinkType linkType, EnumFacing orientation) {
|
||||
return createLink(new Point4D(pos, id), linkType, orientation, null);
|
||||
}
|
||||
|
||||
public DimLink createLink(Point4D source, LinkType linkType, int orientation, DDLock locked)
|
||||
{
|
||||
public DimLink createLink(Point4D source, LinkType linkType, EnumFacing orientation, DDLock locked) {
|
||||
// Return an existing link if there is one to avoid creating multiple links starting at the same point.
|
||||
InnerDimLink link = linkMapping.get(source);
|
||||
if (link == null)
|
||||
{
|
||||
if (link == null) {
|
||||
link = new InnerDimLink(source, linkType, orientation, locked);
|
||||
linkMapping.put(source, link);
|
||||
linkList.add(link);
|
||||
|
||||
// If this code is running on the server side, add this link to chunkMapping.
|
||||
if (linkType != LinkType.CLIENT)
|
||||
{
|
||||
if (linkType != LinkType.CLIENT) {
|
||||
ChunkCoordIntPair chunk = link.getChunkCoordinates();
|
||||
List<InnerDimLink> chunkLinks = chunkMapping.get(chunk);
|
||||
if (chunkLinks == null)
|
||||
{
|
||||
if (chunkLinks == null) {
|
||||
chunkLinks = new ArrayList<InnerDimLink>(EXPECTED_LINKS_PER_CHUNK);
|
||||
chunkMapping.put(chunk, chunkLinks);
|
||||
}
|
||||
chunkLinks.add(link);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
link.overwrite(linkType, orientation);
|
||||
}
|
||||
modified = true;
|
||||
|
||||
//Link created!
|
||||
if (linkType != LinkType.CLIENT)
|
||||
|
||||
{
|
||||
if (linkType != LinkType.CLIENT) {
|
||||
linkWatcher.onCreated(new ClientLinkData(link));
|
||||
}
|
||||
return link;
|
||||
}
|
||||
|
||||
public DimLink createChildLink(int x, int y, int z, DimLink parent)
|
||||
{
|
||||
return createChildLink(new Point4D(x, y, z, id), (InnerDimLink) parent, null);
|
||||
public DimLink createChildLink(BlockPos pos, DimLink parent) {
|
||||
return createChildLink(new Point4D(pos, id), (InnerDimLink) parent, null);
|
||||
}
|
||||
|
||||
public DimLink createChildLink(Point4D source, DimLink parent, DDLock locked)
|
||||
{
|
||||
public DimLink createChildLink(Point4D source, DimLink parent, DDLock locked) {
|
||||
// To avoid having multiple links at a single point, if we find an existing link then we overwrite
|
||||
// its destination data instead of creating a new instance.
|
||||
|
||||
if (parent == null)
|
||||
{
|
||||
if (parent == null) {
|
||||
throw new IllegalArgumentException("parent cannot be null.");
|
||||
}
|
||||
InnerDimLink link = linkMapping.get(source);
|
||||
if (link == null)
|
||||
{
|
||||
if (link == null) {
|
||||
link = new InnerDimLink(source, parent, parent.orientation, locked);
|
||||
linkMapping.put(source, link);
|
||||
linkList.add(link);
|
||||
|
@ -377,12 +324,10 @@ public abstract class NewDimData implements IPackable<PackedDimData>
|
|||
|
||||
// If this code is running on the server side, add this link to chunkMapping.
|
||||
// Granted, the client side code should never create child links anyway...
|
||||
if (link.linkType() != LinkType.CLIENT)
|
||||
{
|
||||
if (link.linkType() != LinkType.CLIENT) {
|
||||
ChunkCoordIntPair chunk = link.getChunkCoordinates();
|
||||
List<InnerDimLink> chunkLinks = chunkMapping.get(chunk);
|
||||
if (chunkLinks == null)
|
||||
{
|
||||
if (chunkLinks == null) {
|
||||
chunkLinks = new ArrayList<InnerDimLink>(EXPECTED_LINKS_PER_CHUNK);
|
||||
chunkMapping.put(chunk, chunkLinks);
|
||||
}
|
||||
|
@ -391,11 +336,8 @@ public abstract class NewDimData implements IPackable<PackedDimData>
|
|||
|
||||
// Link created!
|
||||
linkWatcher.onCreated(new ClientLinkData(link));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (link.overwrite((InnerDimLink) parent, parent.orientation))
|
||||
{
|
||||
} else {
|
||||
if (link.overwrite((InnerDimLink) parent, parent.orientation)) {
|
||||
//Link created!
|
||||
linkWatcher.onCreated(new ClientLinkData(link));
|
||||
}
|
||||
|
@ -404,24 +346,19 @@ public abstract class NewDimData implements IPackable<PackedDimData>
|
|||
return link;
|
||||
}
|
||||
|
||||
public boolean deleteLink(DimLink link)
|
||||
{
|
||||
if (link.source().getDimension() != id)
|
||||
{
|
||||
public boolean deleteLink(DimLink link) {
|
||||
if (link.source().getDimension() != id) {
|
||||
throw new IllegalArgumentException("Attempted to delete a link from another dimension.");
|
||||
}
|
||||
InnerDimLink target = linkMapping.remove(link.source());
|
||||
if (target != null)
|
||||
{
|
||||
if (target != null) {
|
||||
linkList.remove(target);
|
||||
|
||||
// If this code is running on the server side, remove this link to chunkMapping.
|
||||
if (link.linkType() != LinkType.CLIENT)
|
||||
{
|
||||
if (link.linkType() != LinkType.CLIENT) {
|
||||
ChunkCoordIntPair chunk = target.getChunkCoordinates();
|
||||
List<InnerDimLink> chunkLinks = chunkMapping.get(chunk);
|
||||
if (chunkLinks != null)
|
||||
{
|
||||
if (chunkLinks != null) {
|
||||
chunkLinks.remove(target);
|
||||
}
|
||||
}
|
||||
|
@ -435,136 +372,104 @@ public abstract class NewDimData implements IPackable<PackedDimData>
|
|||
return (target != null);
|
||||
}
|
||||
|
||||
public boolean deleteLink(int x, int y, int z)
|
||||
{
|
||||
return this.deleteLink(this.getLink(x, y, z));
|
||||
}
|
||||
public boolean deleteLink(Point4D location)
|
||||
{
|
||||
return this.deleteLink(this.getLink(location));
|
||||
public boolean deleteLink(BlockPos pos) {
|
||||
return this.deleteLink(this.getLink(pos));
|
||||
}
|
||||
|
||||
public DimLink getLink(int x, int y, int z)
|
||||
{
|
||||
Point4D location = new Point4D(x, y, z, id);
|
||||
return linkMapping.get(location);
|
||||
public boolean deleteLink(Point4D location) {
|
||||
return this.deleteLink(this.getLink(location));
|
||||
}
|
||||
|
||||
public DimLink getLink(Point3D location)
|
||||
{
|
||||
return linkMapping.get(new Point4D(location.getX(), location.getY(), location.getZ(), this.id));
|
||||
public DimLink getLink(BlockPos location) {
|
||||
return linkMapping.get(new Point4D(location, this.id));
|
||||
}
|
||||
|
||||
public DimLink getLink(Point4D location)
|
||||
{
|
||||
public DimLink getLink(Point4D location) {
|
||||
if (location.getDimension() != id)
|
||||
return null;
|
||||
|
||||
return linkMapping.get(location);
|
||||
}
|
||||
|
||||
public ArrayList<DimLink> getAllLinks()
|
||||
{
|
||||
public ArrayList<DimLink> getAllLinks() {
|
||||
ArrayList<DimLink> results = new ArrayList<DimLink>(linkMapping.size());
|
||||
results.addAll(linkMapping.values());
|
||||
return results;
|
||||
}
|
||||
|
||||
public boolean isPocketDimension()
|
||||
{
|
||||
public boolean isPocketDimension() {
|
||||
return (root != this);
|
||||
}
|
||||
|
||||
public DimensionType type()
|
||||
{
|
||||
public DimensionType type() {
|
||||
return this.type;
|
||||
}
|
||||
public boolean isFilled()
|
||||
{
|
||||
|
||||
public boolean isFilled() {
|
||||
return isFilled;
|
||||
}
|
||||
|
||||
public void setFilled(boolean isFilled)
|
||||
{
|
||||
public void setFilled(boolean isFilled) {
|
||||
this.isFilled = isFilled;
|
||||
this.modified = true;
|
||||
}
|
||||
|
||||
public int id()
|
||||
{
|
||||
public int id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int depth()
|
||||
{
|
||||
public int depth() {
|
||||
return depth;
|
||||
}
|
||||
|
||||
public int packDepth()
|
||||
{
|
||||
public int packDepth() {
|
||||
return packDepth;
|
||||
}
|
||||
|
||||
public Point4D origin()
|
||||
{
|
||||
public Point4D origin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
public NewDimData parent()
|
||||
{
|
||||
public NewDimData parent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public NewDimData root()
|
||||
{
|
||||
public NewDimData root() {
|
||||
return root;
|
||||
}
|
||||
|
||||
public int orientation()
|
||||
{
|
||||
public EnumFacing orientation() {
|
||||
return orientation;
|
||||
}
|
||||
|
||||
public DungeonData dungeon()
|
||||
{
|
||||
public DungeonData dungeon() {
|
||||
return dungeon;
|
||||
}
|
||||
|
||||
public boolean isInitialized()
|
||||
{
|
||||
|
||||
public boolean isInitialized() {
|
||||
return (origin != null);
|
||||
}
|
||||
|
||||
public int linkCount()
|
||||
{
|
||||
public int linkCount() {
|
||||
return linkList.size();
|
||||
}
|
||||
|
||||
public Iterable<NewDimData> children()
|
||||
{
|
||||
public Iterable<NewDimData> children() {
|
||||
return children;
|
||||
}
|
||||
|
||||
public Iterable<? extends DimLink> links()
|
||||
{
|
||||
public Iterable<? extends DimLink> links() {
|
||||
return linkList;
|
||||
}
|
||||
|
||||
public void initializeDungeon(int originX, int originY, int originZ, int orientation, DimLink incoming, DungeonData dungeon)
|
||||
{
|
||||
if (this.type != DimensionType.DUNGEON)
|
||||
{
|
||||
public void initializeDungeon(BlockPos origin, EnumFacing orientation, DimLink incoming, DungeonData dungeon) {
|
||||
if (this.type != DimensionType.DUNGEON) {
|
||||
throw new IllegalStateException("Cannot invoke initializeDungeon() on a non-dungeon dimension.");
|
||||
}
|
||||
if (isInitialized())
|
||||
{
|
||||
} if (isInitialized()) {
|
||||
throw new IllegalStateException("The dimension has already been initialized.");
|
||||
}
|
||||
if (orientation < 0 || orientation > 3)
|
||||
{
|
||||
throw new IllegalArgumentException("orientation must be between 0 and 3, inclusive.");
|
||||
}
|
||||
setLinkDestination(incoming, originX, originY, originZ);
|
||||
|
||||
setLinkDestination(incoming, origin);
|
||||
this.origin = incoming.destination();
|
||||
this.orientation = orientation;
|
||||
this.dungeon = dungeon;
|
||||
|
@ -575,20 +480,19 @@ public abstract class NewDimData implements IPackable<PackedDimData>
|
|||
/**
|
||||
* Effectively moves the dungeon to the 'top' of a chain as far as dungeon generation is concerned.
|
||||
*/
|
||||
public void setParentToRoot()
|
||||
{
|
||||
public void setParentToRoot() {
|
||||
// Update this dimension's information
|
||||
if (parent != null)
|
||||
{
|
||||
if (parent != null) {
|
||||
parent.children.remove(this);
|
||||
}
|
||||
|
||||
this.depth = 1;
|
||||
this.parent = this.root;
|
||||
this.root.children.add(this);
|
||||
this.root.modified = true;
|
||||
this.modified = true;
|
||||
if (this.type == DimensionType.DUNGEON)
|
||||
{
|
||||
|
||||
if (this.type == DimensionType.DUNGEON) {
|
||||
this.packDepth = calculatePackDepth(this.parent, this.dungeon);
|
||||
}
|
||||
|
||||
|
@ -596,149 +500,120 @@ public abstract class NewDimData implements IPackable<PackedDimData>
|
|||
Stack<NewDimData> ordering = new Stack<NewDimData>();
|
||||
ordering.addAll(this.children);
|
||||
|
||||
while (!ordering.isEmpty())
|
||||
{
|
||||
while (!ordering.isEmpty()) {
|
||||
NewDimData current = ordering.pop();
|
||||
current.resetDepth();
|
||||
ordering.addAll(current.children);
|
||||
}
|
||||
}
|
||||
|
||||
private void resetDepth()
|
||||
{
|
||||
private void resetDepth() {
|
||||
// We assume that this is only applied to dimensions with parents
|
||||
this.depth = this.parent.depth + 1;
|
||||
if (this.type == DimensionType.DUNGEON)
|
||||
{
|
||||
if (this.type == DimensionType.DUNGEON) {
|
||||
this.packDepth = calculatePackDepth(this.parent, this.dungeon);
|
||||
}
|
||||
|
||||
this.modified = true;
|
||||
}
|
||||
|
||||
public static int calculatePackDepth(NewDimData parent, DungeonData current)
|
||||
{
|
||||
public static int calculatePackDepth(NewDimData parent, DungeonData current) {
|
||||
DungeonData predecessor = parent.dungeon();
|
||||
if (current == null)
|
||||
{
|
||||
if (current == null) {
|
||||
throw new IllegalArgumentException("current cannot be null.");
|
||||
}
|
||||
if (predecessor == null)
|
||||
{
|
||||
} if (predecessor == null) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
DungeonPack predOwner = predecessor.dungeonType().Owner;
|
||||
DungeonPack currentOwner = current.dungeonType().Owner;
|
||||
if (currentOwner == null)
|
||||
{
|
||||
|
||||
if (currentOwner == null) {
|
||||
return 1;
|
||||
}
|
||||
if (predOwner == null)
|
||||
{
|
||||
} if (predOwner == null) {
|
||||
return 1;
|
||||
}
|
||||
if (predOwner == currentOwner)
|
||||
{
|
||||
} if (predOwner == currentOwner) {
|
||||
return parent.packDepth + 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
public void initializePocket(int originX, int originY, int originZ, int orientation, DimLink incoming)
|
||||
{
|
||||
if (!isPocketDimension())
|
||||
{
|
||||
public void initializePocket(BlockPos origin, EnumFacing orientation, DimLink incoming) {
|
||||
if (!isPocketDimension()) {
|
||||
throw new IllegalStateException("Cannot invoke initializePocket() on a non-pocket dimension.");
|
||||
}
|
||||
if (isInitialized())
|
||||
{
|
||||
} if (isInitialized()) {
|
||||
throw new IllegalStateException("The dimension has already been initialized.");
|
||||
}
|
||||
|
||||
setLinkDestination(incoming, originX, originY, originZ);
|
||||
setLinkDestination(incoming, origin);
|
||||
this.origin = incoming.destination();
|
||||
this.orientation = orientation;
|
||||
this.modified = true;
|
||||
}
|
||||
|
||||
public void setLinkDestination(DimLink incoming, int x, int y, int z)
|
||||
{
|
||||
public void setLinkDestination(DimLink incoming, BlockPos pos) {
|
||||
InnerDimLink link = (InnerDimLink) incoming;
|
||||
link.setDestination(x, y, z, this);
|
||||
link.setDestination(pos, this);
|
||||
this.modified = true;
|
||||
}
|
||||
|
||||
public void lock(DimLink link, boolean locked)
|
||||
{
|
||||
public void lock(DimLink link, boolean locked) {
|
||||
InnerDimLink innerLink = (InnerDimLink)link;
|
||||
innerLink.lock.setLockState(locked);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
public void setLock(DimLink link, DDLock lock)
|
||||
{
|
||||
public void setLock(DimLink link, DDLock lock) {
|
||||
InnerDimLink innerLink = (InnerDimLink)link;
|
||||
innerLink.setLock(lock);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
public void createLock(DimLink link, ItemStack item, int lockKey)
|
||||
{
|
||||
public void createLock(DimLink link, ItemStack item, int lockKey) {
|
||||
InnerDimLink innerLink = (InnerDimLink)link;
|
||||
innerLink.createLock(item, lockKey);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
public void removeLock(DimLink link, ItemStack item)
|
||||
{
|
||||
public void removeLock(DimLink link, ItemStack item) {
|
||||
InnerDimLink innerLink = (InnerDimLink)link;
|
||||
innerLink.removeLock(item, innerLink);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
public DimLink getRandomLink()
|
||||
{
|
||||
if (linkMapping.isEmpty())
|
||||
{
|
||||
public DimLink getRandomLink() {
|
||||
if (linkMapping.isEmpty()) {
|
||||
throw new IllegalStateException("There are no links to select from in this dimension.");
|
||||
}
|
||||
if (linkList.size() > 1)
|
||||
{
|
||||
} if (linkList.size() > 1) {
|
||||
return linkList.get(random.nextInt(linkList.size()));
|
||||
}
|
||||
return linkList.get(0);
|
||||
}
|
||||
|
||||
public Iterable<? extends DimLink> getChunkLinks(int chunkX, int chunkZ)
|
||||
{
|
||||
public Iterable<? extends DimLink> getChunkLinks(int chunkX, int chunkZ) {
|
||||
List<InnerDimLink> chunkLinks = chunkMapping.get(new ChunkCoordIntPair(chunkX, chunkZ));
|
||||
if (chunkLinks != null)
|
||||
{
|
||||
if (chunkLinks != null) {
|
||||
return chunkLinks;
|
||||
}
|
||||
return new ArrayList<InnerDimLink>(0);
|
||||
}
|
||||
|
||||
public boolean isModified()
|
||||
{
|
||||
public boolean isModified() {
|
||||
return modified;
|
||||
}
|
||||
|
||||
public void clearModified()
|
||||
{
|
||||
public void clearModified() {
|
||||
this.modified = false;
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
public void clear() {
|
||||
// If this dimension has a parent, remove it from its parent's list of children
|
||||
if (parent != null)
|
||||
{
|
||||
if (parent != null) {
|
||||
parent.children.remove(this);
|
||||
}
|
||||
// Remove this dimension as the parent of its children
|
||||
for (NewDimData child : children)
|
||||
{
|
||||
for (NewDimData child : children) {
|
||||
child.parent = null;
|
||||
}
|
||||
// Clear all fields
|
||||
|
@ -754,62 +629,52 @@ public abstract class NewDimData implements IPackable<PackedDimData>
|
|||
depth = Integer.MIN_VALUE;
|
||||
packDepth = Integer.MIN_VALUE;
|
||||
origin = null;
|
||||
orientation = Integer.MIN_VALUE;
|
||||
orientation = EnumFacing.SOUTH;
|
||||
dungeon = null;
|
||||
linkWatcher = null;
|
||||
}
|
||||
|
||||
public PackedDimData pack()
|
||||
{
|
||||
public PackedDimData pack() {
|
||||
ArrayList<Integer> ChildIDs = new ArrayList<Integer>();
|
||||
ArrayList<PackedLinkData> Links = new ArrayList<PackedLinkData>();
|
||||
ArrayList<PackedLinkTail> Tails = new ArrayList<PackedLinkTail>();
|
||||
PackedDungeonData packedDungeon=null;
|
||||
|
||||
if(this.dungeon!=null)
|
||||
{
|
||||
if(this.dungeon!=null) {
|
||||
packedDungeon= new PackedDungeonData(dungeon.weight(), dungeon.isOpen(), dungeon.isInternal(),
|
||||
dungeon.schematicPath(), dungeon.schematicName(), dungeon.dungeonType().Name,
|
||||
dungeon.dungeonType().Owner.getName());
|
||||
}
|
||||
//Make a list of children
|
||||
for(NewDimData data : this.children)
|
||||
{
|
||||
for(NewDimData data : this.children) {
|
||||
ChildIDs.add(data.id);
|
||||
}
|
||||
for(DimLink link:this.links())
|
||||
{
|
||||
ArrayList<Point3D> children = new ArrayList<Point3D>();
|
||||
Point3D parentPoint = new Point3D(-1,-1,-1);
|
||||
if(link.parent!=null)
|
||||
{
|
||||
parentPoint=link.parent.point.toPoint3D();
|
||||
for(DimLink link:this.links()) {
|
||||
ArrayList<BlockPos> children = new ArrayList<BlockPos>();
|
||||
BlockPos parentPoint = new BlockPos(-1,-1,-1);
|
||||
if(link.parent!=null) {
|
||||
parentPoint=link.parent.point.toBlockPos();
|
||||
}
|
||||
|
||||
for(DimLink childLink : link.children)
|
||||
{
|
||||
children.add(childLink.source().toPoint3D());
|
||||
for(DimLink childLink : link.children) {
|
||||
children.add(childLink.source().toBlockPos());
|
||||
}
|
||||
PackedLinkTail tail = new PackedLinkTail(link.tail.getDestination(),link.tail.getLinkType());
|
||||
Links.add(new PackedLinkData(link.point,parentPoint,tail,link.orientation,children,link.lock));
|
||||
|
||||
PackedLinkTail tempTail = new PackedLinkTail(link.tail.getDestination(),link.tail.getLinkType());
|
||||
if(Tails.contains(tempTail))
|
||||
{
|
||||
if(Tails.contains(tempTail)) {
|
||||
Tails.add(tempTail);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
int parentID=this.id;
|
||||
Point3D originPoint=new Point3D(0,0,0);
|
||||
if(this.parent!=null)
|
||||
{
|
||||
BlockPos originPoint=new BlockPos(0,0,0);
|
||||
if(this.parent!=null) {
|
||||
parentID = this.parent.id;
|
||||
}
|
||||
if(this.origin!=null)
|
||||
{
|
||||
originPoint=this.origin.toPoint3D();
|
||||
} if(this.origin!=null) {
|
||||
originPoint=this.origin.toBlockPos();
|
||||
}
|
||||
return new PackedDimData(this.id, depth, this.packDepth, parentID, this.root().id(), orientation,
|
||||
type, isFilled,packedDungeon, originPoint, ChildIDs, Links, Tails);
|
||||
|
|
|
@ -8,7 +8,6 @@ import java.util.ArrayList;
|
|||
import java.util.Random;
|
||||
|
||||
import com.zixiken.dimdoors.DimDoors;
|
||||
import com.zixiken.dimdoors.Point3D;
|
||||
import com.zixiken.dimdoors.blocks.IDimDoor;
|
||||
import com.zixiken.dimdoors.config.DDProperties;
|
||||
import com.zixiken.dimdoors.core.DimLink;
|
||||
|
@ -22,6 +21,8 @@ import net.minecraft.init.Blocks;
|
|||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntitySign;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.world.World;
|
||||
import com.zixiken.dimdoors.core.NewDimData;
|
||||
import com.zixiken.dimdoors.schematic.BlockRotator;
|
||||
|
@ -37,15 +38,14 @@ public class DungeonSchematic extends Schematic {
|
|||
|
||||
private static final int NETHER_DIMENSION_ID = -1;
|
||||
|
||||
private int orientation;
|
||||
private Point3D entranceDoorLocation;
|
||||
private ArrayList<Point3D> exitDoorLocations;
|
||||
private ArrayList<Point3D> dimensionalDoorLocations;
|
||||
private ArrayList<Point3D> monolithSpawnLocations;
|
||||
private EnumFacing orientation;
|
||||
private BlockPos entranceDoorLocation;
|
||||
private ArrayList<BlockPos> exitDoorLocations;
|
||||
private ArrayList<BlockPos> dimensionalDoorLocations;
|
||||
private ArrayList<BlockPos> monolithSpawnLocations;
|
||||
private ArrayList<Block> modBlockFilterExceptions;
|
||||
|
||||
private DungeonSchematic(Schematic source)
|
||||
{
|
||||
private DungeonSchematic(Schematic source) {
|
||||
super(source);
|
||||
modBlockFilterExceptions = new ArrayList<Block>(5);
|
||||
modBlockFilterExceptions.add(DimDoors.blockDimWall);
|
||||
|
@ -55,54 +55,45 @@ public class DungeonSchematic extends Schematic {
|
|||
modBlockFilterExceptions.add(DimDoors.transientDoor);
|
||||
}
|
||||
|
||||
public int getOrientation()
|
||||
{
|
||||
public EnumFacing getOrientation() {
|
||||
return orientation;
|
||||
}
|
||||
|
||||
public Point3D getEntranceDoorLocation()
|
||||
{
|
||||
return (entranceDoorLocation != null) ? entranceDoorLocation.clone() : null;
|
||||
public BlockPos getEntranceDoorLocation() {
|
||||
return (entranceDoorLocation != null) ? entranceDoorLocation : null;
|
||||
}
|
||||
|
||||
private DungeonSchematic()
|
||||
{
|
||||
private DungeonSchematic() {
|
||||
//Used to create a dummy instance for readFromResource()
|
||||
super((short) 0, (short) 0, (short) 0, null, null, null);
|
||||
super(BlockPos.ORIGIN, null, null);
|
||||
}
|
||||
|
||||
public static DungeonSchematic readFromFile(String schematicPath) throws FileNotFoundException, InvalidSchematicException
|
||||
{
|
||||
public static DungeonSchematic readFromFile(String schematicPath) throws FileNotFoundException, InvalidSchematicException {
|
||||
return readFromFile(new File(schematicPath));
|
||||
}
|
||||
|
||||
public static DungeonSchematic readFromFile(File schematicFile) throws FileNotFoundException, InvalidSchematicException
|
||||
{
|
||||
public static DungeonSchematic readFromFile(File schematicFile) throws FileNotFoundException, InvalidSchematicException {
|
||||
return readFromStream(new FileInputStream(schematicFile));
|
||||
}
|
||||
|
||||
public static DungeonSchematic readFromResource(String resourcePath) throws InvalidSchematicException
|
||||
{
|
||||
public static DungeonSchematic readFromResource(String resourcePath) throws InvalidSchematicException {
|
||||
//We need an instance of a class in the mod to retrieve a resource
|
||||
DungeonSchematic empty = new DungeonSchematic();
|
||||
InputStream schematicStream = empty.getClass().getResourceAsStream(resourcePath);
|
||||
return readFromStream(schematicStream);
|
||||
}
|
||||
|
||||
public static DungeonSchematic readFromStream(InputStream schematicStream) throws InvalidSchematicException
|
||||
{
|
||||
public static DungeonSchematic readFromStream(InputStream schematicStream) throws InvalidSchematicException {
|
||||
return new DungeonSchematic(Schematic.readFromStream(schematicStream));
|
||||
}
|
||||
|
||||
public void applyImportFilters(DDProperties properties)
|
||||
{
|
||||
public void applyImportFilters(DDProperties properties) {
|
||||
//Search for special blocks (warp doors, dim doors, and end portal frames that mark Monolith spawn points)
|
||||
SpecialBlockFinder finder = new SpecialBlockFinder(DimDoors.warpDoor, DimDoors.dimensionalDoor,
|
||||
Blocks.end_portal_frame, Blocks.sandstone);
|
||||
applyFilter(finder);
|
||||
Blocks.end_portal_frame, Blocks.sandstone);applyFilter(finder);
|
||||
|
||||
//Flip the entrance's orientation to get the dungeon's orientation
|
||||
orientation = BlockRotator.transformMetadata(finder.getEntranceOrientation(), 2, Blocks.wooden_door);
|
||||
orientation = BlockRotator.transformMetadata(finder.getEntranceOrientation(), 2, Blocks.oak_door);
|
||||
|
||||
entranceDoorLocation = finder.getEntranceDoorLocation();
|
||||
exitDoorLocations = finder.getExitDoorLocations();
|
||||
|
@ -111,8 +102,7 @@ public class DungeonSchematic extends Schematic {
|
|||
|
||||
//Filter out mod blocks except some of our own
|
||||
CompoundFilter standardizer = new CompoundFilter();
|
||||
standardizer.addFilter(new ModBlockFilter(modBlockFilterExceptions,
|
||||
DimDoors.blockDimWall, (byte) 0));
|
||||
standardizer.addFilter(new ModBlockFilter(modBlockFilterExceptions, DimDoors.blockDimWall.getDefaultState()));
|
||||
|
||||
//Also convert standard DD block IDs to local versions
|
||||
applyFilter(standardizer);
|
||||
|
@ -126,8 +116,7 @@ public class DungeonSchematic extends Schematic {
|
|||
|
||||
//Filter out mod blocks except some of our own
|
||||
//This comes after ID standardization because the mod block filter relies on standardized IDs
|
||||
standardizer.addFilter(new ModBlockFilter(modBlockFilterExceptions,
|
||||
DimDoors.blockDimWall, (byte) 0));
|
||||
standardizer.addFilter(new ModBlockFilter(modBlockFilterExceptions, DimDoors.blockDimWall.getDefaultState()));
|
||||
|
||||
applyFilter(standardizer);
|
||||
}
|
||||
|
@ -137,7 +126,7 @@ public class DungeonSchematic extends Schematic {
|
|||
return new DungeonSchematic(Schematic.copyFromWorld(world, x, y, z, width, height, length, doCompactBounds));
|
||||
}
|
||||
|
||||
public void copyToWorld(World world, Point3D pocketCenter, int targetOrientation, DimLink entryLink,
|
||||
public void copyToWorld(World world, BlockPos pocketCenter, int targetOrientation, DimLink entryLink,
|
||||
Random random, DDProperties properties, boolean notifyClients)
|
||||
{
|
||||
if (notifyClients)
|
||||
|
@ -150,8 +139,7 @@ public class DungeonSchematic extends Schematic {
|
|||
}
|
||||
}
|
||||
|
||||
public void copyToWorld(World world, Point3D pocketCenter, int targetOrientation, DimLink entryLink,
|
||||
Random random, DDProperties properties, IBlockSetter blockSetter)
|
||||
public void copyToWorld(World world, BlockPos pocketCenter, int targetOrientation, DimLink entryLink, Random random, DDProperties properties, IBlockSetter blockSetter)
|
||||
{
|
||||
//TODO: This function is an improvised solution so we can get the release moving. In the future,
|
||||
//we should generalize block transformations and implement support for them at the level of Schematic,
|
||||
|
@ -165,7 +153,7 @@ public class DungeonSchematic extends Schematic {
|
|||
Block block;
|
||||
int blockMeta;
|
||||
int dx, dy, dz;
|
||||
Point3D pocketPoint = new Point3D(0, 0, 0);
|
||||
BlockPos pocketPoint = new BlockPos(0, 0, 0);
|
||||
|
||||
//Copy blocks and metadata into the world
|
||||
index = 0;
|
||||
|
@ -208,11 +196,11 @@ public class DungeonSchematic extends Schematic {
|
|||
setUpDungeon(PocketManager.createDimensionData(world), world, pocketCenter, turnAngle, entryLink, random, properties, blockSetter);
|
||||
}
|
||||
|
||||
private void setUpDungeon(NewDimData dimension, World world, Point3D pocketCenter, int turnAngle, DimLink entryLink, Random random, DDProperties properties, IBlockSetter blockSetter)
|
||||
private void setUpDungeon(NewDimData dimension, World world, BlockPos pocketCenter, int turnAngle, DimLink entryLink, Random random, DDProperties properties, IBlockSetter blockSetter)
|
||||
{
|
||||
//Transform dungeon corners
|
||||
Point3D minCorner = new Point3D(0, 0, 0);
|
||||
Point3D maxCorner = new Point3D(width - 1, height - 1, length - 1);
|
||||
BlockPos minCorner = new BlockPos(0, 0, 0);
|
||||
BlockPos maxCorner = new BlockPos(width - 1, height - 1, length - 1);
|
||||
transformCorners(entranceDoorLocation, pocketCenter, turnAngle, minCorner, maxCorner);
|
||||
|
||||
//Fill empty chests and dispensers
|
||||
|
@ -223,20 +211,20 @@ public class DungeonSchematic extends Schematic {
|
|||
createEntranceReverseLink(world, dimension, pocketCenter, entryLink);
|
||||
|
||||
//Set up link data for dimensional doors
|
||||
for (Point3D location : dimensionalDoorLocations)
|
||||
for (BlockPos location : dimensionalDoorLocations)
|
||||
{
|
||||
createDimensionalDoorLink(world, dimension, location, entranceDoorLocation, turnAngle, pocketCenter);
|
||||
}
|
||||
|
||||
//Set up link data for exit door
|
||||
for (Point3D location : exitDoorLocations)
|
||||
for (BlockPos location : exitDoorLocations)
|
||||
{
|
||||
createExitDoorLink(world, dimension, location, entranceDoorLocation, turnAngle, pocketCenter, blockSetter);
|
||||
}
|
||||
|
||||
//Remove end portal frames and spawn Monoliths, if allowed
|
||||
boolean canSpawn = CustomLimboPopulator.isMobSpawningAllowed();
|
||||
for (Point3D location : monolithSpawnLocations)
|
||||
for (BlockPos location : monolithSpawnLocations)
|
||||
{
|
||||
spawnMonolith(world, location, entranceDoorLocation, turnAngle, pocketCenter, canSpawn, blockSetter);
|
||||
}
|
||||
|
@ -252,32 +240,26 @@ public class DungeonSchematic extends Schematic {
|
|||
}
|
||||
}
|
||||
|
||||
private static void transformCorners(Point3D schematicEntrance, Point3D pocketCenter, int turnAngle, Point3D minCorner, Point3D maxCorner)
|
||||
{
|
||||
private static void transformCorners(BlockPos schematicEntrance, BlockPos pocketCenter, EnumFacing turnAngle, BlockPos minCorner, BlockPos maxCorner) {
|
||||
int temp;
|
||||
BlockRotator.transformPoint(minCorner, schematicEntrance, turnAngle, pocketCenter);
|
||||
BlockRotator.transformPoint(maxCorner, schematicEntrance, turnAngle, pocketCenter);
|
||||
if (minCorner.getX() > maxCorner.getX())
|
||||
{
|
||||
if (minCorner.getX() > maxCorner.getX()) {
|
||||
temp = minCorner.getX();
|
||||
minCorner.setX(maxCorner.getX());
|
||||
maxCorner.setX(temp);
|
||||
}
|
||||
if (minCorner.getY() > maxCorner.getY())
|
||||
{
|
||||
minCorner = new BlockPos(maxCorner.getX(), minCorner.getY(), minCorner.getZ());
|
||||
maxCorner = new BlockPos(temp, maxCorner.getY(), maxCorner.getZ());
|
||||
} if (minCorner.getY() > maxCorner.getY()) {
|
||||
temp = minCorner.getY();
|
||||
minCorner.setY(maxCorner.getY());
|
||||
maxCorner.setY(temp);
|
||||
}
|
||||
if (minCorner.getZ() > maxCorner.getZ())
|
||||
{
|
||||
} if (minCorner.getZ() > maxCorner.getZ()) {
|
||||
temp = minCorner.getZ();
|
||||
minCorner.setZ(maxCorner.getZ());
|
||||
maxCorner.setZ(temp);
|
||||
}
|
||||
}
|
||||
|
||||
private static void createEntranceReverseLink(World world, NewDimData dimension, Point3D pocketCenter, DimLink entryLink)
|
||||
private static void createEntranceReverseLink(World world, NewDimData dimension, BlockPos pocketCenter, DimLink entryLink)
|
||||
{
|
||||
int orientation = world.getBlockMetadata(pocketCenter.getX(), pocketCenter.getY() - 1, pocketCenter.getZ());
|
||||
DimLink reverseLink = dimension.createLink(pocketCenter.getX(), pocketCenter.getY(), pocketCenter.getZ(), LinkType.REVERSE, orientation);
|
||||
|
@ -287,10 +269,10 @@ public class DungeonSchematic extends Schematic {
|
|||
initDoorTileEntity(world, pocketCenter);
|
||||
}
|
||||
|
||||
private static void createExitDoorLink(World world, NewDimData dimension, Point3D point, Point3D entrance, int rotation, Point3D pocketCenter, IBlockSetter blockSetter)
|
||||
private static void createExitDoorLink(World world, NewDimData dimension, BlockPos point, BlockPos entrance, EnumFacing rotation, BlockPos pocketCenter, IBlockSetter blockSetter)
|
||||
{
|
||||
//Transform the door's location to the pocket coordinate system
|
||||
Point3D location = point.clone();
|
||||
BlockPos location = point;
|
||||
BlockRotator.transformPoint(location, entrance, rotation, pocketCenter);
|
||||
int orientation = world.getBlockMetadata(location.getX(), location.getY() - 1, location.getZ());
|
||||
dimension.createLink(location.getX(), location.getY(), location.getZ(), LinkType.DUNGEON_EXIT, orientation);
|
||||
|
@ -307,10 +289,10 @@ public class DungeonSchematic extends Schematic {
|
|||
initDoorTileEntity(world, location);
|
||||
}
|
||||
|
||||
private static void createDimensionalDoorLink(World world, NewDimData dimension, Point3D point, Point3D entrance, int rotation, Point3D pocketCenter)
|
||||
private static void createDimensionalDoorLink(World world, NewDimData dimension, BlockPos point, BlockPos entrance, int rotation, BlockPos pocketCenter)
|
||||
{
|
||||
//Transform the door's location to the pocket coordinate system
|
||||
Point3D location = point.clone();
|
||||
BlockPos location = point.clone();
|
||||
BlockRotator.transformPoint(location, entrance, rotation, pocketCenter);
|
||||
int orientation = world.getBlockMetadata(location.getX(), location.getY() - 1, location.getZ());
|
||||
|
||||
|
@ -318,10 +300,10 @@ public class DungeonSchematic extends Schematic {
|
|||
initDoorTileEntity(world, location);
|
||||
}
|
||||
|
||||
private static void spawnMonolith(World world, Point3D point, Point3D entrance, int rotation, Point3D pocketCenter, boolean canSpawn, IBlockSetter blockSetter)
|
||||
private static void spawnMonolith(World world, BlockPos point, BlockPos entrance, int rotation, BlockPos pocketCenter, boolean canSpawn, IBlockSetter blockSetter)
|
||||
{
|
||||
//Transform the frame block's location to the pocket coordinate system
|
||||
Point3D location = point.clone();
|
||||
BlockPos location = point.clone();
|
||||
BlockRotator.transformPoint(location, entrance, rotation, pocketCenter);
|
||||
//Remove frame block
|
||||
blockSetter.setBlock(world, location.getX(), location.getY(), location.getZ(), Blocks.air, 0);
|
||||
|
@ -334,7 +316,7 @@ public class DungeonSchematic extends Schematic {
|
|||
}
|
||||
}
|
||||
|
||||
private static void initDoorTileEntity(World world, Point3D point)
|
||||
private static void initDoorTileEntity(World world, BlockPos point)
|
||||
{
|
||||
Block door = world.getBlock(point.getX(), point.getY(), point.getZ());
|
||||
Block door2 = world.getBlock(point.getX(), point.getY() - 1, point.getZ());
|
||||
|
@ -350,7 +332,7 @@ public class DungeonSchematic extends Schematic {
|
|||
}
|
||||
}
|
||||
|
||||
private static void writeDepthSign(World world, Point3D pocketCenter, int depth)
|
||||
private static void writeDepthSign(World world, BlockPos pocketCenter, int depth)
|
||||
{
|
||||
final int SEARCH_RANGE = 6;
|
||||
|
||||
|
|
|
@ -2,42 +2,36 @@ package com.zixiken.dimdoors.dungeon;
|
|||
|
||||
import net.minecraft.block.Block;
|
||||
import com.zixiken.dimdoors.schematic.SchematicFilter;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ModBlockFilter extends SchematicFilter {
|
||||
|
||||
private List<Block> exceptions;
|
||||
private Block replacementBlock;
|
||||
private byte replacementMetadata;
|
||||
private IBlockState replacementState;
|
||||
|
||||
public ModBlockFilter(List<Block> exceptions, Block replacementBlock, byte replacementMetadata)
|
||||
public ModBlockFilter(List<Block> exceptions, IBlockState state)
|
||||
{
|
||||
super("ModBlockFilter");
|
||||
this.exceptions = exceptions;
|
||||
this.replacementBlock = replacementBlock;
|
||||
this.replacementMetadata = replacementMetadata;
|
||||
this.replacementState = state;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean applyToBlock(int index, Block[] blocks, byte[] metadata)
|
||||
{
|
||||
protected boolean applyToBlock(int index, IBlockState[] state) {
|
||||
int k;
|
||||
Block current = blocks[index];
|
||||
if (!Block.blockRegistry.getNameForObject(current).startsWith("minecraft:"))
|
||||
{
|
||||
Block current = state[index].getBlock();
|
||||
if (!Block.blockRegistry.getNameForObject(current).getResourcePath().startsWith("minecraft:")) {
|
||||
//This might be a mod block. Check if an exception exists.
|
||||
for (k = 0; k < exceptions.size(); k++)
|
||||
{
|
||||
if (current == exceptions.get(k))
|
||||
{
|
||||
for (k = 0; k < exceptions.size(); k++) {
|
||||
if (current == exceptions.get(k)) {
|
||||
//Exception found, not considered a mod block
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//No matching exception found. Replace the block.
|
||||
blocks[index] = replacementBlock;
|
||||
metadata[index] = replacementMetadata;
|
||||
state[index] = replacementState;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -2,10 +2,13 @@ package com.zixiken.dimdoors.dungeon;
|
|||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.zixiken.dimdoors.Point3D;
|
||||
import com.zixiken.dimdoors.schematic.Schematic;
|
||||
import com.zixiken.dimdoors.schematic.SchematicFilter;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockDoor;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
|
||||
public class SpecialBlockFinder extends SchematicFilter {
|
||||
|
||||
|
@ -13,94 +16,79 @@ public class SpecialBlockFinder extends SchematicFilter {
|
|||
private Block dimensionalDoor;
|
||||
private Block monolithSpawnMarker;
|
||||
private Block exitMarker;
|
||||
private int entranceOrientation;
|
||||
private EnumFacing entranceOrientation;
|
||||
private Schematic schematic;
|
||||
private Point3D entranceDoorLocation;
|
||||
private ArrayList<Point3D> exitDoorLocations;
|
||||
private ArrayList<Point3D> dimensionalDoorLocations;
|
||||
private ArrayList<Point3D> monolithSpawnLocations;
|
||||
private BlockPos entranceDoorLocation;
|
||||
private ArrayList<BlockPos> exitDoorLocations;
|
||||
private ArrayList<BlockPos> dimensionalDoorLocations;
|
||||
private ArrayList<BlockPos> monolithSpawnLocations;
|
||||
|
||||
public SpecialBlockFinder(Block warpDoor, Block dimensionalDoor, Block monolithSpawn, Block exitDoor)
|
||||
{
|
||||
public SpecialBlockFinder(Block warpDoor, Block dimensionalDoor, Block monolithSpawn, Block exitDoor) {
|
||||
super("SpecialBlockFinder");
|
||||
this.warpDoor = warpDoor;
|
||||
this.dimensionalDoor = dimensionalDoor;
|
||||
this.monolithSpawnMarker = monolithSpawn;
|
||||
this.exitMarker = exitDoor;
|
||||
this.entranceDoorLocation = null;
|
||||
this.entranceOrientation = 0;
|
||||
this.exitDoorLocations = new ArrayList<Point3D>();
|
||||
this.dimensionalDoorLocations = new ArrayList<Point3D>();
|
||||
this.monolithSpawnLocations = new ArrayList<Point3D>();
|
||||
this.entranceOrientation = EnumFacing.SOUTH;
|
||||
this.exitDoorLocations = new ArrayList<BlockPos>();
|
||||
this.dimensionalDoorLocations = new ArrayList<BlockPos>();
|
||||
this.monolithSpawnLocations = new ArrayList<BlockPos>();
|
||||
this.schematic = null;
|
||||
}
|
||||
|
||||
public int getEntranceOrientation() {
|
||||
public EnumFacing getEntranceOrientation() {
|
||||
return entranceOrientation;
|
||||
}
|
||||
|
||||
public Point3D getEntranceDoorLocation() {
|
||||
public BlockPos getEntranceDoorLocation() {
|
||||
return entranceDoorLocation;
|
||||
}
|
||||
|
||||
public ArrayList<Point3D> getExitDoorLocations() {
|
||||
public ArrayList<BlockPos> getExitDoorLocations() {
|
||||
return exitDoorLocations;
|
||||
}
|
||||
|
||||
public ArrayList<Point3D> getDimensionalDoorLocations() {
|
||||
public ArrayList<BlockPos> getDimensionalDoorLocations() {
|
||||
return dimensionalDoorLocations;
|
||||
}
|
||||
|
||||
public ArrayList<Point3D> getMonolithSpawnLocations() {
|
||||
public ArrayList<BlockPos> getMonolithSpawnLocations() {
|
||||
return monolithSpawnLocations;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean initialize(Schematic schematic, Block[] blocks, byte[] metadata)
|
||||
{
|
||||
protected boolean initialize(Schematic schematic, IBlockState[] state) {
|
||||
this.schematic = schematic;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean applyToBlock(int index, Block[] blocks, byte[] metadata)
|
||||
{
|
||||
protected boolean applyToBlock(int index, IBlockState[] state) {
|
||||
int indexBelow;
|
||||
int indexDoubleBelow;
|
||||
|
||||
if (blocks[index] == monolithSpawnMarker)
|
||||
{
|
||||
if (state[index] == monolithSpawnMarker) {
|
||||
monolithSpawnLocations.add(schematic.calculatePoint(index));
|
||||
return true;
|
||||
}
|
||||
if (blocks[index] == dimensionalDoor)
|
||||
{
|
||||
} if (state[index] == dimensionalDoor) {
|
||||
indexBelow = schematic.calculateIndexBelow(index);
|
||||
if (indexBelow >= 0 && blocks[indexBelow] == dimensionalDoor)
|
||||
{
|
||||
if (indexBelow >= 0 && state[indexBelow] == dimensionalDoor) {
|
||||
dimensionalDoorLocations.add(schematic.calculatePoint(index));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (blocks[index] == warpDoor)
|
||||
{
|
||||
} if (state[index] == warpDoor) {
|
||||
indexBelow = schematic.calculateIndexBelow(index);
|
||||
if (indexBelow >= 0 && blocks[indexBelow] == warpDoor)
|
||||
{
|
||||
if (indexBelow >= 0 && state[indexBelow] == warpDoor) {
|
||||
indexDoubleBelow = schematic.calculateIndexBelow(indexBelow);
|
||||
if (indexDoubleBelow >= 0 && blocks[indexDoubleBelow] == exitMarker)
|
||||
{
|
||||
if (indexDoubleBelow >= 0 && state[indexDoubleBelow] == exitMarker) {
|
||||
exitDoorLocations.add(schematic.calculatePoint(index));
|
||||
return true;
|
||||
}
|
||||
else if (entranceDoorLocation == null)
|
||||
{
|
||||
} else if (entranceDoorLocation == null) {
|
||||
entranceDoorLocation = schematic.calculatePoint(index);
|
||||
entranceOrientation = (metadata[indexBelow] & 3);
|
||||
entranceOrientation = state[indexBelow].getValue(BlockDoor.FACING);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -109,8 +97,7 @@ public class SpecialBlockFinder extends SchematicFilter {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean terminates()
|
||||
{
|
||||
protected boolean terminates() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,58 +1,39 @@
|
|||
package com.zixiken.dimdoors.experimental;
|
||||
|
||||
import com.zixiken.dimdoors.Point3D;
|
||||
import com.zixiken.dimdoors.helpers.BlockPosHelper;
|
||||
import net.minecraft.util.BlockPos;
|
||||
|
||||
public class BoundingBox
|
||||
{
|
||||
protected Point3D minCorner;
|
||||
protected Point3D maxCorner;
|
||||
public class BoundingBox {
|
||||
protected BlockPos minCorner;
|
||||
protected BlockPos maxCorner;
|
||||
|
||||
public BoundingBox(int x, int y, int z, int width, int height, int length)
|
||||
{
|
||||
this.minCorner = new Point3D(x, y, z);
|
||||
this.maxCorner = new Point3D(x + width - 1, y + height - 1, z + length - 1);
|
||||
public BoundingBox(int x, int y, int z, int width, int height, int length) {
|
||||
this.minCorner = new BlockPos(x, y, z);
|
||||
this.maxCorner = new BlockPos(x + width - 1, y + height - 1, z + length - 1);
|
||||
}
|
||||
|
||||
public BoundingBox(Point3D minCorner, Point3D maxCorner)
|
||||
{
|
||||
public BoundingBox(BlockPos minCorner, BlockPos maxCorner) {
|
||||
this.minCorner = minCorner;
|
||||
this.maxCorner = maxCorner;
|
||||
}
|
||||
|
||||
public int width()
|
||||
{
|
||||
return (maxCorner.getX() - minCorner.getX() + 1);
|
||||
public BlockPos volume() {
|
||||
return maxCorner.subtract(minCorner).add(1,1,1);
|
||||
}
|
||||
|
||||
public int height()
|
||||
{
|
||||
return (maxCorner.getY() - minCorner.getY() + 1);
|
||||
}
|
||||
|
||||
public int length()
|
||||
{
|
||||
return (maxCorner.getZ() - minCorner.getZ() + 1);
|
||||
}
|
||||
|
||||
public Point3D minCorner()
|
||||
{
|
||||
public BlockPos minCorner() {
|
||||
return minCorner;
|
||||
}
|
||||
|
||||
public Point3D maxCorner()
|
||||
{
|
||||
public BlockPos maxCorner() {
|
||||
return maxCorner;
|
||||
}
|
||||
|
||||
public boolean contains(int x, int y, int z)
|
||||
{
|
||||
return ((minCorner.getX() <= x && x <= maxCorner.getX()) &&
|
||||
(minCorner.getY() <= y && y <= maxCorner.getY()) &&
|
||||
(minCorner.getZ() <= z && z <= maxCorner.getZ()));
|
||||
public boolean contains(BlockPos pos) {
|
||||
return BlockPosHelper.between(pos, minCorner, maxCorner);
|
||||
}
|
||||
|
||||
public boolean intersects(BoundingBox other)
|
||||
{
|
||||
public boolean intersects(BoundingBox other) {
|
||||
// To be clear, having one box inside another counts as intersecting
|
||||
|
||||
boolean xi = (this.minCorner.getX() <= other.minCorner.getX() && other.minCorner.getX() <= this.maxCorner.getX()) ||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.zixiken.dimdoors.experimental;
|
||||
|
||||
import com.zixiken.dimdoors.Point3D;
|
||||
import net.minecraft.util.BlockPos;
|
||||
|
||||
public class DoorwayData
|
||||
{
|
||||
|
@ -8,23 +9,23 @@ public class DoorwayData
|
|||
public static final char Y_AXIS = 'Y';
|
||||
public static final char Z_AXIS = 'Z';
|
||||
|
||||
private Point3D minCorner;
|
||||
private Point3D maxCorner;
|
||||
private BlockPos minCorner;
|
||||
private BlockPos maxCorner;
|
||||
private char axis;
|
||||
|
||||
public DoorwayData(Point3D minCorner, Point3D maxCorner, char axis)
|
||||
public DoorwayData(BlockPos minCorner, BlockPos maxCorner, char axis)
|
||||
{
|
||||
this.minCorner = minCorner;
|
||||
this.maxCorner = maxCorner;
|
||||
this.axis = axis;
|
||||
}
|
||||
|
||||
public Point3D minCorner()
|
||||
public BlockPos minCorner()
|
||||
{
|
||||
return minCorner;
|
||||
}
|
||||
|
||||
public Point3D maxCorner()
|
||||
public BlockPos maxCorner()
|
||||
{
|
||||
return maxCorner;
|
||||
}
|
||||
|
@ -34,18 +35,7 @@ public class DoorwayData
|
|||
return axis;
|
||||
}
|
||||
|
||||
public int width()
|
||||
{
|
||||
return (maxCorner.getX() - minCorner.getX() + 1);
|
||||
}
|
||||
|
||||
public int height()
|
||||
{
|
||||
return (maxCorner.getY() - minCorner.getY() + 1);
|
||||
}
|
||||
|
||||
public int length()
|
||||
{
|
||||
return (maxCorner.getZ() - minCorner.getZ() + 1);
|
||||
public BlockPos volume() {
|
||||
return maxCorner.subtract(minCorner).add(1,1,1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,19 +4,18 @@ import java.util.Random;
|
|||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
import com.zixiken.dimdoors.Point3D;
|
||||
|
||||
public class MazeBuilder
|
||||
{
|
||||
public class MazeBuilder {
|
||||
private MazeBuilder() { }
|
||||
|
||||
public static void generate(World world, int x, int y, int z, Random random)
|
||||
{
|
||||
public static void generate(World world, int x, int y, int z, Random random) {
|
||||
MazeDesign design = MazeDesigner.generate(random);
|
||||
Point3D offset = new Point3D(x - design.width() / 2, y - design.height() - 1, z - design.length() / 2);
|
||||
BlockPos offset = new BlockPos(x - design.width() / 2, y - design.height() - 1, z - design.length() / 2);
|
||||
SphereDecayOperation decay = new SphereDecayOperation(random, Blocks.air, 0, Blocks.stonebrick, 2);
|
||||
|
||||
buildRooms(design.getRoomGraph(), world, offset);
|
||||
|
@ -28,12 +27,12 @@ public class MazeBuilder
|
|||
}
|
||||
|
||||
private static void applyRandomDestruction(MazeDesign design, World world,
|
||||
Point3D offset, SphereDecayOperation decay, Random random)
|
||||
BlockPos offset, SphereDecayOperation decay, Random random)
|
||||
{
|
||||
//final int DECAY_BOX_SIZE = 8
|
||||
}
|
||||
|
||||
private static void buildRooms(DirectedGraph<PartitionNode, DoorwayData> roomGraph, World world, Point3D offset)
|
||||
private static void buildRooms(DirectedGraph<PartitionNode, DoorwayData> roomGraph, World world, BlockPos offset)
|
||||
{
|
||||
for (IGraphNode<PartitionNode, DoorwayData> node : roomGraph.nodes())
|
||||
{
|
||||
|
@ -43,10 +42,10 @@ public class MazeBuilder
|
|||
}
|
||||
|
||||
private static void carveDoorways(DirectedGraph<PartitionNode, DoorwayData> roomGraph, World world,
|
||||
Point3D offset, SphereDecayOperation decay, Random random)
|
||||
BlockPos offset, SphereDecayOperation decay, Random random)
|
||||
{
|
||||
char axis;
|
||||
Point3D lower;
|
||||
BlockPos lower;
|
||||
DoorwayData doorway;
|
||||
|
||||
for (IGraphNode<PartitionNode, DoorwayData> node : roomGraph.nodes())
|
||||
|
@ -168,7 +167,7 @@ public class MazeBuilder
|
|||
}
|
||||
|
||||
|
||||
private static void buildBox(World world, Point3D offset, Point3D minCorner, Point3D maxCorner, Block block, int metadata)
|
||||
private static void buildBox(World world, BlockPos offset, BlockPos minCorner, BlockPos maxCorner, Block block, int metadata)
|
||||
{
|
||||
int minX = minCorner.getX() + offset.getX();
|
||||
int minY = minCorner.getY() + offset.getY();
|
||||
|
|
|
@ -8,8 +8,9 @@ import java.util.Queue;
|
|||
import java.util.Random;
|
||||
import java.util.Stack;
|
||||
|
||||
import com.zixiken.dimdoors.helpers.BlockPosHelper;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import com.zixiken.dimdoors.Point3D;
|
||||
|
||||
public class MazeDesigner
|
||||
{
|
||||
|
@ -22,8 +23,7 @@ public class MazeDesigner
|
|||
|
||||
private MazeDesigner() { }
|
||||
|
||||
public static MazeDesign generate(Random random)
|
||||
{
|
||||
public static MazeDesign generate(Random random) {
|
||||
// Construct a random binary space partitioning of our maze volume
|
||||
PartitionNode root = partitionRooms(MAZE_WIDTH, MAZE_HEIGHT, MAZE_LENGTH, SPLIT_COUNT, random);
|
||||
|
||||
|
@ -48,100 +48,79 @@ public class MazeDesigner
|
|||
return new MazeDesign(root, rooms, cores);
|
||||
}
|
||||
|
||||
private static void listRoomPartitions(PartitionNode node, ArrayList<PartitionNode> partitions)
|
||||
{
|
||||
if (node.isLeaf())
|
||||
{
|
||||
private static void listRoomPartitions(PartitionNode node, ArrayList<PartitionNode> partitions) {
|
||||
if (node.isLeaf()) {
|
||||
partitions.add(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
listRoomPartitions(node.leftChild(), partitions);
|
||||
listRoomPartitions(node.rightChild(), partitions);
|
||||
}
|
||||
}
|
||||
|
||||
private static void removeRoomPartitions(PartitionNode node)
|
||||
{
|
||||
private static void removeRoomPartitions(PartitionNode node) {
|
||||
// Remove a node and any of its ancestors that become leaf nodes
|
||||
PartitionNode parent;
|
||||
PartitionNode current;
|
||||
|
||||
current = node;
|
||||
while (current != null && current.isLeaf())
|
||||
{
|
||||
while (current != null && current.isLeaf()) {
|
||||
parent = current.parent();
|
||||
current.remove();
|
||||
current = parent;
|
||||
}
|
||||
}
|
||||
|
||||
private static PartitionNode partitionRooms(int width, int height, int length, int maxLevels, Random random)
|
||||
{
|
||||
PartitionNode root = new PartitionNode(width, height, length);
|
||||
private static PartitionNode partitionRooms(int width, int height, int length, int maxLevels, Random random) {
|
||||
PartitionNode root = new PartitionNode(new BlockPos(width, height, length));
|
||||
splitByRandomX(root, maxLevels, random);
|
||||
return root;
|
||||
}
|
||||
|
||||
private static void splitByRandomX(PartitionNode node, int levels, Random random)
|
||||
{
|
||||
if (node.width() >= 2 * MIN_SIDE)
|
||||
{
|
||||
private static void splitByRandomX(PartitionNode node, int levels, Random random) {
|
||||
if (node.volume().getX() >= 2 * MIN_SIDE) {
|
||||
node.splitByX(MathHelper.getRandomIntegerInRange(random,
|
||||
node.minCorner().getX() + MIN_SIDE, node.maxCorner().getX() - MIN_SIDE + 1));
|
||||
|
||||
if (levels > 1)
|
||||
{
|
||||
if (levels > 1) {
|
||||
splitByRandomZ(node.leftChild(), levels - 1, random);
|
||||
splitByRandomZ(node.rightChild(), levels - 1, random);
|
||||
}
|
||||
}
|
||||
else if (levels > 1)
|
||||
{
|
||||
} else if (levels > 1) {
|
||||
splitByRandomZ(node, levels - 1, random);
|
||||
}
|
||||
}
|
||||
|
||||
private static void splitByRandomZ(PartitionNode node, int levels, Random random)
|
||||
{
|
||||
if (node.length() >= 2 * MIN_SIDE)
|
||||
{
|
||||
if (node.volume().getZ() >= 2 * MIN_SIDE) {
|
||||
node.splitByZ(MathHelper.getRandomIntegerInRange(random,
|
||||
node.minCorner().getZ() + MIN_SIDE, node.maxCorner().getZ() - MIN_SIDE + 1));
|
||||
|
||||
if (levels > 1)
|
||||
{
|
||||
if (levels > 1) {
|
||||
splitByRandomY(node.leftChild(), levels - 1, random);
|
||||
splitByRandomY(node.rightChild(), levels - 1, random);
|
||||
}
|
||||
}
|
||||
else if (levels > 1)
|
||||
{
|
||||
else if (levels > 1) {
|
||||
splitByRandomY(node, levels - 1, random);
|
||||
}
|
||||
}
|
||||
|
||||
private static void splitByRandomY(PartitionNode node, int levels, Random random)
|
||||
{
|
||||
if (node.height() >= 2 * MIN_HEIGHT)
|
||||
{
|
||||
private static void splitByRandomY(PartitionNode node, int levels, Random random) {
|
||||
if (node.volume().getY() >= 2 * MIN_HEIGHT) {
|
||||
node.splitByY(MathHelper.getRandomIntegerInRange(random,
|
||||
node.minCorner().getY() + MIN_HEIGHT, node.maxCorner().getY() - MIN_HEIGHT + 1));
|
||||
|
||||
if (levels > 1)
|
||||
{
|
||||
if (levels > 1) {
|
||||
splitByRandomX(node.leftChild(), levels - 1, random);
|
||||
splitByRandomX(node.rightChild(), levels - 1, random);
|
||||
}
|
||||
}
|
||||
else if (levels > 1)
|
||||
{
|
||||
} else if (levels > 1) {
|
||||
splitByRandomX(node, levels - 1, random);
|
||||
}
|
||||
}
|
||||
|
||||
private static DirectedGraph<PartitionNode, DoorwayData> createRoomGraph(PartitionNode root, ArrayList<PartitionNode> partitions, Random random)
|
||||
{
|
||||
private static DirectedGraph<PartitionNode, DoorwayData> createRoomGraph(PartitionNode root, ArrayList<PartitionNode> partitions, Random random) {
|
||||
DirectedGraph<PartitionNode, DoorwayData> roomGraph = new DirectedGraph<PartitionNode, DoorwayData>();
|
||||
HashMap<PartitionNode, IGraphNode<PartitionNode, DoorwayData>> roomsToGraph = new HashMap<PartitionNode, IGraphNode<PartitionNode, DoorwayData>>(2 * partitions.size());
|
||||
|
||||
|
@ -152,14 +131,12 @@ public class MazeDesigner
|
|||
// Add all rooms to a graph
|
||||
// Also add them to a map so we can associate rooms with their graph nodes
|
||||
// The map is needed for linking graph nodes based on adjacent partitions
|
||||
for (PartitionNode partition : partitions)
|
||||
{
|
||||
for (PartitionNode partition : partitions) {
|
||||
roomsToGraph.put(partition, roomGraph.addNode(partition));
|
||||
}
|
||||
|
||||
// Add edges for each room
|
||||
for (IGraphNode<PartitionNode, DoorwayData> node : roomGraph.nodes())
|
||||
{
|
||||
for (IGraphNode<PartitionNode, DoorwayData> node : roomGraph.nodes()) {
|
||||
findDoorways(node, root, roomsToGraph, roomGraph);
|
||||
}
|
||||
|
||||
|
@ -168,8 +145,7 @@ public class MazeDesigner
|
|||
|
||||
private static void findDoorways(IGraphNode<PartitionNode, DoorwayData> roomNode, PartitionNode root,
|
||||
HashMap<PartitionNode, IGraphNode<PartitionNode, DoorwayData>> roomsToGraph,
|
||||
DirectedGraph<PartitionNode, DoorwayData> roomGraph)
|
||||
{
|
||||
DirectedGraph<PartitionNode, DoorwayData> roomGraph) {
|
||||
// This function finds rooms adjacent to a specified room that could be connected
|
||||
// to it through a doorway. Edges are added to the room graph to denote rooms that
|
||||
// could be connected. The areas of their common bounds that could be carved
|
||||
|
@ -190,62 +166,43 @@ public class MazeDesigner
|
|||
|
||||
int a, b, c;
|
||||
int p, q, r;
|
||||
int minXI, minYI, minZI;
|
||||
int maxXI, maxYI, maxZI;
|
||||
Point3D otherMin;
|
||||
Point3D otherMax;
|
||||
BlockPos minI;
|
||||
BlockPos maxI;
|
||||
BlockPos diff;
|
||||
BlockPos otherMin;
|
||||
BlockPos otherMax;
|
||||
DoorwayData doorway;
|
||||
IGraphNode<PartitionNode, DoorwayData> adjacentNode;
|
||||
|
||||
PartitionNode room = roomNode.data();
|
||||
Point3D minCorner = room.minCorner();
|
||||
Point3D maxCorner = room.maxCorner();
|
||||
BlockPos minCorner = room.minCorner();
|
||||
BlockPos maxCorner = room.maxCorner();
|
||||
|
||||
int minX = minCorner.getX();
|
||||
int minY = minCorner.getY();
|
||||
int minZ = minCorner.getZ();
|
||||
BlockPos volume = room.volume();
|
||||
|
||||
int maxX = maxCorner.getX();
|
||||
int maxY = maxCorner.getY();
|
||||
int maxZ = maxCorner.getZ();
|
||||
|
||||
int width = room.width();
|
||||
int height = room.height();
|
||||
int length = room.length();
|
||||
|
||||
if (maxZ < root.maxCorner().getZ())
|
||||
{
|
||||
if (maxCorner.getZ() < root.maxCorner().getZ()) {
|
||||
// Check for adjacent rooms along the XY plane
|
||||
detected = new boolean[width][height];
|
||||
for (a = 0; a < width; a++)
|
||||
{
|
||||
for (b = 0; b < height; b++)
|
||||
{
|
||||
if (!detected[a][b])
|
||||
{
|
||||
adjacent = root.findPoint(minX + a, minY + b, maxZ + 1);
|
||||
if (adjacent != null)
|
||||
{
|
||||
detected = new boolean[volume.getX()][volume.getY()];
|
||||
for (a = 0; a < volume.getX(); a++) {
|
||||
for (b = 0; b < volume.getY(); b++) {
|
||||
if (!detected[a][b]) {
|
||||
adjacent = root.findPoint(minCorner.add(a, b, 1));
|
||||
if (adjacent != null) {
|
||||
// Compute the dimensions available for a doorway
|
||||
otherMin = adjacent.minCorner();
|
||||
otherMax = adjacent.maxCorner();
|
||||
minXI = Math.max(minX, otherMin.getX());
|
||||
maxXI = Math.min(maxX, otherMax.getX());
|
||||
minYI = Math.max(minY, otherMin.getY());
|
||||
maxYI = Math.min(maxY, otherMax.getY());
|
||||
minI = BlockPosHelper.max(minCorner, adjacent.minCorner());
|
||||
maxI = BlockPosHelper.min(maxCorner, adjacent.maxCorner());
|
||||
diff = maxI.subtract(minI);
|
||||
|
||||
for (p = 0; p <= maxXI - minXI; p++)
|
||||
{
|
||||
for (q = 0; q <= maxYI - minYI; q++)
|
||||
{
|
||||
for (p = 0; p <= diff.getX(); p++) {
|
||||
for (q = 0; q <= diff.getY(); q++) {
|
||||
detected[p + a][q + b] = true;
|
||||
}
|
||||
}
|
||||
// Check if we meet the minimum dimensions needed for a doorway
|
||||
if (maxXI - minXI + 1 >= MIN_SIDE && maxYI - minYI + 1 >= MIN_HEIGHT)
|
||||
if (diff.add(1,0,0).getX() + 1 >= MIN_SIDE && maxYI - minYI + 1 >= MIN_HEIGHT)
|
||||
{
|
||||
otherMin = new Point3D(minXI, minYI, maxZ);
|
||||
otherMax = new Point3D(maxXI, maxYI, maxZ + 1);
|
||||
otherMin = new BlockPos(minXI, minYI, maxZ);
|
||||
otherMax = new BlockPos(maxXI, maxYI, maxZ + 1);
|
||||
doorway = new DoorwayData(otherMin, otherMax, DoorwayData.Z_AXIS);
|
||||
adjacentNode = roomsToGraph.get(adjacent);
|
||||
roomGraph.addEdge(roomNode, adjacentNode, doorway);
|
||||
|
@ -292,8 +249,8 @@ public class MazeDesigner
|
|||
// Check if we meet the minimum dimensions needed for a doorway
|
||||
if (maxYI - minYI + 1 >= MIN_HEIGHT && maxZI - minZI + 1 >= MIN_SIDE)
|
||||
{
|
||||
otherMin = new Point3D(maxX, minYI, minZI);
|
||||
otherMax = new Point3D(maxX + 1, maxYI, maxZI);
|
||||
otherMin = new BlockPos(maxX, minYI, minZI);
|
||||
otherMax = new BlockPos(maxX + 1, maxYI, maxZI);
|
||||
doorway = new DoorwayData(otherMin, otherMax, DoorwayData.X_AXIS);
|
||||
adjacentNode = roomsToGraph.get(adjacent);
|
||||
roomGraph.addEdge(roomNode, adjacentNode, doorway);
|
||||
|
@ -340,8 +297,8 @@ public class MazeDesigner
|
|||
// Check if we meet the minimum dimensions needed for a doorway
|
||||
if (maxXI - minXI + 1 >= MIN_SIDE && maxZI - minZI + 1 >= MIN_SIDE)
|
||||
{
|
||||
otherMin = new Point3D(minXI, maxY, minZI);
|
||||
otherMax = new Point3D(maxXI, maxY + 1, maxZI);
|
||||
otherMin = new BlockPos(minXI, maxY, minZI);
|
||||
otherMax = new BlockPos(maxXI, maxY + 1, maxZI);
|
||||
doorway = new DoorwayData(otherMin, otherMax, DoorwayData.Y_AXIS);
|
||||
adjacentNode = roomsToGraph.get(adjacent);
|
||||
roomGraph.addEdge(roomNode, adjacentNode, doorway);
|
||||
|
|
|
@ -1,91 +1,74 @@
|
|||
package com.zixiken.dimdoors.experimental;
|
||||
|
||||
import com.zixiken.dimdoors.Point3D;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.Vec3i;
|
||||
|
||||
public class PartitionNode extends BoundingBox
|
||||
{
|
||||
public class PartitionNode extends BoundingBox {
|
||||
private PartitionNode parent;
|
||||
private PartitionNode leftChild = null;
|
||||
private PartitionNode rightChild = null;
|
||||
|
||||
public PartitionNode(int width, int height, int length)
|
||||
{
|
||||
super(new Point3D(0, 0, 0), new Point3D(width - 1, height - 1, length - 1));
|
||||
public PartitionNode(BlockPos volume) {
|
||||
super(new BlockPos(0, 0, 0), volume.subtract(new Vec3i(1,1,1)));
|
||||
parent = null;
|
||||
}
|
||||
|
||||
private PartitionNode(PartitionNode parent, Point3D minCorner, Point3D maxCorner)
|
||||
private PartitionNode(PartitionNode parent, BlockPos minCorner, BlockPos maxCorner)
|
||||
{
|
||||
super(minCorner, maxCorner);
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public boolean isLeaf()
|
||||
{
|
||||
public boolean isLeaf() {
|
||||
return (leftChild == null && rightChild == null);
|
||||
}
|
||||
|
||||
public PartitionNode leftChild()
|
||||
{
|
||||
public PartitionNode leftChild() {
|
||||
return leftChild;
|
||||
}
|
||||
|
||||
public PartitionNode rightChild()
|
||||
{
|
||||
public PartitionNode rightChild() {
|
||||
return rightChild;
|
||||
}
|
||||
|
||||
public PartitionNode parent()
|
||||
{
|
||||
public PartitionNode parent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public void splitByX(int rightStart)
|
||||
{
|
||||
if (!this.isLeaf())
|
||||
{
|
||||
public void splitByX(int rightStart) {
|
||||
if (!this.isLeaf()) {
|
||||
throw new IllegalStateException("This node has already been split.");
|
||||
} if (rightStart <= minCorner.getX() || rightStart > maxCorner.getX()) {
|
||||
throw new IllegalArgumentException("The specified cutting plane is invalid.");
|
||||
}
|
||||
if (rightStart <= minCorner.getX() || rightStart > maxCorner.getX())
|
||||
leftChild = new PartitionNode(this, minCorner, new BlockPos(rightStart - 1, maxCorner.getY(), maxCorner.getZ()));
|
||||
rightChild = new PartitionNode(this, new BlockPos(rightStart, minCorner.getY(), minCorner.getZ()), maxCorner);
|
||||
}
|
||||
|
||||
public void splitByY(int rightStart) {
|
||||
if (!this.isLeaf()) {
|
||||
throw new IllegalStateException("This node has already been split.");
|
||||
} if (rightStart <= minCorner.getY() || rightStart > maxCorner.getY()) {
|
||||
throw new IllegalArgumentException("The specified cutting plane is invalid.");
|
||||
}
|
||||
leftChild = new PartitionNode(this, minCorner, new BlockPos(maxCorner.getX(), rightStart - 1, maxCorner.getZ()));
|
||||
rightChild = new PartitionNode(this, new BlockPos(minCorner.getX(), rightStart, minCorner.getZ()), maxCorner);
|
||||
}
|
||||
|
||||
public void splitByZ(int rightStart) {
|
||||
if (!this.isLeaf()) {
|
||||
throw new IllegalStateException("This node has already been split.");
|
||||
} if (rightStart <= minCorner.getZ() || rightStart > maxCorner.getZ())
|
||||
{
|
||||
throw new IllegalArgumentException("The specified cutting plane is invalid.");
|
||||
}
|
||||
leftChild = new PartitionNode(this, minCorner, new Point3D(rightStart - 1, maxCorner.getY(), maxCorner.getZ()));
|
||||
rightChild = new PartitionNode(this, new Point3D(rightStart, minCorner.getY(), minCorner.getZ()), maxCorner);
|
||||
leftChild = new PartitionNode(this, minCorner, new BlockPos(maxCorner.getX(), maxCorner.getY(), rightStart - 1));
|
||||
rightChild = new PartitionNode(this, new BlockPos(minCorner.getX(), minCorner.getY(), rightStart), maxCorner);
|
||||
}
|
||||
|
||||
public void splitByY(int rightStart)
|
||||
{
|
||||
if (!this.isLeaf())
|
||||
{
|
||||
throw new IllegalStateException("This node has already been split.");
|
||||
}
|
||||
if (rightStart <= minCorner.getY() || rightStart > maxCorner.getY())
|
||||
{
|
||||
throw new IllegalArgumentException("The specified cutting plane is invalid.");
|
||||
}
|
||||
leftChild = new PartitionNode(this, minCorner, new Point3D(maxCorner.getX(), rightStart - 1, maxCorner.getZ()));
|
||||
rightChild = new PartitionNode(this, new Point3D(minCorner.getX(), rightStart, minCorner.getZ()), maxCorner);
|
||||
}
|
||||
|
||||
public void splitByZ(int rightStart)
|
||||
{
|
||||
if (!this.isLeaf())
|
||||
{
|
||||
throw new IllegalStateException("This node has already been split.");
|
||||
}
|
||||
if (rightStart <= minCorner.getZ() || rightStart > maxCorner.getZ())
|
||||
{
|
||||
throw new IllegalArgumentException("The specified cutting plane is invalid.");
|
||||
}
|
||||
leftChild = new PartitionNode(this, minCorner, new Point3D(maxCorner.getX(), maxCorner.getY(), rightStart - 1));
|
||||
rightChild = new PartitionNode(this, new Point3D(minCorner.getX(), minCorner.getY(), rightStart), maxCorner);
|
||||
}
|
||||
|
||||
public void remove()
|
||||
{
|
||||
if (parent != null)
|
||||
{
|
||||
public void remove() {
|
||||
if (parent != null) {
|
||||
if (parent.leftChild == this)
|
||||
parent.leftChild = null;
|
||||
else
|
||||
|
@ -94,31 +77,21 @@ public class PartitionNode extends BoundingBox
|
|||
}
|
||||
}
|
||||
|
||||
public PartitionNode findPoint(int x, int y, int z)
|
||||
{
|
||||
public PartitionNode findPoint(BlockPos pos) {
|
||||
// Find the lowest node that contains the specified point or return null
|
||||
if (this.contains(x, y, z))
|
||||
{
|
||||
return this.findPointInternal(x, y, z);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.contains(pos)) {
|
||||
return this.findPointInternal(pos);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private PartitionNode findPointInternal(int x, int y, int z)
|
||||
{
|
||||
if (leftChild != null && leftChild.contains(x, y, z))
|
||||
{
|
||||
return leftChild.findPointInternal(x, y, z);
|
||||
}
|
||||
else if (rightChild != null && rightChild.contains(x, y, z))
|
||||
{
|
||||
return rightChild.findPointInternal(x, y, z);
|
||||
}
|
||||
else
|
||||
{
|
||||
private PartitionNode findPointInternal(BlockPos pos) {
|
||||
if (leftChild != null && leftChild.contains(pos)) {
|
||||
return leftChild.findPointInternal(pos);
|
||||
} else if (rightChild != null && rightChild.contains(pos)) {
|
||||
return rightChild.findPointInternal(pos);
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
package com.zixiken.dimdoors.helpers;
|
||||
|
||||
import net.minecraft.util.BlockPos;
|
||||
|
||||
/**
|
||||
* Created by Jared Johnson on 6/22/2016.
|
||||
*/
|
||||
public class BlockPosHelper {
|
||||
public static boolean between(BlockPos pos, BlockPos min, BlockPos max) {
|
||||
return ((min.getX() <= pos.getX() && pos.getX() <= max.getX()) &&
|
||||
(min.getY() <= pos.getY() && pos.getY() <= max.getY()) &&
|
||||
(min.getZ() <= pos.getZ() && pos.getZ() <= max.getZ()));
|
||||
}
|
||||
|
||||
public static BlockPos max(BlockPos a, BlockPos b) {
|
||||
return new BlockPos(Math.max(a.getX(), b.getX()), Math.max(a.getY(), b.getY()), Math.max(a.getZ(), b.getZ()));
|
||||
}
|
||||
|
||||
public static BlockPos min(BlockPos a, BlockPos b) {
|
||||
return new BlockPos(Math.min(a.getX(), b.getX()), Math.min(a.getY(), b.getY()), Math.min(a.getZ(), b.getZ()));
|
||||
}
|
||||
|
||||
public static boolean greaterThan(BlockPos a, BlockPos b) {
|
||||
return (a.getX() > b.getX() && a.getY() > b.getY() && a.getZ() > b.getZ());
|
||||
}
|
||||
|
||||
public static boolean lessThan(BlockPos a, BlockPos b) {
|
||||
return (a.getX() < b.getX() && a.getY() < b.getY() && a.getZ() < b.getZ());
|
||||
}
|
||||
}
|
|
@ -65,8 +65,8 @@ public class ChunkLoaderHelper implements LoadingCallback
|
|||
public static void forcePocketChunks(NewDimData pocket, Ticket ticket)
|
||||
{
|
||||
BoundingBox bounds = PocketBuilder.calculateDefaultBounds(pocket);
|
||||
Point3D minCorner = bounds.minCorner();
|
||||
Point3D maxCorner = bounds.maxCorner();
|
||||
BlockPos minCorner = bounds.minCorner();
|
||||
BlockPos maxCorner = bounds.maxCorner();
|
||||
int minX = minCorner.getX() >> 4;
|
||||
int minZ = minCorner.getZ() >> 4;
|
||||
int maxX = maxCorner.getX() >> 4;
|
||||
|
|
|
@ -17,8 +17,7 @@ public class Compactor
|
|||
{
|
||||
|
||||
@SuppressWarnings("unused") // ?
|
||||
private static class DimComparator implements Comparator<NewDimData>
|
||||
{
|
||||
private static class DimComparator implements Comparator<NewDimData> {
|
||||
@Override
|
||||
public int compare(NewDimData a, NewDimData b)
|
||||
{
|
||||
|
@ -26,18 +25,15 @@ public class Compactor
|
|||
}
|
||||
}
|
||||
|
||||
public static void write(Collection<? extends NewDimData> values, ByteBuf output) throws IOException
|
||||
{
|
||||
public static void write(Collection<? extends NewDimData> values, ByteBuf output) throws IOException {
|
||||
// SenseiKiwi: Just encode the data straight up for now. I'll implement fancier compression later.
|
||||
output.writeInt(values.size());
|
||||
for (NewDimData dimension : values)
|
||||
{
|
||||
for (NewDimData dimension : values) {
|
||||
output.writeInt(dimension.id());
|
||||
output.writeInt(dimension.root().id());
|
||||
output.writeInt(dimension.type().index);
|
||||
output.writeInt(dimension.linkCount());
|
||||
for (DimLink link : dimension.links())
|
||||
{
|
||||
for (DimLink link : dimension.links()) {
|
||||
(new ClientLinkData(link)).write(output);
|
||||
}
|
||||
}
|
||||
|
@ -55,29 +51,25 @@ public class Compactor
|
|||
*/
|
||||
}
|
||||
|
||||
public static void readDimensions(ByteBuf input, IDimRegistrationCallback callback) throws IOException
|
||||
{
|
||||
public static void readDimensions(ByteBuf input, IDimRegistrationCallback callback) throws IOException {
|
||||
// Read in the dimensions one by one. Make sure we register root dimensions before
|
||||
// attempting to register the dimensions under them.
|
||||
|
||||
HashSet<Integer> rootIDs = new HashSet<Integer>();
|
||||
|
||||
int dimCount = input.readInt();
|
||||
for (int k = 0; k < dimCount; k++)
|
||||
{
|
||||
for (int k = 0; k < dimCount; k++) {
|
||||
int id = input.readInt();
|
||||
int rootID = input.readInt();
|
||||
DimensionType type = DimensionType.getTypeFromIndex(input.readInt());
|
||||
|
||||
if (rootIDs.add(rootID))
|
||||
{
|
||||
if (rootIDs.add(rootID)) {
|
||||
callback.registerDimension(rootID, rootID, type);
|
||||
}
|
||||
// Don't check if (id != rootID) - we want to retrieve the reference anyway
|
||||
NewDimData dimension = callback.registerDimension(id, rootID, type);
|
||||
int linkCount = input.readInt();
|
||||
for (int h = 0; h < linkCount; h++)
|
||||
{
|
||||
for (int h = 0; h < linkCount; h++) {
|
||||
ClientLinkData link = ClientLinkData.read(input);
|
||||
Point4D source = link.point;
|
||||
dimension.createLink(source.getX(), source.getY(), source.getZ(), LinkType.CLIENT,0);
|
||||
|
|
|
@ -2,31 +2,21 @@ package com.zixiken.dimdoors.helpers;
|
|||
|
||||
import java.io.File;
|
||||
|
||||
public class DeleteFolder
|
||||
{
|
||||
public static boolean deleteFolder(File directory)
|
||||
{
|
||||
try
|
||||
{
|
||||
public class DeleteFolder {
|
||||
public static boolean deleteFolder(File directory) {
|
||||
try {
|
||||
File[] contents = directory.listFiles();
|
||||
if (contents != null)
|
||||
{
|
||||
for (File entry : contents)
|
||||
{
|
||||
if (entry.isDirectory())
|
||||
{
|
||||
if (contents != null) {
|
||||
for (File entry : contents) {
|
||||
if (entry.isDirectory()) {
|
||||
deleteFolder(entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
entry.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
return directory.delete();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.zixiken.dimdoors.helpers;
|
||||
|
||||
public class PersonalPocketHelper
|
||||
{
|
||||
public class PersonalPocketHelper {
|
||||
|
||||
}
|
||||
|
|
|
@ -6,12 +6,9 @@ import java.io.OutputStream;
|
|||
|
||||
import com.zixiken.dimdoors.DimDoors;
|
||||
|
||||
public class copyfile
|
||||
{
|
||||
public static boolean copyFile(String ori, String dest)
|
||||
{
|
||||
try
|
||||
{
|
||||
public class copyfile {
|
||||
public static boolean copyFile(String ori, String dest) {
|
||||
try {
|
||||
//Note: For this to work properly, you must use getClass() on an instance of the class,
|
||||
//not on the value obtained from .class. That was what caused this code to fail before.
|
||||
//SchematicLoader didn't have this problem because we used instances of it.
|
||||
|
@ -24,9 +21,7 @@ public class copyfile
|
|||
}
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
} catch (Exception e) {
|
||||
System.out.println("Unable to get resource: " + ori);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ package com.zixiken.dimdoors.helpers;
|
|||
import com.zixiken.dimdoors.Point3D;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
@ -14,14 +16,12 @@ public class yCoordHelper
|
|||
|
||||
private yCoordHelper() { }
|
||||
|
||||
public static int getFirstUncovered(World world, int x, int yStart, int z)
|
||||
{
|
||||
public static int getFirstUncovered(World world, int x, int yStart, int z) {
|
||||
return getFirstUncovered(world, x, yStart, z, false);
|
||||
}
|
||||
|
||||
public static int getFirstUncovered(World world, int x, int yStart, int z, boolean fromTop)
|
||||
{
|
||||
Chunk chunk = world.getChunkProvider().loadChunk(x >> 4, z >> 4);
|
||||
public static int getFirstUncovered(World world, int x, int yStart, int z, boolean fromTop) {
|
||||
Chunk chunk = world.getChunkProvider().provideChunk(x >> 4, z >> 4);
|
||||
|
||||
int localX = x < 0 ? (x % 16) + 16 : (x % 16);
|
||||
int localZ = z < 0 ? (z % 16) + 16 : (z % 16);
|
||||
|
@ -66,8 +66,7 @@ public class yCoordHelper
|
|||
return (material.isLiquid() || !material.isReplaceable());
|
||||
}
|
||||
|
||||
public static Point3D findSafeCubeUp(World world, int x, int startY, int z)
|
||||
{
|
||||
public static BlockPos findSafeCubeUp(World world, int x, int startY, int z) {
|
||||
// Search for a 3x2x3 box with solid opaque blocks (without tile entities)
|
||||
// or replaceable blocks underneath. The box must contain either air and
|
||||
// non-liquid replaceable blocks only.
|
||||
|
@ -84,7 +83,8 @@ public class yCoordHelper
|
|||
Chunk chunk = initializeChunkArea(world, x >> 4, z >> 4);
|
||||
|
||||
int height = world.getActualHeight();
|
||||
int y, dx, dz, blockID, metadata;
|
||||
int y, dx, dz, blockID;
|
||||
IBlockState state;
|
||||
boolean isSafe;
|
||||
Block block;
|
||||
|
||||
|
@ -97,39 +97,30 @@ public class yCoordHelper
|
|||
// Treat non-liquid replaceable blocks like air
|
||||
// If we find a layer that contains replaceable blocks or solid opaque blocks without
|
||||
// tile entities, then it can serve as the base where we'll place the player and door.
|
||||
for (y = Math.max(startY - 1, 0); y < height; y++)
|
||||
{
|
||||
for (y = Math.max(startY - 1, 0); y < height; y++) {
|
||||
isSafe = true;
|
||||
for (dx = -1; dx <= 1 && isSafe; dx++)
|
||||
{
|
||||
for (dz = -1; dz <= 1 && isSafe; dz++)
|
||||
{
|
||||
for (dx = -1; dx <= 1 && isSafe; dx++) {
|
||||
for (dz = -1; dz <= 1 && isSafe; dz++) {
|
||||
block = chunk.getBlock(localX + dx, y, localZ + dz);
|
||||
metadata = chunk.getBlockMetadata(localX + dx, y, localZ + dz);
|
||||
if (!block.isAir(world, x, y, z) && (!block.getMaterial().isReplaceable() || block.getMaterial().isLiquid()))
|
||||
{
|
||||
if (!block.getMaterial().isReplaceable() && (!block.isOpaqueCube() || block.hasTileEntity(metadata)))
|
||||
{
|
||||
state = chunk.getBlockState(new BlockPos(localX + dx, y, localZ + dz));
|
||||
if (!block.isAir(world, new BlockPos(x, y, z)) && (!block.getMaterial().isReplaceable() || block.getMaterial().isLiquid())) {
|
||||
if (!block.getMaterial().isReplaceable() && (!block.isOpaqueCube() || block.hasTileEntity(state))) {
|
||||
isSafe = false;
|
||||
}
|
||||
layers = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isSafe)
|
||||
{
|
||||
} if (isSafe) {
|
||||
layers++;
|
||||
if (layers == 3)
|
||||
{
|
||||
return new Point3D(localX + cornerX, y - 2, localZ + cornerZ);
|
||||
if (layers == 3) {
|
||||
return new BlockPos(localX + cornerX, y - 2, localZ + cornerZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Point3D findSafeCubeDown(World world, int x, int startY, int z)
|
||||
{
|
||||
public static BlockPos findSafeCubeDown(World world, int x, int startY, int z) {
|
||||
// Search for a 3x2x3 box with solid opaque blocks (without tile entities)
|
||||
// or replaceable blocks underneath. The box must contain either air and
|
||||
// non-liquid replaceable blocks only.
|
||||
|
@ -146,7 +137,8 @@ public class yCoordHelper
|
|||
Chunk chunk = initializeChunkArea(world, x >> 4, z >> 4);
|
||||
|
||||
int height = world.getActualHeight();
|
||||
int y, dx, dz, blockID, metadata;
|
||||
int y, dx, dz, blockID;
|
||||
IBlockState state;
|
||||
boolean isSafe;
|
||||
boolean hasBlocks;
|
||||
Block block;
|
||||
|
@ -160,34 +152,25 @@ public class yCoordHelper
|
|||
{
|
||||
isSafe = true;
|
||||
hasBlocks = false;
|
||||
for (dx = -1; dx <= 1 && isSafe; dx++)
|
||||
{
|
||||
for (dz = -1; dz <= 1 && isSafe; dz++)
|
||||
{
|
||||
for (dx = -1; dx <= 1 && isSafe; dx++) {
|
||||
for (dz = -1; dz <= 1 && isSafe; dz++) {
|
||||
block = chunk.getBlock(localX + dx, y, localZ + dz);
|
||||
metadata = chunk.getBlockMetadata(localX + dx, y, localZ + dz);
|
||||
if (!block.isAir(world,x,y,z) && (!block.getMaterial().isReplaceable() || block.getMaterial().isLiquid()))
|
||||
{
|
||||
if (!block.getMaterial().isReplaceable() && (!block.isOpaqueCube() || block.hasTileEntity(metadata)))
|
||||
{
|
||||
if (layers >= 3)
|
||||
{
|
||||
return new Point3D(localX + cornerX, y + 1, localZ + cornerZ);
|
||||
state = chunk.getBlockState(new BlockPos(localX + dx, y, localZ + dz));
|
||||
if (!block.isAir(world, new BlockPos(x,y,z)) && (!block.getMaterial().isReplaceable() || block.getMaterial().isLiquid())) {
|
||||
if (!block.getMaterial().isReplaceable() && (!block.isOpaqueCube() || block.hasTileEntity(state))) {
|
||||
if (layers >= 3) {
|
||||
return new BlockPos(localX + cornerX, y + 1, localZ + cornerZ);
|
||||
}
|
||||
isSafe = false;
|
||||
}
|
||||
hasBlocks = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isSafe)
|
||||
{
|
||||
} if (isSafe) {
|
||||
layers++;
|
||||
if (hasBlocks)
|
||||
{
|
||||
if (layers >= 3)
|
||||
{
|
||||
return new Point3D(localX + cornerX, y, localZ + cornerZ);
|
||||
if (hasBlocks) {
|
||||
if (layers >= 3) {
|
||||
return new BlockPos(localX + cornerX, y, localZ + cornerZ);
|
||||
}
|
||||
layers = 0;
|
||||
}
|
||||
|
@ -196,26 +179,22 @@ public class yCoordHelper
|
|||
return null;
|
||||
}
|
||||
|
||||
private static Chunk initializeChunkArea(World world, int chunkX, int chunkZ)
|
||||
{
|
||||
private static Chunk initializeChunkArea(World world, int chunkX, int chunkZ) {
|
||||
// We initialize a 3x3 area of chunks instead of just initializing
|
||||
// the target chunk because things generated in adjacent chunks
|
||||
// (e.g. trees) might intrude into the target chunk.
|
||||
|
||||
IChunkProvider provider = world.getChunkProvider();
|
||||
Chunk target = provider.loadChunk(chunkX, chunkZ);
|
||||
for (int dx = -1; dx <= 1; dx++)
|
||||
{
|
||||
for (int dz = -1; dz <= 1; dz++)
|
||||
{
|
||||
provider.loadChunk(chunkX, chunkZ);
|
||||
Chunk target = provider.provideChunk(chunkX, chunkZ);
|
||||
for (int dx = -1; dx <= 1; dx++) {
|
||||
for (int dz = -1; dz <= 1; dz++) {
|
||||
provider.provideChunk(chunkX, chunkZ);
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
public static Point3D findDropPoint(World world, int x, int startY, int z)
|
||||
{
|
||||
public static BlockPos findDropPoint(World world, int x, int startY, int z) {
|
||||
// Find a simple 2-block-high air gap
|
||||
// Search across a 3x3 column
|
||||
final int GAP_HEIGHT = 2;
|
||||
|
@ -234,35 +213,25 @@ public class yCoordHelper
|
|||
int[] gaps = new int[9];
|
||||
|
||||
// Check 3x3 layers of blocks for air spaces
|
||||
for (y = Math.min(startY, height - 1); y > 0; y--)
|
||||
{
|
||||
for (dx = -1, index = 0; dx <= 1; dx++)
|
||||
{
|
||||
for (dz = -1; dz <= 1; dz++, index++)
|
||||
{
|
||||
if (!chunk.getBlock(localX + dx, y, localZ + dz).isAir(world, x+dx,y,z+dz))
|
||||
{
|
||||
for (y = Math.min(startY, height - 1); y > 0; y--) {
|
||||
for (dx = -1, index = 0; dx <= 1; dx++) {
|
||||
for (dz = -1; dz <= 1; dz++, index++) {
|
||||
if (!chunk.getBlock(localX + dx, y, localZ + dz).isAir(world, new BlockPos(x+dx, y, z+dz))) {
|
||||
gaps[index] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
gaps[index]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check if an acceptable gap exists in the center of the search column
|
||||
if (gaps[index / 2] == GAP_HEIGHT)
|
||||
{
|
||||
return new Point3D(localX + cornerX, y + GAP_HEIGHT - 1, localZ + cornerZ);
|
||||
if (gaps[index / 2] == GAP_HEIGHT) {
|
||||
return new BlockPos(localX + cornerX, y + GAP_HEIGHT - 1, localZ + cornerZ);
|
||||
}
|
||||
// Check the other positions in the column
|
||||
for (dx = -1, index = 0; dx <= 1; dx++)
|
||||
{
|
||||
for (dz = -1; dz <= 1; dz++, index++)
|
||||
{
|
||||
if (gaps[index] == GAP_HEIGHT)
|
||||
{
|
||||
return new Point3D(localX + cornerX + dx, y + GAP_HEIGHT - 1, localZ + cornerZ + dz);
|
||||
for (dx = -1, index = 0; dx <= 1; dx++) {
|
||||
for (dz = -1; dz <= 1; dz++, index++) {
|
||||
if (gaps[index] == GAP_HEIGHT) {
|
||||
return new BlockPos(localX + cornerX + dx, y + GAP_HEIGHT - 1, localZ + cornerZ + dz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -270,22 +239,19 @@ public class yCoordHelper
|
|||
return null;
|
||||
}
|
||||
|
||||
public static int adjustDestinationY(int y, int worldHeight, int entranceY, int dungeonHeight)
|
||||
{
|
||||
public static int adjustDestinationY(int y, int worldHeight, int entranceY, int dungeonHeight) {
|
||||
//The goal here is to guarantee that the dungeon fits within the vertical bounds
|
||||
//of the world while shifting it as little as possible.
|
||||
int destY = y;
|
||||
|
||||
//Is the top of the dungeon going to be at Y < worldHeight?
|
||||
int pocketTop = (dungeonHeight - 1) + destY - entranceY;
|
||||
if (pocketTop >= worldHeight)
|
||||
{
|
||||
if (pocketTop >= worldHeight) {
|
||||
destY = (worldHeight - 1) - (dungeonHeight - 1) + entranceY;
|
||||
}
|
||||
|
||||
//Is the bottom of the dungeon at Y >= 0?
|
||||
if (destY < entranceY)
|
||||
{
|
||||
if (destY < entranceY) {
|
||||
destY = entranceY;
|
||||
}
|
||||
return destY;
|
||||
|
|
|
@ -199,7 +199,7 @@ public class DDSaveHandler
|
|||
|
||||
public static boolean unpackLinkData(List<PackedLinkData> linksToUnpack)
|
||||
{
|
||||
Point3D fakePoint = new Point3D(-1,-1,-1);
|
||||
BlockPos fakePoint = new BlockPos(-1,-1,-1);
|
||||
List<PackedLinkData> unpackedLinks = new ArrayList<PackedLinkData>();
|
||||
/**
|
||||
* sort through the list, unpacking links that do not have parents.
|
||||
|
|
|
@ -77,9 +77,9 @@ public class OldSaveImporter
|
|||
Point4D source = new Point4D(link.locXCoord,link.locYCoord,link.locZCoord,link.locDimID);
|
||||
Point4D destintion = new Point4D(link.destXCoord,link.destYCoord,link.destZCoord,link.destDimID);
|
||||
PackedLinkTail tail = new PackedLinkTail(destintion, LinkType.NORMAL);
|
||||
List<Point3D> children = new ArrayList<Point3D>();
|
||||
List<BlockPos> children = new ArrayList<BlockPos>();
|
||||
|
||||
PackedLinkData newPackedLink = new PackedLinkData(source, new Point3D(-1,-1,-1), tail, link.linkOrientation,children, null);
|
||||
PackedLinkData newPackedLink = new PackedLinkData(source, new BlockPos(-1,-1,-1), tail, link.linkOrientation,children, null);
|
||||
|
||||
newPackedLinkData.add(newPackedLink);
|
||||
allPackedLinks.add(newPackedLink);
|
||||
|
@ -104,11 +104,11 @@ public class OldSaveImporter
|
|||
}
|
||||
if(data.isPocket)
|
||||
{
|
||||
dim = new PackedDimData(data.dimID, data.depth, data.depth, data.exitDimLink.locDimID, data.exitDimLink.locDimID, 0, type, data.hasBeenFilled, null, new Point3D(0,64,0), childDims, newPackedLinkData, null);
|
||||
dim = new PackedDimData(data.dimID, data.depth, data.depth, data.exitDimLink.locDimID, data.exitDimLink.locDimID, 0, type, data.hasBeenFilled, null, new BlockPos(0,64,0), childDims, newPackedLinkData, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
dim = new PackedDimData(data.dimID, data.depth, data.depth, data.dimID, data.dimID, 0, type, data.hasBeenFilled, null, new Point3D(0,64,0), childDims, newPackedLinkData, null);
|
||||
dim = new PackedDimData(data.dimID, data.depth, data.depth, data.dimID, data.dimID, 0, type, data.hasBeenFilled, null, new BlockPos(0,64,0), childDims, newPackedLinkData, null);
|
||||
}
|
||||
newPackedDimData.put(dim.ID,dim);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import java.util.List;
|
|||
|
||||
import com.zixiken.dimdoors.Point3D;
|
||||
import com.zixiken.dimdoors.core.DimensionType;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
|
||||
public class PackedDimData
|
||||
{
|
||||
|
@ -18,18 +20,17 @@ public class PackedDimData
|
|||
public final int ParentID;
|
||||
public final int RootID;
|
||||
public final PackedDungeonData DungeonData;
|
||||
public final Point3D Origin;
|
||||
public final int Orientation;
|
||||
public final BlockPos Origin;
|
||||
public final EnumFacing Orientation;
|
||||
public final List<Integer> ChildIDs;
|
||||
public final List<PackedLinkData> Links;
|
||||
public final List<PackedLinkTail> Tails;
|
||||
|
||||
// FIXME Missing dungeon data, not sure how to include it
|
||||
|
||||
public PackedDimData(int id, int depth, int packDepth, int parentID, int rootID, int orientation,
|
||||
DimensionType type, boolean isFilled,PackedDungeonData dungeonData, Point3D origin, List<Integer> childIDs, List<PackedLinkData> links,
|
||||
List<PackedLinkTail> tails)
|
||||
{
|
||||
public PackedDimData(int id, int depth, int packDepth, int parentID, int rootID, EnumFacing orientation,
|
||||
DimensionType type, boolean isFilled, PackedDungeonData dungeonData, BlockPos origin, List<Integer> childIDs, List<PackedLinkData> links,
|
||||
List<PackedLinkTail> tails) {
|
||||
ID = id;
|
||||
Depth = depth;
|
||||
PackDepth = packDepth;
|
||||
|
@ -46,8 +47,7 @@ public class PackedDimData
|
|||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
public String toString() {
|
||||
return "ID= "+this.ID;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,18 +5,19 @@ import java.util.List;
|
|||
import com.zixiken.dimdoors.Point3D;
|
||||
import com.zixiken.dimdoors.core.DDLock;
|
||||
import com.zixiken.dimdoors.util.Point4D;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
|
||||
public class PackedLinkData
|
||||
{
|
||||
public final Point4D source;
|
||||
public final Point3D parent;
|
||||
public final BlockPos parent;
|
||||
public final PackedLinkTail tail;
|
||||
public final int orientation;
|
||||
public final List<Point3D> children;
|
||||
public final EnumFacing orientation;
|
||||
public final List<BlockPos> children;
|
||||
public final DDLock lock;
|
||||
|
||||
public PackedLinkData(Point4D source, Point3D parent, PackedLinkTail tail, int orientation, List<Point3D> children, DDLock lock)
|
||||
{
|
||||
public PackedLinkData(Point4D source, BlockPos parent, PackedLinkTail tail, EnumFacing orientation, List<BlockPos> children, DDLock lock) {
|
||||
this.source=source;
|
||||
this.parent=parent;
|
||||
this.tail=tail;
|
||||
|
|
|
@ -3,7 +3,10 @@ package com.zixiken.dimdoors.schematic;
|
|||
import com.zixiken.dimdoors.DimDoors;
|
||||
import net.minecraft.block.*;
|
||||
import com.zixiken.dimdoors.Point3D;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -75,7 +78,7 @@ public class BlockRotator
|
|||
hasOrientations.put(DimDoors.personalDimDoor, true);
|
||||
}
|
||||
|
||||
public static int transformMetadata(int metadata, int turns, Block block)
|
||||
public static IBlockState transformMetadata(IBlockState state, int turns, Block block)
|
||||
{
|
||||
//I changed rotations to reduce the monstrous code we had. It might be
|
||||
//slightly less efficient, but it's easier to maintain for now. ~SenseiKiwi
|
||||
|
@ -88,14 +91,14 @@ public class BlockRotator
|
|||
{
|
||||
while (turns > 0)
|
||||
{
|
||||
metadata = rotateMetadataBy90(metadata, block);
|
||||
state = rotateMetadataBy90(state, block);
|
||||
turns--;
|
||||
}
|
||||
}
|
||||
return metadata;
|
||||
return state;
|
||||
}
|
||||
|
||||
private static int rotateMetadataBy90(int metadata, Block block)
|
||||
private static IBlockState rotateMetadataBy90(IBlockState state, Block block)
|
||||
{
|
||||
//TODO: Replace this horrible function with something prettier. We promise we will for the next version,
|
||||
//after switching to MC 1.6. PADRE, PLEASE FORGIVE OUR SINS.
|
||||
|
@ -501,7 +504,7 @@ public class BlockRotator
|
|||
return metadata;
|
||||
}
|
||||
|
||||
public static void transformPoint(Point3D position, Point3D srcOrigin, int angle, Point3D destOrigin)
|
||||
public static void transformPoint(BlockPos position, BlockPos srcOrigin, EnumFacing angle, BlockPos destOrigin)
|
||||
{
|
||||
//This function receives a position (e.g. point in schematic space), translates it relative
|
||||
//to a source coordinate system (e.g. the point that will be the center of a schematic),
|
||||
|
@ -512,9 +515,7 @@ public class BlockRotator
|
|||
|
||||
//Position is only overwritten at the end, so it's okay to provide it as srcOrigin or destOrigin as well.
|
||||
|
||||
int tx = position.getX() - srcOrigin.getX();
|
||||
int ty = position.getY() - srcOrigin.getY();
|
||||
int tz = position.getZ() - srcOrigin.getZ();
|
||||
BlockPos t = position.subtract(srcOrigin);
|
||||
|
||||
//"int angle" specifies a rotation consistent with Minecraft's orientation system.
|
||||
//That means each increment of 1 in angle would be a 90-degree clockwise turn.
|
||||
|
@ -522,40 +523,32 @@ public class BlockRotator
|
|||
//calculated by (B - A).
|
||||
|
||||
//Adjust angle into the expected range
|
||||
if (angle < 0)
|
||||
{
|
||||
int correction = -(angle / 4);
|
||||
angle = angle + 4 * (correction + 1);
|
||||
}
|
||||
angle = angle % 4;
|
||||
|
||||
|
||||
int rx;
|
||||
int rz;
|
||||
switch (angle)
|
||||
{
|
||||
case 0: //No rotation
|
||||
rx = tx;
|
||||
rz = tz;
|
||||
|
||||
switch (angle) {
|
||||
case SOUTH: //No rotation
|
||||
rx = t.getX();
|
||||
rz = t.getZ();
|
||||
break;
|
||||
case 1: //90 degrees clockwise
|
||||
rx = -tz;
|
||||
rz = tx;
|
||||
case WEST: //90 degrees clockwise
|
||||
rx = -t.getZ();
|
||||
rz = t.getX();
|
||||
break;
|
||||
case 2: //180 degrees
|
||||
rx = -tx;
|
||||
rz = -tz;
|
||||
case NORTH: //180 degrees
|
||||
rx = -t.getX();
|
||||
rz = -t.getZ();
|
||||
break;
|
||||
case 3: //270 degrees clockwise
|
||||
rx = tz;
|
||||
rz = -tx;
|
||||
case EAST: //270 degrees clockwise
|
||||
rx = t.getZ();
|
||||
rz = -t.getX();
|
||||
|
||||
break;
|
||||
default: //This should never happen
|
||||
throw new IllegalStateException("Invalid angle value. This should never happen!");
|
||||
}
|
||||
|
||||
position.setX( rx + destOrigin.getX() );
|
||||
position.setY( ty + destOrigin.getY() );
|
||||
position.setZ( rz + destOrigin.getZ() );
|
||||
position = new BlockPos(rx + destOrigin.getX(), t.getY() + destOrigin.getY(), rz + destOrigin.getZ() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
package com.zixiken.dimdoors.schematic;
|
||||
|
||||
import com.zixiken.dimdoors.helpers.BlockPosHelper;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import com.zixiken.dimdoors.Point3D;
|
||||
|
||||
public class CompactBoundsOperation extends WorldOperation
|
||||
{
|
||||
private int minX;
|
||||
private int minY;
|
||||
private int minZ;
|
||||
private int maxX;
|
||||
private int maxY;
|
||||
private int maxZ;
|
||||
public class CompactBoundsOperation extends WorldOperation {
|
||||
private BlockPos minCorner;
|
||||
private BlockPos maxCorner;
|
||||
|
||||
public CompactBoundsOperation()
|
||||
{
|
||||
|
@ -18,57 +15,39 @@ public class CompactBoundsOperation extends WorldOperation
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean initialize(World world, int x, int y, int z, int width, int height, int length)
|
||||
{
|
||||
minX = Integer.MAX_VALUE;
|
||||
minY = Integer.MAX_VALUE;
|
||||
minZ = Integer.MAX_VALUE;
|
||||
maxX = x;
|
||||
maxY = y;
|
||||
maxZ = z;
|
||||
protected boolean initialize(World world, BlockPos pos, BlockPos volume) {
|
||||
minCorner = new BlockPos(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||
maxCorner = pos;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean applyToBlock(World world, int x, int y, int z)
|
||||
{
|
||||
protected boolean applyToBlock(World world, BlockPos pos) {
|
||||
//This could be done more efficiently, but honestly, this is the simplest approach and it
|
||||
//makes it easy for us to verify that the code is correct.
|
||||
if (!world.isAirBlock(x, y, z))
|
||||
{
|
||||
maxX = x > maxX ? x : maxX;
|
||||
maxZ = z > maxZ ? z : maxZ;
|
||||
maxY = y > maxY ? y : maxY;
|
||||
|
||||
minX = x < minX ? x : minX;
|
||||
minZ = z < minZ ? z : minZ;
|
||||
minY = y < minY ? y : minY;
|
||||
if (!world.isAirBlock(pos)) {
|
||||
maxCorner = BlockPosHelper.greaterThan(pos, maxCorner) ? pos : maxCorner;
|
||||
minCorner = BlockPosHelper.lessThan(pos, minCorner) ? pos : minCorner;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean finish()
|
||||
{
|
||||
if (minX == Integer.MAX_VALUE)
|
||||
{
|
||||
protected boolean finish() {
|
||||
if (minCorner.getX() == Integer.MAX_VALUE) {
|
||||
//The whole search space was empty!
|
||||
//Compact the space to a single block.
|
||||
minX = maxX;
|
||||
minY = maxY;
|
||||
minZ = maxZ;
|
||||
minCorner = maxCorner;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public Point3D getMaxCorner()
|
||||
{
|
||||
return new Point3D(maxX, maxY, maxZ);
|
||||
public BlockPos getMaxCorner() {
|
||||
return maxCorner;
|
||||
}
|
||||
|
||||
public Point3D getMinCorner()
|
||||
{
|
||||
return new Point3D(minX, minY, minZ);
|
||||
public BlockPos getMinCorner() {
|
||||
return minCorner;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.zixiken.dimdoors.schematic;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
@ -8,8 +9,7 @@ public class CompoundFilter extends SchematicFilter {
|
|||
|
||||
private ArrayList<SchematicFilter> filters;
|
||||
|
||||
public CompoundFilter()
|
||||
{
|
||||
public CompoundFilter() {
|
||||
super("CompoundFilter");
|
||||
filters = new ArrayList<SchematicFilter>();
|
||||
}
|
||||
|
@ -20,12 +20,9 @@ public class CompoundFilter extends SchematicFilter {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean initialize(Schematic schematic,Block[] blocks, byte[] metadata)
|
||||
{
|
||||
for (SchematicFilter filter : filters)
|
||||
{
|
||||
if (!filter.initialize(schematic, blocks, metadata))
|
||||
{
|
||||
protected boolean initialize(Schematic schematic, IBlockState[] metadata) {
|
||||
for (SchematicFilter filter : filters) {
|
||||
if (!filter.initialize(schematic, metadata)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -33,12 +30,9 @@ public class CompoundFilter extends SchematicFilter {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean finish()
|
||||
{
|
||||
for (SchematicFilter filter : filters)
|
||||
{
|
||||
if (!filter.finish())
|
||||
{
|
||||
protected boolean finish() {
|
||||
for (SchematicFilter filter : filters) {
|
||||
if (!filter.finish()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -46,12 +40,9 @@ public class CompoundFilter extends SchematicFilter {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean applyToBlock(int index, Block[] blocks, byte[] metadata)
|
||||
{
|
||||
for (SchematicFilter filter : filters)
|
||||
{
|
||||
if (filter.applyToBlock(index, blocks, metadata))
|
||||
{
|
||||
protected boolean applyToBlock(int index, IBlockState[] state) {
|
||||
for (SchematicFilter filter : filters) {
|
||||
if (filter.applyToBlock(index, state)) {
|
||||
return filter.terminates();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package com.zixiken.dimdoors.schematic;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public interface IBlockSetter
|
||||
{
|
||||
public void setBlock(World world, int x, int y, int z, Block block, int metadata);
|
||||
public void setBlock(World world, BlockPos pos, IBlockState state);
|
||||
}
|
||||
|
|
|
@ -10,12 +10,14 @@ import java.util.LinkedList;
|
|||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.nbt.CompressedStreamTools;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.World;
|
||||
import com.zixiken.dimdoors.Point3D;
|
||||
|
||||
/**
|
||||
* Represents an MC schematic and provides functions for loading, storing, and manipulating schematics.
|
||||
|
@ -23,162 +25,96 @@ import com.zixiken.dimdoors.Point3D;
|
|||
*/
|
||||
public class Schematic {
|
||||
|
||||
protected short width;
|
||||
protected short height;
|
||||
protected short length;
|
||||
|
||||
protected Block[] blocks;
|
||||
protected byte[] metadata;
|
||||
protected BlockPos volume;
|
||||
protected IBlockState[] state;
|
||||
protected NBTTagList tileEntities;
|
||||
|
||||
protected Schematic(short width, short height, short length, String[] blockPalette, short[] blockIds, byte[] metadata, NBTTagList tileEntities)
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.length = length;
|
||||
this.metadata = metadata;
|
||||
protected Schematic(BlockPos volume, IBlockState[] state, NBTTagList tileEntities) {
|
||||
this.volume = volume;
|
||||
this.state = state;
|
||||
this.tileEntities = tileEntities;
|
||||
|
||||
if (blockPalette != null)
|
||||
loadBlockList(blockPalette, blockIds);
|
||||
}
|
||||
|
||||
protected Schematic(short width, short height, short length, Block[] blocks, byte[] metadata, NBTTagList tileEntities) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.length = length;
|
||||
this.blocks = blocks;
|
||||
this.metadata = metadata;
|
||||
this.tileEntities = tileEntities;
|
||||
}
|
||||
|
||||
protected Schematic(Schematic source)
|
||||
{
|
||||
protected Schematic(Schematic source) {
|
||||
//Shallow copy constructor - critical for code reuse in derived classes since
|
||||
//source's fields will be inaccessible if the derived class is in another package.
|
||||
this.width = source.width;
|
||||
this.height = source.height;
|
||||
this.length = source.length;
|
||||
this.blocks = source.blocks;
|
||||
this.metadata = source.metadata;
|
||||
this.volume = source.volume;
|
||||
this.state = source.state;
|
||||
this.tileEntities = source.tileEntities;
|
||||
}
|
||||
|
||||
private void loadBlockList(String[] blockPalette, short[] blockIds) {
|
||||
this.blocks = new Block[blockIds.length];
|
||||
|
||||
Block[] blockObjPalette = new Block[blockPalette.length];
|
||||
|
||||
for (int i = 0; i < blockPalette.length; i++) {
|
||||
blockObjPalette[i] = (Block)Block.blockRegistry.getObject(blockPalette[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < blockIds.length; i++) {
|
||||
this.blocks[i] = blockObjPalette[blockIds[i]];
|
||||
}
|
||||
}
|
||||
|
||||
public int calculateIndex(int x, int y, int z)
|
||||
{
|
||||
if (x < 0 || x >= width)
|
||||
public int calculateIndex(BlockPos pos) {
|
||||
if (pos.getX() < 0 || pos.getX() >= volume.getX())
|
||||
throw new IndexOutOfBoundsException("x must be non-negative and less than width");
|
||||
if (y < 0 || y >= height)
|
||||
if (pos.getY() < 0 || pos.getY() >= volume.getY())
|
||||
throw new IndexOutOfBoundsException("y must be non-negative and less than height");
|
||||
if (z < 0 || z >= length)
|
||||
if (pos.getZ() < 0 || pos.getZ() >= volume.getZ())
|
||||
throw new IndexOutOfBoundsException("z must be non-negative and less than length");
|
||||
|
||||
return (y * width * length + z * width + x);
|
||||
return (pos.getY() * volume.getX() * volume.getZ() + pos.getZ() * volume.getX() + pos.getX());
|
||||
}
|
||||
|
||||
public Point3D calculatePoint(int index)
|
||||
{
|
||||
int y = index / (width * length);
|
||||
index -= y * width * length;
|
||||
int z = index / width;
|
||||
index -= z * width;
|
||||
public BlockPos calculatePoint(int index) {
|
||||
int y = index / (volume.getX() * volume.getZ());
|
||||
index -= y * volume.getX() * volume.getZ();
|
||||
int z = index / volume.getX();
|
||||
index -= z * volume.getX();
|
||||
int x = index;
|
||||
|
||||
return new Point3D(x, y, z);
|
||||
return new BlockPos(x, y, z);
|
||||
}
|
||||
|
||||
public int calculateIndexBelow(int index)
|
||||
{
|
||||
return index - (width * length);
|
||||
public int calculateIndexBelow(int index) {
|
||||
return index - (volume.getX() * volume.getZ());
|
||||
}
|
||||
|
||||
public short getWidth()
|
||||
{
|
||||
return width;
|
||||
public BlockPos getVolume() {
|
||||
return volume;
|
||||
}
|
||||
|
||||
public short getHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
public short getLength()
|
||||
{
|
||||
return length;
|
||||
}
|
||||
|
||||
public Block getBlock(int x, int y, int z)
|
||||
{
|
||||
return (Block)Block.blockRegistry.getObject(blocks[calculateIndex(x, y, z)]);
|
||||
public Block getBlock(BlockPos pos) {
|
||||
return state[calculateIndex(pos)].getBlock();
|
||||
}
|
||||
|
||||
public byte getBlockMetadata(int x, int y, int z)
|
||||
{
|
||||
return metadata[calculateIndex(x, y, z)];
|
||||
public IBlockState getBlockState(BlockPos pos) {
|
||||
return state[calculateIndex(pos)];
|
||||
}
|
||||
|
||||
public NBTTagList getTileEntities()
|
||||
{
|
||||
public NBTTagList getTileEntities() {
|
||||
return (NBTTagList) tileEntities.copy();
|
||||
}
|
||||
|
||||
public static Schematic readFromFile(String schematicPath) throws FileNotFoundException, InvalidSchematicException
|
||||
{
|
||||
public static Schematic readFromFile(String schematicPath) throws FileNotFoundException, InvalidSchematicException {
|
||||
return readFromFile(new File(schematicPath));
|
||||
}
|
||||
|
||||
public static Schematic readFromFile(File schematicFile) throws FileNotFoundException, InvalidSchematicException
|
||||
{
|
||||
public static Schematic readFromFile(File schematicFile) throws FileNotFoundException, InvalidSchematicException {
|
||||
// There is no resource leak... readFromStream() closes the stream TWICE.
|
||||
return readFromStream(new FileInputStream(schematicFile));
|
||||
}
|
||||
|
||||
public static Schematic readFromResource(String resourcePath) throws InvalidSchematicException
|
||||
{
|
||||
public static Schematic readFromResource(String resourcePath) throws InvalidSchematicException {
|
||||
InputStream schematicStream = Schematic.class.getResourceAsStream(resourcePath);
|
||||
return readFromStream(schematicStream);
|
||||
}
|
||||
|
||||
public static Schematic readFromStream(InputStream schematicStream) throws InvalidSchematicException
|
||||
{
|
||||
public static Schematic readFromStream(InputStream schematicStream) throws InvalidSchematicException {
|
||||
short width;
|
||||
short height;
|
||||
short length;
|
||||
int volume;
|
||||
int pairs;
|
||||
|
||||
byte[] metadata = null; //block metadata
|
||||
byte[] lowBits = null; //first 8 bits of the block IDs
|
||||
byte[] highBits = null; //additional 4 bits of the block IDs
|
||||
short[] blockIds = null; //list of combined block IDs
|
||||
String[] blockPalette = null;
|
||||
IBlockState[] state = null; //block state
|
||||
NBTTagList tileEntities = null; //storage for tile entities in NBT form
|
||||
NBTTagCompound schematicTag; //the NBT data extracted from the schematic file
|
||||
boolean hasExtendedBlockIDs; //indicates whether the schematic contains extended block IDs
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
try {
|
||||
try {
|
||||
schematicTag = CompressedStreamTools.readCompressed(schematicStream);
|
||||
schematicStream.close(); //readCompressed() probably closes the stream anyway, but close again to be sure.
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
throw new InvalidSchematicException("The schematic could not be decoded.");
|
||||
|
||||
|
@ -197,68 +133,20 @@ public class Schematic {
|
|||
if (length < 0)
|
||||
throw new InvalidSchematicException("The schematic cannot have a negative length.");
|
||||
|
||||
|
||||
NBTTagList nbtPalette = schematicTag.getTagList("Palette", 8);
|
||||
|
||||
if (nbtPalette.tagCount() < 1) {
|
||||
throw new InvalidSchematicException("The schematic must have a valid block palette.");
|
||||
}
|
||||
|
||||
blockPalette = new String[nbtPalette.tagCount()];
|
||||
|
||||
for (int i = 0; i < nbtPalette.tagCount(); i++) {
|
||||
blockPalette[i] = nbtPalette.getStringTagAt(i);
|
||||
}
|
||||
|
||||
//load block info
|
||||
lowBits = schematicTag.getByteArray("Blocks");
|
||||
highBits = schematicTag.getByteArray("AddBlocks");
|
||||
metadata = schematicTag.getByteArray("Data");
|
||||
hasExtendedBlockIDs = (highBits.length != 0);
|
||||
int[] temp = schematicTag.getIntArray("Data");
|
||||
state = new IBlockState[temp.length];
|
||||
|
||||
if (volume != lowBits.length)
|
||||
throw new InvalidSchematicException("The schematic has data for fewer blocks than its dimensions indicate.");
|
||||
if (volume != metadata.length)
|
||||
throw new InvalidSchematicException("The schematic has metadata for fewer blocks than its dimensions indicate.");
|
||||
if (volume > 2 * highBits.length && hasExtendedBlockIDs)
|
||||
throw new InvalidSchematicException("The schematic has extended block IDs for fewer blocks than its dimensions indicate.");
|
||||
for(int i = 0; i < temp.length; i++)
|
||||
state[i] = Block.getStateById(temp[i]);
|
||||
|
||||
blockIds = new short[volume];
|
||||
if (hasExtendedBlockIDs)
|
||||
{
|
||||
//Combine the split block IDs into a single value
|
||||
pairs = volume - (volume & 1);
|
||||
int index;
|
||||
for (index = 0; index < pairs; index += 2)
|
||||
{
|
||||
blockIds[index] = (short) (((highBits[index >> 1] & 0x0F) << 8) + (lowBits[index] & 0xFF));
|
||||
blockIds[index + 1] = (short) (((highBits[index >> 1] & 0xF0) << 4) + (lowBits[index + 1] & 0xFF));
|
||||
}
|
||||
if (index < volume)
|
||||
{
|
||||
blockIds[index] = lowBits[index >> 1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Copy the blockIDs
|
||||
for (int index = 0; index < volume; index++)
|
||||
{
|
||||
blockIds[index] = (short) (lowBits[index] & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < blockIds.length; i++) {
|
||||
int paletteIndex = blockIds[i];
|
||||
if (paletteIndex < 0 || paletteIndex >= blockPalette.length) {
|
||||
throw new InvalidSchematicException("Block entry referenced a non-existant palette entry.");
|
||||
}
|
||||
}
|
||||
if (volume != state.length)
|
||||
throw new InvalidSchematicException("The schematic has IBlockState for fewer blocks than its dimensions indicate.");
|
||||
|
||||
//Get the list of tile entities
|
||||
tileEntities = schematicTag.getTagList("TileEntities", 10);
|
||||
|
||||
Schematic result = new Schematic(width, height, length, blockPalette, blockIds, metadata, tileEntities);
|
||||
Schematic result = new Schematic(new BlockPos(width, height, length), state, tileEntities);
|
||||
return result;
|
||||
}
|
||||
catch (InvalidSchematicException ex)
|
||||
|
@ -272,132 +160,71 @@ public class Schematic {
|
|||
}
|
||||
}
|
||||
|
||||
public static Schematic copyFromWorld(World world, int x, int y, int z, short width, short height, short length, boolean doCompactBounds)
|
||||
{
|
||||
if (doCompactBounds)
|
||||
{
|
||||
public static Schematic copyFromWorld(World world, BlockPos pos, BlockPos volume, boolean doCompactBounds) {
|
||||
if (doCompactBounds) {
|
||||
//Adjust the vertical bounds to reasonable values if necessary
|
||||
int worldHeight = world.getHeight();
|
||||
int fixedY = (y < 0) ? 0 : y;
|
||||
int fixedHeight = height + y - fixedY;
|
||||
int fixedY = (pos.getY() < 0) ? 0 : pos.getY();
|
||||
int fixedHeight = volume.getY() + pos.getY() - fixedY;
|
||||
|
||||
if (fixedHeight + fixedY >= worldHeight)
|
||||
{
|
||||
if (fixedHeight + fixedY >= worldHeight) {
|
||||
fixedHeight = worldHeight - fixedY;
|
||||
}
|
||||
|
||||
//Compact the area to be copied to remove empty borders
|
||||
CompactBoundsOperation compactor = new CompactBoundsOperation();
|
||||
compactor.apply(world, x, fixedY, z, width, fixedHeight, length);
|
||||
Point3D minCorner = compactor.getMinCorner();
|
||||
Point3D maxCorner = compactor.getMaxCorner();
|
||||
compactor.apply(world, new BlockPos(pos.getX(), fixedY, pos.getZ()), new BlockPos(volume.getX(), fixedHeight, volume.getZ()));
|
||||
BlockPos minCorner = compactor.getMinCorner();
|
||||
BlockPos maxCorner = compactor.getMaxCorner();
|
||||
|
||||
short compactWidth = (short) (maxCorner.getX() - minCorner.getX() + 1);
|
||||
short compactHeight = (short) (maxCorner.getY() - minCorner.getY() + 1);
|
||||
short compactLength = (short) (maxCorner.getZ() - minCorner.getZ() + 1);
|
||||
BlockPos compact = maxCorner.subtract(minCorner).add(1,1,1);
|
||||
|
||||
return copyFromWorld(world, minCorner.getX(), minCorner.getY(), minCorner.getZ(),
|
||||
compactWidth, compactHeight, compactLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
return copyFromWorld(world, x, y, z, width, height, length);
|
||||
return copyFromWorld(world, minCorner, compact);
|
||||
} else {
|
||||
return copyFromWorld(world, pos, volume);
|
||||
}
|
||||
}
|
||||
|
||||
private static Schematic copyFromWorld(World world, int x, int y, int z, short width, short height, short length)
|
||||
{
|
||||
private static Schematic copyFromWorld(World world, BlockPos pos, BlockPos volume) {
|
||||
//Short and sweet ^_^
|
||||
WorldCopyOperation copier = new WorldCopyOperation();
|
||||
copier.apply(world, x, y, z, width, height, length);
|
||||
return new Schematic(width, height, length, copier.getBlocks(), copier.getMetadata(), copier.getTileEntities());
|
||||
copier.apply(world, pos, volume);
|
||||
return new Schematic(volume, copier.getBlockState(), copier.getTileEntities());
|
||||
}
|
||||
|
||||
private static boolean encodeBlockIDs(short[] blocks, byte[] lowBits, byte[] highBits)
|
||||
{
|
||||
int index;
|
||||
int length = blocks.length - (blocks.length & 1);
|
||||
boolean hasHighBits = false;
|
||||
for (index = 0; index < length; index += 2)
|
||||
{
|
||||
highBits[index >> 1] = (byte) (((blocks[index] >> 8) & 0x0F) + ((blocks[index + 1] >> 4) & 0xF0));
|
||||
hasHighBits |= (highBits[index >> 1] != 0);
|
||||
}
|
||||
if (index < blocks.length)
|
||||
{
|
||||
highBits[index >> 1] = (byte) ((blocks[index] >> 8) & 0x0F);
|
||||
hasHighBits |= (highBits[index >> 1] != 0);
|
||||
}
|
||||
for (index = 0; index < blocks.length; index++)
|
||||
{
|
||||
lowBits[index] = (byte) (blocks[index] & 0xFF);
|
||||
}
|
||||
return hasHighBits;
|
||||
}
|
||||
|
||||
private static void reduceToPalette(Block[] blocks, List<String> blockPalette, short[] blockIds) {
|
||||
for (int i = 0; i < blocks.length; i++) {
|
||||
String blockName = Block.blockRegistry.getNameForObject(blocks[i]);
|
||||
int blockIndex = blockPalette.indexOf(blockName);
|
||||
|
||||
if (blockIndex < 0) {
|
||||
blockIndex = blockPalette.size();
|
||||
blockPalette.add(blockName);
|
||||
}
|
||||
|
||||
blockIds[i] = (short)blockIndex;
|
||||
}
|
||||
}
|
||||
|
||||
public NBTTagCompound writeToNBT()
|
||||
{
|
||||
public NBTTagCompound writeToNBT() {
|
||||
return writeToNBT(true);
|
||||
}
|
||||
|
||||
protected NBTTagCompound writeToNBT(boolean copyTileEntities)
|
||||
{
|
||||
return writeToNBT(width, height, length, blocks, metadata, tileEntities, copyTileEntities);
|
||||
protected NBTTagCompound writeToNBT(boolean copyTileEntities) {
|
||||
return writeToNBT(volume, state, tileEntities, copyTileEntities);
|
||||
}
|
||||
|
||||
protected static NBTTagCompound writeToNBT(short width, short height, short length, Block[] blocks, byte[] metadata,
|
||||
NBTTagList tileEntities, boolean copyTileEntities)
|
||||
{
|
||||
protected static NBTTagCompound writeToNBT(BlockPos volume, IBlockState[] state, NBTTagList tileEntities, boolean copyTileEntities) {
|
||||
//This is the main storage function. Schematics are really compressed NBT tags, so if we can generate
|
||||
//the tags, most of the work is done. All the other storage functions will rely on this one.
|
||||
|
||||
NBTTagCompound schematicTag = new NBTTagCompound();
|
||||
|
||||
schematicTag.setShort("Width", width);
|
||||
schematicTag.setShort("Length", length);
|
||||
schematicTag.setShort("Height", height);
|
||||
schematicTag.setInteger("Width", volume.getX());
|
||||
schematicTag.setInteger("Length", volume.getZ());
|
||||
schematicTag.setInteger("Height", volume.getY());
|
||||
|
||||
schematicTag.setTag("Entities", new NBTTagList());
|
||||
schematicTag.setString("Materials", "Alpha");
|
||||
|
||||
List<String> blockPalette = new LinkedList<String>();
|
||||
short[] blockIds = new short[blocks.length];
|
||||
reduceToPalette(blocks, blockPalette, blockIds);
|
||||
int[] temp = new int[state.length];
|
||||
|
||||
byte[] lowBits = new byte[blocks.length];
|
||||
byte[] highBits = new byte[(blocks.length >> 1) + (blocks.length & 1)];
|
||||
boolean hasExtendedIDs = encodeBlockIDs(blockIds, lowBits, highBits);
|
||||
for(int i = 0; i < temp.length; i++)
|
||||
temp[i] = Block.getStateId(state[i]);
|
||||
|
||||
schematicTag.setByteArray("Blocks", lowBits);
|
||||
schematicTag.setByteArray("Data", metadata);
|
||||
schematicTag.setIntArray("Data", temp);
|
||||
|
||||
if (hasExtendedIDs)
|
||||
{
|
||||
schematicTag.setByteArray("AddBlocks", highBits);
|
||||
}
|
||||
|
||||
if (copyTileEntities)
|
||||
{
|
||||
if (copyTileEntities) {
|
||||
//Used when the result of this function will be passed outside this class.
|
||||
//Avoids exposing the private field to external modifications.
|
||||
schematicTag.setTag("TileEntities", tileEntities.copy());
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
//Used when the result of this function is for internal use.
|
||||
//It's more efficient not to copy the tags unless it's needed.
|
||||
schematicTag.setTag("TileEntities", tileEntities);
|
||||
|
@ -405,13 +232,11 @@ public class Schematic {
|
|||
return schematicTag;
|
||||
}
|
||||
|
||||
public void writeToFile(String schematicPath) throws IOException
|
||||
{
|
||||
public void writeToFile(String schematicPath) throws IOException {
|
||||
writeToFile(new File(schematicPath));
|
||||
}
|
||||
|
||||
public void writeToFile(File schematicFile) throws IOException
|
||||
{
|
||||
public void writeToFile(File schematicFile) throws IOException {
|
||||
FileOutputStream outputStream = new FileOutputStream(schematicFile);
|
||||
CompressedStreamTools.writeCompressed(writeToNBT(false), outputStream);
|
||||
//writeCompressed() probably closes the stream on its own - call close again just in case.
|
||||
|
@ -419,25 +244,19 @@ public class Schematic {
|
|||
outputStream.close();
|
||||
}
|
||||
|
||||
public boolean applyFilter(SchematicFilter filter)
|
||||
{
|
||||
return filter.apply(this, this.blocks, this.metadata);
|
||||
public boolean applyFilter(SchematicFilter filter) {
|
||||
return filter.apply(this, this.state);
|
||||
}
|
||||
|
||||
public void copyToWorld(World world, int x, int y, int z, boolean notifyClients, boolean ignoreAir)
|
||||
{
|
||||
if (notifyClients)
|
||||
{
|
||||
copyToWorld(world, x, y, z, new WorldBlockSetter(false, true, ignoreAir));
|
||||
}
|
||||
else
|
||||
{
|
||||
copyToWorld(world, x, y, z, new ChunkBlockSetter(ignoreAir));
|
||||
public void copyToWorld(World world, BlockPos pos, boolean notifyClients, boolean ignoreAir) {
|
||||
if (notifyClients) {
|
||||
copyToWorld(world, pos, new WorldBlockSetter(false, true, ignoreAir));
|
||||
} else {
|
||||
copyToWorld(world, pos, new ChunkBlockSetter(ignoreAir));
|
||||
}
|
||||
}
|
||||
|
||||
protected void copyToWorld(World world, int x, int y, int z, IBlockSetter blockSetter)
|
||||
{
|
||||
protected void copyToWorld(World world, BlockPos pos, IBlockSetter blockSetter) {
|
||||
//This isn't implemented as a WorldOperation because it doesn't quite fit the structure of those operations.
|
||||
//It's not worth the trouble in this case.
|
||||
int index;
|
||||
|
@ -446,13 +265,10 @@ public class Schematic {
|
|||
|
||||
//Copy blocks and metadata into the world
|
||||
index = 0;
|
||||
for (dy = 0; dy < height; dy++)
|
||||
{
|
||||
for (dz = 0; dz < length; dz++)
|
||||
{
|
||||
for (dx = 0; dx < width; dx++)
|
||||
{
|
||||
blockSetter.setBlock(world, x + dx, y + dy, z + dz, blocks[index], metadata[index]);
|
||||
for (dy = 0; dy < volume.getY(); dy++) {
|
||||
for (dz = 0; dz < volume.getZ(); dz++) {
|
||||
for (dx = 0; dx < volume.getX(); dx++) {
|
||||
blockSetter.setBlock(world, pos.add(dx, dy, dz), state[index]);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
@ -464,14 +280,14 @@ public class Schematic {
|
|||
{
|
||||
NBTTagCompound tileTag = (NBTTagCompound) tileEntities.getCompoundTagAt(index);
|
||||
//Rewrite its location to be in world coordinates
|
||||
dx = tileTag.getInteger("x") + x;
|
||||
dy = tileTag.getInteger("y") + y;
|
||||
dz = tileTag.getInteger("z") + z;
|
||||
dx = tileTag.getInteger("x") + pos.getX();
|
||||
dy = tileTag.getInteger("y") + pos.getY();
|
||||
dz = tileTag.getInteger("z") + pos.getZ();
|
||||
tileTag.setInteger("x", dx);
|
||||
tileTag.setInteger("y", dy);
|
||||
tileTag.setInteger("z", dz);
|
||||
//Load the tile entity and put it in the world
|
||||
world.setTileEntity(dx, dy, dz, TileEntity.createAndLoadEntity(tileTag));
|
||||
world.setTileEntity(new BlockPos(dx, dy, dz), TileEntity.createAndLoadEntity(tileTag));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,58 +1,51 @@
|
|||
package com.zixiken.dimdoors.schematic;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
|
||||
public class SchematicFilter {
|
||||
|
||||
private String name;
|
||||
|
||||
protected SchematicFilter(String name)
|
||||
{
|
||||
protected SchematicFilter(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean apply(Schematic schematic, Block[] blocks, byte[] metadata)
|
||||
public boolean apply(Schematic schematic, IBlockState[] state)
|
||||
{
|
||||
if (!initialize(schematic, blocks, metadata))
|
||||
if (!initialize(schematic, state))
|
||||
return false;
|
||||
|
||||
for (int index = 0; index < blocks.length; index++)
|
||||
{
|
||||
if (applyToBlock(index, blocks, metadata) && terminates())
|
||||
for (int index = 0; index < state.length; index++) {
|
||||
if (applyToBlock(index, state) && terminates())
|
||||
return false;
|
||||
}
|
||||
|
||||
return finish();
|
||||
}
|
||||
|
||||
protected boolean initialize(Schematic schematic, Block[] blocks, byte[] metadata)
|
||||
{
|
||||
protected boolean initialize(Schematic schematic, IBlockState[] state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean applyToBlock(int index, Block[] blocks, byte[] metadata)
|
||||
{
|
||||
protected boolean applyToBlock(int index, IBlockState[] state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean finish()
|
||||
{
|
||||
protected boolean finish() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean terminates()
|
||||
{
|
||||
protected boolean terminates() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,77 +1,59 @@
|
|||
package com.zixiken.dimdoors.schematic;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class WorldCopyOperation extends WorldOperation
|
||||
{
|
||||
private int originX;
|
||||
private int originY;
|
||||
private int originZ;
|
||||
public class WorldCopyOperation extends WorldOperation {
|
||||
private BlockPos origin;
|
||||
private int index;
|
||||
private Block[] blocks;
|
||||
private byte[] metadata;
|
||||
private IBlockState[] state;
|
||||
private NBTTagList tileEntities;
|
||||
|
||||
public WorldCopyOperation()
|
||||
{
|
||||
public WorldCopyOperation() {
|
||||
super("WorldCopyOperation");
|
||||
blocks = null;
|
||||
metadata = null;
|
||||
state = null;
|
||||
tileEntities = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean initialize(World world, int x, int y, int z, int width, int height, int length)
|
||||
{
|
||||
protected boolean initialize(World world, BlockPos pos, BlockPos volume) {
|
||||
index = 0;
|
||||
originX = x;
|
||||
originY = y;
|
||||
originZ = z;
|
||||
blocks = new Block[width * height * length];
|
||||
metadata = new byte[width * height * length];
|
||||
origin = pos;
|
||||
state = new IBlockState[volume.getX() * volume.getY() * volume.getZ()];
|
||||
tileEntities = new NBTTagList();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean applyToBlock(World world, int x, int y, int z)
|
||||
{
|
||||
blocks[index] = world.getBlock(x, y, z);
|
||||
metadata[index] = (byte) world.getBlockMetadata(x, y, z);
|
||||
protected boolean applyToBlock(World world, BlockPos pos) {
|
||||
state[index] = world.getBlockState(pos);
|
||||
|
||||
TileEntity tileEntity = world.getTileEntity(x, y, z);
|
||||
if (tileEntity != null)
|
||||
{
|
||||
TileEntity tileEntity = world.getTileEntity(pos);
|
||||
if (tileEntity != null) {
|
||||
//Extract tile entity data
|
||||
NBTTagCompound tileTag = new NBTTagCompound();
|
||||
tileEntity.writeToNBT(tileTag);
|
||||
//Translate the tile entity's position from the world's coordinate system
|
||||
//to the schematic's coordinate system.
|
||||
tileTag.setInteger("x", x - originX);
|
||||
tileTag.setInteger("y", y - originY);
|
||||
tileTag.setInteger("z", z - originZ);
|
||||
tileTag.setInteger("x", pos.getX() - origin.getX());
|
||||
tileTag.setInteger("y", pos.getY() - origin.getY());
|
||||
tileTag.setInteger("z", pos.getZ() - origin.getZ());
|
||||
tileEntities.appendTag(tileTag);
|
||||
}
|
||||
index++; //This works assuming the loops in WorldOperation are done in YZX order
|
||||
return true;
|
||||
}
|
||||
|
||||
public Block[] getBlocks()
|
||||
{
|
||||
return blocks;
|
||||
public IBlockState[] getBlockState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public byte[] getMetadata()
|
||||
{
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public NBTTagList getTileEntities()
|
||||
{
|
||||
public NBTTagList getTileEntities() {
|
||||
return tileEntities;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.zixiken.dimdoors.schematic;
|
||||
|
||||
import com.zixiken.dimdoors.Point3D;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public abstract class WorldOperation {
|
||||
|
@ -12,48 +12,29 @@ public abstract class WorldOperation {
|
|||
this.name = name;
|
||||
}
|
||||
|
||||
protected boolean initialize(World world, int x, int y, int z, int width, int height, int length)
|
||||
{
|
||||
protected boolean initialize(World world, BlockPos pos, BlockPos volume) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected abstract boolean applyToBlock(World world, int x, int y, int z);
|
||||
protected abstract boolean applyToBlock(World world, BlockPos pos);
|
||||
|
||||
protected boolean finish()
|
||||
{
|
||||
protected boolean finish() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean apply(World world, Point3D minCorner, Point3D maxCorner)
|
||||
{
|
||||
int x = minCorner.getX();
|
||||
int y = minCorner.getY();
|
||||
int z = minCorner.getZ();
|
||||
int width = maxCorner.getX() - x + 1;
|
||||
int height = maxCorner.getY() - y + 1;
|
||||
int length = maxCorner.getZ() - z + 1;
|
||||
return apply(world, x, y, z, width, height, length);
|
||||
}
|
||||
|
||||
public boolean apply(World world, int x, int y, int z, int width, int height, int length)
|
||||
{
|
||||
if (!initialize(world, x, y, z, width, height, length))
|
||||
public boolean apply(World world, BlockPos pos, BlockPos volume) {
|
||||
if (!initialize(world, pos, volume))
|
||||
return false;
|
||||
|
||||
int cx, cy, cz;
|
||||
int limitX = x + width;
|
||||
int limitY = y + height;
|
||||
int limitZ = z + length;
|
||||
BlockPos limit = pos.add(volume);
|
||||
|
||||
//The order of these loops is important. Don't change it! It's used to avoid calculating
|
||||
//indeces in some schematic operations. The proper order is YZX.
|
||||
for (cy = y; cy < limitY; cy++)
|
||||
{
|
||||
for (cz = z; cz < limitZ; cz++)
|
||||
{
|
||||
for (cx = x; cx < limitX; cx++)
|
||||
{
|
||||
if (!applyToBlock(world, cx, cy, cz))
|
||||
for (cy = pos.getY(); cy < limit.getY(); cy++) {
|
||||
for (cz = pos.getZ(); cz < limit.getZ(); cz++) {
|
||||
for (cx = pos.getX(); cx < limit.getX(); cx++) {
|
||||
if (!applyToBlock(world, new BlockPos(cx, cy, cz)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -63,14 +44,12 @@ public abstract class WorldOperation {
|
|||
}
|
||||
|
||||
|
||||
public String getName()
|
||||
{
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,44 +5,39 @@ import java.io.*;
|
|||
import com.zixiken.dimdoors.Point3D;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.BlockPos;
|
||||
|
||||
|
||||
public final class Point4D implements Comparable<Point4D>
|
||||
{
|
||||
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
private final BlockPos pos;
|
||||
private final int dimension;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @param pos
|
||||
* @param dimension
|
||||
*/
|
||||
public Point4D(int x, int y, int z, int dimension)
|
||||
public Point4D(BlockPos pos, int dimension)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.pos = pos;
|
||||
this.dimension = dimension;
|
||||
}
|
||||
|
||||
public int getX()
|
||||
{
|
||||
return x;
|
||||
return pos.getX();
|
||||
}
|
||||
|
||||
public int getY()
|
||||
{
|
||||
return y;
|
||||
return pos.getY();
|
||||
}
|
||||
|
||||
public int getZ()
|
||||
{
|
||||
return z;
|
||||
return pos.getZ();
|
||||
}
|
||||
|
||||
public int getDimension()
|
||||
|
@ -51,8 +46,7 @@ public final class Point4D implements Comparable<Point4D>
|
|||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
public int hashCode() {
|
||||
//Time for some witchcraft.
|
||||
//The code here is inspired by a discussion on Stack Overflow regarding hash codes for 3D.
|
||||
//Source: http://stackoverflow.com/questions/9858376/hashcode-for-3d-integer-coordinates-with-high-spatial-coherence
|
||||
|
@ -67,153 +61,87 @@ public final class Point4D implements Comparable<Point4D>
|
|||
|
||||
hash = 0;
|
||||
index = 0;
|
||||
for (bit = 0; bit < 8; bit++)
|
||||
{
|
||||
hash |= ((y >> bit) & 1) << index;
|
||||
for (bit = 0; bit < 8; bit++) {
|
||||
hash |= ((pos.getY() >> bit) & 1) << index;
|
||||
index++;
|
||||
hash |= ((x >> bit) & 1) << index;
|
||||
hash |= ((pos.getX() >> bit) & 1) << index;
|
||||
index++;
|
||||
hash |= ((z >> bit) & 1) << index;
|
||||
hash |= ((pos.getZ() >> bit) & 1) << index;
|
||||
index++;
|
||||
}
|
||||
for (; bit < 12; bit++)
|
||||
{
|
||||
hash |= ((x >> bit) & 1) << index;
|
||||
for (; bit < 12; bit++) {
|
||||
hash |= ((pos.getX() >> bit) & 1) << index;
|
||||
index++;
|
||||
hash |= ((z >> bit) & 1) << index;
|
||||
hash |= ((pos.getZ() >> bit) & 1) << index;
|
||||
index++;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
public long toSeed()
|
||||
{
|
||||
//Time for some witchcraft.
|
||||
//The code here is inspired by a discussion on Stack Overflow regarding hash codes for 3D.
|
||||
//Source: http://stackoverflow.com/questions/9858376/hashcode-for-3d-integer-coordinates-with-high-spatial-coherence
|
||||
|
||||
//Use 8 bits from Y and 16 bits from X and Z. Mix in 8 bits from the destination dim ID too - that means
|
||||
//even if you aligned two doors perfectly between two pockets, it's unlikely they would lead to the same dungeon.
|
||||
//We map bits in reverse order to produce more varied RNG output for nearly-identical points. The reason is
|
||||
//that Java's Random outputs the 32 MSBs of its internal state to produce its output. If the differences
|
||||
//between two seeds are small (i.e. in the LSBs), then they will tend to produce similar random outputs anyway!
|
||||
|
||||
//Only bother to assign the 48 least-significant bits since Random only takes those bits from its seed.
|
||||
//NOTE: The casts to long are necessary to get the right results from the bit shifts!!!
|
||||
|
||||
int bit;
|
||||
int index;
|
||||
long hash;
|
||||
final int w = this.dimension;
|
||||
final int x = this.x;
|
||||
final int y = this.y;
|
||||
final int z = this.z;
|
||||
|
||||
hash = 0;
|
||||
index = 48;
|
||||
for (bit = 0; bit < 8; bit++)
|
||||
{
|
||||
hash |= (long) ((w >> bit) & 1) << index;
|
||||
index--;
|
||||
hash |= (long) ((x >> bit) & 1) << index;
|
||||
index--;
|
||||
hash |= (long) ((y >> bit) & 1) << index;
|
||||
index--;
|
||||
hash |= (long) ((z >> bit) & 1) << index;
|
||||
index--;
|
||||
}
|
||||
for (; bit < 16; bit++)
|
||||
{
|
||||
hash |= (long) ((x >> bit) & 1) << index;
|
||||
index--;
|
||||
hash |= (long) ((z >> bit) & 1) << index;
|
||||
index--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
return equals((Point4D) obj);
|
||||
}
|
||||
|
||||
public Point3D toPoint3D()
|
||||
{
|
||||
return new Point3D(this.x, this.y, this.z);
|
||||
public BlockPos toBlockPos() {
|
||||
return new BlockPos(this.pos);
|
||||
}
|
||||
|
||||
public int[] toIntArray()
|
||||
{
|
||||
return new int[] {x, y, z, dimension};
|
||||
}
|
||||
|
||||
public boolean equals(Point4D other)
|
||||
{
|
||||
public boolean equals(Point4D other) {
|
||||
if (this == other)
|
||||
return true;
|
||||
if (other == null)
|
||||
return false;
|
||||
|
||||
return (x == other.x && y == other.y && z == other.z && dimension == other.dimension);
|
||||
return (pos.equals(other.pos) && dimension == other.dimension);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Point4D other)
|
||||
{
|
||||
int diff = x - other.x;
|
||||
if (diff != 0)
|
||||
return diff;
|
||||
diff = y - other.y;
|
||||
if (diff != 0)
|
||||
return diff;
|
||||
diff = z - other.z;
|
||||
if (diff != 0)
|
||||
return diff;
|
||||
public int compareTo(Point4D other) {
|
||||
BlockPos diff = pos.subtract(other.pos);
|
||||
if (diff.getX() != 0)
|
||||
return diff.getX();
|
||||
if (diff.getY() != 0)
|
||||
return diff.getZ();
|
||||
if (diff.getZ() != 0)
|
||||
return diff.getZ();
|
||||
return dimension - other.dimension;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "(" + x + ", " + y + ", " + z + ", " + dimension + ")";
|
||||
return "(" + pos + ", " + dimension + ")";
|
||||
}
|
||||
|
||||
public static void writeToNBT(Point4D point, NBTTagCompound tag) {
|
||||
if (point != null) {
|
||||
tag.setInteger("X", point.x);
|
||||
tag.setInteger("Y", point.y);
|
||||
tag.setInteger("Z", point.z);
|
||||
tag.setInteger("X", point.getX());
|
||||
tag.setInteger("Y", point.getY());
|
||||
tag.setInteger("Z", point.getZ());
|
||||
tag.setInteger("Dimension", point.dimension);
|
||||
}
|
||||
}
|
||||
|
||||
public static void write(Point4D point, ByteBuf stream) throws IOException
|
||||
{
|
||||
public static void write(Point4D point, ByteBuf stream) throws IOException {
|
||||
stream.writeBoolean(point != null);
|
||||
if (point != null)
|
||||
{
|
||||
stream.writeInt(point.x);
|
||||
stream.writeInt(point.y);
|
||||
stream.writeInt(point.z);
|
||||
if (point != null) {
|
||||
stream.writeInt(point.getX());
|
||||
stream.writeInt(point.getY());
|
||||
stream.writeInt(point.getZ());
|
||||
stream.writeInt(point.dimension);
|
||||
}
|
||||
}
|
||||
|
||||
public static Point4D read(ByteBuf stream) throws IOException
|
||||
{
|
||||
if (stream.readBoolean())
|
||||
{
|
||||
return new Point4D( stream.readInt(), stream.readInt(), stream.readInt(), stream.readInt() );
|
||||
}
|
||||
else
|
||||
{
|
||||
public static Point4D read(ByteBuf stream) throws IOException {
|
||||
if (stream.readBoolean()) {
|
||||
return new Point4D(new BlockPos(stream.readInt(), stream.readInt(), stream.readInt()), stream.readInt() );
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Point4D readFromNBT(NBTTagCompound tag) {
|
||||
return new Point4D(tag.getInteger("X"), tag.getInteger("Y"), tag.getInteger("Z"), tag.getInteger("Dimension"));
|
||||
return new Point4D(new BlockPos(tag.getInteger("X"), tag.getInteger("Y"), tag.getInteger("Z")), tag.getInteger("Dimension"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ import com.zixiken.dimdoors.core.DimLink;
|
|||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
@ -44,21 +46,17 @@ public class PocketBuilder
|
|||
|
||||
private PocketBuilder() { }
|
||||
|
||||
private static boolean buildDungeonPocket(DungeonData dungeon, NewDimData dimension, DimLink link, DungeonSchematic schematic, World world, DDProperties properties)
|
||||
{
|
||||
private static boolean buildDungeonPocket(DungeonData dungeon, NewDimData dimension, DimLink link, DungeonSchematic schematic, World world, DDProperties properties) {
|
||||
//Calculate the destination point
|
||||
DungeonPackConfig packConfig = dungeon.dungeonType().Owner != null ? dungeon.dungeonType().Owner.getConfig() : null;
|
||||
Point4D source = link.source();
|
||||
int orientation = link.orientation();
|
||||
Point3D destination;
|
||||
EnumFacing orientation = link.orientation();
|
||||
BlockPos destination;
|
||||
|
||||
if (packConfig != null && packConfig.doDistortDoorCoordinates())
|
||||
{
|
||||
if (packConfig != null && packConfig.doDistortDoorCoordinates()) {
|
||||
destination = calculateNoisyDestination(source, dimension, dungeon, orientation);
|
||||
}
|
||||
else
|
||||
{
|
||||
destination = new Point3D(source.getX(), source.getY(), source.getZ());
|
||||
} else {
|
||||
destination = new BlockPos(source.getX(), source.getY(), source.getZ());
|
||||
}
|
||||
|
||||
destination.setY( yCoordHelper.adjustDestinationY(destination.getY(), world.getHeight(), schematic.getEntranceDoorLocation().getY(), schematic.getHeight()) );
|
||||
|
@ -67,7 +65,7 @@ public class PocketBuilder
|
|||
schematic.copyToWorld(world, destination, orientation, link, random, properties, false);
|
||||
|
||||
//Finish up destination initialization
|
||||
dimension.initializeDungeon(destination.getX(), destination.getY(), destination.getZ(), orientation, link, dungeon);
|
||||
dimension.initializeDungeon(destination, orientation, link, dungeon);
|
||||
dimension.setFilled(true);
|
||||
|
||||
return true;
|
||||
|
@ -160,7 +158,7 @@ public class PocketBuilder
|
|||
}
|
||||
|
||||
|
||||
private static Point3D calculateNoisyDestination(Point4D source, NewDimData dimension, DungeonData dungeon, int orientation)
|
||||
private static BlockPos calculateNoisyDestination(Point4D source, NewDimData dimension, DungeonData dungeon, int orientation)
|
||||
{
|
||||
int depth = NewDimData.calculatePackDepth(dimension.parent(), dungeon);
|
||||
int forwardNoise = MathHelper.getRandomIntegerInRange(random, 10 * depth, 130 * depth);
|
||||
|
@ -169,9 +167,9 @@ public class PocketBuilder
|
|||
//Rotate the link destination noise to point in the same direction as the door exit
|
||||
//and add it to the door's location. Use EAST as the reference orientation since linkDestination
|
||||
//is constructed as if pointing East.
|
||||
Point3D linkDestination = new Point3D(forwardNoise, 0, sidewaysNoise);
|
||||
Point3D sourcePoint = new Point3D(source.getX(), source.getY(), source.getZ());
|
||||
Point3D zeroPoint = new Point3D(0, 0, 0);
|
||||
BlockPos linkDestination = new BlockPos(forwardNoise, 0, sidewaysNoise);
|
||||
BlockPos sourcePoint = new BlockPos(source.getX(), source.getY(), source.getZ());
|
||||
BlockPos zeroPoint = new BlockPos(0, 0, 0);
|
||||
BlockRotator.transformPoint(linkDestination, zeroPoint, orientation - BlockRotator.EAST_DOOR_METADATA, sourcePoint);
|
||||
return linkDestination;
|
||||
}
|
||||
|
@ -450,8 +448,8 @@ public class PocketBuilder
|
|||
}
|
||||
|
||||
|
||||
Point3D center = new Point3D(x - wallThickness + 1 + (size / 2), y - wallThickness - 1 + (size / 2), z);
|
||||
Point3D door = new Point3D(x, y, z);
|
||||
BlockPos center = new BlockPos(x - wallThickness + 1 + (size / 2), y - wallThickness - 1 + (size / 2), z);
|
||||
BlockPos door = new BlockPos(x, y, z);
|
||||
BlockRotator.transformPoint(center, door, orientation - BlockRotator.EAST_DOOR_METADATA, door);
|
||||
|
||||
//Build the outer layer of Eternal Fabric
|
||||
|
|
|
@ -36,7 +36,7 @@ public abstract class BaseSchematicGateway extends BaseGateway
|
|||
schematic.applyFilter(gatewayFilter);
|
||||
schematic.applyImportFilters(properties);
|
||||
|
||||
Point3D doorLocation = gatewayFilter.getEntranceDoorLocation();
|
||||
BlockPos doorLocation = gatewayFilter.getEntranceDoorLocation();
|
||||
int orientation = gatewayFilter.getEntranceOrientation();
|
||||
|
||||
// Build the gateway into the world
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package com.zixiken.dimdoors.world.gateways;
|
||||
|
||||
import com.zixiken.dimdoors.Point3D;
|
||||
import com.zixiken.dimdoors.DimDoors;
|
||||
import com.zixiken.dimdoors.schematic.Schematic;
|
||||
import com.zixiken.dimdoors.schematic.SchematicFilter;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.util.BlockPos;
|
||||
|
||||
public class GatewayBlockFilter extends SchematicFilter {
|
||||
|
||||
|
@ -14,7 +14,7 @@ public class GatewayBlockFilter extends SchematicFilter {
|
|||
|
||||
private int entranceOrientation;
|
||||
private Schematic schematic;
|
||||
private Point3D entranceDoorLocation;
|
||||
private BlockPos entranceDoorLocation;
|
||||
|
||||
public GatewayBlockFilter()
|
||||
{
|
||||
|
@ -28,7 +28,7 @@ public class GatewayBlockFilter extends SchematicFilter {
|
|||
return entranceOrientation;
|
||||
}
|
||||
|
||||
public Point3D getEntranceDoorLocation() {
|
||||
public BlockPos getEntranceDoorLocation() {
|
||||
return entranceDoorLocation;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue