Merge branch 'schematic-creation' into 1.12-WIP and fix conflicts
This commit is contained in:
commit
7c34879757
44 changed files with 411 additions and 84 deletions
|
@ -1,11 +1,14 @@
|
|||
package org.dimdev.ddutils.schem;
|
||||
|
||||
import com.flowpowered.math.vector.Vector3i;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagDouble;
|
||||
|
@ -13,6 +16,7 @@ import net.minecraft.nbt.NBTTagList;
|
|||
import net.minecraft.nbt.NBTTagString;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
@ -38,11 +42,32 @@ public class Schematic {
|
|||
public short length;
|
||||
public int[] offset = {0, 0, 0};
|
||||
public int paletteMax;
|
||||
public List<IBlockState> pallette = new ArrayList<>();
|
||||
public List<IBlockState> palette = new ArrayList<>();
|
||||
public int[][][] blockData; //[x][y][z]
|
||||
public List<NBTTagCompound> tileEntities = new ArrayList<>();
|
||||
public List<NBTTagCompound> entities = new ArrayList<>(); // Not in the specification, but we need this
|
||||
|
||||
public Schematic() {
|
||||
paletteMax = -1;
|
||||
}
|
||||
|
||||
public Schematic(short width, short height, short length) {
|
||||
this();
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.length = length;
|
||||
blockData = new int[width][length][height];
|
||||
palette.add(Blocks.AIR.getDefaultState());
|
||||
paletteMax++;
|
||||
creationDate = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public Schematic(String name, String author, short width, short height, short length) {
|
||||
this(width, height, length);
|
||||
this.name = name;
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public static Schematic loadFromNBT(NBTTagCompound nbt) {
|
||||
Schematic schematic = new Schematic();
|
||||
schematic.version = nbt.getInteger("Version"); //Version is required
|
||||
|
@ -102,12 +127,12 @@ public class Schematic {
|
|||
String[] properties = stateString.split(",");
|
||||
blockstate = getBlockStateWithProperties(block, properties);
|
||||
}
|
||||
schematic.pallette.add(blockstate); //@todo, can we assume that a schematic file always has all palette integers used from 0 to pallettemax-1?
|
||||
schematic.palette.add(blockstate); //@todo, can we assume that a schematic file always has all palette integers used from 0 to pallettemax-1?
|
||||
}
|
||||
if (nbt.hasKey("PaletteMax")) { //PaletteMax is not required
|
||||
schematic.paletteMax = nbt.getInteger("PaletteMax");
|
||||
} else {
|
||||
schematic.paletteMax = schematic.pallette.size() - 1;
|
||||
schematic.paletteMax = schematic.palette.size() - 1;
|
||||
}
|
||||
|
||||
byte[] blockDataIntArray = nbt.getByteArray("BlockData"); //BlockData is required
|
||||
|
@ -161,8 +186,8 @@ public class Schematic {
|
|||
nbt.setInteger("PaletteMax", schematic.paletteMax);
|
||||
|
||||
NBTTagCompound paletteNBT = new NBTTagCompound();
|
||||
for (int i = 0; i < schematic.pallette.size(); i++) {
|
||||
IBlockState state = schematic.pallette.get(i);
|
||||
for (int i = 0; i < schematic.palette.size(); i++) {
|
||||
IBlockState state = schematic.palette.get(i);
|
||||
String blockStateString = getBlockStateStringFromState(state);
|
||||
paletteNBT.setInteger(blockStateString, i);
|
||||
}
|
||||
|
@ -247,9 +272,83 @@ public class Schematic {
|
|||
return totalString;
|
||||
}
|
||||
|
||||
public static void place(Schematic schematic, World world, int xBase, int yBase, int zBase) {
|
||||
// TODO: use the setBlockState method
|
||||
public static Schematic createFromWorld(World world, Vector3i from, Vector3i to) {
|
||||
Schematic schematic = new Schematic();
|
||||
|
||||
Vector3i min = from.min(to);
|
||||
Vector3i max = from.max(to);
|
||||
Vector3i dimensions = max.sub(min).add(1, 1, 1);
|
||||
|
||||
schematic.width = (short) dimensions.getX();
|
||||
schematic.height = (short) dimensions.getY();
|
||||
schematic.length = (short) dimensions.getZ();
|
||||
|
||||
schematic.blockData = new int[schematic.width][schematic.height][schematic.length];
|
||||
|
||||
ArrayListMultimap<IBlockState, BlockPos> states = ArrayListMultimap.create();
|
||||
Set<String> mods = new HashSet<>();
|
||||
|
||||
for (int x = 0; x < dimensions.getX(); x++) {
|
||||
for (int y = 0; y < dimensions.getY(); y++) {
|
||||
for (int z = 0; z < dimensions.getZ(); z++) {
|
||||
BlockPos pos = new BlockPos(min.getX() + x, min.getY() + y, min.getZ() + z);
|
||||
|
||||
IBlockState state = world.getBlockState(pos);
|
||||
String id = getBlockStateStringFromState(state);
|
||||
if (id.contains(":")) mods.add(id.split(":")[0]);
|
||||
states.put(state, new BlockPos(x, y, z));
|
||||
|
||||
TileEntity tileEntity = world.getChunkFromBlockCoords(pos).getTileEntity(pos, Chunk.EnumCreateEntityType.CHECK);
|
||||
if (tileEntity != null) {
|
||||
NBTTagCompound tileEntityNBT = tileEntity.serializeNBT();
|
||||
tileEntityNBT.setInteger("x", tileEntityNBT.getInteger("x") - min.getX());
|
||||
tileEntityNBT.setInteger("y", tileEntityNBT.getInteger("y") - min.getY());
|
||||
tileEntityNBT.setInteger("z", tileEntityNBT.getInteger("z") - min.getZ());
|
||||
|
||||
schematic.tileEntities.add(tileEntityNBT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IBlockState[] keys = states.keySet().toArray(new IBlockState[states.keySet().size()]);
|
||||
|
||||
for (int i = 0; i < keys.length; i++) {
|
||||
for (BlockPos pos : states.get(keys[i])) {
|
||||
schematic.blockData[pos.getX()][pos.getY()][pos.getZ()] = i;
|
||||
}
|
||||
|
||||
schematic.palette.add(i, keys[i]);
|
||||
}
|
||||
|
||||
for (Entity entity : world.getEntitiesInAABBexcluding(null, getBoundingBox(from, to), entity -> !(entity instanceof EntityPlayerMP))) {
|
||||
NBTTagCompound entityNBT = entity.serializeNBT();
|
||||
|
||||
NBTTagList posNBT = (NBTTagList) entityNBT.getTag("Pos");
|
||||
NBTTagList newPosNBT = new NBTTagList();
|
||||
newPosNBT.appendTag(new NBTTagDouble(posNBT.getDoubleAt(0) - from.getX()));
|
||||
newPosNBT.appendTag(new NBTTagDouble(posNBT.getDoubleAt(1) - from.getY()));
|
||||
newPosNBT.appendTag(new NBTTagDouble(posNBT.getDoubleAt(2) - from.getZ()));
|
||||
entityNBT.setTag("Pos", newPosNBT);
|
||||
|
||||
schematic.entities.add(entityNBT);
|
||||
}
|
||||
|
||||
schematic.requiredMods = mods.toArray(new String[mods.size()]);
|
||||
schematic.paletteMax = keys.length - 1;
|
||||
schematic.creationDate = System.currentTimeMillis();
|
||||
|
||||
return schematic;
|
||||
}
|
||||
|
||||
private static AxisAlignedBB getBoundingBox(Vector3i pos1, Vector3i pos2) {
|
||||
return new AxisAlignedBB(new BlockPos(pos1.getX(), pos1.getY(), pos1.getZ()), new BlockPos(pos2.getX(), pos2.getY(), pos2.getZ()));
|
||||
}
|
||||
|
||||
public static void place(Schematic schematic, World world, int xBase, int yBase, int zBase) { // TODO: check if entities and tileentities are within pocket bounds
|
||||
// Place the schematic's blocks
|
||||
List<IBlockState> palette = schematic.pallette;
|
||||
List<IBlockState> palette = schematic.palette;
|
||||
int[][][] blockData = schematic.blockData;
|
||||
Set<Chunk> changedChunks = new HashSet<>();
|
||||
long start = System.currentTimeMillis();
|
||||
|
@ -307,7 +406,7 @@ public class Schematic {
|
|||
throw new RuntimeException("Schematic contained TileEntity " + schematicTileEntityId + " at " + pos + " but the TileEntity of that block (" + world.getBlockState(pos) + ") must be " + blockTileEntityId);
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Schematic contained TileEntity info at " + pos + "but the block there (" + world.getBlockState(pos) + ") has no TileEntity.");
|
||||
throw new RuntimeException("Schematic contained TileEntity info at " + pos + " but the block there (" + world.getBlockState(pos) + ") has no TileEntity.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -327,4 +426,13 @@ public class Schematic {
|
|||
world.spawnEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBlockState(int x, int y, int z, IBlockState state) {
|
||||
if (palette.contains(state)) {
|
||||
blockData[x][y][z] = palette.indexOf(state); // TODO: optimize this (there must be some efficient list implementations)
|
||||
} else {
|
||||
palette.add(state);
|
||||
blockData[x][y][z] = ++paletteMax;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import org.dimdev.dimdoors.shared.commands.CommandPocket;
|
|||
import org.dimdev.dimdoors.shared.commands.CommandDimTeleport;
|
||||
import org.dimdev.dimdoors.shared.Config;
|
||||
import org.dimdev.dimdoors.shared.CommonProxy;
|
||||
import org.dimdev.dimdoors.shared.commands.CommandSaveSchem;
|
||||
import org.dimdev.dimdoors.shared.items.ModItems;
|
||||
import org.dimdev.dimdoors.shared.world.gateways.GatewayGenerator;
|
||||
import lombok.Getter;
|
||||
|
@ -68,6 +69,7 @@ public class DimDoors {
|
|||
private void registerCommands(FMLServerStartingEvent event) {
|
||||
event.registerServerCommand(new CommandDimTeleport());
|
||||
event.registerServerCommand(new CommandPocket());
|
||||
event.registerServerCommand(new CommandSaveSchem());
|
||||
}
|
||||
|
||||
public static void sendMessage(Entity entity, String text) {
|
||||
|
|
|
@ -96,7 +96,8 @@ public class CommandPocket extends CommandBase {
|
|||
TileEntityRift entrance = (TileEntityRift) player.world.getTileEntity(pocket.getEntrance().getPos());
|
||||
entrance.teleportTo(player);
|
||||
} else {
|
||||
TeleportUtils.teleport(player, new Location(player.world, pocket.getOrigin().add(30, 30, 30)));
|
||||
int size = (pocket.getSize() + 1) * 16;
|
||||
TeleportUtils.teleport(player, new Location(player.world, pocket.getOrigin().add(size / 2, size / 2, size / 2)));
|
||||
}
|
||||
} else {
|
||||
DimDoors.log.info("Not executing command /" + getName() + " because it wasn't sent by a player.");
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
package org.dimdev.dimdoors.shared.commands;
|
||||
|
||||
import com.flowpowered.math.vector.Vector3i;
|
||||
import net.minecraft.command.CommandBase;
|
||||
import net.minecraft.command.CommandException;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import org.dimdev.ddutils.schem.Schematic;
|
||||
import org.dimdev.dimdoors.DimDoors;
|
||||
import org.dimdev.dimdoors.shared.pockets.Pocket;
|
||||
import org.dimdev.dimdoors.shared.pockets.PocketRegistry;
|
||||
import org.dimdev.dimdoors.shared.pockets.SchematicHandler;
|
||||
import org.dimdev.dimdoors.shared.world.pocketdimension.WorldProviderPocket;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CommandSaveSchem extends CommandBase {
|
||||
private final List<String> aliases;
|
||||
|
||||
public CommandSaveSchem() {
|
||||
aliases = new ArrayList<>();
|
||||
aliases.add("saveschem");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "saveschem";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(ICommandSender sender) {
|
||||
return "saveschem <name>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAliases() {
|
||||
return aliases;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { // TODO: more pocket commands (replace pocket, get ID, teleport to pocket, etc.)
|
||||
// Check that the number of arguments is correct
|
||||
if (args.length != 1) {
|
||||
sender.sendMessage(new TextComponentString("[DimDoors] Usage: /" + getUsage(sender)));
|
||||
return;
|
||||
}
|
||||
|
||||
// Execute only if it's a player
|
||||
if (sender instanceof EntityPlayerMP) {
|
||||
EntityPlayerMP player = getCommandSenderAsPlayer(sender);
|
||||
|
||||
if (!(player.world.provider instanceof WorldProviderPocket)) {
|
||||
DimDoors.chat(player, "Current Dimension isn't a pocket dimension");
|
||||
return;
|
||||
}
|
||||
|
||||
Pocket pocket = PocketRegistry.instance(player.dimension).getPocketAt(player.getPosition());
|
||||
Schematic schematic = Schematic.createFromWorld(player.world, toVector3i(pocket.getOrigin()), toVector3i(pocket.getOrigin()).add(Vector3i.from((pocket.getSize() + 1) * 16 - 1)));
|
||||
schematic.name = args[0];
|
||||
schematic.author = player.getName();
|
||||
|
||||
SchematicHandler.INSTANCE.saveSchematic(schematic, args[0]);
|
||||
DimDoors.chat(player, "Pocket " + args[0] + " has been saved.");
|
||||
} else {
|
||||
DimDoors.log.info("Not executing command /" + getName() + " because it wasn't sent by a player.");
|
||||
}
|
||||
}
|
||||
|
||||
private Vector3i toVector3i(BlockPos pos) {
|
||||
return Vector3i.from(pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
}
|
|
@ -29,7 +29,7 @@ import java.util.List;
|
|||
@Saved @Getter protected int id;
|
||||
@Saved @Getter protected int x; // Grid x TODO: rename to gridX and gridY, or just convert to non-grid dependant coordinates
|
||||
@Saved @Getter protected int z; // Grid y
|
||||
@Saved @Getter @Setter protected int size; // In chunks TODO: non chunk-based size, better bounds such as minX, minZ, maxX, maxZ, etc.
|
||||
@Saved @Getter @Setter protected int size; // TODO: size = sizeInChunks - 1 ???!!! TODO: non chunk-based size, better bounds such as minX, minZ, maxX, maxZ, etc.
|
||||
@Saved @Getter @Setter protected VirtualLocation virtualLocation;
|
||||
@Saved @Getter @Setter protected Location entrance; // TODO: move this to the rift registry (pocketlib)
|
||||
@Saved @Getter protected List<Location> riftLocations; // TODO: convert to a list of all tile entities (for chests, and to make it independant of pocketlib)
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.dimdev.dimdoors.shared.pockets;
|
|||
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import net.minecraft.world.World;
|
||||
import org.dimdev.annotatednbt.Saved;
|
||||
import org.dimdev.annotatednbt.NBTSerializable;
|
||||
import org.dimdev.dimdoors.shared.Config;
|
||||
|
@ -9,7 +10,6 @@ import org.dimdev.ddutils.math.GridUtils;
|
|||
import org.dimdev.dimdoors.DimDoors;
|
||||
import org.dimdev.ddutils.nbt.NBTUtils;
|
||||
import org.dimdev.ddutils.WorldUtils;
|
||||
import org.dimdev.dimdoors.shared.world.ModDimensions;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -21,6 +21,7 @@ import net.minecraft.nbt.NBTTagCompound;
|
|||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.storage.MapStorage;
|
||||
import net.minecraft.world.storage.WorldSavedData;
|
||||
import org.dimdev.dimdoors.shared.world.pocketdimension.WorldProviderPocket;
|
||||
|
||||
@NBTSerializable public class
|
||||
PocketRegistry extends WorldSavedData { // TODO: unregister pocket entrances, private pocket entrances/exits
|
||||
|
@ -47,9 +48,13 @@ PocketRegistry extends WorldSavedData { // TODO: unregister pocket entrances, pr
|
|||
}
|
||||
|
||||
public static PocketRegistry instance(int dim) {
|
||||
if (!ModDimensions.isDimDoorsPocketDimension(dim)) throw new UnsupportedOperationException("PocketRegistry is only available for pocket dimensions!");
|
||||
World world = WorldUtils.getWorld(dim);
|
||||
|
||||
MapStorage storage = WorldUtils.getWorld(dim).getPerWorldStorage();
|
||||
if (!(world.provider instanceof WorldProviderPocket)) {
|
||||
throw new UnsupportedOperationException("PocketRegistry is only available for pocket dimensions (asked for dim " + dim + ")!");
|
||||
}
|
||||
|
||||
MapStorage storage = world.getPerWorldStorage();
|
||||
PocketRegistry instance = (PocketRegistry) storage.getOrLoadData(PocketRegistry.class, DATA_NAME);
|
||||
|
||||
if (instance == null) {
|
||||
|
|
|
@ -34,7 +34,8 @@ import org.dimdev.dimdoors.shared.world.ModDimensions;
|
|||
*/
|
||||
public class SchematicHandler {
|
||||
|
||||
public static final SchematicHandler INSTANCE = new SchematicHandler(); // TODO: make static
|
||||
private static final String SAVED_POCKETS_GROUP_NAME = "saved_pockets";
|
||||
public static final SchematicHandler INSTANCE = new SchematicHandler();
|
||||
|
||||
private List<PocketTemplate> templates;
|
||||
private Map<String, Map<String, Integer>> nameMap; // group -> name -> index in templates
|
||||
|
@ -44,7 +45,7 @@ public class SchematicHandler {
|
|||
|
||||
templates = new ArrayList<>();
|
||||
|
||||
String[] names = {"default_dungeon_nether", "default_dungeon_normal", "default_private", "default_public"}; // TODO: don't hardcode
|
||||
String[] names = {"default_dungeon_nether", "default_dungeon_normal", "default_private", "default_public", "default_blank"}; // TODO: don't hardcode
|
||||
for (String name : names) {
|
||||
try {
|
||||
URL resource = DimDoors.class.getResource("/assets/dimdoors/pockets/json/" + name + ".json");
|
||||
|
@ -74,6 +75,21 @@ public class SchematicHandler {
|
|||
DimDoors.log.error("Error reading file " + file.toURI() + ". The following exception occured: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Load saved schematics
|
||||
File saveFolder = new File(Config.configurationFolder, "/schematics/saved");
|
||||
if (saveFolder.exists()) {
|
||||
for (File file : saveFolder.listFiles()) {
|
||||
if (file.isDirectory() || !file.getName().endsWith(".schem")) continue;
|
||||
try {
|
||||
Schematic schematic = Schematic.loadFromNBT(CompressedStreamTools.readCompressed(new FileInputStream(file)));
|
||||
templates.add(new PocketTemplate(SAVED_POCKETS_GROUP_NAME, file.getName(), null, null, null, schematic, -1, 0));
|
||||
} catch (IOException e) {
|
||||
DimDoors.log.error("Error reading schematic " + file.getName() + ": " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constructNameMap();
|
||||
|
||||
DimDoors.log.info("Loaded " + templates.size() + " templates in " + (System.currentTimeMillis() - startTime) + " ms.");
|
||||
|
@ -205,6 +221,8 @@ public class SchematicHandler {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
nameMap.put(SAVED_POCKETS_GROUP_NAME, new HashMap<>());
|
||||
}
|
||||
|
||||
public Set<String> getTemplateGroups() {
|
||||
|
@ -276,14 +294,14 @@ public class SchematicHandler {
|
|||
return getRandomTemplate("public", -1, Math.min(Config.getPublicPocketSize(), PocketRegistry.instance(ModDimensions.getPublicDim()).getPublicPocketSize()), true);
|
||||
}
|
||||
|
||||
public void saveSchematic(Schematic schematic, String name) {
|
||||
public void saveSchematic(Schematic schematic, String id) {
|
||||
NBTTagCompound schematicNBT = Schematic.saveToNBT(schematic);
|
||||
File saveFolder = new File(Config.configurationFolder, "/Schematics/Saved");
|
||||
File saveFolder = new File(Config.configurationFolder, "/schematics/saved");
|
||||
if (!saveFolder.exists()) {
|
||||
saveFolder.mkdirs();
|
||||
}
|
||||
|
||||
File saveFile = new File(saveFolder.getAbsolutePath() + "/" + name + ".schem");
|
||||
File saveFile = new File(saveFolder.getAbsolutePath() + "/" + id + ".schem");
|
||||
try {
|
||||
saveFile.createNewFile();
|
||||
DataOutputStream schematicDataStream = new DataOutputStream(new FileOutputStream(saveFile));
|
||||
|
@ -293,5 +311,17 @@ public class SchematicHandler {
|
|||
} catch (IOException ex) {
|
||||
Logger.getLogger(SchematicHandler.class.getName()).log(Level.SEVERE, "Something went wrong while saving " + saveFile.getAbsolutePath() + " to disk.", ex);
|
||||
}
|
||||
|
||||
if (!nameMap.containsKey(SAVED_POCKETS_GROUP_NAME)) {
|
||||
nameMap.put(SAVED_POCKETS_GROUP_NAME, new HashMap<>());
|
||||
}
|
||||
|
||||
Map<String, Integer> savedDungeons = nameMap.get(SAVED_POCKETS_GROUP_NAME);
|
||||
if (savedDungeons.containsKey(id)) {
|
||||
templates.remove((int) savedDungeons.remove(id));
|
||||
}
|
||||
|
||||
templates.add(new PocketTemplate(SAVED_POCKETS_GROUP_NAME, id, null, null, null, schematic, -1, 0));
|
||||
nameMap.get(SAVED_POCKETS_GROUP_NAME).put(id, templates.size() - 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ public class RiftRegistry extends WorldSavedData {
|
|||
// method rather than RiftSubregistry) and save each in the appropriate registry, we can't do this because it is not
|
||||
// always the case that all worlds will be saved at once.
|
||||
@Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) {
|
||||
if (riftRegistry == null) RiftRegistry.instance();
|
||||
if (riftRegistry == null) riftRegistry = RiftRegistry.instance();
|
||||
// Write rifts in this dimension
|
||||
NBTTagList riftsNBT = new NBTTagList();
|
||||
NBTTagList pocketsNBT = new NBTTagList();
|
||||
|
|
|
@ -3,7 +3,6 @@ package org.dimdev.dimdoors.shared.tools;
|
|||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockDoor;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.init.Bootstrap;
|
||||
import net.minecraft.item.EnumDyeColor;
|
||||
import net.minecraft.nbt.CompressedStreamTools;
|
||||
|
@ -19,6 +18,7 @@ import org.dimdev.ddutils.schem.Schematic;
|
|||
import org.dimdev.dimdoors.DimDoors;
|
||||
import org.dimdev.dimdoors.server.ServerProxy;
|
||||
import org.dimdev.dimdoors.shared.blocks.BlockDimensionalDoor;
|
||||
import org.dimdev.dimdoors.shared.blocks.BlockFabric;
|
||||
import org.dimdev.dimdoors.shared.blocks.BlockFabricAncient;
|
||||
import org.dimdev.dimdoors.shared.blocks.ModBlocks;
|
||||
import org.dimdev.dimdoors.shared.rifts.RiftDestination;
|
||||
|
@ -73,102 +73,102 @@ public final class PocketSchematicGenerator {
|
|||
}
|
||||
|
||||
// Generate the schematics
|
||||
List<Schematic> schematics = generatePocketSchematics(8);
|
||||
List<Schematic> schematics = generatePocketSchematics();
|
||||
|
||||
// Save the schematics
|
||||
boolean isPublic = true;
|
||||
String[] saveFolders = {"public/", "private/", "blank/", "blank/"};
|
||||
int i = 0;
|
||||
for (Schematic schematic : schematics) {
|
||||
NBTTagCompound schematicNBT = Schematic.saveToNBT(schematic);
|
||||
File saveFile = new File(schematicDir, (isPublic ? "public/" : "private/") + schematic.name + ".schem");
|
||||
File saveFile = new File(schematicDir, saveFolders[i++ % saveFolders.length] + schematic.name + ".schem");
|
||||
saveFile.getParentFile().mkdirs();
|
||||
DataOutputStream schematicDataStream = new DataOutputStream(new FileOutputStream(saveFile));
|
||||
CompressedStreamTools.writeCompressed(schematicNBT, schematicDataStream);
|
||||
schematicDataStream.flush();
|
||||
schematicDataStream.close();
|
||||
isPublic = !isPublic;
|
||||
}
|
||||
// TODO: also generate JSON files
|
||||
}
|
||||
|
||||
public static List<Schematic> generatePocketSchematics(int maxPocketSize) {
|
||||
public static List<Schematic> generatePocketSchematics() {
|
||||
List<Schematic> schematics = new ArrayList<>();
|
||||
for (int pocketSize = 0; pocketSize < maxPocketSize; pocketSize++) {
|
||||
schematics.add(generatePocketSchematic(
|
||||
for (int pocketSize = 0; pocketSize < 8; pocketSize++) {
|
||||
schematics.add(generateBlankWithDoor(
|
||||
"public_pocket", // base name
|
||||
pocketSize, // size
|
||||
ModBlocks.ANCIENT_FABRIC.getDefaultState(), // outer wall
|
||||
ModBlocks.FABRIC.getDefaultState(), // inner wall
|
||||
ModBlocks.DIMENSIONAL_DOOR, // door
|
||||
PocketExitDestination.builder().build(),// exit rift destination
|
||||
1)); // TODO: pass destination rather than just chaos weight
|
||||
schematics.add(generatePocketSchematic(
|
||||
LinkProperties.builder()
|
||||
.groups(Collections.singleton(1))
|
||||
.linksRemaining(1)
|
||||
.entranceWeight(1)
|
||||
.floatingWeight(1)
|
||||
.build()));
|
||||
|
||||
schematics.add(generateBlankWithDoor(
|
||||
"private_pocket", // base name
|
||||
pocketSize, // size
|
||||
ModBlocks.ANCIENT_FABRIC.getDefaultState().withProperty(BlockFabricAncient.COLOR, EnumDyeColor.WHITE), // outer wall
|
||||
ModBlocks.FABRIC.getDefaultState().withProperty(BlockFabricAncient.COLOR, EnumDyeColor.WHITE), // inner wall
|
||||
ModBlocks.PERSONAL_DIMENSIONAL_DOOR, // door
|
||||
PrivatePocketExitDestination.builder().build(),// exit rift destination
|
||||
0));
|
||||
null));
|
||||
|
||||
schematics.add(generateBlank("blank_pocket",
|
||||
pocketSize,
|
||||
ModBlocks.ANCIENT_FABRIC.getDefaultState(),
|
||||
ModBlocks.FABRIC.getDefaultState()));
|
||||
|
||||
schematics.add(generateFrame("void_pocket",
|
||||
pocketSize,
|
||||
ModBlocks.FABRIC.getDefaultState().withProperty(BlockFabric.COLOR, EnumDyeColor.LIGHT_BLUE)));
|
||||
}
|
||||
return schematics;
|
||||
}
|
||||
|
||||
private static Schematic generatePocketSchematic(String baseName, int pocketSize, IBlockState outerWallBlockState, IBlockState innerWallBlockState, BlockDimensionalDoor doorBlock, RiftDestination exitDest, float chaosWeight) {
|
||||
int size = (pocketSize + 1) * 16 - 1; // -1 so that the door can be centered
|
||||
private static Schematic generateBlank(String baseName, int pocketSize, IBlockState outerWall, IBlockState innerWall) {
|
||||
short size = (short) ((pocketSize + 1) * 16 - 1); // -1 so that the door can be centered
|
||||
|
||||
// Set schematic info
|
||||
Schematic schematic = new Schematic();
|
||||
schematic.version = 1;
|
||||
schematic.author = "Robijnvogel"; //@todo set in build.gradle ${modID}
|
||||
schematic.name = baseName + "_" + pocketSize;
|
||||
schematic.creationDate = System.currentTimeMillis();
|
||||
schematic.requiredMods = new String[1];
|
||||
schematic.requiredMods[0] = DimDoors.MODID;
|
||||
schematic.width = (short) size;
|
||||
schematic.height = (short) size;
|
||||
schematic.length = (short) size;
|
||||
schematic.offset = new int[]{0, 0, 0}; // TODO: center pockets
|
||||
|
||||
// Generate the pallette
|
||||
schematic.paletteMax = 4;
|
||||
schematic.pallette = new ArrayList<>();
|
||||
schematic.pallette.add(Blocks.AIR.getDefaultState());
|
||||
schematic.pallette.add(outerWallBlockState);
|
||||
schematic.pallette.add(innerWallBlockState);
|
||||
schematic.pallette.add(doorBlock.getDefaultState().withProperty(BlockDoor.HALF, BlockDoor.EnumDoorHalf.LOWER)); //bottom
|
||||
schematic.pallette.add(doorBlock.getDefaultState().withProperty(BlockDoor.HALF, BlockDoor.EnumDoorHalf.UPPER)); //top
|
||||
Schematic schematic = new Schematic(baseName + "_" + pocketSize, "DimDoors", size, size, size);
|
||||
schematic.requiredMods = new String[] { DimDoors.MODID };
|
||||
|
||||
// Set block data
|
||||
schematic.blockData = new int[size][size][size]; //[x][y][z]
|
||||
for (int x = 0; x < size; x++) {
|
||||
for (int y = 0; y < size; y++) {
|
||||
for (int z = 0; z < size; z++) {
|
||||
int layer = Collections.min(Arrays.asList(x, y, z, size - 1 - x, size - 1 - y, size - 1 - z));
|
||||
if (layer == 0) {
|
||||
schematic.blockData[x][y][z] = 1; // outer wall
|
||||
schematic.setBlockState(x, y, z, outerWall);
|
||||
} else if (layer < 5) {
|
||||
schematic.blockData[x][y][z] = 2; // inner wall
|
||||
} else {
|
||||
schematic.blockData[x][y][z] = 0; // air
|
||||
schematic.setBlockState(x, y, z, innerWall);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
schematic.blockData[(size - 1) / 2][5][4] = 3; // door bottom
|
||||
schematic.blockData[(size - 1) / 2][6][4] = 4; // door top
|
||||
|
||||
// Generate the rift TileEntities
|
||||
return schematic;
|
||||
}
|
||||
|
||||
private static Schematic generateBlankWithDoor(String baseName, int pocketSize, IBlockState outerWall, IBlockState innerWall, BlockDimensionalDoor doorBlock, RiftDestination exitDest, LinkProperties link) {
|
||||
short size = (short) ((pocketSize + 1) * 16 - 1); // -1 so that the door can be centered
|
||||
|
||||
// Make the schematic
|
||||
Schematic schematic = generateBlank(baseName, pocketSize, outerWall, innerWall);
|
||||
|
||||
// Add the door
|
||||
schematic.setBlockState((size - 1) / 2, 5, 4, doorBlock.getDefaultState().withProperty(BlockDoor.HALF, BlockDoor.EnumDoorHalf.LOWER));
|
||||
schematic.setBlockState((size - 1) / 2, 6, 4, doorBlock.getDefaultState().withProperty(BlockDoor.HALF, BlockDoor.EnumDoorHalf.UPPER));
|
||||
|
||||
// Set the rift entities
|
||||
schematic.tileEntities = new ArrayList<>();
|
||||
TileEntityEntranceRift rift = (TileEntityEntranceRift) doorBlock.createTileEntity(null, doorBlock.getDefaultState());
|
||||
rift.setDestination(PocketEntranceDestination.builder()
|
||||
.ifDestination(exitDest)
|
||||
.build());
|
||||
rift.setProperties(LinkProperties.builder()
|
||||
.groups(Collections.singleton(1))
|
||||
.linksRemaining(1)
|
||||
.entranceWeight(chaosWeight)
|
||||
.floatingWeight(chaosWeight)
|
||||
.build());
|
||||
rift.setProperties(link);
|
||||
|
||||
rift.setPlaceRiftOnBreak(true);
|
||||
NBTTagCompound tileNBT = rift.serializeNBT();
|
||||
|
@ -179,4 +179,30 @@ public final class PocketSchematicGenerator {
|
|||
|
||||
return schematic;
|
||||
}
|
||||
|
||||
private static Schematic generateFrame(String baseName, int chunkSize, IBlockState frame) {
|
||||
short size = (short) ((chunkSize + 1) * 16 - 1); // -1 so that the door can be centered
|
||||
|
||||
// Set schematic info
|
||||
Schematic schematic = new Schematic(baseName + "_" + chunkSize, "DimDoors", size, size, size);
|
||||
schematic.requiredMods = new String[] { DimDoors.MODID };
|
||||
|
||||
// Set block data
|
||||
for (int x = 0; x < size; x++) {
|
||||
for (int y = 0; y < size; y++) {
|
||||
for (int z = 0; z < size; z++) {
|
||||
int sides = 0;
|
||||
if (x == 0 || x == size - 1) sides++;
|
||||
if (y == 0 || y == size - 1) sides++;
|
||||
if (z == 0 || z == size - 1) sides++;
|
||||
|
||||
if (sides >= 2) {
|
||||
schematic.setBlockState(x, y, z, frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return schematic;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ public final class SchematicConverter {
|
|||
|
||||
byte[] blockIdArray = nbt.getByteArray("Blocks");
|
||||
byte[] addId = nbt.getByteArray("AddBlocks");
|
||||
Map<Integer, Byte> palletteMap = new HashMap<>(); // block ID -> pallette index
|
||||
Map<Integer, Byte> palletteMap = new HashMap<>(); // block ID -> palette index
|
||||
byte currentPalletteIndex = 0;
|
||||
for (int i = 0; i < blockIdArray.length; i++) {
|
||||
int id;
|
||||
|
@ -96,13 +96,9 @@ public final class SchematicConverter {
|
|||
if (id != 0 && block.getBlock().getRegistryName().toString().equals("minecraft:air")) {
|
||||
throw new RuntimeException("Unknown ID " + id + " in schematic " + schematicId);
|
||||
}
|
||||
if (block.equals(Blocks.IRON_DOOR)) {
|
||||
block = ModBlocks.DIMENSIONAL_DOOR.getDefaultState();
|
||||
}
|
||||
if (block.equals(Blocks.OAK_DOOR)) {
|
||||
block = ModBlocks.WARP_DIMENSIONAL_DOOR.getDefaultState();
|
||||
}
|
||||
schematic.pallette.add(block);
|
||||
if (block.equals(Blocks.IRON_DOOR)) block = ModBlocks.DIMENSIONAL_DOOR.getDefaultState();
|
||||
if (block.equals(Blocks.OAK_DOOR)) block = ModBlocks.WARP_DIMENSIONAL_DOOR.getDefaultState();
|
||||
schematic.palette.add(block);
|
||||
palletteMap.put(id, currentPalletteIndex);
|
||||
blockIdArray[i] = currentPalletteIndex;
|
||||
currentPalletteIndex++;
|
||||
|
@ -139,7 +135,7 @@ public final class SchematicConverter {
|
|||
int blockInt = blockIdArray[x + z * schematic.width + y * schematic.width * schematic.length]; //according to the documentation on https://github.com/SpongePowered/Schematic-Specification/blob/master/versions/schematic-1.md
|
||||
int metadata = dataIntArray[x + z * schematic.width + y * schematic.width * schematic.length]; //according to the documentation on https://github.com/SpongePowered/Schematic-Specification/blob/master/versions/schematic-1.md
|
||||
|
||||
IBlockState baseState = schematic.pallette.get(blockInt); //this is the default blockstate except for ancient fabric
|
||||
IBlockState baseState = schematic.palette.get(blockInt); //this is the default blockstate except for ancient fabric
|
||||
if (baseState == baseState.getBlock().getDefaultState() || baseState.getBlock().equals(ModBlocks.FABRIC) || baseState.getBlock().equals(ModBlocks.ANCIENT_FABRIC)) { //should only be false if {@code baseState} is ancient fabric
|
||||
IBlockState blockState;
|
||||
if (baseState.getBlock().equals(ModBlocks.FABRIC) || baseState.getBlock().equals(ModBlocks.ANCIENT_FABRIC)) {
|
||||
|
@ -147,12 +143,12 @@ public final class SchematicConverter {
|
|||
} else {
|
||||
blockState = baseState.getBlock().getStateFromMeta(metadata);
|
||||
}
|
||||
if (schematic.pallette.contains(blockState)) { //check whether or not this blockstate is already in the list
|
||||
blockInt = schematic.pallette.indexOf(blockState);
|
||||
if (schematic.palette.contains(blockState)) { //check whether or not this blockstate is already in the list
|
||||
blockInt = schematic.palette.indexOf(blockState);
|
||||
} else {
|
||||
schematic.pallette.add(blockState);
|
||||
schematic.palette.add(blockState);
|
||||
//DimDoors.log.info("New blockstate detected. Original blockInt = " + blockInt + " and blockState is " + blockState);
|
||||
blockInt = schematic.pallette.size() - 1;
|
||||
blockInt = schematic.palette.size() - 1;
|
||||
}
|
||||
Block block = blockState.getBlock();
|
||||
if (block.equals(Blocks.DIAMOND_BLOCK)) {
|
||||
|
@ -175,7 +171,7 @@ public final class SchematicConverter {
|
|||
} else if (block.equals(Blocks.END_PORTAL_FRAME)) {
|
||||
monoliths++;
|
||||
// I think it's safe to assume that air is present
|
||||
blockInt = schematic.pallette.indexOf(Blocks.AIR.getDefaultState());
|
||||
blockInt = schematic.palette.indexOf(Blocks.AIR.getDefaultState());
|
||||
EntityMonolith monolith = new EntityMonolith(null);
|
||||
EnumFacing facing = blockState.getValue(BlockEndPortalFrame.FACING);
|
||||
monolith.setLocationAndAngles(x + 0.5d, y, z + 0.5d, facing.getHorizontalAngle(), 0);
|
||||
|
@ -200,7 +196,7 @@ public final class SchematicConverter {
|
|||
.weightMaximum(100)
|
||||
.newRiftWeight(1).build());
|
||||
} else if (block.equals(ModBlocks.WARP_DIMENSIONAL_DOOR)) {
|
||||
IBlockState stateBelow = schematic.pallette.get(schematic.blockData[x][y - 1][z]);
|
||||
IBlockState stateBelow = schematic.palette.get(schematic.blockData[x][y - 1][z]);
|
||||
if (stateBelow.getBlock().equals(Blocks.SANDSTONE)) {
|
||||
sandstoneDoors++;
|
||||
rift.setProperties(null); // TODO: this should be removed once the linking equations are made symmetric
|
||||
|
@ -247,9 +243,19 @@ public final class SchematicConverter {
|
|||
|
||||
schematic.tileEntities.add(rift.serializeNBT());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (blockState.getBlock().equals(Blocks.END_PORTAL_FRAME)) {
|
||||
monoliths++;
|
||||
// I think it's safe to assume that air is present
|
||||
blockInt = schematic.palette.indexOf(Blocks.AIR.getDefaultState());
|
||||
EntityMonolith monolith = new EntityMonolith(null);
|
||||
EnumFacing facing = blockState.getValue(BlockEndPortalFrame.FACING);
|
||||
monolith.setLocationAndAngles(x + 0.5d, y, z + 0.5d, facing.getHorizontalAngle(), 0);
|
||||
schematic.entities.add(monolith.serializeNBT());
|
||||
}
|
||||
} else { // if this is ancient fabric
|
||||
blockInt = schematic.pallette.indexOf(baseState);
|
||||
blockInt = schematic.palette.indexOf(baseState);
|
||||
}
|
||||
assert blockInt >= 0;
|
||||
schematic.blockData[x][y][z] = blockInt;
|
||||
|
@ -259,7 +265,7 @@ public final class SchematicConverter {
|
|||
if (!nbt.getTag("Entities").hasNoTags()) {
|
||||
throw new RuntimeException("Schematic contains entities, but those aren't implemented in the conversion code");
|
||||
}
|
||||
schematic.paletteMax = schematic.pallette.size() - 1;
|
||||
schematic.paletteMax = schematic.palette.size() - 1;
|
||||
|
||||
DimDoors.log.info(schematicId + "," + ironDoors + "," + woodDoors + "," + sandstoneDoors + "," + monoliths + "," +
|
||||
chests + "," + dispensers + "," + diamondBlocks + "," + goldBlocks + "," + ironBlocks);
|
||||
|
|
|
@ -23,7 +23,9 @@ public final class ModDimensions {
|
|||
@Getter private static int privateDim;
|
||||
@Getter private static int publicDim;
|
||||
@Getter private static int dungeonDim;
|
||||
@Getter private static int dungeonMakingDim;
|
||||
|
||||
@SuppressWarnings("UnusedAssignment")
|
||||
public static void registerDimensions() {
|
||||
// TODO: more than 1 dimension/dimension type
|
||||
int dim = Config.getBaseDim();
|
||||
|
@ -31,10 +33,12 @@ public final class ModDimensions {
|
|||
privateDim = dim++;
|
||||
publicDim = dim++;
|
||||
dungeonDim = dim++;
|
||||
dungeonMakingDim = dim++;
|
||||
DimensionManager.registerDimension(limboDim, LIMBO);
|
||||
DimensionManager.registerDimension(privateDim, PRIVATE);
|
||||
DimensionManager.registerDimension(publicDim, PUBLIC);
|
||||
DimensionManager.registerDimension(dungeonDim, DUNGEON);
|
||||
DimensionManager.registerDimension(dungeonMakingDim, DUNGEON);
|
||||
}
|
||||
|
||||
public static boolean isDimDoorsPocketDimension(int id) {
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
{
|
||||
"group": "blank",
|
||||
"pockets": [
|
||||
{
|
||||
"id": "blank_pocket_0",
|
||||
"size": 0
|
||||
},
|
||||
{
|
||||
"id": "blank_pocket_1",
|
||||
"size": 1
|
||||
},
|
||||
{
|
||||
"id": "blank_pocket_2",
|
||||
"size": 2
|
||||
},
|
||||
{
|
||||
"id": "blank_pocket_3",
|
||||
"size": 3
|
||||
},
|
||||
{
|
||||
"id": "blank_pocket_4",
|
||||
"size": 4
|
||||
},
|
||||
{
|
||||
"id": "blank_pocket_5",
|
||||
"size": 5
|
||||
},
|
||||
{
|
||||
"id": "blank_pocket_6",
|
||||
"size": 6
|
||||
},
|
||||
{
|
||||
"id": "blank_pocket_7",
|
||||
"size": 7
|
||||
},
|
||||
{
|
||||
"id": "void_pocket_0",
|
||||
"size": 0
|
||||
},
|
||||
{
|
||||
"id": "void_pocket_1",
|
||||
"size": 1
|
||||
},
|
||||
{
|
||||
"id": "void_pocket_2",
|
||||
"size": 2
|
||||
},
|
||||
{
|
||||
"id": "void_pocket_3",
|
||||
"size": 3
|
||||
},
|
||||
{
|
||||
"id": "void_pocket_4",
|
||||
"size": 4
|
||||
},
|
||||
{
|
||||
"id": "void_pocket_5",
|
||||
"size": 5
|
||||
},
|
||||
{
|
||||
"id": "void_pocket_6",
|
||||
"size": 6
|
||||
},
|
||||
{
|
||||
"id": "void_pocket_7",
|
||||
"size": 7
|
||||
}
|
||||
]
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in a new issue