Skip to content

Commit

Permalink
initial sponge schematic v2 format loader
Browse files Browse the repository at this point in the history
  • Loading branch information
mcmonkey4eva committed Oct 14, 2019
1 parent 3f66ba0 commit 5deed93
Show file tree
Hide file tree
Showing 8 changed files with 216 additions and 48 deletions.
Expand Up @@ -68,4 +68,22 @@ default float getBlockStength(Material mat) {
default void setBlockStrength(Material mat, float strength) {
throw new UnsupportedOperationException();
}

default ModernBlockData parseBlockData(String text) {
int openBracket = text.indexOf('[');
String material = text;
String otherData = null;
if (openBracket > 0) {
material = text.substring(0, openBracket);
otherData = text.substring(openBracket);
}
if (material.startsWith("minecraft:")) {
material = material.substring("minecraft:".length());
}
return parseBlockData(Material.getMaterial(material.toUpperCase()), otherData);
}

default ModernBlockData parseBlockData(Material material, String otherData) {
throw new UnsupportedOperationException();
}
}
Expand Up @@ -4,6 +4,7 @@
import com.denizenscript.denizen.utilities.Utilities;
import com.denizenscript.denizen.utilities.blocks.CuboidBlockSet;
import com.denizenscript.denizen.utilities.blocks.MCEditSchematicHelper;
import com.denizenscript.denizen.utilities.blocks.SpongeSchematicHelper;
import com.denizenscript.denizen.utilities.debugging.Debug;
import com.denizenscript.denizen.nms.interfaces.BlockData;
import com.denizenscript.denizen.objects.CuboidTag;
Expand Down Expand Up @@ -55,6 +56,8 @@ public class SchematicCommand extends AbstractCommand implements Holdable, Liste
// For 'save', 'load', and 'rotate', this processes async to prevent server lockup.
// For 'paste' and 'create', this delays how many blocks can be processed at once, spread over many ticks.
//
// The "load" option by default will load '.schem' files. If no '.schem' file is available, will attempt to load a legacy '.schematic' file instead.
//
// @Tags
// <schematic[<name>].height>
// <schematic[<name>].length>
Expand Down Expand Up @@ -236,19 +239,29 @@ public void execute(final ScriptEntry scriptEntry) {
return;
}
String directory = URLDecoder.decode(System.getProperty("user.dir"));
File f = new File(directory + "/plugins/Denizen/schematics/" + fname + ".schematic");
File f = new File(directory + "/plugins/Denizen/schematics/" + fname + ".schem");
if (!Utilities.canReadFile(f)) {
Debug.echoError("Server config denies reading files in that location.");
return;
}
if (!f.exists()) {
Debug.echoError("Schematic file " + fname + " does not exist. Are you sure it's in " + directory + "/plugins/Denizen/schematics/?");
return;
f = new File(directory + "/plugins/Denizen/schematics/" + fname + ".schematic");
if (!f.exists()) {
Debug.echoError("Schematic file " + fname + " does not exist. Are you sure it's in " + directory + "/plugins/Denizen/schematics/?");
return;
}
}
File schemFile = f;
Runnable loadRunnable = () -> {
try {
InputStream fs = new FileInputStream(f);
CuboidBlockSet newSet = MCEditSchematicHelper.fromMCEditStream(fs);
InputStream fs = new FileInputStream(schemFile);
CuboidBlockSet newSet;
if (schemFile.getName().endsWith(".schem")) {
newSet = SpongeSchematicHelper.fromSpongeStream(fs);
}
else {
newSet = MCEditSchematicHelper.fromMCEditStream(fs);
}
fs.close();
Bukkit.getScheduler().runTask(DenizenAPI.getCurrentInstance(), () -> {
schematics.put(name.asString().toUpperCase(), newSet);
Expand Down Expand Up @@ -536,7 +549,7 @@ public void schematicTags(ReplaceableTagEvent event) {
// Returns the number of blocks in the schematic.
// -->
if (attribute.startsWith("blocks")) {
event.setReplaced(new ElementTag(set.blocks.size())
event.setReplaced(new ElementTag(set.blocks.length)
.getAttribute(attribute.fulfill(1)));
return;
}
Expand Down
Expand Up @@ -3,11 +3,9 @@
import com.denizenscript.denizen.nms.interfaces.BlockData;
import org.bukkit.Location;

import java.util.List;

public interface BlockSet {

List<BlockData> getBlocks();
BlockData[] getBlocks();

void setBlocksDelayed(Location loc, Runnable runme, boolean noAir);

Expand Down
Expand Up @@ -9,9 +9,6 @@
import org.bukkit.Material;
import org.bukkit.scheduler.BukkitRunnable;

import java.util.ArrayList;
import java.util.List;

public class CuboidBlockSet implements BlockSet {

public CuboidBlockSet() {
Expand All @@ -20,16 +17,18 @@ public CuboidBlockSet() {
public CuboidBlockSet(CuboidTag cuboid, Location center) {
Location low = cuboid.pairs.get(0).low;
Location high = cuboid.pairs.get(0).high;
x_width = (high.getX() - low.getX()) + 1;
y_length = (high.getY() - low.getY()) + 1;
z_height = (high.getZ() - low.getZ()) + 1;
x_width = (int) ((high.getX() - low.getX()) + 1);
y_length = (int) ((high.getY() - low.getY()) + 1);
z_height = (int) ((high.getZ() - low.getZ()) + 1);
center_x = center.getX() - low.getX();
center_y = center.getY() - low.getY();
center_z = center.getZ() - low.getZ();
blocks = new BlockData[(int) (x_width * y_length * z_height)];
int index = 0;
for (int x = 0; x < x_width; x++) {
for (int y = 0; y < y_length; y++) {
for (int z = 0; z < z_height; z++) {
blocks.add(NMSHandler.getBlockHelper().getBlockData(low.clone().add(x, y, z).getBlock()));
blocks[index++] = NMSHandler.getBlockHelper().getBlockData(low.clone().add(x, y, z).getBlock());
}
}
}
Expand All @@ -38,23 +37,23 @@ public CuboidBlockSet(CuboidTag cuboid, Location center) {
public void buildDelayed(CuboidTag cuboid, Location center, Runnable runme) {
Location low = cuboid.pairs.get(0).low;
Location high = cuboid.pairs.get(0).high;
x_width = (high.getX() - low.getX()) + 1;
y_length = (high.getY() - low.getY()) + 1;
z_height = (high.getZ() - low.getZ()) + 1;
x_width = (int) ((high.getX() - low.getX()) + 1);
y_length = (int) ((high.getY() - low.getY()) + 1);
z_height = (int) ((high.getZ() - low.getZ()) + 1);
center_x = center.getX() - low.getX();
center_y = center.getY() - low.getY();
center_z = center.getZ() - low.getZ();
final long goal = (long) (x_width * y_length * z_height);
new BukkitRunnable() {
int index;
int index = 0;
@Override
public void run() {
long start = System.currentTimeMillis();
while (index < goal) {
long z = index % ((long) (z_height));
long y = ((index - z) % ((long) (y_length * z_height))) / ((long) z_height);
long x = (index - y - z) / ((long) (y_length * z_height));
blocks.add(NMSHandler.getBlockHelper().getBlockData(low.clone().add(x, y, z).getBlock()));
blocks[index] = NMSHandler.getBlockHelper().getBlockData(low.clone().add(x, y, z).getBlock());
index++;
if (System.currentTimeMillis() - start > 50) {
SchematicCommand.noPhys = false;
Expand All @@ -70,13 +69,13 @@ public void run() {
}.runTaskTimer(DenizenAPI.getCurrentInstance(), 1, 1);
}

public List<BlockData> blocks = new ArrayList<>();
public BlockData[] blocks = null;

public double x_width;
public int x_width;

public double y_length;
public int y_length;

public double z_height;
public int z_height;

public double center_x;

Expand All @@ -85,7 +84,7 @@ public void run() {
public double center_z;

@Override
public List<BlockData> getBlocks() {
public BlockData[] getBlocks() {
return blocks;
}

Expand All @@ -108,8 +107,8 @@ public void run() {
long z = index % ((long) (z_height));
long y = ((index - z) % ((long) (y_length * z_height))) / ((long) z_height);
long x = (index - y - z) / ((long) (y_length * z_height));
if (!noAir || blocks.get(index).getMaterial() != Material.AIR) {
blocks.get(index).setBlock(loc.clone().add(x - center_x, y - center_y, z - center_z).getBlock(), false);
if (!noAir || blocks[index].getMaterial() != Material.AIR) {
blocks[index].setBlock(loc.clone().add(x - center_x, y - center_y, z - center_z).getBlock(), false);
}
index++;
if (System.currentTimeMillis() - start > 50) {
Expand All @@ -134,8 +133,8 @@ public void setBlocks(Location loc, boolean noAir) {
for (int x = 0; x < x_width; x++) {
for (int y = 0; y < y_length; y++) {
for (int z = 0; z < z_height; z++) {
if (!noAir || blocks.get(index).getMaterial() != Material.AIR) {
blocks.get(index).setBlock(loc.clone().add(x - center_x, y - center_y, z - center_z).getBlock(), false);
if (!noAir || blocks[index].getMaterial() != Material.AIR) {
blocks[index].setBlock(loc.clone().add(x - center_x, y - center_y, z - center_z).getBlock(), false);
}
index++;
}
Expand All @@ -145,64 +144,68 @@ public void setBlocks(Location loc, boolean noAir) {
}

public void rotateOne() {
List<BlockData> bd = new ArrayList<>();
BlockData[] bd = new BlockData[blocks.length];
int index = 0;
double cx = center_x;
center_x = center_z;
center_z = cx;
for (int x = 0; x < z_height; x++) {
for (int y = 0; y < y_length; y++) {
for (int z = (int) x_width - 1; z >= 0; z--) {
bd.add(blockAt(z, y, x));
bd[index++] = blockAt(z, y, x);
}
}
}
double xw = x_width;
int xw = x_width;
x_width = z_height;
z_height = xw;
blocks = bd;
}

public void flipX() {
List<BlockData> bd = new ArrayList<>();
BlockData[] bd = new BlockData[blocks.length];
int index = 0;
center_x = x_width - center_x;
for (int x = (int) x_width - 1; x >= 0; x--) {
for (int y = 0; y < y_length; y++) {
for (int z = 0; z < z_height; z++) {
bd.add(blockAt(x, y, z));
bd[index++] = blockAt(x, y, z);
}
}
}
blocks = bd;
}

public void flipY() {
List<BlockData> bd = new ArrayList<>();
BlockData[] bd = new BlockData[blocks.length];
int index = 0;
center_x = x_width - center_x;
for (int x = 0; x < x_width; x++) {
for (int y = (int) y_length - 1; y >= 0; y--) {
for (int z = 0; z < z_height; z++) {
bd.add(blockAt(x, y, z));
bd[index++] = blockAt(x, y, z);
}
}
}
blocks = bd;
}

public void flipZ() {
List<BlockData> bd = new ArrayList<>();
BlockData[] bd = new BlockData[blocks.length];
int index = 0;
center_x = x_width - center_x;
for (int x = 0; x < x_width; x++) {
for (int y = 0; y < y_length; y++) {
for (int z = (int) z_height - 1; z >= 0; z--) {
bd.add(blockAt(x, y, z));
bd[index++] = blockAt(x, y, z);
}
}
}
blocks = bd;
}

public BlockData blockAt(double X, double Y, double Z) {
return blocks.get((int) (Z + Y * z_height + X * z_height * y_length));
return blocks[(int) (Z + Y * z_height + X * z_height * y_length)];
// This calculation should produce the same result as the below nonsense:
/*
int index = 0;
Expand Down
Expand Up @@ -6,7 +6,6 @@
import com.denizenscript.denizen.objects.MaterialTag;
import com.denizenscript.denizen.utilities.debugging.Debug;
import org.bukkit.util.BlockVector;
import org.bukkit.util.Vector;

import java.io.InputStream;
import java.io.OutputStream;
Expand Down Expand Up @@ -107,20 +106,19 @@ else if (entry.getKey().equals("z")) {
BlockVector vec = new BlockVector(x, y, z);
tileEntitiesMap.put(vec, values);
}
org.bukkit.util.Vector vec = new Vector(width, height, length);
int finalIndex = 0;
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
for (int z = 0; z < length; z++) {
int index = y * width * length + z * width + x;
BlockVector pt = new BlockVector(x, y, z);
// TODO: 1.13 - move away from legacy IDs somehow?
MaterialTag dMat = OldMaterialsHelper.getMaterialFrom(OldMaterialsHelper.getLegacyMaterial(blocks[index]), blockData[index]);
BlockData block = dMat.getNmsBlockData();
if (tileEntitiesMap.containsKey(pt)) {
CompoundTag otag = NMSHandler.getInstance().createCompoundTag(tileEntitiesMap.get(pt));
block.setCompoundTag(otag);
}
cbs.blocks.add(block);
cbs.blocks[finalIndex++] = block;
}
}
}
Expand All @@ -131,8 +129,7 @@ else if (entry.getKey().equals("z")) {
return cbs;
}

private static <T extends Tag> T getChildTag(Map<String, Tag> items, String key,
Class<T> expected) throws Exception {
private static <T extends Tag> T getChildTag(Map<String, Tag> items, String key, Class<T> expected) throws Exception {
if (!items.containsKey(key)) {
throw new Exception("Schematic file is missing a '" + key + "' tag");
}
Expand Down Expand Up @@ -169,7 +166,7 @@ public static void saveMCEditFormatToStream(CuboidBlockSet blockSet, OutputStrea
for (int y = 0; y < blockSet.y_length; y++) {
for (int z = 0; z < blockSet.z_height; z++) {
int index = (int) (y * (blockSet.x_width) * (blockSet.z_height) + z * (blockSet.x_width) + x);
BlockData bd = blockSet.blocks.get(indexer);//blockAt(x, y, z);
BlockData bd = blockSet.blocks[indexer];//blockAt(x, y, z);
indexer++;
int matId = NMSHandler.getBlockHelper().idFor(bd.getMaterial());
if (matId > 255) {
Expand All @@ -189,7 +186,6 @@ public static void saveMCEditFormatToStream(CuboidBlockSet blockSet, OutputStrea
for (Map.Entry<String, Tag> entry : rawTag.getValue().entrySet()) {
values.put(entry.getKey(), entry.getValue());
}
// TODO: ??? -> values.put("id", new StringTag(null)); // block.getNbtId()
values.put("x", new IntTag(x));
values.put("y", new IntTag(y));
values.put("z", new IntTag(z));
Expand Down

0 comments on commit 5deed93

Please sign in to comment.