Fix /saveschem and support loading schematics from save folder
This commit is contained in:
parent
9fa97d6ff2
commit
d8d3fa4fc9
6 changed files with 90 additions and 44 deletions
|
@ -2,7 +2,6 @@ package org.dimdev.ddutils.schem;
|
|||
|
||||
import com.flowpowered.math.vector.Vector3i;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import javafx.geometry.BoundingBox;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
|
@ -252,14 +251,12 @@ public class Schematic {
|
|||
return totalString;
|
||||
}
|
||||
|
||||
public static Schematic createFromWorld(String name, String author, World world, Vector3i pos1, Vector3i pos2) {
|
||||
public static Schematic createFromWorld(World world, Vector3i from, Vector3i to) {
|
||||
Schematic schematic = new Schematic();
|
||||
schematic.author = author;
|
||||
schematic.name = name;
|
||||
|
||||
Vector3i min = pos1.min(pos2);
|
||||
Vector3i max = pos1.max(pos2);
|
||||
Vector3i dimensions = max.sub(min);
|
||||
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();
|
||||
|
@ -273,38 +270,50 @@ public class Schematic {
|
|||
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);
|
||||
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));
|
||||
if (id.contains(":")) mods.add(id.split(":")[0]);
|
||||
states.put(state, new BlockPos(x, y, z));
|
||||
|
||||
Optional.ofNullable(world.getTileEntity(pos)).ifPresent(tileEntity -> schematic.tileEntities.add(tileEntity.serializeNBT()));
|
||||
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[0]);
|
||||
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])) {
|
||||
for (BlockPos pos : states.get(keys[i])) {
|
||||
schematic.blockData[pos.getX()][pos.getY()][pos.getZ()] = i;
|
||||
}
|
||||
|
||||
schematic.pallette.add(i, keys[i]);
|
||||
}
|
||||
|
||||
for(Entity entity : world.getEntitiesInAABBexcluding(null, getBoundingBox(pos1, pos2), entity -> !(entity instanceof EntityPlayerMP))) {
|
||||
try {
|
||||
schematic.entities.add(entity.serializeNBT());
|
||||
System.out.println(entity.getName() + " has serialized. Skipping.");
|
||||
} catch (Exception e) {
|
||||
System.out.println(entity.getName() + " has failed to serialize. Skipping.");
|
||||
}
|
||||
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[0]);
|
||||
schematic.requiredMods = mods.toArray(new String[mods.size()]);
|
||||
schematic.paletteMax = keys.length;
|
||||
schematic.creationDate = System.currentTimeMillis();
|
||||
|
||||
|
@ -315,7 +324,7 @@ public class Schematic {
|
|||
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) {
|
||||
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;
|
||||
int[][][] blockData = schematic.blockData;
|
||||
|
@ -375,7 +384,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.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,14 +8,12 @@ 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.Location;
|
||||
import org.dimdev.ddutils.TeleportUtils;
|
||||
import org.dimdev.ddutils.WorldUtils;
|
||||
import org.dimdev.ddutils.schem.Schematic;
|
||||
import org.dimdev.dimdoors.DimDoors;
|
||||
import org.dimdev.dimdoors.shared.pockets.*;
|
||||
import org.dimdev.dimdoors.shared.rifts.TileEntityRift;
|
||||
import org.dimdev.dimdoors.shared.world.ModDimensions;
|
||||
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;
|
||||
|
@ -46,27 +44,27 @@ public class CommandSaveSchem extends CommandBase {
|
|||
@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) {
|
||||
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(ModDimensions.isDimDoorsPocketDimension(player.world)) {
|
||||
player.sendMessage(new TextComponentString("Current Dimension isn't a pocket dimension"));
|
||||
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(args[0], player.getName(), player.world, toVector3i(pocket.getOrigin()), toVector3i(pocket.getOrigin()).add(Vector3i.from(pocket.getSize()*16)));
|
||||
Schematic schematic = Schematic.createFromWorld(player.world, toVector3i(pocket.getOrigin()), toVector3i(pocket.getOrigin()).add(Vector3i.from((pocket.getSize() + 1) * 16)));
|
||||
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.");
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -33,7 +33,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
|
||||
|
@ -71,6 +72,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.");
|
||||
|
@ -202,6 +218,8 @@ public class SchematicHandler {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
nameMap.put(SAVED_POCKETS_GROUP_NAME, new HashMap<>());
|
||||
}
|
||||
|
||||
public Set<String> getTemplateGroups() {
|
||||
|
@ -273,14 +291,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));
|
||||
|
@ -290,5 +308,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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue