Merge pull request #56 from SenseiKiwi/master
Overhauled Schematic Importing and Exporting
This commit is contained in:
@@ -101,4 +101,10 @@ public class Point3D implements Serializable {
|
|||||||
}
|
}
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "(" + x + ", " + "y" + ", " + z + ")";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
417
StevenDimDoors/mod_pocketDim/dungeon/DungeonSchematic.java
Normal file
417
StevenDimDoors/mod_pocketDim/dungeon/DungeonSchematic.java
Normal file
@@ -0,0 +1,417 @@
|
|||||||
|
package StevenDimDoors.mod_pocketDim.dungeon;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.util.MathHelper;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||||
|
import StevenDimDoors.mod_pocketDim.LinkData;
|
||||||
|
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||||
|
import StevenDimDoors.mod_pocketDim.helpers.dimHelper;
|
||||||
|
import StevenDimDoors.mod_pocketDim.helpers.yCoordHelper;
|
||||||
|
import StevenDimDoors.mod_pocketDim.schematic.BlockRotator;
|
||||||
|
import StevenDimDoors.mod_pocketDim.schematic.CompoundFilter;
|
||||||
|
import StevenDimDoors.mod_pocketDim.schematic.InvalidSchematicException;
|
||||||
|
import StevenDimDoors.mod_pocketDim.schematic.ReplacementFilter;
|
||||||
|
import StevenDimDoors.mod_pocketDim.schematic.Schematic;
|
||||||
|
import StevenDimDoors.mod_pocketDim.ticking.MobMonolith;
|
||||||
|
|
||||||
|
public class DungeonSchematic extends Schematic {
|
||||||
|
|
||||||
|
private static final short MAX_VANILLA_BLOCK_ID = 158;
|
||||||
|
private static final short STANDARD_FABRIC_OF_REALITY_ID = 1973;
|
||||||
|
private static final short STANDARD_ETERNAL_FABRIC_ID = 220;
|
||||||
|
private static final short STANDARD_WARP_DOOR_ID = (short) Block.doorWood.blockID;//1975;
|
||||||
|
private static final short STANDARD_DIMENSIONAL_DOOR_ID = (short) Block.doorIron.blockID;//1970;
|
||||||
|
private static final short MONOLITH_SPAWN_MARKER_ID = (short) Block.endPortalFrame.blockID;
|
||||||
|
private static final short EXIT_DOOR_MARKER_ID = (short) Block.sandStone.blockID;
|
||||||
|
|
||||||
|
private int orientation;
|
||||||
|
private Point3D entranceDoorLocation;
|
||||||
|
private ArrayList<Point3D> exitDoorLocations;
|
||||||
|
private ArrayList<Point3D> dimensionalDoorLocations;
|
||||||
|
private ArrayList<Point3D> monolithSpawnLocations;
|
||||||
|
|
||||||
|
private static final short[] MOD_BLOCK_FILTER_EXCEPTIONS = new short[] {
|
||||||
|
STANDARD_FABRIC_OF_REALITY_ID,
|
||||||
|
STANDARD_ETERNAL_FABRIC_ID
|
||||||
|
//STANDARD_WARP_DOOR_ID,
|
||||||
|
//STANDARD_DIMENSIONAL_DOOR_ID
|
||||||
|
};
|
||||||
|
|
||||||
|
private DungeonSchematic(Schematic source)
|
||||||
|
{
|
||||||
|
super(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getOrientation()
|
||||||
|
{
|
||||||
|
return orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point3D getEntranceDoorLocation()
|
||||||
|
{
|
||||||
|
return entranceDoorLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DungeonSchematic()
|
||||||
|
{
|
||||||
|
//Used to create a dummy instance for readFromResource()
|
||||||
|
super((short) 0, (short) 0, (short) 0, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DungeonSchematic readFromFile(String schematicPath) throws FileNotFoundException, InvalidSchematicException
|
||||||
|
{
|
||||||
|
return readFromFile(new File(schematicPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DungeonSchematic readFromFile(File schematicFile) throws FileNotFoundException, InvalidSchematicException
|
||||||
|
{
|
||||||
|
return readFromStream(new FileInputStream(schematicFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
return new DungeonSchematic(Schematic.readFromStream(schematicStream));
|
||||||
|
}
|
||||||
|
|
||||||
|
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(STANDARD_WARP_DOOR_ID, STANDARD_DIMENSIONAL_DOOR_ID,
|
||||||
|
MONOLITH_SPAWN_MARKER_ID, EXIT_DOOR_MARKER_ID);
|
||||||
|
applyFilter(finder);
|
||||||
|
|
||||||
|
orientation = (finder.getEntranceOrientation() + 2) & 3; //Flip the entrance's orientation to get the dungeon's orientation
|
||||||
|
entranceDoorLocation = finder.getEntranceDoorLocation();
|
||||||
|
exitDoorLocations = finder.getExitDoorLocations();
|
||||||
|
dimensionalDoorLocations = finder.getDimensionalDoorLocations();
|
||||||
|
monolithSpawnLocations = finder.getMonolithSpawnLocations();
|
||||||
|
|
||||||
|
//Filter out mod blocks except some of our own
|
||||||
|
CompoundFilter standardizer = new CompoundFilter();
|
||||||
|
standardizer.addFilter(new ModBlockFilter(MAX_VANILLA_BLOCK_ID, MOD_BLOCK_FILTER_EXCEPTIONS,
|
||||||
|
(short) properties.FabricBlockID, (byte) 0));
|
||||||
|
|
||||||
|
//Also convert standard DD block IDs to local versions
|
||||||
|
Map<Short, Short> mapping = getAssignedToStandardIDMapping(properties);
|
||||||
|
|
||||||
|
for (Entry<Short, Short> entry : mapping.entrySet())
|
||||||
|
{
|
||||||
|
if (entry.getKey() != entry.getValue())
|
||||||
|
{
|
||||||
|
standardizer.addFilter(new ReplacementFilter(entry.getValue(), entry.getKey()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
applyFilter(standardizer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyExportFilters(DDProperties properties)
|
||||||
|
{
|
||||||
|
//Check if some block IDs assigned by Forge differ from our standard IDs
|
||||||
|
//If so, change the IDs to standard values
|
||||||
|
CompoundFilter standardizer = new CompoundFilter();
|
||||||
|
Map<Short, Short> mapping = getAssignedToStandardIDMapping(properties);
|
||||||
|
|
||||||
|
for (Entry<Short, Short> entry : mapping.entrySet())
|
||||||
|
{
|
||||||
|
if (entry.getKey() != entry.getValue())
|
||||||
|
{
|
||||||
|
standardizer.addFilter(new ReplacementFilter(entry.getKey(), entry.getValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//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(MAX_VANILLA_BLOCK_ID, MOD_BLOCK_FILTER_EXCEPTIONS,
|
||||||
|
STANDARD_FABRIC_OF_REALITY_ID, (byte) 0));
|
||||||
|
|
||||||
|
applyFilter(standardizer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<Short, Short> getAssignedToStandardIDMapping(DDProperties properties)
|
||||||
|
{
|
||||||
|
//If we ever need this broadly or support other mods, this should be moved to a separate class
|
||||||
|
TreeMap<Short, Short> mapping = new TreeMap<Short, Short>();
|
||||||
|
mapping.put((short) properties.FabricBlockID, STANDARD_FABRIC_OF_REALITY_ID);
|
||||||
|
mapping.put((short) properties.PermaFabricBlockID, STANDARD_ETERNAL_FABRIC_ID);
|
||||||
|
mapping.put((short) properties.WarpDoorID, STANDARD_WARP_DOOR_ID);
|
||||||
|
mapping.put((short) properties.DimensionalDoorID, STANDARD_DIMENSIONAL_DOOR_ID);
|
||||||
|
return mapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DungeonSchematic copyFromWorld(World world, int x, int y, int z, short width, short height, short length, boolean doCompactBounds)
|
||||||
|
{
|
||||||
|
return new DungeonSchematic(Schematic.copyFromWorld(world, x, y, z, width, height, length, doCompactBounds));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void copyToWorld(World world, Point3D pocketCenter, int dungeonOrientation, int originDimID, int destDimID)
|
||||||
|
{
|
||||||
|
//TODO: This function is an improvised solution so we can get the release moving. In the future,
|
||||||
|
//we should generalize block tranformations and implement support for them at the level of Schematic,
|
||||||
|
//then just use that support from DungeonSchematic instead of making this local fix.
|
||||||
|
//It might be easiest to support transformations using a WorldOperation
|
||||||
|
|
||||||
|
final int turnAngle = dungeonOrientation - orientation;
|
||||||
|
|
||||||
|
|
||||||
|
int index;
|
||||||
|
int count;
|
||||||
|
int blockID;
|
||||||
|
int blockMeta;
|
||||||
|
int dx, dy, dz;
|
||||||
|
Point3D pocketPoint = new Point3D(0, 0, 0);
|
||||||
|
|
||||||
|
//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++)
|
||||||
|
{
|
||||||
|
pocketPoint.setX(dx);
|
||||||
|
pocketPoint.setY(dy);
|
||||||
|
pocketPoint.setZ(dz);
|
||||||
|
blockID = blocks[index];
|
||||||
|
BlockRotator.transformPoint(pocketPoint, entranceDoorLocation, turnAngle, pocketCenter);
|
||||||
|
blockMeta = BlockRotator.transformMetadata(metadata[index], turnAngle + BlockRotator.NORTH_DOOR_METADATA, blockID);
|
||||||
|
|
||||||
|
//In the future, we might want to make this more efficient by building whole chunks at a time
|
||||||
|
setBlockDirectly(world, pocketPoint.getX(), pocketPoint.getY(), pocketPoint.getZ(), blockID, blockMeta);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Copy tile entities into the world
|
||||||
|
count = tileEntities.tagCount();
|
||||||
|
for (index = 0; index < count; index++)
|
||||||
|
{
|
||||||
|
NBTTagCompound tileTag = (NBTTagCompound) tileEntities.tagAt(index);
|
||||||
|
//Rewrite its location to be in world coordinates
|
||||||
|
pocketPoint.setX(tileTag.getInteger("x"));
|
||||||
|
pocketPoint.setY(tileTag.getInteger("y"));
|
||||||
|
pocketPoint.setZ(tileTag.getInteger("z"));
|
||||||
|
BlockRotator.transformPoint(pocketPoint, entranceDoorLocation, turnAngle, pocketCenter);
|
||||||
|
tileTag.setInteger("x", pocketPoint.getX());
|
||||||
|
tileTag.setInteger("y", pocketPoint.getY());
|
||||||
|
tileTag.setInteger("z", pocketPoint.getZ());
|
||||||
|
//Load the tile entity and put it in the world
|
||||||
|
world.setBlockTileEntity(pocketPoint.getX(), pocketPoint.getY(), pocketPoint.getZ(), TileEntity.createAndLoadEntity(tileTag));
|
||||||
|
}
|
||||||
|
|
||||||
|
setUpDungeon(world, pocketCenter, turnAngle, originDimID, destDimID);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpDungeon(World world, Point3D pocketCenter, int turnAngle, int originDimID, int destDimID)
|
||||||
|
{
|
||||||
|
//The following Random initialization code is based on code from ChunkProviderGenerate.
|
||||||
|
//It makes our generation depend on the world seed.
|
||||||
|
Random random = new Random(world.getSeed());
|
||||||
|
long factorA = random.nextLong() / 2L * 2L + 1L;
|
||||||
|
long factorB = random.nextLong() / 2L * 2L + 1L;
|
||||||
|
random.setSeed((pocketCenter.getX() >> 4) * factorA + (pocketCenter.getZ() >> 4) * factorB ^ world.getSeed());
|
||||||
|
|
||||||
|
//Transform dungeon corners
|
||||||
|
Point3D minCorner = new Point3D(0, 0, 0);
|
||||||
|
Point3D maxCorner = new Point3D(width - 1, height - 1, length - 1);
|
||||||
|
transformCorners(entranceDoorLocation, pocketCenter, turnAngle, minCorner, maxCorner);
|
||||||
|
|
||||||
|
//Fill empty chests and dispensers
|
||||||
|
FillContainersOperation filler = new FillContainersOperation(random);
|
||||||
|
filler.apply(world, minCorner, maxCorner);
|
||||||
|
|
||||||
|
//Set up entrance door rift
|
||||||
|
setUpEntranceDoorLink(world, entranceDoorLocation, turnAngle, pocketCenter);
|
||||||
|
|
||||||
|
//Set up link data for dimensional doors
|
||||||
|
for (Point3D location : dimensionalDoorLocations)
|
||||||
|
{
|
||||||
|
setUpDimensionalDoorLink(world, location, entranceDoorLocation, turnAngle, pocketCenter, originDimID, destDimID, random);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set up link data for exit door
|
||||||
|
for (Point3D location : exitDoorLocations)
|
||||||
|
{
|
||||||
|
setUpExitDoorLink(world, location, entranceDoorLocation, turnAngle, pocketCenter, originDimID, destDimID, random);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Remove end portal frames and spawn Monoliths
|
||||||
|
for (Point3D location : monolithSpawnLocations)
|
||||||
|
{
|
||||||
|
spawnMonolith(world, location, entranceDoorLocation, turnAngle, pocketCenter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void transformCorners(Point3D schematicEntrance, Point3D pocketCenter, int turnAngle, Point3D minCorner, Point3D maxCorner)
|
||||||
|
{
|
||||||
|
int temp;
|
||||||
|
BlockRotator.transformPoint(minCorner, schematicEntrance, turnAngle, pocketCenter);
|
||||||
|
BlockRotator.transformPoint(maxCorner, schematicEntrance, turnAngle, pocketCenter);
|
||||||
|
if (minCorner.getX() > maxCorner.getX())
|
||||||
|
{
|
||||||
|
temp = minCorner.getX();
|
||||||
|
minCorner.setX(maxCorner.getX());
|
||||||
|
maxCorner.setX(temp);
|
||||||
|
}
|
||||||
|
if (minCorner.getY() > maxCorner.getY())
|
||||||
|
{
|
||||||
|
temp = minCorner.getY();
|
||||||
|
minCorner.setY(maxCorner.getY());
|
||||||
|
maxCorner.setY(temp);
|
||||||
|
}
|
||||||
|
if (minCorner.getZ() > maxCorner.getZ())
|
||||||
|
{
|
||||||
|
temp = minCorner.getZ();
|
||||||
|
minCorner.setZ(maxCorner.getZ());
|
||||||
|
maxCorner.setZ(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setUpEntranceDoorLink(World world, Point3D entrance, int rotation, Point3D pocketCenter)
|
||||||
|
{
|
||||||
|
//Set the orientation of the rift exit
|
||||||
|
Point3D entranceRiftLocation = entrance.clone();
|
||||||
|
BlockRotator.transformPoint(entranceRiftLocation, entrance, rotation, pocketCenter);
|
||||||
|
LinkData sideLink = dimHelper.instance.getLinkDataFromCoords(
|
||||||
|
entranceRiftLocation.getX(),
|
||||||
|
entranceRiftLocation.getY(),
|
||||||
|
entranceRiftLocation.getZ(),
|
||||||
|
world);
|
||||||
|
sideLink.linkOrientation = world.getBlockMetadata(
|
||||||
|
entranceRiftLocation.getX(),
|
||||||
|
entranceRiftLocation.getY() - 1,
|
||||||
|
entranceRiftLocation.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setUpExitDoorLink(World world, Point3D point, Point3D entrance, int rotation, Point3D pocketCenter, int originDimID, int destDimID, Random random)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//TODO: Hax, remove this later
|
||||||
|
DDProperties properties = DDProperties.instance();
|
||||||
|
|
||||||
|
//Transform doorLocation to the pocket coordinate system.
|
||||||
|
Point3D location = point.clone();
|
||||||
|
BlockRotator.transformPoint(location, entrance, rotation, pocketCenter);
|
||||||
|
int blockDirection = world.getBlockMetadata(location.getX(), location.getY() - 1, location.getZ());
|
||||||
|
Point3D linkDestination = location.clone();
|
||||||
|
|
||||||
|
LinkData randomLink = dimHelper.instance.getRandomLinkData(false);
|
||||||
|
LinkData sideLink = new LinkData(destDimID,
|
||||||
|
dimHelper.dimList.get(originDimID).exitDimLink.destDimID,
|
||||||
|
location.getX(),
|
||||||
|
location.getY(),
|
||||||
|
location.getZ(),
|
||||||
|
linkDestination.getX(),
|
||||||
|
linkDestination.getY() + 1,
|
||||||
|
linkDestination.getZ(),
|
||||||
|
true, blockDirection);
|
||||||
|
|
||||||
|
if (sideLink.destDimID == properties.LimboDimensionID)
|
||||||
|
{
|
||||||
|
sideLink.destDimID = 0;
|
||||||
|
}
|
||||||
|
else if ((random.nextBoolean() && randomLink != null))
|
||||||
|
{
|
||||||
|
sideLink.destDimID = randomLink.locDimID;
|
||||||
|
}
|
||||||
|
sideLink.destYCoord = yCoordHelper.getFirstUncovered(sideLink.destDimID, linkDestination.getX(), 10, linkDestination.getZ());
|
||||||
|
|
||||||
|
if (sideLink.destYCoord < 5)
|
||||||
|
{
|
||||||
|
sideLink.destYCoord = 70;
|
||||||
|
}
|
||||||
|
sideLink.linkOrientation = world.getBlockMetadata(linkDestination.getX(), linkDestination.getY() - 1, linkDestination.getZ());
|
||||||
|
|
||||||
|
dimHelper.instance.createLink(sideLink);
|
||||||
|
dimHelper.instance.createLink(sideLink.destDimID ,
|
||||||
|
sideLink.locDimID,
|
||||||
|
sideLink.destXCoord,
|
||||||
|
sideLink.destYCoord,
|
||||||
|
sideLink.destZCoord,
|
||||||
|
sideLink.locXCoord,
|
||||||
|
sideLink.locYCoord,
|
||||||
|
sideLink.locZCoord,
|
||||||
|
dimHelper.instance.flipDoorMetadata(sideLink.linkOrientation));
|
||||||
|
|
||||||
|
if (world.getBlockId(linkDestination.getX(), linkDestination.getY() - 3, linkDestination.getZ()) == properties.FabricBlockID)
|
||||||
|
{
|
||||||
|
setBlockDirectly(world, linkDestination.getX(), linkDestination.getY() - 2, linkDestination.getZ(), Block.stoneBrick.blockID, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setBlockDirectly(world,linkDestination.getX(), linkDestination.getY() - 2, linkDestination.getZ(),
|
||||||
|
world.getBlockId(linkDestination.getX(), linkDestination.getY() - 3, linkDestination.getZ()),
|
||||||
|
world.getBlockMetadata(linkDestination.getX(), linkDestination.getY() - 3, linkDestination.getZ()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setUpDimensionalDoorLink(World world, Point3D point, Point3D entrance, int rotation, Point3D pocketCenter, int originDimID, int destDimID, Random random)
|
||||||
|
{
|
||||||
|
int depth = dimHelper.instance.getDimDepth(originDimID) + 1;
|
||||||
|
int forwardNoise = MathHelper.getRandomIntegerInRange(random, -50 * depth, 150 * depth);
|
||||||
|
int sidewaysNoise = MathHelper.getRandomIntegerInRange(random, -10 * depth, 10 * depth);
|
||||||
|
|
||||||
|
//Transform doorLocation to the pocket coordinate system
|
||||||
|
Point3D location = point.clone();
|
||||||
|
BlockRotator.transformPoint(location, entrance, rotation, pocketCenter);
|
||||||
|
int blockDirection = world.getBlockMetadata(location.getX(), location.getY() - 1, location.getZ());
|
||||||
|
|
||||||
|
//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 zeroPoint = new Point3D(0, 0, 0);
|
||||||
|
BlockRotator.transformPoint(linkDestination, zeroPoint, blockDirection - BlockRotator.EAST_DOOR_METADATA, location);
|
||||||
|
|
||||||
|
//Create the link between our current door and its intended exit in destination pocket
|
||||||
|
LinkData sideLink = new LinkData(destDimID, 0,
|
||||||
|
location.getX(),
|
||||||
|
location.getY(),
|
||||||
|
location.getZ(),
|
||||||
|
linkDestination.getX(),
|
||||||
|
linkDestination.getY() + 1,
|
||||||
|
linkDestination.getZ(),
|
||||||
|
true, blockDirection);
|
||||||
|
dimHelper.instance.createPocket(sideLink, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void spawnMonolith(World world, Point3D point, Point3D entrance, int rotation, Point3D pocketCenter)
|
||||||
|
{
|
||||||
|
//Transform the frame block's location to the pocket coordinate system
|
||||||
|
Point3D location = point.clone();
|
||||||
|
BlockRotator.transformPoint(location, entrance, rotation, pocketCenter);
|
||||||
|
//Remove frame block
|
||||||
|
setBlockDirectly(world, location.getX(), location.getY(), location.getZ(), 0, 0);
|
||||||
|
//Spawn Monolith
|
||||||
|
Entity mob = new MobMonolith(world);
|
||||||
|
mob.setLocationAndAngles(location.getX(), location.getY(), location.getZ(), 1, 1);
|
||||||
|
world.spawnEntityInWorld(mob);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
package StevenDimDoors.mod_pocketDim.dungeon;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.BlockContainer;
|
||||||
|
import net.minecraft.inventory.IInventory;
|
||||||
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.tileentity.TileEntityChest;
|
||||||
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
|
import net.minecraft.util.WeightedRandomChestContent;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.common.ChestGenHooks;
|
||||||
|
import StevenDimDoors.mod_pocketDim.DDLoot;
|
||||||
|
import StevenDimDoors.mod_pocketDim.schematic.WorldOperation;
|
||||||
|
|
||||||
|
public class FillContainersOperation extends WorldOperation
|
||||||
|
{
|
||||||
|
private Random random;
|
||||||
|
|
||||||
|
public FillContainersOperation(Random random)
|
||||||
|
{
|
||||||
|
super("FillContainersOperation");
|
||||||
|
this.random = random;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean applyToBlock(World world, int x, int y, int z)
|
||||||
|
{
|
||||||
|
int blockID = world.getBlockId(x, y, z);
|
||||||
|
|
||||||
|
//Fill empty chests and dispensers
|
||||||
|
if (Block.blocksList[blockID] instanceof BlockContainer)
|
||||||
|
{
|
||||||
|
TileEntity tileEntity = world.getBlockTileEntity(x, y, z);
|
||||||
|
|
||||||
|
//Fill chests
|
||||||
|
if (tileEntity instanceof TileEntityChest)
|
||||||
|
{
|
||||||
|
TileEntityChest chest = (TileEntityChest) tileEntity;
|
||||||
|
if (isInventoryEmpty(chest))
|
||||||
|
{
|
||||||
|
ChestGenHooks info = DDLoot.DungeonChestInfo;
|
||||||
|
WeightedRandomChestContent.generateChestContents(random, info.getItems(random), chest, info.getCount(random));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Fill dispensers
|
||||||
|
if (tileEntity instanceof TileEntityDispenser)
|
||||||
|
{
|
||||||
|
TileEntityDispenser dispenser = (TileEntityDispenser) tileEntity;
|
||||||
|
if (isInventoryEmpty(dispenser))
|
||||||
|
{
|
||||||
|
dispenser.addItem(new ItemStack(Item.arrow, 64));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isInventoryEmpty(IInventory inventory)
|
||||||
|
{
|
||||||
|
int size = inventory.getSizeInventory();
|
||||||
|
for (int index = 0; index < size; index++)
|
||||||
|
{
|
||||||
|
if (inventory.getStackInSlot(index) != null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
51
StevenDimDoors/mod_pocketDim/dungeon/ModBlockFilter.java
Normal file
51
StevenDimDoors/mod_pocketDim/dungeon/ModBlockFilter.java
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package StevenDimDoors.mod_pocketDim.dungeon;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import StevenDimDoors.mod_pocketDim.schematic.SchematicFilter;
|
||||||
|
|
||||||
|
public class ModBlockFilter extends SchematicFilter {
|
||||||
|
|
||||||
|
private short maxVanillaBlockID;
|
||||||
|
private short[] exceptions;
|
||||||
|
private short replacementBlockID;
|
||||||
|
private byte replacementMetadata;
|
||||||
|
|
||||||
|
public ModBlockFilter(short maxVanillaBlockID, short[] exceptions, short replacementBlockID, byte replacementMetadata)
|
||||||
|
{
|
||||||
|
super("ModBlockFilter");
|
||||||
|
this.maxVanillaBlockID = maxVanillaBlockID;
|
||||||
|
this.exceptions = exceptions;
|
||||||
|
this.replacementBlockID = replacementBlockID;
|
||||||
|
this.replacementMetadata = replacementMetadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean applyToBlock(int index, short[] blocks, byte[] metadata)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
short currentID = blocks[index];
|
||||||
|
if (currentID > maxVanillaBlockID || (currentID != 0 && Block.blocksList[currentID] == null))
|
||||||
|
{
|
||||||
|
//This might be a mod block. Check if an exception exists.
|
||||||
|
for (k = 0; k < exceptions.length; k++)
|
||||||
|
{
|
||||||
|
if (currentID == exceptions[k])
|
||||||
|
{
|
||||||
|
//Exception found, not considered a mod block
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//No matching exception found. Replace the block.
|
||||||
|
blocks[index] = replacementBlockID;
|
||||||
|
metadata[index] = replacementMetadata;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean terminates()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
115
StevenDimDoors/mod_pocketDim/dungeon/SpecialBlockFinder.java
Normal file
115
StevenDimDoors/mod_pocketDim/dungeon/SpecialBlockFinder.java
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
package StevenDimDoors.mod_pocketDim.dungeon;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||||
|
import StevenDimDoors.mod_pocketDim.schematic.Schematic;
|
||||||
|
import StevenDimDoors.mod_pocketDim.schematic.SchematicFilter;
|
||||||
|
|
||||||
|
public class SpecialBlockFinder extends SchematicFilter {
|
||||||
|
|
||||||
|
private short warpDoorID;
|
||||||
|
private short dimensionalDoorID;
|
||||||
|
private short monolithSpawnMarkerID;
|
||||||
|
private short exitMarkerID;
|
||||||
|
private int entranceOrientation;
|
||||||
|
private Schematic schematic;
|
||||||
|
private Point3D entranceDoorLocation;
|
||||||
|
private ArrayList<Point3D> exitDoorLocations;
|
||||||
|
private ArrayList<Point3D> dimensionalDoorLocations;
|
||||||
|
private ArrayList<Point3D> monolithSpawnLocations;
|
||||||
|
|
||||||
|
public SpecialBlockFinder(short warpDoorID, short dimensionalDoorID, short monolithSpawnMarkerID, short exitMarkerID)
|
||||||
|
{
|
||||||
|
super("SpecialBlockFinder");
|
||||||
|
this.warpDoorID = warpDoorID;
|
||||||
|
this.dimensionalDoorID = dimensionalDoorID;
|
||||||
|
this.monolithSpawnMarkerID = monolithSpawnMarkerID;
|
||||||
|
this.exitMarkerID = exitMarkerID;
|
||||||
|
this.entranceDoorLocation = null;
|
||||||
|
this.entranceOrientation = 0;
|
||||||
|
this.exitDoorLocations = new ArrayList<Point3D>();
|
||||||
|
this.dimensionalDoorLocations = new ArrayList<Point3D>();
|
||||||
|
this.monolithSpawnLocations = new ArrayList<Point3D>();
|
||||||
|
this.schematic = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getEntranceOrientation() {
|
||||||
|
return entranceOrientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point3D getEntranceDoorLocation() {
|
||||||
|
return entranceDoorLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Point3D> getExitDoorLocations() {
|
||||||
|
return exitDoorLocations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Point3D> getDimensionalDoorLocations() {
|
||||||
|
return dimensionalDoorLocations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Point3D> getMonolithSpawnLocations() {
|
||||||
|
return monolithSpawnLocations;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean initialize(Schematic schematic, short[] blocks, byte[] metadata)
|
||||||
|
{
|
||||||
|
this.schematic = schematic;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean applyToBlock(int index, short[] blocks, byte[] metadata)
|
||||||
|
{
|
||||||
|
int indexBelow;
|
||||||
|
int indexDoubleBelow;
|
||||||
|
|
||||||
|
if (blocks[index] == monolithSpawnMarkerID)
|
||||||
|
{
|
||||||
|
monolithSpawnLocations.add(schematic.calculatePoint(index));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (blocks[index] == dimensionalDoorID)
|
||||||
|
{
|
||||||
|
indexBelow = schematic.calculateIndexBelow(index);
|
||||||
|
if (indexBelow >= 0 && blocks[indexBelow] == dimensionalDoorID)
|
||||||
|
{
|
||||||
|
dimensionalDoorLocations.add(schematic.calculatePoint(index));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (blocks[index] == warpDoorID)
|
||||||
|
{
|
||||||
|
indexBelow = schematic.calculateIndexBelow(index);
|
||||||
|
if (indexBelow >= 0 && blocks[indexBelow] == warpDoorID)
|
||||||
|
{
|
||||||
|
indexDoubleBelow = schematic.calculateIndexBelow(indexBelow);
|
||||||
|
if (indexDoubleBelow >= 0 && blocks[indexDoubleBelow] == exitMarkerID)
|
||||||
|
{
|
||||||
|
exitDoorLocations.add(schematic.calculatePoint(index));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (entranceDoorLocation == null)
|
||||||
|
{
|
||||||
|
entranceDoorLocation = schematic.calculatePoint(index);
|
||||||
|
entranceOrientation = (metadata[indexBelow] & 3);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean terminates()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package StevenDimDoors.mod_pocketDim.helpers;
|
package StevenDimDoors.mod_pocketDim.helpers;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -10,11 +9,6 @@ import java.util.HashSet;
|
|||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import net.minecraft.block.Block;
|
|
||||||
import net.minecraft.nbt.CompressedStreamTools;
|
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
|
||||||
import net.minecraft.nbt.NBTTagList;
|
|
||||||
import net.minecraft.tileentity.TileEntity;
|
|
||||||
import net.minecraft.util.WeightedRandom;
|
import net.minecraft.util.WeightedRandom;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||||
@@ -22,6 +16,7 @@ import StevenDimDoors.mod_pocketDim.DimData;
|
|||||||
import StevenDimDoors.mod_pocketDim.DungeonGenerator;
|
import StevenDimDoors.mod_pocketDim.DungeonGenerator;
|
||||||
import StevenDimDoors.mod_pocketDim.LinkData;
|
import StevenDimDoors.mod_pocketDim.LinkData;
|
||||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||||
|
import StevenDimDoors.mod_pocketDim.dungeon.DungeonSchematic;
|
||||||
import StevenDimDoors.mod_pocketDim.items.itemDimDoor;
|
import StevenDimDoors.mod_pocketDim.items.itemDimDoor;
|
||||||
import StevenDimDoors.mod_pocketDim.util.WeightedContainer;
|
import StevenDimDoors.mod_pocketDim.util.WeightedContainer;
|
||||||
|
|
||||||
@@ -73,8 +68,6 @@ public class DungeonHelper
|
|||||||
private ArrayList<DungeonGenerator> pistonTraps = new ArrayList<DungeonGenerator>();
|
private ArrayList<DungeonGenerator> pistonTraps = new ArrayList<DungeonGenerator>();
|
||||||
private ArrayList<DungeonGenerator> exits = new ArrayList<DungeonGenerator>();
|
private ArrayList<DungeonGenerator> exits = new ArrayList<DungeonGenerator>();
|
||||||
|
|
||||||
public ArrayList<Integer> metadataFlipList = new ArrayList<Integer>();
|
|
||||||
public ArrayList<Integer> metadataNextList = new ArrayList<Integer>();
|
|
||||||
public DungeonGenerator defaultBreak = new DungeonGenerator(DEFAULT_DUNGEON_WEIGHT, "/schematics/somethingBroke.schematic", true);
|
public DungeonGenerator defaultBreak = new DungeonGenerator(DEFAULT_DUNGEON_WEIGHT, "/schematics/somethingBroke.schematic", true);
|
||||||
public DungeonGenerator defaultUp = new DungeonGenerator(DEFAULT_DUNGEON_WEIGHT, "/schematics/simpleStairsUp.schematic", true);
|
public DungeonGenerator defaultUp = new DungeonGenerator(DEFAULT_DUNGEON_WEIGHT, "/schematics/simpleStairsUp.schematic", true);
|
||||||
|
|
||||||
@@ -116,7 +109,6 @@ public class DungeonHelper
|
|||||||
{
|
{
|
||||||
copyfile.copyFile("/mods/DimDoors/text/How_to_add_dungeons.txt", file.getAbsolutePath() + "/How_to_add_dungeons.txt");
|
copyfile.copyFile("/mods/DimDoors/text/How_to_add_dungeons.txt", file.getAbsolutePath() + "/How_to_add_dungeons.txt");
|
||||||
}
|
}
|
||||||
registerFlipBlocks();
|
|
||||||
importCustomDungeons(properties.CustomSchematicDirectory);
|
importCustomDungeons(properties.CustomSchematicDirectory);
|
||||||
registerBaseDungeons();
|
registerBaseDungeons();
|
||||||
}
|
}
|
||||||
@@ -261,44 +253,6 @@ public class DungeonHelper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerFlipBlocks()
|
|
||||||
{
|
|
||||||
metadataFlipList.add(Block.dispenser.blockID);
|
|
||||||
metadataFlipList.add(Block.stairsStoneBrick.blockID);
|
|
||||||
metadataFlipList.add(Block.lever.blockID);
|
|
||||||
metadataFlipList.add(Block.stoneButton.blockID);
|
|
||||||
metadataFlipList.add(Block.redstoneRepeaterIdle.blockID);
|
|
||||||
metadataFlipList.add(Block.redstoneRepeaterActive.blockID);
|
|
||||||
metadataFlipList.add(Block.tripWireSource.blockID);
|
|
||||||
metadataFlipList.add(Block.torchWood.blockID);
|
|
||||||
metadataFlipList.add(Block.torchRedstoneIdle.blockID);
|
|
||||||
metadataFlipList.add(Block.torchRedstoneActive.blockID);
|
|
||||||
metadataFlipList.add(Block.doorIron.blockID);
|
|
||||||
metadataFlipList.add(Block.doorWood.blockID);
|
|
||||||
metadataFlipList.add(Block.pistonBase.blockID);
|
|
||||||
metadataFlipList.add(Block.pistonStickyBase.blockID);
|
|
||||||
metadataFlipList.add(Block.pistonExtension.blockID);
|
|
||||||
metadataFlipList.add(Block.redstoneComparatorIdle.blockID);
|
|
||||||
metadataFlipList.add(Block.redstoneComparatorActive.blockID);
|
|
||||||
metadataFlipList.add(Block.signPost.blockID);
|
|
||||||
metadataFlipList.add(Block.signWall.blockID);
|
|
||||||
metadataFlipList.add(Block.skull.blockID);
|
|
||||||
metadataFlipList.add(Block.ladder.blockID);
|
|
||||||
metadataFlipList.add(Block.vine.blockID);
|
|
||||||
metadataFlipList.add(Block.anvil.blockID);
|
|
||||||
metadataFlipList.add(Block.chest.blockID);
|
|
||||||
metadataFlipList.add(Block.chestTrapped.blockID);
|
|
||||||
metadataFlipList.add(Block.hopperBlock.blockID);
|
|
||||||
metadataFlipList.add(Block.stairsNetherBrick.blockID);
|
|
||||||
metadataFlipList.add(Block.stairsCobblestone.blockID);
|
|
||||||
metadataFlipList.add(Block.stairsNetherBrick.blockID);
|
|
||||||
metadataFlipList.add(Block.stairsNetherQuartz.blockID);
|
|
||||||
metadataFlipList.add(Block.stairsSandStone.blockID);
|
|
||||||
|
|
||||||
metadataNextList.add(Block.redstoneRepeaterIdle.blockID);
|
|
||||||
metadataNextList.add(Block.redstoneRepeaterActive.blockID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerBaseDungeons()
|
public void registerBaseDungeons()
|
||||||
{
|
{
|
||||||
hubs.add(new DungeonGenerator(2 * DEFAULT_DUNGEON_WEIGHT, "/schematics/4WayBasicHall.schematic", false));
|
hubs.add(new DungeonGenerator(2 * DEFAULT_DUNGEON_WEIGHT, "/schematics/4WayBasicHall.schematic", false));
|
||||||
@@ -383,153 +337,14 @@ public class DungeonHelper
|
|||||||
|
|
||||||
public boolean exportDungeon(World world, int centerX, int centerY, int centerZ, String exportPath)
|
public boolean exportDungeon(World world, int centerX, int centerY, int centerZ, String exportPath)
|
||||||
{
|
{
|
||||||
int xMin, yMin, zMin;
|
|
||||||
int xMax, yMax, zMax;
|
|
||||||
int xStart, yStart, zStart;
|
|
||||||
int xEnd, yEnd, zEnd;
|
|
||||||
|
|
||||||
//Find the smallest bounding box that contains all non-air blocks within a max radius around the player.
|
|
||||||
xMax = yMax = zMax = Integer.MIN_VALUE;
|
|
||||||
xMin = yMin = zMin = Integer.MAX_VALUE;
|
|
||||||
|
|
||||||
xStart = centerX - MAX_EXPORT_RADIUS;
|
|
||||||
zStart = centerZ - MAX_EXPORT_RADIUS;
|
|
||||||
yStart = Math.max(centerY - MAX_EXPORT_RADIUS, 0);
|
|
||||||
|
|
||||||
xEnd = centerX + MAX_EXPORT_RADIUS;
|
|
||||||
zEnd = centerZ + MAX_EXPORT_RADIUS;
|
|
||||||
yEnd = Math.min(centerY + MAX_EXPORT_RADIUS, world.getHeight());
|
|
||||||
|
|
||||||
//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.
|
|
||||||
for (int y = yStart; y <= yEnd; y++)
|
|
||||||
{
|
|
||||||
for (int z = zStart; z <= zEnd; z++)
|
|
||||||
{
|
|
||||||
for (int x = xStart; x <= xEnd; x++)
|
|
||||||
{
|
|
||||||
if (!world.isAirBlock(x, y, z))
|
|
||||||
{
|
|
||||||
xMax = x > xMax ? x : xMax;
|
|
||||||
zMax = z > zMax ? z : zMax;
|
|
||||||
yMax = y > yMax ? y : yMax;
|
|
||||||
|
|
||||||
xMin = x < xMin ? x : xMin;
|
|
||||||
zMin = z < zMin ? z : zMin;
|
|
||||||
yMin = y < yMin ? y : yMin;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Export all the blocks within our selected bounding box
|
|
||||||
short width = (short) (xMax - xMin + 1);
|
|
||||||
short height = (short) (yMax - yMin + 1);
|
|
||||||
short length = (short) (zMax - zMin + 1);
|
|
||||||
|
|
||||||
byte[] blocks = new byte[width * height * length];
|
|
||||||
byte[] addBlocks = null;
|
|
||||||
byte[] blockData = new byte[width * height * length];
|
|
||||||
NBTTagList tileEntities = new NBTTagList();
|
|
||||||
|
|
||||||
for (int y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
for (int z = 0; z < length; z++)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
int index = y * width * length + z * width + x;
|
|
||||||
int blockID = world.getBlockId(x + xMin, y + yMin, z + zMin);
|
|
||||||
int metadata = world.getBlockMetadata(x + xMin, y + yMin, z + zMin);
|
|
||||||
boolean changed = false;
|
|
||||||
|
|
||||||
if (blockID == properties.DimensionalDoorID)
|
|
||||||
{
|
|
||||||
blockID = Block.doorIron.blockID;
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
if (blockID == properties.WarpDoorID)
|
|
||||||
{
|
|
||||||
blockID = Block.doorWood.blockID;
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
//Map fabric of reality and permafabric blocks to standard export IDs
|
|
||||||
if (blockID == properties.FabricBlockID)
|
|
||||||
{
|
|
||||||
blockID = FABRIC_OF_REALITY_EXPORT_ID;
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
if (blockID == properties.PermaFabricBlockID)
|
|
||||||
{
|
|
||||||
blockID = PERMAFABRIC_EXPORT_ID;
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save 4096 IDs in an AddBlocks section
|
|
||||||
if (blockID > 255)
|
|
||||||
{
|
|
||||||
if (addBlocks == null)
|
|
||||||
{
|
|
||||||
//Lazily create section
|
|
||||||
addBlocks = new byte[(blocks.length >> 1) + 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
addBlocks[index >> 1] = (byte) (((index & 1) == 0) ?
|
|
||||||
addBlocks[index >> 1] & 0xF0 | (blockID >> 8) & 0xF
|
|
||||||
: addBlocks[index >> 1] & 0xF | ((blockID >> 8) & 0xF) << 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
blocks[index] = (byte) blockID;
|
|
||||||
blockData[index] = (byte) metadata;
|
|
||||||
|
|
||||||
//Obtain and export the tile entity of the current block, if any.
|
|
||||||
//Do not obtain a tile entity if the block was changed from its original ID.
|
|
||||||
//I'm not sure if this approach is the most efficient but it works. ~SenseiKiwi
|
|
||||||
TileEntity tileEntity = !changed ? world.getBlockTileEntity(x + xMin, y + yMin, z + zMin) : null;
|
|
||||||
|
|
||||||
if (tileEntity != null)
|
|
||||||
{
|
|
||||||
//Get the tile entity's description as a compound NBT tag
|
|
||||||
NBTTagCompound entityData = new NBTTagCompound();
|
|
||||||
tileEntity.writeToNBT(entityData);
|
|
||||||
//Change the tile entity's location to the schematic coordinate system
|
|
||||||
entityData.setInteger("x", x);
|
|
||||||
entityData.setInteger("y", y);
|
|
||||||
entityData.setInteger("z", z);
|
|
||||||
|
|
||||||
tileEntities.appendTag(entityData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Write NBT tags for schematic file
|
|
||||||
NBTTagCompound schematicTag = new NBTTagCompound("Schematic");
|
|
||||||
|
|
||||||
schematicTag.setShort("Width", width);
|
|
||||||
schematicTag.setShort("Length", length);
|
|
||||||
schematicTag.setShort("Height", height);
|
|
||||||
|
|
||||||
schematicTag.setByteArray("Blocks", blocks);
|
|
||||||
schematicTag.setByteArray("Data", blockData);
|
|
||||||
|
|
||||||
schematicTag.setTag("Entities", new NBTTagList());
|
|
||||||
schematicTag.setTag("TileEntities", tileEntities);
|
|
||||||
schematicTag.setString("Materials", "Alpha");
|
|
||||||
|
|
||||||
if (addBlocks != null)
|
|
||||||
{
|
|
||||||
schematicTag.setByteArray("AddBlocks", addBlocks);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Write schematic data to a file
|
//Write schematic data to a file
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
FileOutputStream outputStream = new FileOutputStream(new File(exportPath));
|
short size = (short) 2 * MAX_EXPORT_RADIUS + 1;
|
||||||
CompressedStreamTools.writeCompressed(schematicTag, outputStream);
|
DungeonSchematic dungeon = DungeonSchematic.copyFromWorld(world,
|
||||||
//writeCompressed() probably closes the stream on its own - call close again just in case.
|
centerX - MAX_EXPORT_RADIUS, centerY - MAX_EXPORT_RADIUS, centerZ - MAX_EXPORT_RADIUS, size, size, size, true);
|
||||||
//Closing twice will not throw an exception.
|
dungeon.applyExportFilters(properties);
|
||||||
outputStream.close();
|
dungeon.writeToFile(exportPath);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import StevenDimDoors.mod_pocketDim.LinkData;
|
|||||||
import StevenDimDoors.mod_pocketDim.ObjectSaveInputStream;
|
import StevenDimDoors.mod_pocketDim.ObjectSaveInputStream;
|
||||||
import StevenDimDoors.mod_pocketDim.PacketHandler;
|
import StevenDimDoors.mod_pocketDim.PacketHandler;
|
||||||
import StevenDimDoors.mod_pocketDim.Point3D;
|
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||||
|
import StevenDimDoors.mod_pocketDim.SchematicLoader;
|
||||||
import StevenDimDoors.mod_pocketDim.TileEntityRift;
|
import StevenDimDoors.mod_pocketDim.TileEntityRift;
|
||||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||||
import StevenDimDoors.mod_pocketDim.world.LimboProvider;
|
import StevenDimDoors.mod_pocketDim.world.LimboProvider;
|
||||||
@@ -751,12 +752,8 @@ public class dimHelper extends DimensionManager
|
|||||||
}
|
}
|
||||||
else if(!data.hasBeenFilled&&data.isPocket&&data.isDimRandomRift)
|
else if(!data.hasBeenFilled&&data.isPocket&&data.isDimRandomRift)
|
||||||
{
|
{
|
||||||
//System.out.println("genning dungeon pocket");
|
SchematicLoader.generateDungeonPocket(incomingLink, properties);
|
||||||
|
|
||||||
|
|
||||||
mod_pocketDim.loader.generateDungeonPocket(incomingLink);
|
|
||||||
data.hasBeenFilled=true;
|
data.hasBeenFilled=true;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -770,7 +767,7 @@ public class dimHelper extends DimensionManager
|
|||||||
|
|
||||||
mod_pocketDim.hasInitDims=true;
|
mod_pocketDim.hasInitDims=true;
|
||||||
this.load();
|
this.load();
|
||||||
if(!this.dimList.isEmpty())
|
if(!dimHelper.dimList.isEmpty())
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -99,9 +99,7 @@ public class mod_pocketDim
|
|||||||
@Instance("PocketDimensions")
|
@Instance("PocketDimensions")
|
||||||
public static mod_pocketDim instance = new mod_pocketDim();
|
public static mod_pocketDim instance = new mod_pocketDim();
|
||||||
|
|
||||||
public static SchematicLoader loader;
|
|
||||||
public static pocketTeleporter teleporter;
|
public static pocketTeleporter teleporter;
|
||||||
public static BlockRotationHelper rotationHelper;
|
|
||||||
|
|
||||||
public static Block transientDoor;
|
public static Block transientDoor;
|
||||||
public static Block ExitDoor;
|
public static Block ExitDoor;
|
||||||
@@ -170,11 +168,9 @@ public class mod_pocketDim
|
|||||||
//These fields MUST be initialized after properties are loaded to prevent
|
//These fields MUST be initialized after properties are loaded to prevent
|
||||||
//instances from holding onto null references to the properties.
|
//instances from holding onto null references to the properties.
|
||||||
|
|
||||||
loader = new SchematicLoader();
|
|
||||||
teleporter = new pocketTeleporter();
|
teleporter = new pocketTeleporter();
|
||||||
tracker = new PlayerRespawnTracker();
|
tracker = new PlayerRespawnTracker();
|
||||||
riftGen = new RiftGenerator();
|
riftGen = new RiftGenerator();
|
||||||
rotationHelper = new BlockRotationHelper();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Init
|
@Init
|
||||||
|
|||||||
797
StevenDimDoors/mod_pocketDim/schematic/BlockRotator.java
Normal file
797
StevenDimDoors/mod_pocketDim/schematic/BlockRotator.java
Normal file
@@ -0,0 +1,797 @@
|
|||||||
|
package StevenDimDoors.mod_pocketDim.schematic;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.BlockComparator;
|
||||||
|
import net.minecraft.block.BlockDoor;
|
||||||
|
import net.minecraft.block.BlockRedstoneRepeater;
|
||||||
|
import net.minecraft.block.BlockStairs;
|
||||||
|
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||||
|
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||||
|
import StevenDimDoors.mod_pocketDim.blocks.dimDoor;
|
||||||
|
|
||||||
|
public class BlockRotator
|
||||||
|
{
|
||||||
|
//This class is temporary. It's just a place in which to hold the old block rotation and transformation code
|
||||||
|
//until we can rewrite it.
|
||||||
|
|
||||||
|
public final static int EAST_DOOR_METADATA = 0;
|
||||||
|
private final static int SOUTH_DOOR_METADATA = 1;
|
||||||
|
private final static int WEST_DOOR_METADATA = 2;
|
||||||
|
public final static int NORTH_DOOR_METADATA = 3;
|
||||||
|
|
||||||
|
private final static ArrayList<Integer> metadataFlipList = new ArrayList<Integer>();
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
metadataFlipList.add(Block.dispenser.blockID);
|
||||||
|
metadataFlipList.add(Block.stairsStoneBrick.blockID);
|
||||||
|
metadataFlipList.add(Block.lever.blockID);
|
||||||
|
metadataFlipList.add(Block.stoneButton.blockID);
|
||||||
|
metadataFlipList.add(Block.redstoneRepeaterIdle.blockID);
|
||||||
|
metadataFlipList.add(Block.redstoneRepeaterActive.blockID);
|
||||||
|
metadataFlipList.add(Block.tripWireSource.blockID);
|
||||||
|
metadataFlipList.add(Block.torchWood.blockID);
|
||||||
|
metadataFlipList.add(Block.torchRedstoneIdle.blockID);
|
||||||
|
metadataFlipList.add(Block.torchRedstoneActive.blockID);
|
||||||
|
metadataFlipList.add(Block.doorIron.blockID);
|
||||||
|
metadataFlipList.add(Block.doorWood.blockID);
|
||||||
|
metadataFlipList.add(Block.pistonBase.blockID);
|
||||||
|
metadataFlipList.add(Block.pistonStickyBase.blockID);
|
||||||
|
metadataFlipList.add(Block.pistonExtension.blockID);
|
||||||
|
metadataFlipList.add(Block.redstoneComparatorIdle.blockID);
|
||||||
|
metadataFlipList.add(Block.redstoneComparatorActive.blockID);
|
||||||
|
metadataFlipList.add(Block.signPost.blockID);
|
||||||
|
metadataFlipList.add(Block.signWall.blockID);
|
||||||
|
metadataFlipList.add(Block.skull.blockID);
|
||||||
|
metadataFlipList.add(Block.ladder.blockID);
|
||||||
|
metadataFlipList.add(Block.vine.blockID);
|
||||||
|
metadataFlipList.add(Block.anvil.blockID);
|
||||||
|
metadataFlipList.add(Block.chest.blockID);
|
||||||
|
metadataFlipList.add(Block.chestTrapped.blockID);
|
||||||
|
metadataFlipList.add(Block.hopperBlock.blockID);
|
||||||
|
metadataFlipList.add(Block.stairsNetherBrick.blockID);
|
||||||
|
metadataFlipList.add(Block.stairsCobblestone.blockID);
|
||||||
|
metadataFlipList.add(Block.stairsNetherBrick.blockID);
|
||||||
|
metadataFlipList.add(Block.stairsNetherQuartz.blockID);
|
||||||
|
metadataFlipList.add(Block.stairsSandStone.blockID);
|
||||||
|
metadataFlipList.add(mod_pocketDim.dimDoor.blockID);
|
||||||
|
metadataFlipList.add(mod_pocketDim.ExitDoor.blockID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int transformMetadata(int metadata, int orientation, int blockID)
|
||||||
|
{
|
||||||
|
//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 ME.
|
||||||
|
|
||||||
|
//Hax to fix negative orientations
|
||||||
|
orientation += 1 << 16;
|
||||||
|
orientation %= 4;
|
||||||
|
|
||||||
|
if (metadataFlipList.contains(blockID))
|
||||||
|
{
|
||||||
|
switch (orientation)
|
||||||
|
{
|
||||||
|
case EAST_DOOR_METADATA:
|
||||||
|
|
||||||
|
if (blockID == Block.hopperBlock.blockID)
|
||||||
|
{
|
||||||
|
switch (metadata)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
metadata = 5;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
metadata = 4;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
metadata = 2;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
metadata = 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Block.blocksList[blockID] instanceof BlockStairs)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (metadata)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
metadata = 2;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
metadata = 3;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
metadata = 1;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
metadata = 0;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
metadata = 4;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
metadata = 5;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
metadata = 7;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
metadata = 6;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(blockID== Block.chest.blockID||blockID== Block.chestTrapped.blockID||blockID== Block.ladder.blockID)
|
||||||
|
{
|
||||||
|
switch (metadata)
|
||||||
|
{
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
metadata = 5;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
metadata = 4;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
metadata = 2;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
metadata = 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (blockID==Block.vine.blockID)
|
||||||
|
{
|
||||||
|
switch (metadata)
|
||||||
|
{
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
metadata = 2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
metadata = 4;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
metadata = 8;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
metadata = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(blockID== Block.lever.blockID||blockID== Block.stoneButton.blockID||blockID== Block.woodenButton.blockID||blockID== Block.torchWood.blockID||blockID== Block.torchRedstoneIdle.blockID||blockID== Block.torchRedstoneActive.blockID)
|
||||||
|
{
|
||||||
|
switch (metadata)
|
||||||
|
{
|
||||||
|
case 12:
|
||||||
|
metadata = 9;
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
metadata = 10;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
metadata = 12;
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
metadata = 11;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
metadata = 4;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
metadata = 2;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
metadata = 3;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
metadata = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(blockID== Block.pistonBase.blockID||blockID==Block.pistonExtension.blockID||blockID==Block.pistonStickyBase.blockID||blockID==Block.dispenser.blockID||blockID==Block.dropper.blockID)
|
||||||
|
{
|
||||||
|
switch (metadata)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
metadata = 2;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
metadata = 3;
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
metadata = 11;
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
metadata = 10;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
metadata = 4;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
metadata = 5;
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
metadata = 12;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
metadata = 13;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(Block.blocksList[blockID] instanceof BlockRedstoneRepeater || Block.blocksList[blockID] instanceof BlockDoor || Block.blocksList[blockID] instanceof dimDoor || blockID== Block.tripWireSource.blockID || Block.blocksList[blockID] instanceof BlockComparator)
|
||||||
|
{
|
||||||
|
switch (metadata)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
metadata = 1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
metadata = 2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
metadata = 3;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
metadata = 0;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
metadata = 5;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
metadata = 6;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
metadata = 7;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
metadata = 4;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
metadata = 9;
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
metadata = 10;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
metadata = 11;
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
metadata = 8;
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
metadata = 13;
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
metadata = 14;
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
metadata = 15;
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
metadata = 12;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SOUTH_DOOR_METADATA:
|
||||||
|
|
||||||
|
if (blockID == Block.hopperBlock.blockID)
|
||||||
|
{
|
||||||
|
switch (metadata)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
metadata = 3;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
metadata = 2;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
metadata = 5;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
metadata = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Block.blocksList[blockID] instanceof BlockStairs)
|
||||||
|
{
|
||||||
|
switch (metadata)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
metadata = 1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
metadata = 0;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
metadata = 3;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
metadata = 2;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
metadata = 6;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
metadata = 7;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
metadata = 4;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
metadata = 5;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(blockID== Block.chest.blockID||blockID== Block.chestTrapped.blockID||blockID==Block.ladder.blockID)
|
||||||
|
{
|
||||||
|
switch (metadata)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
metadata = 3;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
metadata = 2;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
metadata = 5;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
metadata = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(blockID==Block.vine.blockID)
|
||||||
|
{
|
||||||
|
switch (metadata)
|
||||||
|
{
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
metadata = 4;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
metadata = 8;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
metadata = 1;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
metadata = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
else if(blockID== Block.lever.blockID||blockID== Block.torchWood.blockID||blockID== Block.torchRedstoneIdle.blockID||blockID== Block.torchRedstoneActive.blockID)
|
||||||
|
{
|
||||||
|
switch (metadata)
|
||||||
|
{
|
||||||
|
case 12:
|
||||||
|
metadata = 11;
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
metadata = 12;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
metadata = 9;
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
metadata = 10;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
metadata = 1;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
metadata = 4;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
metadata = 2;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
metadata = 3;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(blockID== Block.pistonBase.blockID||blockID==Block.pistonStickyBase.blockID||blockID==Block.dispenser.blockID||blockID==Block.dropper.blockID)
|
||||||
|
{
|
||||||
|
switch (metadata)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
metadata = 5;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
metadata = 4;
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
metadata = 12;
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
metadata = 13;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
metadata = 2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
metadata = 3;
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
metadata = 10;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
metadata = 11;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(Block.blocksList[blockID] instanceof BlockRedstoneRepeater ||Block.blocksList[blockID] instanceof BlockDoor || Block.blocksList[blockID] instanceof dimDoor || blockID== Block.tripWireSource.blockID||Block.blocksList[blockID] instanceof BlockComparator)
|
||||||
|
{
|
||||||
|
switch (metadata)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
metadata = 2;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
metadata = 3;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
metadata = 0;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
metadata = 1;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
metadata = 6;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
metadata = 7;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
metadata = 4;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
metadata = 5;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
metadata = 10;
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
metadata = 11;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
metadata = 8;
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
metadata = 9;
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
metadata = 14;
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
metadata = 15;
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
metadata = 12;
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
metadata = 13;
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case WEST_DOOR_METADATA:
|
||||||
|
|
||||||
|
if (blockID == Block.hopperBlock.blockID)
|
||||||
|
{
|
||||||
|
switch (metadata)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
metadata = 4;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
metadata = 5;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
metadata = 3;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
metadata = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Block.blocksList[blockID] instanceof BlockStairs)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (metadata)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
metadata = 0;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
metadata = 1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
metadata = 2;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
metadata = 3;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
metadata = 7;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
metadata = 6;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
metadata = 5;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
metadata = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(blockID== Block.chest.blockID||blockID== Block.chestTrapped.blockID||blockID==Block.ladder.blockID)
|
||||||
|
{
|
||||||
|
switch (metadata)
|
||||||
|
{
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
metadata = 4;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
metadata = 5;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
metadata = 3;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
metadata = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(blockID==Block.vine.blockID)
|
||||||
|
{
|
||||||
|
switch (metadata)
|
||||||
|
{
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
metadata = 8;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
metadata = 1;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
metadata = 2;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
metadata = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
else if(blockID== Block.lever.blockID||blockID== Block.torchWood.blockID||blockID== Block.torchRedstoneIdle.blockID||blockID== Block.torchRedstoneActive.blockID)
|
||||||
|
{
|
||||||
|
switch (metadata)
|
||||||
|
{
|
||||||
|
case 9:
|
||||||
|
metadata = 12;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
metadata = 11;
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
metadata = 10;
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
metadata = 9;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
metadata = 2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
metadata = 3;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
metadata = 1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
metadata = 4;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(blockID== Block.pistonBase.blockID||blockID==Block.pistonStickyBase.blockID||blockID==Block.dispenser.blockID||blockID==Block.dropper.blockID)
|
||||||
|
|
||||||
|
{
|
||||||
|
switch (metadata)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
metadata = 4;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
metadata = 5;
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
metadata = 13;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
metadata = 12;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
metadata = 3;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
metadata = 2;
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
metadata = 11;
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
metadata = 10;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(Block.blocksList[blockID] instanceof BlockRedstoneRepeater ||Block.blocksList[blockID] instanceof BlockDoor || Block.blocksList[blockID] instanceof dimDoor || blockID== Block.tripWireSource.blockID||Block.blocksList[blockID] instanceof BlockComparator)
|
||||||
|
{
|
||||||
|
switch (metadata)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
metadata = 0;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
metadata = 1;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
metadata = 2;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
metadata = 3;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
metadata = 4;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
metadata = 5;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
metadata = 6;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
metadata = 7;
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
metadata = 8;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
metadata = 9;
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
metadata = 10;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
metadata = 11;
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
metadata = 12;
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
metadata = 13;
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
metadata = 14;
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
metadata = 15;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NORTH_DOOR_METADATA:
|
||||||
|
/**
|
||||||
|
* this is the default case- never need to change anything here
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void transformPoint(Point3D position, Point3D srcOrigin, int angle, Point3D 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),
|
||||||
|
//then rotates and translates it to obtain the corresponding point in a destination
|
||||||
|
//coordinate system (e.g. the location of the entry rift in the pocket being generated).
|
||||||
|
//The result is returned by overwriting the original position so that new object references
|
||||||
|
//aren't needed. That way, repeated use of this function will not incur as much overhead.
|
||||||
|
|
||||||
|
//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();
|
||||||
|
|
||||||
|
//"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.
|
||||||
|
//Given a starting direction A and a destination direction B, the rotation would be
|
||||||
|
//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;
|
||||||
|
break;
|
||||||
|
case 1: //90 degrees clockwise
|
||||||
|
rx = -tz;
|
||||||
|
rz = tx;
|
||||||
|
break;
|
||||||
|
case 2: //180 degrees
|
||||||
|
rx = -tx;
|
||||||
|
rz = -tz;
|
||||||
|
break;
|
||||||
|
case 3: //270 degrees clockwise
|
||||||
|
rx = tz;
|
||||||
|
rz = -tx;
|
||||||
|
|
||||||
|
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() );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
package StevenDimDoors.mod_pocketDim.schematic;
|
||||||
|
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import StevenDimDoors.mod_pocketDim.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 CompactBoundsOperation()
|
||||||
|
{
|
||||||
|
super("CompactBoundsOperation");
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean applyToBlock(World world, int x, int y, int z)
|
||||||
|
{
|
||||||
|
//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;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean finish()
|
||||||
|
{
|
||||||
|
if (minX == Integer.MAX_VALUE)
|
||||||
|
{
|
||||||
|
//The whole search space was empty!
|
||||||
|
//Compact the space to a single block.
|
||||||
|
minX = maxX;
|
||||||
|
minY = maxY;
|
||||||
|
minZ = maxZ;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point3D getMaxCorner()
|
||||||
|
{
|
||||||
|
return new Point3D(maxX, maxY, maxZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point3D getMinCorner()
|
||||||
|
{
|
||||||
|
return new Point3D(minX, minY, minZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
58
StevenDimDoors/mod_pocketDim/schematic/CompoundFilter.java
Normal file
58
StevenDimDoors/mod_pocketDim/schematic/CompoundFilter.java
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package StevenDimDoors.mod_pocketDim.schematic;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class CompoundFilter extends SchematicFilter {
|
||||||
|
|
||||||
|
private ArrayList<SchematicFilter> filters;
|
||||||
|
|
||||||
|
public CompoundFilter()
|
||||||
|
{
|
||||||
|
super("CompoundFilter");
|
||||||
|
filters = new ArrayList<SchematicFilter>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addFilter(SchematicFilter filter)
|
||||||
|
{
|
||||||
|
filters.add(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean initialize(Schematic schematic, short[] blocks, byte[] metadata)
|
||||||
|
{
|
||||||
|
for (SchematicFilter filter : filters)
|
||||||
|
{
|
||||||
|
if (!filter.initialize(schematic, blocks, metadata))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return !filters.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean finish()
|
||||||
|
{
|
||||||
|
for (SchematicFilter filter : filters)
|
||||||
|
{
|
||||||
|
if (!filter.finish())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean applyToBlock(int index, short[] blocks, byte[] metadata)
|
||||||
|
{
|
||||||
|
for (SchematicFilter filter : filters)
|
||||||
|
{
|
||||||
|
if (filter.applyToBlock(index, blocks, metadata))
|
||||||
|
{
|
||||||
|
return filter.terminates();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package StevenDimDoors.mod_pocketDim.schematic;
|
||||||
|
|
||||||
|
public class InvalidSchematicException extends Exception {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -1011044077455149932L;
|
||||||
|
|
||||||
|
public InvalidSchematicException()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public InvalidSchematicException(String message)
|
||||||
|
{
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InvalidSchematicException(String message, Throwable cause)
|
||||||
|
{
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package StevenDimDoors.mod_pocketDim.schematic;
|
||||||
|
|
||||||
|
|
||||||
|
public class ReplacementFilter extends SchematicFilter {
|
||||||
|
|
||||||
|
private short targetBlock;
|
||||||
|
private byte targetMetadata;
|
||||||
|
private boolean matchMetadata;
|
||||||
|
private short replacementBlock;
|
||||||
|
private byte replacementMetadata;
|
||||||
|
private boolean changeMetadata;
|
||||||
|
|
||||||
|
public ReplacementFilter(short targetBlock, byte targetMetadata, short replacementBlock, byte replacementMetadata)
|
||||||
|
{
|
||||||
|
super("ReplacementFilter");
|
||||||
|
this.targetBlock = targetBlock;
|
||||||
|
this.targetMetadata = targetMetadata;
|
||||||
|
this.matchMetadata = true;
|
||||||
|
this.replacementBlock = replacementBlock;
|
||||||
|
this.replacementMetadata = replacementMetadata;
|
||||||
|
this.changeMetadata = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReplacementFilter(short targetBlock, short replacementBlock, byte replacementMetadata)
|
||||||
|
{
|
||||||
|
super("ReplacementFilter");
|
||||||
|
this.targetBlock = targetBlock;
|
||||||
|
this.matchMetadata = false;
|
||||||
|
this.replacementBlock = replacementBlock;
|
||||||
|
this.replacementMetadata = replacementMetadata;
|
||||||
|
this.changeMetadata = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReplacementFilter(short targetBlock, byte targetMetadata, short replacementBlock)
|
||||||
|
{
|
||||||
|
super("ReplacementFilter");
|
||||||
|
this.targetBlock = targetBlock;
|
||||||
|
this.targetMetadata = targetMetadata;
|
||||||
|
this.matchMetadata = true;
|
||||||
|
this.replacementBlock = replacementBlock;
|
||||||
|
this.changeMetadata = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReplacementFilter(short targetBlock, short replacementBlock)
|
||||||
|
{
|
||||||
|
super("ReplacementFilter");
|
||||||
|
this.targetBlock = targetBlock;
|
||||||
|
this.matchMetadata = false;
|
||||||
|
this.replacementBlock = replacementBlock;
|
||||||
|
this.changeMetadata = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean applyToBlock(int index, short[] blocks, byte[] metadata)
|
||||||
|
{
|
||||||
|
if (blocks[index] == targetBlock)
|
||||||
|
{
|
||||||
|
if ((matchMetadata && metadata[index] == targetMetadata) || !matchMetadata)
|
||||||
|
{
|
||||||
|
blocks[index] = replacementBlock;
|
||||||
|
if (changeMetadata)
|
||||||
|
{
|
||||||
|
metadata[index] = replacementMetadata;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean terminates()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
434
StevenDimDoors/mod_pocketDim/schematic/Schematic.java
Normal file
434
StevenDimDoors/mod_pocketDim/schematic/Schematic.java
Normal file
@@ -0,0 +1,434 @@
|
|||||||
|
package StevenDimDoors.mod_pocketDim.schematic;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.nbt.CompressedStreamTools;
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.nbt.NBTTagList;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.chunk.Chunk;
|
||||||
|
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||||
|
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an MC schematic and provides functions for loading, storing, and manipulating schematics.
|
||||||
|
* This functionality has no dependencies to Dimensional Doors.
|
||||||
|
*/
|
||||||
|
public class Schematic {
|
||||||
|
|
||||||
|
protected short width;
|
||||||
|
protected short height;
|
||||||
|
protected short length;
|
||||||
|
|
||||||
|
protected short[] blocks;
|
||||||
|
protected byte[] metadata;
|
||||||
|
protected NBTTagList tileEntities;
|
||||||
|
|
||||||
|
protected Schematic(short width, short height, short length, short[] 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)
|
||||||
|
{
|
||||||
|
//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.tileEntities = source.tileEntities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int calculateIndex(int x, int y, int z)
|
||||||
|
{
|
||||||
|
if (x < 0 || x >= width)
|
||||||
|
throw new IndexOutOfBoundsException("x must be non-negative and less than width");
|
||||||
|
if (y < 0 || y >= height)
|
||||||
|
throw new IndexOutOfBoundsException("y must be non-negative and less than height");
|
||||||
|
if (z < 0 || z >= length)
|
||||||
|
throw new IndexOutOfBoundsException("z must be non-negative and less than length");
|
||||||
|
|
||||||
|
return (y * width * length + z * width + x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point3D calculatePoint(int index)
|
||||||
|
{
|
||||||
|
int y = index / (width * length);
|
||||||
|
index -= y * width * length;
|
||||||
|
int z = index / width;
|
||||||
|
index -= z * width;
|
||||||
|
int x = index;
|
||||||
|
|
||||||
|
return new Point3D(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int calculateIndexBelow(int index)
|
||||||
|
{
|
||||||
|
return index - (width * length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getWidth()
|
||||||
|
{
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getHeight()
|
||||||
|
{
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getLength()
|
||||||
|
{
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getBlockID(int x, int y, int z)
|
||||||
|
{
|
||||||
|
return blocks[calculateIndex(x, y, z)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getBlockMetadata(int x, int y, int z)
|
||||||
|
{
|
||||||
|
return metadata[calculateIndex(x, y, z)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public NBTTagList getTileEntities()
|
||||||
|
{
|
||||||
|
return (NBTTagList) tileEntities.copy();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Schematic readFromFile(String schematicPath) throws FileNotFoundException, InvalidSchematicException
|
||||||
|
{
|
||||||
|
return readFromFile(new File(schematicPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Schematic readFromFile(File schematicFile) throws FileNotFoundException, InvalidSchematicException
|
||||||
|
{
|
||||||
|
return readFromStream(new FileInputStream(schematicFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Schematic readFromResource(String resourcePath) throws InvalidSchematicException
|
||||||
|
{
|
||||||
|
//We need an instance of a class in the mod to retrieve a resource
|
||||||
|
Schematic empty = new Schematic((short) 0, (short) 0, (short) 0, null, null, null);
|
||||||
|
InputStream schematicStream = empty.getClass().getResourceAsStream(resourcePath);
|
||||||
|
return readFromStream(schematicStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
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[] blocks = null; //list of combined block IDs
|
||||||
|
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
|
||||||
|
{
|
||||||
|
schematicTag = CompressedStreamTools.readCompressed(schematicStream);
|
||||||
|
schematicStream.close(); //readCompressed() probably closes the stream anyway, but close again to be sure.
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new InvalidSchematicException("The schematic could not be decoded.");
|
||||||
|
}
|
||||||
|
|
||||||
|
//load size of schematic to generate
|
||||||
|
width = schematicTag.getShort("Width");
|
||||||
|
height = schematicTag.getShort("Height");
|
||||||
|
length = schematicTag.getShort("Length");
|
||||||
|
volume = width * length * height;
|
||||||
|
|
||||||
|
if (width < 0)
|
||||||
|
throw new InvalidSchematicException("The schematic cannot have a negative width.");
|
||||||
|
if (height < 0)
|
||||||
|
throw new InvalidSchematicException("The schematic cannot have a negative height.");
|
||||||
|
if (length < 0)
|
||||||
|
throw new InvalidSchematicException("The schematic cannot have a negative length.");
|
||||||
|
|
||||||
|
//load block info
|
||||||
|
lowBits = schematicTag.getByteArray("Blocks");
|
||||||
|
highBits = schematicTag.getByteArray("AddBlocks");
|
||||||
|
metadata = schematicTag.getByteArray("Data");
|
||||||
|
hasExtendedBlockIDs = (highBits.length != 0);
|
||||||
|
|
||||||
|
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.");
|
||||||
|
|
||||||
|
blocks = 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)
|
||||||
|
{
|
||||||
|
blocks[index] = (short) (((highBits[index >> 1] & 0x0F) << 8) + (lowBits[index] & 0xFF));
|
||||||
|
blocks[index + 1] = (short) (((highBits[index >> 1] & 0xF0) << 4) + (lowBits[index + 1] & 0xFF));
|
||||||
|
}
|
||||||
|
if (index < volume)
|
||||||
|
{
|
||||||
|
blocks[index] = lowBits[index >> 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Copy the blockIDs
|
||||||
|
for (int index = 0; index < volume; index++)
|
||||||
|
{
|
||||||
|
blocks[index] = (short) (lowBits[index] & 0xFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get the list of tile entities
|
||||||
|
tileEntities = schematicTag.getTagList("TileEntities");
|
||||||
|
|
||||||
|
Schematic result = new Schematic(width, height, length, blocks, metadata, tileEntities);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (InvalidSchematicException ex)
|
||||||
|
{
|
||||||
|
//Throw the exception again to pass it to the caller.
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new InvalidSchematicException("An unexpected error occurred while trying to decode the schematic.", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Schematic copyFromWorld(World world, int x, int y, int z, short width, short height, short length, 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;
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
short compactWidth = (short) (maxCorner.getX() - minCorner.getX() + 1);
|
||||||
|
short compactHeight = (short) (maxCorner.getY() - minCorner.getY() + 1);
|
||||||
|
short compactLength = (short) (maxCorner.getZ() - minCorner.getZ() + 1);
|
||||||
|
|
||||||
|
return copyFromWorld(world, minCorner.getX(), minCorner.getY(), minCorner.getZ(),
|
||||||
|
compactWidth, compactHeight, compactLength);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return copyFromWorld(world, x, y, z, width, height, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Schematic copyFromWorld(World world, int x, int y, int z, short width, short height, short length)
|
||||||
|
{
|
||||||
|
//Short and sweet ^_^
|
||||||
|
WorldCopyOperation copier = new WorldCopyOperation();
|
||||||
|
copier.apply(world, x, y, z, width, height, length);
|
||||||
|
return new Schematic(width, height, length, copier.getBlockIDs(), copier.getMetadata(), 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NBTTagCompound writeToNBT()
|
||||||
|
{
|
||||||
|
return writeToNBT(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected NBTTagCompound writeToNBT(boolean copyTileEntities)
|
||||||
|
{
|
||||||
|
return writeToNBT(width, height, length, blocks, metadata, tileEntities, copyTileEntities);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static NBTTagCompound writeToNBT(short width, short height, short length, short[] blocks, byte[] metadata,
|
||||||
|
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("Schematic");
|
||||||
|
|
||||||
|
schematicTag.setShort("Width", width);
|
||||||
|
schematicTag.setShort("Length", length);
|
||||||
|
schematicTag.setShort("Height", height);
|
||||||
|
|
||||||
|
schematicTag.setTag("Entities", new NBTTagList());
|
||||||
|
schematicTag.setString("Materials", "Alpha");
|
||||||
|
|
||||||
|
byte[] lowBits = new byte[blocks.length];
|
||||||
|
byte[] highBits = new byte[(blocks.length >> 1) + 1];
|
||||||
|
boolean hasExtendedIDs = encodeBlockIDs(blocks, lowBits, highBits);
|
||||||
|
|
||||||
|
schematicTag.setByteArray("Blocks", lowBits);
|
||||||
|
schematicTag.setByteArray("Data", metadata);
|
||||||
|
|
||||||
|
if (hasExtendedIDs)
|
||||||
|
{
|
||||||
|
schematicTag.setByteArray("AddBlocks", highBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
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", (NBTTagList) tileEntities.copy());
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
return schematicTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeToFile(String schematicPath) throws IOException
|
||||||
|
{
|
||||||
|
writeToFile(new File(schematicPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
//Closing twice will not throw an exception.
|
||||||
|
outputStream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean applyFilter(SchematicFilter filter)
|
||||||
|
{
|
||||||
|
return filter.apply(this, this.blocks, this.metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void copyToWorld(World world, int x, int y, int z)
|
||||||
|
{
|
||||||
|
//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;
|
||||||
|
int count;
|
||||||
|
int dx, dy, dz;
|
||||||
|
|
||||||
|
//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++)
|
||||||
|
{
|
||||||
|
//In the future, we might want to make this more efficient by building whole chunks at a time
|
||||||
|
setBlockDirectly(world, x + dx, y + dy, z + dz, blocks[index], metadata[index]);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Copy tile entities into the world
|
||||||
|
count = tileEntities.tagCount();
|
||||||
|
for (index = 0; index < count; index++)
|
||||||
|
{
|
||||||
|
NBTTagCompound tileTag = (NBTTagCompound) tileEntities.tagAt(index);
|
||||||
|
//Rewrite its location to be in world coordinates
|
||||||
|
dx = tileTag.getInteger("x") + x;
|
||||||
|
dy = tileTag.getInteger("y") + y;
|
||||||
|
dz = tileTag.getInteger("z") + z;
|
||||||
|
tileTag.setInteger("x", dx);
|
||||||
|
tileTag.setInteger("y", dy);
|
||||||
|
tileTag.setInteger("z", dz);
|
||||||
|
//Load the tile entity and put it in the world
|
||||||
|
world.setBlockTileEntity(dx, dy, dz, TileEntity.createAndLoadEntity(tileTag));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void setBlockDirectly(World world, int x, int y, int z, int blockID, int metadata)
|
||||||
|
{
|
||||||
|
if (blockID != 0 && Block.blocksList[blockID] == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cX = x >> 4;
|
||||||
|
int cZ = z >> 4;
|
||||||
|
int cY = y >> 4;
|
||||||
|
Chunk chunk;
|
||||||
|
|
||||||
|
int localX = (x % 16) < 0 ? (x % 16) + 16 : (x % 16);
|
||||||
|
int localZ = (z % 16) < 0 ? (z % 16) + 16 : (z % 16);
|
||||||
|
ExtendedBlockStorage extBlockStorage;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
chunk = world.getChunkFromChunkCoords(cX, cZ);
|
||||||
|
extBlockStorage = chunk.getBlockStorageArray()[cY];
|
||||||
|
if (extBlockStorage == null)
|
||||||
|
{
|
||||||
|
extBlockStorage = new ExtendedBlockStorage(cY << 4, !world.provider.hasNoSky);
|
||||||
|
chunk.getBlockStorageArray()[cY] = extBlockStorage;
|
||||||
|
}
|
||||||
|
extBlockStorage.setExtBlockID(localX, y & 15, localZ, blockID);
|
||||||
|
extBlockStorage.setExtBlockMetadata(localX, y & 15, localZ, metadata);
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
55
StevenDimDoors/mod_pocketDim/schematic/SchematicFilter.java
Normal file
55
StevenDimDoors/mod_pocketDim/schematic/SchematicFilter.java
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package StevenDimDoors.mod_pocketDim.schematic;
|
||||||
|
|
||||||
|
public class SchematicFilter {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
protected SchematicFilter(String name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean apply(Schematic schematic, short[] blocks, byte[] metadata)
|
||||||
|
{
|
||||||
|
if (!initialize(schematic, blocks, metadata))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (int index = 0; index < blocks.length; index++)
|
||||||
|
{
|
||||||
|
if (applyToBlock(index, blocks, metadata) && terminates())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean initialize(Schematic schematic, short[] blocks, byte[] metadata)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean applyToBlock(int index, short[] blocks, byte[] metadata)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean finish()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean terminates()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package StevenDimDoors.mod_pocketDim.schematic;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.nbt.NBTTagList;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public class WorldCopyOperation extends WorldOperation
|
||||||
|
{
|
||||||
|
private int originX;
|
||||||
|
private int originY;
|
||||||
|
private int originZ;
|
||||||
|
private int index;
|
||||||
|
private short[] blockIDs;
|
||||||
|
private byte[] metadata;
|
||||||
|
private NBTTagList tileEntities;
|
||||||
|
|
||||||
|
public WorldCopyOperation()
|
||||||
|
{
|
||||||
|
super("WorldCopyOperation");
|
||||||
|
blockIDs = null;
|
||||||
|
metadata = null;
|
||||||
|
tileEntities = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean initialize(World world, int x, int y, int z, int width, int height, int length)
|
||||||
|
{
|
||||||
|
index = 0;
|
||||||
|
originX = x;
|
||||||
|
originY = y;
|
||||||
|
originZ = z;
|
||||||
|
blockIDs = new short[width * height * length];
|
||||||
|
metadata = new byte[width * height * length];
|
||||||
|
tileEntities = new NBTTagList();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean applyToBlock(World world, int x, int y, int z)
|
||||||
|
{
|
||||||
|
blockIDs[index] = (short) world.getBlockId(x, y, z);
|
||||||
|
metadata[index] = (byte) world.getBlockMetadata(x, y, z);
|
||||||
|
|
||||||
|
TileEntity tileEntity = world.getBlockTileEntity(x, y, z);
|
||||||
|
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);
|
||||||
|
tileEntities.appendTag(tileTag);
|
||||||
|
}
|
||||||
|
index++; //This works assuming the loops in WorldOperation are done in YZX order
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short[] getBlockIDs()
|
||||||
|
{
|
||||||
|
return blockIDs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getMetadata()
|
||||||
|
{
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NBTTagList getTileEntities()
|
||||||
|
{
|
||||||
|
return tileEntities;
|
||||||
|
}
|
||||||
|
}
|
||||||
76
StevenDimDoors/mod_pocketDim/schematic/WorldOperation.java
Normal file
76
StevenDimDoors/mod_pocketDim/schematic/WorldOperation.java
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
package StevenDimDoors.mod_pocketDim.schematic;
|
||||||
|
|
||||||
|
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public abstract class WorldOperation {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public WorldOperation(String name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean initialize(World world, int x, int y, int z, int width, int height, int length)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract boolean applyToBlock(World world, int x, int y, int z);
|
||||||
|
|
||||||
|
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))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int cx, cy, cz;
|
||||||
|
int limitX = x + width;
|
||||||
|
int limitY = y + height;
|
||||||
|
int limitZ = z + length;
|
||||||
|
|
||||||
|
//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))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user