lazy pocket gen for SchematicGenerator
This commit is contained in:
parent
a3233054f1
commit
6de63151cb
42 changed files with 352 additions and 53 deletions
|
@ -1,8 +1,11 @@
|
|||
package org.dimdev.dimdoors.listener;
|
||||
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.ServerTask;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.world.chunk.WorldChunk;
|
||||
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
|
||||
import org.dimdev.dimdoors.pockets.generator.LazyPocketGenerator;
|
||||
import org.dimdev.dimdoors.world.ModDimensions;
|
||||
import org.dimdev.dimdoors.world.level.DimensionalRegistry;
|
||||
|
@ -18,7 +21,8 @@ public class ChunkLoadListener implements ServerChunkEvents.Load {
|
|||
if (LazyPocketGenerator.currentlyGenerating) {
|
||||
LazyPocketGenerator.generationQueue.add(chunk);
|
||||
} else {
|
||||
((LazyGenerationPocket) pocket).chunkLoaded(chunk);
|
||||
MinecraftServer server = DimensionalDoorsInitializer.getServer();
|
||||
DimensionalDoorsInitializer.getServer().send(new ServerTask(server.getTicks(), () -> ((LazyGenerationPocket) pocket).chunkLoaded(chunk)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
package org.dimdev.dimdoors.pockets;
|
||||
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
|
||||
import org.dimdev.dimdoors.block.entity.RiftBlockEntity;
|
||||
import org.dimdev.dimdoors.util.schematic.v2.Schematic;
|
||||
import org.dimdev.dimdoors.util.schematic.v2.SchematicPlacer;
|
||||
import org.dimdev.dimdoors.world.pocket.type.LazyGenerationPocket;
|
||||
import org.dimdev.dimdoors.world.pocket.type.Pocket;
|
||||
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PocketTemplateV2 {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static final boolean replacingPlaceholders = false;
|
||||
|
@ -61,9 +66,22 @@ public class PocketTemplateV2 {
|
|||
ServerWorld world = DimensionalDoorsInitializer.getWorld(pocket.getWorld());
|
||||
BlockPos origin = pocket.getOrigin();
|
||||
LOGGER.info("Placing new pocket using schematic " + this.id + " at x = " + origin.getX() + ", z = " + origin.getZ());
|
||||
SchematicPlacer.place(this.schematic, world, origin);
|
||||
SchematicPlacer.place(this.schematic, world, origin);
|
||||
}
|
||||
|
||||
public List<RiftBlockEntity> placeRiftsOnly(Pocket pocket) {
|
||||
pocket.setSize(schematic.getWidth(), schematic.getHeight(), schematic.getLength());
|
||||
ServerWorld world = DimensionalDoorsInitializer.getWorld(pocket.getWorld());
|
||||
BlockPos origin = pocket.getOrigin();
|
||||
LOGGER.info("Placing new pocket using schematic " + this.id + " at x = " + origin.getX() + ", z = " + origin.getZ());
|
||||
return SchematicPlacer.placeRiftsOnly(this.schematic, world, origin);
|
||||
}
|
||||
|
||||
public void place(LazyGenerationPocket pocket, Chunk chunk, BlockPos originalOrigin) {
|
||||
BlockPos origin = pocket.getOrigin();
|
||||
SchematicPlacer.place(this.schematic, DimensionalDoorsInitializer.getWorld(pocket.getWorld()), chunk, originalOrigin);
|
||||
}
|
||||
|
||||
public static boolean isReplacingPlaceholders() {
|
||||
return replacingPlaceholders;
|
||||
}
|
||||
|
|
|
@ -71,6 +71,9 @@ public class TemplateUtils {
|
|||
}
|
||||
LootContext ctx = new LootContext.Builder(world).random(world.random).parameter(LootContextParameters.ORIGIN, Vec3d.of(tile.getPos())).build(LootContextTypes.CHEST);
|
||||
table.supplyInventory(inventory, ctx);
|
||||
if (inventory.isEmpty()) {
|
||||
logger.error(", however Inventory is: empty!");
|
||||
}
|
||||
}
|
||||
|
||||
static public void registerRifts(List<? extends RiftBlockEntity> rifts, VirtualTarget linkTo, LinkProperties linkProperties, Pocket pocket) {
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
package org.dimdev.dimdoors.pockets.generator;
|
||||
|
||||
import net.minecraft.block.entity.ChestBlockEntity;
|
||||
import net.minecraft.block.entity.DispenserBlockEntity;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
|
||||
import org.dimdev.dimdoors.pockets.TemplateUtils;
|
||||
import org.dimdev.dimdoors.pockets.modifier.LazyModifier;
|
||||
import org.dimdev.dimdoors.pockets.modifier.Modifier;
|
||||
import org.dimdev.dimdoors.pockets.modifier.RiftManager;
|
||||
|
@ -13,6 +21,8 @@ import java.util.*;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
public abstract class LazyPocketGenerator extends PocketGenerator {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
public static boolean currentlyGenerating = false;
|
||||
public static Queue<Chunk> generationQueue = new LinkedList<>();
|
||||
|
||||
|
@ -60,20 +70,24 @@ public abstract class LazyPocketGenerator extends PocketGenerator {
|
|||
|
||||
@Override
|
||||
public RiftManager getRiftManager(Pocket pocket) {
|
||||
return new RiftManager(pocket, true);
|
||||
if (pocket instanceof LazyGenerationPocket) {
|
||||
return new RiftManager(pocket, true);
|
||||
} else {
|
||||
return new RiftManager(pocket, false);
|
||||
}
|
||||
}
|
||||
|
||||
public void attachLazyModifiers(Collection<LazyModifier> lazyModifiers) {
|
||||
this.lazyModifierList.addAll(lazyModifiers);
|
||||
}
|
||||
|
||||
public LazyPocketGenerator cloneWithLazyModifiers() {
|
||||
LazyPocketGenerator clone = cloneWithEmptyModifiers();
|
||||
public LazyPocketGenerator cloneWithLazyModifiers(BlockPos originalOrigin) {
|
||||
LazyPocketGenerator clone = cloneWithEmptyModifiers(originalOrigin);
|
||||
clone.attachLazyModifiers(this.modifierList.stream().filter(LazyModifier.class::isInstance).map(LazyModifier.class::cast).collect(Collectors.toList()));
|
||||
return clone;
|
||||
}
|
||||
|
||||
public LazyPocketGenerator cloneWithEmptyModifiers() {
|
||||
public LazyPocketGenerator cloneWithEmptyModifiers(BlockPos originalOrigin) {
|
||||
LazyPocketGenerator generator = getNewInstance();
|
||||
|
||||
// Builder/ weight related stuff seems irrelevant here
|
||||
|
@ -82,5 +96,22 @@ public abstract class LazyPocketGenerator extends PocketGenerator {
|
|||
return generator;
|
||||
}
|
||||
|
||||
public void setSetupLoot(Boolean setupLoot) {
|
||||
this.setupLoot = setupLoot;
|
||||
}
|
||||
|
||||
abstract public LazyPocketGenerator getNewInstance();
|
||||
|
||||
public void setupChunk(Pocket pocket, Chunk chunk, boolean setupLootTables) {
|
||||
chunk.getBlockEntityPositions().stream().map(chunk::getBlockEntity).forEach(blockEntity -> { // RiftBlockEntities should already be initialized here
|
||||
if (setupLootTables && blockEntity instanceof Inventory) {
|
||||
Inventory inventory = (Inventory) blockEntity;
|
||||
if (inventory.isEmpty()) {
|
||||
if (blockEntity instanceof ChestBlockEntity || blockEntity instanceof DispenserBlockEntity) {
|
||||
TemplateUtils.setupLootTable(DimensionalDoorsInitializer.getWorld(pocket.getWorld()), blockEntity, inventory, LOGGER);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import net.minecraft.util.math.Vec3i;
|
|||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.util.registry.RegistryKey;
|
||||
import net.minecraft.util.registry.SimpleRegistry;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
|
||||
|
@ -146,8 +147,8 @@ public abstract class PocketGenerator implements Weighted<PocketGenerationParame
|
|||
return this.weightEquation.apply(parameters.toVariableMap(new HashMap<>()));
|
||||
}
|
||||
|
||||
public Boolean getSetupLoot() {
|
||||
return setupLoot;
|
||||
public boolean isSetupLoot() {
|
||||
return setupLoot != null && setupLoot;
|
||||
}
|
||||
|
||||
public void applyModifiers(PocketGenerationParameters parameters, RiftManager manager) {
|
||||
|
|
|
@ -1,23 +1,30 @@
|
|||
package org.dimdev.dimdoors.pockets.generator;
|
||||
|
||||
import net.fabricmc.fabric.api.util.NbtType;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dimdev.dimdoors.block.entity.RiftBlockEntity;
|
||||
import org.dimdev.dimdoors.pockets.PocketTemplateV2;
|
||||
import org.dimdev.dimdoors.pockets.SchematicV2Handler;
|
||||
import org.dimdev.dimdoors.pockets.modifier.RiftManager;
|
||||
import org.dimdev.dimdoors.util.PocketGenerationParameters;
|
||||
import org.dimdev.dimdoors.util.math.Equation;
|
||||
import org.dimdev.dimdoors.util.schematic.v2.Schematic;
|
||||
import org.dimdev.dimdoors.world.level.DimensionalRegistry;
|
||||
import org.dimdev.dimdoors.world.pocket.type.LazyGenerationPocket;
|
||||
import org.dimdev.dimdoors.world.pocket.type.Pocket;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class SchematicGenerator extends PocketGenerator {
|
||||
public class SchematicGenerator extends LazyPocketGenerator{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
public static final String KEY = "schematic";
|
||||
|
||||
|
@ -31,6 +38,8 @@ public class SchematicGenerator extends PocketGenerator {
|
|||
|
||||
private String id;
|
||||
private Identifier templateID;
|
||||
private final List<RiftBlockEntity> rifts = new ArrayList<>();
|
||||
private BlockPos origin;
|
||||
|
||||
public SchematicGenerator() {
|
||||
}
|
||||
|
@ -49,12 +58,26 @@ public class SchematicGenerator extends PocketGenerator {
|
|||
return templateID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateChunk(LazyGenerationPocket pocket, Chunk chunk) {
|
||||
PocketTemplateV2 template = SchematicV2Handler.getInstance().getTemplates().get(templateID);
|
||||
if (template == null) throw new RuntimeException("Pocket template of id " + templateID + " not found!");
|
||||
template.place(pocket, chunk, origin);
|
||||
setupChunk(pocket, chunk, isSetupLoot());
|
||||
|
||||
super.generateChunk(pocket, chunk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PocketGenerator fromTag(CompoundTag tag) {
|
||||
super.fromTag(tag);
|
||||
|
||||
this.id = tag.getString("id");
|
||||
this.id = tag.getString("id"); // TODO: should we force having the "dimdoors:" in the json?
|
||||
this.templateID = new Identifier("dimdoors", id);
|
||||
if (tag.contains("origin", NbtType.INT_ARRAY)) {
|
||||
int[] originInts = tag.getIntArray("origin");
|
||||
this.origin = new BlockPos(originInts[0], originInts[1], originInts[2]);
|
||||
}
|
||||
|
||||
SchematicV2Handler.getInstance().loadSchematic(templateID, id);
|
||||
|
||||
|
@ -66,10 +89,36 @@ public class SchematicGenerator extends PocketGenerator {
|
|||
super.toTag(tag);
|
||||
|
||||
tag.putString("id", this.id);
|
||||
if (origin != null) tag.putIntArray("origin", new int[]{origin.getX(), origin.getY(), origin.getZ()});
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RiftManager getRiftManager(Pocket pocket) {
|
||||
RiftManager manager = super.getRiftManager(pocket);
|
||||
|
||||
rifts.forEach(manager::add);
|
||||
|
||||
return manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LazyPocketGenerator cloneWithEmptyModifiers(BlockPos originalOrigin) {
|
||||
SchematicGenerator generator = (SchematicGenerator) super.cloneWithEmptyModifiers(originalOrigin);
|
||||
|
||||
generator.id = id;
|
||||
generator.templateID = templateID;
|
||||
generator.origin = originalOrigin;
|
||||
|
||||
return generator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LazyPocketGenerator getNewInstance() {
|
||||
return new SchematicGenerator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pocket prepareAndPlacePocket(PocketGenerationParameters parameters, Pocket.PocketBuilder<?, ?> builder) {
|
||||
ServerWorld world = parameters.getWorld();
|
||||
|
@ -81,9 +130,11 @@ public class SchematicGenerator extends PocketGenerator {
|
|||
Pocket pocket = DimensionalRegistry.getPocketDirectory(world.getRegistryKey()).newPocket(builder);
|
||||
LOGGER.info("Generating pocket from template " + template.getId() + " at location " + pocket.getOrigin());
|
||||
|
||||
template.place(pocket);
|
||||
|
||||
pocket.virtualLocation = parameters.getSourceVirtualLocation(); // TODO: this makes very little sense
|
||||
if (pocket instanceof LazyGenerationPocket) {
|
||||
rifts.addAll(template.placeRiftsOnly(pocket));
|
||||
} else {
|
||||
template.place(pocket);
|
||||
}
|
||||
|
||||
return pocket;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.dimdev.dimdoors.pockets.generator;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
@ -79,8 +80,8 @@ public class VoidGenerator extends LazyPocketGenerator {
|
|||
}
|
||||
|
||||
@Override
|
||||
public LazyPocketGenerator cloneWithEmptyModifiers() {
|
||||
VoidGenerator generator = (VoidGenerator) super.cloneWithEmptyModifiers();
|
||||
public LazyPocketGenerator cloneWithEmptyModifiers(BlockPos originalOrigin) {
|
||||
VoidGenerator generator = (VoidGenerator) super.cloneWithEmptyModifiers(originalOrigin);
|
||||
generator.width = width;
|
||||
generator.height = height;
|
||||
generator.length = length;
|
||||
|
|
|
@ -21,6 +21,7 @@ import net.minecraft.world.chunk.Chunk;
|
|||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import org.dimdev.dimdoors.util.BlockBoxUtil;
|
||||
import org.dimdev.dimdoors.util.PocketGenerationParameters;
|
||||
import org.dimdev.dimdoors.util.math.Equation;
|
||||
import org.dimdev.dimdoors.util.schematic.v2.SchematicBlockPalette;
|
||||
|
@ -66,42 +67,42 @@ public class ShellModifier implements LazyModifier {
|
|||
|
||||
// x-planes
|
||||
temp = BlockBox.create(boxToDrawAround.maxX + 1 + boxExpansion, boxToDrawAround.minY - thickness - boxExpansion, boxToDrawAround.minZ - thickness - boxExpansion, boxToDrawAround.maxX + thickness + boxExpansion, boxToDrawAround.maxY + thickness + boxExpansion, boxToDrawAround.maxZ + thickness + boxExpansion);
|
||||
temp = intersection(temp, chunkBox);
|
||||
if (isRealBox(temp)) BlockPos.stream(temp)
|
||||
temp = BlockBoxUtil.intersection(temp, chunkBox);
|
||||
if (BlockBoxUtil.isRealBox(temp)) BlockPos.stream(temp)
|
||||
.forEach(blockPos -> {
|
||||
if(chunk.getBlockState(blockPos).isAir()) chunk.setBlockState(blockPos, blockState, false);
|
||||
});
|
||||
temp = BlockBox.create(boxToDrawAround.minX - 1 - boxExpansion, boxToDrawAround.minY - thickness - boxExpansion, boxToDrawAround.minZ - thickness - boxExpansion, boxToDrawAround.minX - thickness - boxExpansion, boxToDrawAround.maxY + thickness + boxExpansion, boxToDrawAround.maxZ + thickness + boxExpansion);
|
||||
temp = intersection(temp, chunkBox);
|
||||
if (isRealBox(temp)) BlockPos.stream(temp)
|
||||
temp = BlockBoxUtil.intersection(temp, chunkBox);
|
||||
if (BlockBoxUtil.isRealBox(temp)) BlockPos.stream(temp)
|
||||
.forEach(blockPos -> {
|
||||
if(chunk.getBlockState(blockPos).isAir()) chunk.setBlockState(blockPos, blockState, false);
|
||||
});
|
||||
|
||||
// y-planes
|
||||
temp = BlockBox.create(boxToDrawAround.minX - boxExpansion, boxToDrawAround.maxY + 1 + boxExpansion, boxToDrawAround.minZ - thickness - boxExpansion, boxToDrawAround.maxX + boxExpansion, boxToDrawAround.maxY + thickness + boxExpansion, boxToDrawAround.maxZ + thickness + boxExpansion);
|
||||
temp = intersection(temp, chunkBox);
|
||||
if (isRealBox(temp)) BlockPos.stream(temp)
|
||||
temp = BlockBoxUtil.intersection(temp, chunkBox);
|
||||
if (BlockBoxUtil.isRealBox(temp)) BlockPos.stream(temp)
|
||||
.forEach(blockPos -> {
|
||||
if(chunk.getBlockState(blockPos).getBlock() instanceof AirBlock) chunk.setBlockState(blockPos, blockState, false);
|
||||
});
|
||||
temp = BlockBox.create(boxToDrawAround.minX - boxExpansion, boxToDrawAround.minY - 1 - boxExpansion, boxToDrawAround.minZ - thickness - boxExpansion, boxToDrawAround.maxX + boxExpansion, boxToDrawAround.minY - thickness - boxExpansion, boxToDrawAround.maxZ + thickness + boxExpansion);
|
||||
temp = intersection(temp, chunkBox);
|
||||
if (isRealBox(temp)) BlockPos.stream(temp)
|
||||
temp = BlockBoxUtil.intersection(temp, chunkBox);
|
||||
if (BlockBoxUtil.isRealBox(temp)) BlockPos.stream(temp)
|
||||
.forEach(blockPos -> {
|
||||
if(chunk.getBlockState(blockPos).isAir()) chunk.setBlockState(blockPos, blockState, false);
|
||||
});
|
||||
|
||||
// z-planes
|
||||
temp = BlockBox.create(boxToDrawAround.minX - boxExpansion, boxToDrawAround.minY - boxExpansion, boxToDrawAround.minZ - 1 - boxExpansion, boxToDrawAround.maxX + boxExpansion, boxToDrawAround.maxY + boxExpansion, boxToDrawAround.minZ - thickness - boxExpansion);
|
||||
temp = intersection(temp, chunkBox);
|
||||
if (isRealBox(temp)) BlockPos.stream(temp)
|
||||
temp = BlockBoxUtil.intersection(temp, chunkBox);
|
||||
if (BlockBoxUtil.isRealBox(temp)) BlockPos.stream(temp)
|
||||
.forEach(blockPos -> {
|
||||
if(chunk.getBlockState(blockPos).isAir()) chunk.setBlockState(blockPos, blockState, false);
|
||||
});
|
||||
temp = BlockBox.create(boxToDrawAround.minX - boxExpansion, boxToDrawAround.minY - boxExpansion, boxToDrawAround.maxZ + 1 + boxExpansion, boxToDrawAround.maxX + boxExpansion, boxToDrawAround.maxY + boxExpansion, boxToDrawAround.maxZ + thickness + boxExpansion);
|
||||
temp = intersection(temp, chunkBox);
|
||||
if (isRealBox(temp)) BlockPos.stream(temp)
|
||||
temp = BlockBoxUtil.intersection(temp, chunkBox);
|
||||
if (BlockBoxUtil.isRealBox(temp)) BlockPos.stream(temp)
|
||||
.forEach(blockPos -> {
|
||||
if(chunk.getBlockState(blockPos).isAir()) chunk.setBlockState(blockPos, blockState, false);
|
||||
});
|
||||
|
@ -234,13 +235,4 @@ public class ShellModifier implements LazyModifier {
|
|||
return new Layer(tag.getString("block_state"), tag.getString("thickness"));
|
||||
}
|
||||
}
|
||||
|
||||
// intersection might be non real box, check with isRealBox
|
||||
private BlockBox intersection(BlockBox box1, BlockBox box2) {
|
||||
return new BlockBox(Math.max(box1.minX, box2.minX), Math.max(box1.minY, box2.minY), Math.max(box1.minZ, box2.minZ), Math.min(box1.maxX, box2.maxX), Math.min(box1.maxY, box2.maxY), Math.min(box1.maxZ, box2.maxZ));
|
||||
}
|
||||
|
||||
private boolean isRealBox(BlockBox box) {
|
||||
return box.minX <= box.maxX && box.minY <= box.maxY && box.minZ <= box.maxZ;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,13 @@ import java.util.stream.Collectors;
|
|||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import net.fabricmc.fabric.api.util.NbtType;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.ServerTask;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
|
||||
import org.dimdev.dimdoors.pockets.generator.LazyPocketGenerator;
|
||||
import org.dimdev.dimdoors.pockets.generator.PocketGenerator;
|
||||
import org.dimdev.dimdoors.pockets.modifier.LazyModifier;
|
||||
|
@ -131,24 +135,29 @@ public abstract class PocketGeneratorReference extends VirtualSingularPocket {
|
|||
|
||||
LazyPocketGenerator.currentlyGenerating = true;
|
||||
Pocket pocket = generator.prepareAndPlacePocket(parameters, builder);
|
||||
BlockPos originalOrigin = pocket.getOrigin();
|
||||
|
||||
RiftManager manager = generator.getRiftManager(pocket);
|
||||
|
||||
generator.applyModifiers(parameters, manager);
|
||||
|
||||
this.applyModifiers(parameters, manager);
|
||||
generator.setup(pocket, manager, parameters, setupLoot != null ? setupLoot : (generator.getSetupLoot()) != null ? generator.getSetupLoot() : true);
|
||||
generator.setup(pocket, manager, parameters, setupLoot != null ? setupLoot : generator.isSetupLoot());
|
||||
if (pocket instanceof LazyGenerationPocket) {
|
||||
if (!(generator instanceof LazyPocketGenerator)) throw new RuntimeException("pocket was instance of LazyGenerationPocket but generator was not instance of LazyPocketGenerator");
|
||||
LazyGenerationPocket lazyPocket = (LazyGenerationPocket) pocket;
|
||||
LazyPocketGenerator clonedGenerator = ((LazyPocketGenerator) generator).cloneWithLazyModifiers();
|
||||
LazyPocketGenerator clonedGenerator = ((LazyPocketGenerator) generator).cloneWithLazyModifiers(originalOrigin);
|
||||
if (setupLoot != null) clonedGenerator.setSetupLoot(setupLoot);
|
||||
|
||||
attachLazyModifiers(clonedGenerator);
|
||||
clonedGenerator.attachToPocket(lazyPocket);
|
||||
lazyPocket.init();
|
||||
|
||||
LazyPocketGenerator.currentlyGenerating = false;
|
||||
while (!LazyPocketGenerator.generationQueue.isEmpty()) {
|
||||
lazyPocket.chunkLoaded(LazyPocketGenerator.generationQueue.remove());
|
||||
Chunk chunk = LazyPocketGenerator.generationQueue.remove();
|
||||
MinecraftServer server = DimensionalDoorsInitializer.getServer();
|
||||
DimensionalDoorsInitializer.getServer().send(new ServerTask(server.getTicks(), () -> (lazyPocket).chunkLoaded(chunk)));
|
||||
}
|
||||
} else {
|
||||
LazyPocketGenerator.generationQueue.clear();
|
||||
|
|
14
src/main/java/org/dimdev/dimdoors/util/BlockBoxUtil.java
Normal file
14
src/main/java/org/dimdev/dimdoors/util/BlockBoxUtil.java
Normal file
|
@ -0,0 +1,14 @@
|
|||
package org.dimdev.dimdoors.util;
|
||||
|
||||
import net.minecraft.util.math.BlockBox;
|
||||
|
||||
public class BlockBoxUtil {
|
||||
// intersection might be non real box, check with isRealBox
|
||||
public static BlockBox intersection(BlockBox box1, BlockBox box2) {
|
||||
return new BlockBox(Math.max(box1.minX, box2.minX), Math.max(box1.minY, box2.minY), Math.max(box1.minZ, box2.minZ), Math.min(box1.maxX, box2.maxX), Math.min(box1.maxY, box2.maxY), Math.min(box1.maxZ, box2.maxZ));
|
||||
}
|
||||
|
||||
public static boolean isRealBox(BlockBox box) {
|
||||
return box.minX <= box.maxX && box.minY <= box.maxY && box.minZ <= box.maxZ;
|
||||
}
|
||||
}
|
|
@ -2,6 +2,9 @@
|
|||
"type": "dimdoors:schematic",
|
||||
"setup_loot": true,
|
||||
"id": "v2/custom/broken_pillars",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
"type": "dimdoors:schematic",
|
||||
"setup_loot": true,
|
||||
"id": "v2/custom/buggy_top_entry",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/cage_monolithless",
|
||||
"setup_loot": true,
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"layers": [
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/chain_crossing",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/chain_t",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/collapsed_single_tunnel",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/crumbled_hall",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/decaying_chain_tunnel",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/door_totem_ruins",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/exit_cube",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/exit_ruins_with_hidden_door",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/honey_parkour",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/lantredom",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/lantredom_end",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/lantredom_red",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/line_walker",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/mob_prison",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/monolith_cage",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/party",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/returning_eye",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/rising_hand",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/river_road_twin_bridges",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/silverfish_bridge",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
"type": "dimdoors:schematic",
|
||||
"setup_loot": true,
|
||||
"id": "v2/custom/smile_6",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"layers": [
|
||||
|
@ -17,8 +20,5 @@
|
|||
"ids": [0],
|
||||
"rift_data": "rift_data/pocket_entrance"
|
||||
}
|
||||
],
|
||||
"offset_x": "1",
|
||||
"offset_y": "1",
|
||||
"offset_z": "1"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/stone_brick_bridge",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
"type": "dimdoors:schematic",
|
||||
"setup_loot": true,
|
||||
"id": "v2/custom/trap_rib_tunnel",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/upwards_pillars",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/upwards_t_treasure",
|
||||
"setup_loot": true,
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/waiting_room",
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
"type": "dimdoors:schematic",
|
||||
"id": "v2/custom/white_fabric_maze",
|
||||
"setup_loot": true,
|
||||
"builder": {
|
||||
"type": "dimdoors:lazy_gen_pocket"
|
||||
},
|
||||
"modifiers": [
|
||||
{
|
||||
"type": "dimdoors:rift_data",
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
package org.dimdev.dimdoors.util.schematic.v2;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.google.common.collect.ImmutableBiMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.util.math.*;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import org.dimdev.dimdoors.block.entity.RiftBlockEntity;
|
||||
import org.dimdev.dimdoors.util.BlockBoxUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockEntityProvider;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
|
@ -21,8 +20,6 @@ import net.minecraft.fluid.FluidState;
|
|||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.NbtOps;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.ModifiableWorld;
|
||||
import net.minecraft.world.StructureWorldAccess;
|
||||
|
@ -131,6 +128,71 @@ public class RelativeBlockSample implements BlockView, ModifiableWorld {
|
|||
}
|
||||
}
|
||||
|
||||
public void place(BlockPos origin, StructureWorldAccess world, Chunk chunk, boolean biomes) {
|
||||
ChunkPos pos = chunk.getPos();
|
||||
BlockBox chunkBox = BlockBox.create(pos.getStartX(), chunk.getBottomY(), pos.getStartZ(), pos.getEndX(), chunk.getTopY(), pos.getEndZ());
|
||||
BlockBox schemBox = BlockBox.create(origin.getX(), origin.getY(), origin.getZ(), origin.getX() + schematic.getWidth() - 1, origin.getY() + schematic.getHeight() - 1, origin.getZ() + schematic.getLength() - 1);
|
||||
BlockBox intersection = BlockBoxUtil.intersection(chunkBox, schemBox);
|
||||
if (!BlockBoxUtil.isRealBox(intersection)) return;
|
||||
|
||||
BlockPos.stream(intersection).forEach(blockPos -> {
|
||||
if(chunk.getBlockState(blockPos).isAir()) chunk.setBlockState(blockPos, this.blockContainer.get(blockPos.subtract(origin)), false);
|
||||
});
|
||||
|
||||
// TODO: depending on size of blockEntityContainer it might be faster to iterate over BlockPos.stream(intersection) instead
|
||||
this.blockEntityContainer.forEach((blockPos, tag) -> {
|
||||
BlockPos actualPos = blockPos.add(origin);
|
||||
if (intersection.contains(actualPos)) {
|
||||
if(tag.contains("Id")) {
|
||||
tag.put("id", tag.get("Id")); // boogers
|
||||
tag.remove("Id");
|
||||
}
|
||||
|
||||
BlockEntity blockEntity = BlockEntity.createFromTag(actualPos, this.getBlockState(blockPos), tag);
|
||||
if (blockEntity != null && !(blockEntity instanceof RiftBlockEntity)) {
|
||||
chunk.setBlockEntity(blockEntity);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.entityContainer.forEach(((tag, vec3d) -> {
|
||||
ListTag doubles = tag.getList("Pos", NbtType.DOUBLE);
|
||||
Vec3d vec = vec3d.add(origin.getX(), origin.getY(), origin.getZ());
|
||||
if (intersection.contains(new Vec3i(vec.x, vec.y, vec.z))) {
|
||||
doubles.set(0, NbtOps.INSTANCE.createDouble(vec.x));
|
||||
doubles.set(1, NbtOps.INSTANCE.createDouble(vec.y));
|
||||
doubles.set(2, NbtOps.INSTANCE.createDouble(vec.z));
|
||||
tag.put("Pos", doubles);
|
||||
|
||||
Entity entity = EntityType.getEntityFromTag(tag, world.toServerWorld()).orElseThrow(NoSuchElementException::new);
|
||||
world.spawnEntity(entity);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public List<RiftBlockEntity> placeRiftsOnly(BlockPos origin, StructureWorldAccess world) {
|
||||
List<RiftBlockEntity> rifts = new ArrayList<>();
|
||||
this.blockEntityContainer.forEach( (blockPos, tag) -> {
|
||||
BlockPos actualPos = origin.add(blockPos);
|
||||
|
||||
if(tag.contains("Id")) {
|
||||
tag.put("id", tag.get("Id")); // boogers
|
||||
tag.remove("Id");
|
||||
}
|
||||
BlockState state = getBlockState(blockPos);
|
||||
BlockEntity blockEntity = BlockEntity.createFromTag(actualPos, state, tag);
|
||||
if (blockEntity instanceof RiftBlockEntity) {
|
||||
world.setBlockState(actualPos, state, 0);
|
||||
if (state.getBlock() instanceof DoorBlock) {
|
||||
world.setBlockState(actualPos.up(), getBlockState(blockPos.up()), 0);
|
||||
}
|
||||
world.toServerWorld().addBlockEntity(blockEntity);
|
||||
rifts.add((RiftBlockEntity) blockEntity);
|
||||
}
|
||||
});
|
||||
return rifts;
|
||||
}
|
||||
|
||||
public int[][][] getBlockData() {
|
||||
return this.blockData;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.util.List;
|
|||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
|
@ -17,6 +18,7 @@ import net.minecraft.util.math.BlockPos;
|
|||
import net.minecraft.world.StructureWorldAccess;
|
||||
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import org.dimdev.dimdoors.block.entity.RiftBlockEntity;
|
||||
|
||||
public final class SchematicPlacer {
|
||||
public static final Logger LOGGER = LogManager.getLogger();
|
||||
|
@ -35,6 +37,30 @@ public final class SchematicPlacer {
|
|||
blockSample.place(origin, world, false);
|
||||
}
|
||||
|
||||
public static List<RiftBlockEntity> placeRiftsOnly(Schematic schematic, StructureWorldAccess world, BlockPos origin) {
|
||||
LOGGER.debug("Placing schematic rifts only: {}", schematic.getMetadata().getName());
|
||||
for (String id : schematic.getMetadata().getRequiredMods()) {
|
||||
if (!FabricLoader.getInstance().isModLoaded(id)) {
|
||||
LOGGER.warn("Schematic \"" + schematic.getMetadata().getName() + "\" depends on mod \"" + id + "\", which is missing!");
|
||||
}
|
||||
}
|
||||
RelativeBlockSample blockSample = Schematic.getBlockSample(schematic);
|
||||
return blockSample.placeRiftsOnly(origin, world);
|
||||
}
|
||||
|
||||
public static void place(Schematic schematic, StructureWorldAccess world, Chunk chunk, BlockPos origin) {
|
||||
LOGGER.debug("Placing schematic: {}", schematic.getMetadata().getName());
|
||||
for (String id : schematic.getMetadata().getRequiredMods()) {
|
||||
if (!FabricLoader.getInstance().isModLoaded(id)) {
|
||||
LOGGER.warn("Schematic \"" + schematic.getMetadata().getName() + "\" depends on mod \"" + id + "\", which is missing!");
|
||||
}
|
||||
}
|
||||
RelativeBlockSample blockSample = Schematic.getBlockSample(schematic);
|
||||
blockSample.place(origin, world, chunk, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static int[][][] getBlockData(Schematic schematic) {
|
||||
int width = schematic.getWidth();
|
||||
int height = schematic.getHeight();
|
||||
|
|
Loading…
Reference in a new issue