Created DungeonSchematic Class
Created DungeonSchematic, a class that extends Schematic and adds DD-specific functionality such as methods for filtering the schematic's block before importing and exporting. Testing confirms that DungeonSchematic works well so far, although it still lacks critical features. Made some minor changes to Schematic and copied SchematicLoader.setBlockDirectly(). I realized during testing that setting blocks without using that function could cause problems. First, it's possible that the blocks would not be placed if chunks weren't created. Second, there are issues with blocks updating if we use World to set them, even if block updates are disabled. That causes some torches to break and other weird problems. Added classes to support block filtering operations applied to Schematic. These are used to implement ID standardization and removing mod blocks when importing.
This commit is contained in:
parent
8b64165e2e
commit
877678c945
8 changed files with 446 additions and 10 deletions
|
@ -1,13 +1,17 @@
|
||||||
package StevenDimDoors.mod_pocketDim.commands;
|
package StevenDimDoors.mod_pocketDim.commands;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||||
import StevenDimDoors.mod_pocketDim.DungeonGenerator;
|
import StevenDimDoors.mod_pocketDim.DungeonGenerator;
|
||||||
import StevenDimDoors.mod_pocketDim.LinkData;
|
import StevenDimDoors.mod_pocketDim.LinkData;
|
||||||
|
import StevenDimDoors.mod_pocketDim.dungeon.DungeonSchematic;
|
||||||
import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper;
|
import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper;
|
||||||
import StevenDimDoors.mod_pocketDim.helpers.dimHelper;
|
import StevenDimDoors.mod_pocketDim.helpers.dimHelper;
|
||||||
|
import StevenDimDoors.mod_pocketDim.schematic.InvalidSchematicException;
|
||||||
|
|
||||||
public class CommandCreateDungeonRift extends DDCommandBase
|
public class CommandCreateDungeonRift extends DDCommandBase
|
||||||
{
|
{
|
||||||
|
@ -81,6 +85,25 @@ public class CommandCreateDungeonRift extends DDCommandBase
|
||||||
link = dimHelper.instance.createPocket(link, true, true);
|
link = dimHelper.instance.createPocket(link, true, true);
|
||||||
dimHelper.dimList.get(link.destDimID).dungeonGenerator = result;
|
dimHelper.dimList.get(link.destDimID).dungeonGenerator = result;
|
||||||
sender.sendChatToPlayer("Created a rift to \"" + getSchematicName(result) + "\" dungeon (Dimension ID = " + link.destDimID + ").");
|
sender.sendChatToPlayer("Created a rift to \"" + getSchematicName(result) + "\" dungeon (Dimension ID = " + link.destDimID + ").");
|
||||||
|
|
||||||
|
/*try {
|
||||||
|
DungeonSchematic dungeon;
|
||||||
|
if ((new File(result.schematicPath)).exists())
|
||||||
|
{
|
||||||
|
dungeon = DungeonSchematic.readFromFile(result.schematicPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dungeon = DungeonSchematic.readFromResource(result.schematicPath);
|
||||||
|
}
|
||||||
|
dungeon.ApplyImportFilters(DDProperties.instance());
|
||||||
|
dungeon.copyToWorld(sender.worldObj, x, y, z);
|
||||||
|
} catch (InvalidSchematicException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}*/
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
112
StevenDimDoors/mod_pocketDim/dungeon/DungeonSchematic.java
Normal file
112
StevenDimDoors/mod_pocketDim/dungeon/DungeonSchematic.java
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
package StevenDimDoors.mod_pocketDim.dungeon;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||||
|
import StevenDimDoors.mod_pocketDim.schematic.CompoundFilter;
|
||||||
|
import StevenDimDoors.mod_pocketDim.schematic.InvalidSchematicException;
|
||||||
|
import StevenDimDoors.mod_pocketDim.schematic.ReplacementFilter;
|
||||||
|
import StevenDimDoors.mod_pocketDim.schematic.Schematic;
|
||||||
|
|
||||||
|
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[] MOD_BLOCK_FILTER_EXCEPTIONS = new short[] {
|
||||||
|
STANDARD_FABRIC_OF_REALITY_ID,
|
||||||
|
STANDARD_ETERNAL_FABRIC_ID
|
||||||
|
};
|
||||||
|
|
||||||
|
private DungeonSchematic(Schematic source)
|
||||||
|
{
|
||||||
|
super(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
//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()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
standardizer.apply(this, this.blocks, this.metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
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()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
standardizer.apply(this, this.blocks, this.metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,8 +17,8 @@ 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.schematic.Schematic;
|
|
||||||
import StevenDimDoors.mod_pocketDim.util.WeightedContainer;
|
import StevenDimDoors.mod_pocketDim.util.WeightedContainer;
|
||||||
|
|
||||||
public class DungeonHelper
|
public class DungeonHelper
|
||||||
|
@ -383,9 +383,10 @@ public class DungeonHelper
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
short size = (short) 2 * MAX_EXPORT_RADIUS + 1;
|
short size = (short) 2 * MAX_EXPORT_RADIUS + 1;
|
||||||
Schematic schematic = Schematic.copyFromWorld(world,
|
DungeonSchematic dungeon = DungeonSchematic.copyFromWorld(world,
|
||||||
centerX - MAX_EXPORT_RADIUS, centerY - MAX_EXPORT_RADIUS, centerZ - MAX_EXPORT_RADIUS, size, size, size, true);
|
centerX - MAX_EXPORT_RADIUS, centerY - MAX_EXPORT_RADIUS, centerZ - MAX_EXPORT_RADIUS, size, size, size, true);
|
||||||
schematic.writeToFile(exportPath);
|
dungeon.ApplyExportFilters(properties);
|
||||||
|
dungeon.writeToFile(exportPath);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
|
|
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 true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,11 +7,14 @@ import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.nbt.CompressedStreamTools;
|
import net.minecraft.nbt.CompressedStreamTools;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.nbt.NBTTagList;
|
import net.minecraft.nbt.NBTTagList;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.chunk.Chunk;
|
||||||
|
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||||
import StevenDimDoors.mod_pocketDim.Point3D;
|
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,7 +29,7 @@ public class Schematic {
|
||||||
|
|
||||||
protected short[] blocks;
|
protected short[] blocks;
|
||||||
protected byte[] metadata;
|
protected byte[] metadata;
|
||||||
protected NBTTagList tileEntities = new NBTTagList();
|
protected NBTTagList tileEntities;
|
||||||
|
|
||||||
protected Schematic(short width, short height, short length, short[] blocks, byte[] metadata, NBTTagList tileEntities)
|
protected Schematic(short width, short height, short length, short[] blocks, byte[] metadata, NBTTagList tileEntities)
|
||||||
{
|
{
|
||||||
|
@ -38,7 +41,19 @@ public class Schematic {
|
||||||
this.tileEntities = tileEntities;
|
this.tileEntities = tileEntities;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int calculateIndex(int x, int y, int z)
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int calculateIndex(int x, int y, int z)
|
||||||
{
|
{
|
||||||
if (x < 0 || x >= width)
|
if (x < 0 || x >= width)
|
||||||
throw new IndexOutOfBoundsException("x must be non-negative and less than width");
|
throw new IndexOutOfBoundsException("x must be non-negative and less than width");
|
||||||
|
@ -83,7 +98,7 @@ public class Schematic {
|
||||||
return readFromStream(schematicStream);
|
return readFromStream(schematicStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Schematic readFromStream(InputStream schematicStream) throws InvalidSchematicException
|
public static Schematic readFromStream(InputStream schematicStream) throws InvalidSchematicException
|
||||||
{
|
{
|
||||||
short width;
|
short width;
|
||||||
short height;
|
short height;
|
||||||
|
@ -165,7 +180,8 @@ public class Schematic {
|
||||||
//Get the list of tile entities
|
//Get the list of tile entities
|
||||||
tileEntities = schematicTag.getTagList("TileEntities");
|
tileEntities = schematicTag.getTagList("TileEntities");
|
||||||
|
|
||||||
return new Schematic(width, height, length, blocks, metadata, tileEntities);
|
Schematic result = new Schematic(width, height, length, blocks, metadata, tileEntities);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
catch (InvalidSchematicException ex)
|
catch (InvalidSchematicException ex)
|
||||||
{
|
{
|
||||||
|
@ -246,7 +262,13 @@ public class Schematic {
|
||||||
return writeToNBT(true);
|
return writeToNBT(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private NBTTagCompound writeToNBT(boolean copyTileEntities)
|
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
|
//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.
|
//the tags, most of the work is done. All the other storage functions will rely on this one.
|
||||||
|
@ -301,6 +323,11 @@ public class Schematic {
|
||||||
outputStream.close();
|
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)
|
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.
|
//This isn't implemented as a WorldOperation because it doesn't quite fit the structure of those operations.
|
||||||
|
@ -317,8 +344,8 @@ public class Schematic {
|
||||||
{
|
{
|
||||||
for (dx = 0; dx < width; dx++)
|
for (dx = 0; dx < width; dx++)
|
||||||
{
|
{
|
||||||
//Don't cause block updates!
|
//In the future, we might want to make this more efficient by building whole chunks at a time
|
||||||
world.setBlock(x + dx, y + dy, z + dz, blocks[index], metadata[index], 2);
|
setBlockDirectly(world, x + dx, y + dy, z + dz, blocks[index], metadata[index]);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -339,4 +366,38 @@ public class Schematic {
|
||||||
world.setBlockTileEntity(dx, dy, dz, TileEntity.createAndLoadEntity(tileTag));
|
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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue