diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/structures/StructureNBT.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/structures/StructureNBT.java index fb260309..3b062ac6 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/structures/StructureNBT.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/structures/StructureNBT.java @@ -23,6 +23,12 @@ import com.google.common.collect.Maps; import java.io.IOException; import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.*; +import java.util.HashMap; +import java.util.List; import java.util.Map; import org.jetbrains.annotations.Nullable; @@ -109,6 +115,7 @@ public class StructureNBT { String ns = resource.getNamespace(); String nm = resource.getPath(); + allResourcesFrom(resource); try { InputStream inputstream = MinecraftServer.class.getResourceAsStream("/data/" + ns + "/structures/" + nm + ".nbt"); return readStructureFromStream(inputstream); @@ -119,6 +126,61 @@ public class StructureNBT { return null; } + public static List allResourcesFrom(ResourceLocation resource) { + String ns = resource.getNamespace(); + String nm = resource.getPath(); + + final URL url = MinecraftServer.class.getClassLoader().getResource("data/" + ns + "/structures/" + nm); + if (url != null) { + final URI uri; + try { + uri = url.toURI(); + } catch (URISyntaxException e) { + BCLib.LOGGER.error("Unable to load Resources: ", e); + return null; + } + Path myPath; + if (uri.getScheme().equals("jar")) { + FileSystem fileSystem = null; + try { + fileSystem = FileSystems.newFileSystem(uri, new HashMap<>()); + } catch (IOException e) { + BCLib.LOGGER.error("Unable to load Resources: ", e); + return null; + } + myPath = fileSystem.getPath("/resources"); + } else { + myPath = Paths.get(uri); + } + if (myPath.toFile().isDirectory()) { + try { + return Files.walk(myPath, 1) + .filter(p -> p.toFile().isFile()) + .map(p -> p.getFileName().toFile()) + .filter(f -> f.toString().endsWith(".nbt")) + .map(f -> f.toString()) + .map(s -> new ResourceLocation( + ns, + (nm.isEmpty() ? "" : (nm + "/")) + s.substring(0, s.length() - 4) + )) + .map(r -> { + BCLib.LOGGER.info("Loading Structure: " + r); + try { + return StructureNBT.create(r); + } catch (Exception e) { + BCLib.LOGGER.error("Unable to load Structure " + r, e); + } + return null; + }).toList(); + } catch (IOException e) { + BCLib.LOGGER.error("Unable to load Resources: ", e); + return null; + } + } + } + return null; + } + private static StructureTemplate readStructureFromStream(InputStream stream) throws IOException { CompoundTag nbttagcompound = NbtIo.readCompressed(stream); diff --git a/src/main/java/org/betterx/bclib/commands/PlaceCommand.java b/src/main/java/org/betterx/bclib/commands/PlaceCommand.java index 46a421bf..02c599dd 100644 --- a/src/main/java/org/betterx/bclib/commands/PlaceCommand.java +++ b/src/main/java/org/betterx/bclib/commands/PlaceCommand.java @@ -1,5 +1,6 @@ package org.betterx.bclib.commands; +import de.ambertation.wunderlib.math.Bounds; import de.ambertation.wunderlib.math.Float3; import org.betterx.bclib.api.v2.levelgen.structures.StructureNBT; import org.betterx.bclib.commands.arguments.Float3ArgumentType; @@ -128,6 +129,7 @@ class PlaceCommandBuilder { ) throws CommandSyntaxException; } + // /bclib place nbt betternether:city southOf 0 -59 0 controller protected static int placeNBT( CommandContext ctx, boolean border, @@ -136,18 +138,64 @@ class PlaceCommandBuilder { final ResourceLocation id = ResourceLocationArgument.getId(ctx, PATH); final PlacementDirections searchDir = TemplatePlacementArgument.getPlacement(ctx, PLACEMENT); final BlockInput blockInput = border ? BlockStateArgument.getBlock(ctx, BORDER) : null; - final StructureNBT structureNBT = StructureNBT.create(id); + final BlockPos pos = BlockPosArgument.getLoadedBlockPos(ctx, POS); + var structures = StructureNBT.allResourcesFrom(id); + if (structures != null) { + Bounds b = Bounds.of(pos); + Bounds all = Bounds.of(pos); + BlockPos pNew = pos; + for (var s : structures) { + Bounds bb = Bounds.of(PlaceCommand.placeBlocks( + ctx.getSource(), + pNew, + searchDir.getOffset(), + blockInput, + controlBlocks, + s.location, + (p) -> s.getBoundingBox(p, Rotation.NONE, Mirror.NONE), + (level, p) -> s.generateAt(level, p, Rotation.NONE, Mirror.NONE) + )); + b = b.encapsulate(bb); + all = all.encapsulate(bb); + if (searchDir == PlacementDirections.NORTH_OF || searchDir == PlacementDirections.SOUTH_OF) { + if (b.getSize().z > 10 * 16) { + pNew = new BlockPos((int) b.max.x + 3, pNew.getY(), pNew.getZ()); + b = Bounds.of(pNew); + } + } else if (searchDir == PlacementDirections.EAST_OF || searchDir == PlacementDirections.WEST_OF) { + if (b.getSize().x > 10 * 16) { + pNew = new BlockPos(pNew.getX(), pNew.getY(), (int) b.max.z + 3); + b = Bounds.of(pNew); + } + } else { + if (b.getSize().y > 10 * 16) { + pNew = new BlockPos(pNew.getX(), pNew.getY(), (int) b.max.z + 3); + b = Bounds.of(pNew); + } + } - return PlaceCommand.placeBlocks( - ctx.getSource(), - BlockPosArgument.getLoadedBlockPos(ctx, POS), - searchDir.getOffset(), - blockInput, - controlBlocks, - structureNBT.location, - (p) -> structureNBT.getBoundingBox(p, Rotation.NONE, Mirror.NONE), - (level, p) -> structureNBT.generateAt(level, p, Rotation.NONE, Mirror.NONE) - ); + } + Bounds finalAll = all; + ctx.getSource() + .sendSuccess(() -> Component.literal("Placed " + structures.size() + " NBTs: " + finalAll.toString()) + .setStyle(Style.EMPTY.withColor(ChatFormatting.LIGHT_PURPLE)), true); + + + return 0; + } else { + final StructureNBT structureNBT = StructureNBT.create(id); + + return PlaceCommand.placeBlocks( + ctx.getSource(), + pos, + searchDir.getOffset(), + blockInput, + controlBlocks, + structureNBT.location, + (p) -> structureNBT.getBoundingBox(p, Rotation.NONE, Mirror.NONE), + (level, p) -> structureNBT.generateAt(level, p, Rotation.NONE, Mirror.NONE) + ) == null ? Command.SINGLE_SUCCESS : -1; + } } protected static int placeEmpty( @@ -182,7 +230,7 @@ class PlaceCommandBuilder { ); } } - ); + ) == null ? Command.SINGLE_SUCCESS : -1; } } @@ -320,7 +368,7 @@ public class PlaceCommand { } - static int placeBlocks( + static BoundingBox placeBlocks( CommandSourceStack stack, BlockPos pos, BlockPos searchDir, @@ -340,7 +388,6 @@ public class PlaceCommand { structureBlock ) )) { - pos = pos.offset(searchDir); tries--; } @@ -348,16 +395,19 @@ public class PlaceCommand { if (tries <= 0) { stack.sendFailure(Component.literal("Failed to find free space") .setStyle(Style.EMPTY.withColor(ChatFormatting.RED))); - return -1; + return null; } } final BoundingBox bbNBT = getBounds.apply(pos); + final BoundingBox bb; if (blockInput != null) { - final BoundingBox bb = bbNBT.inflatedBy(1); + bb = bbNBT.inflatedBy(1); outline(stack.getLevel(), bb, blockInput.getState()); stack.sendSuccess(() -> Component.literal("Placed border: " + bb.toString()) .setStyle(Style.EMPTY.withColor(ChatFormatting.GREEN)), true); + } else { + bb = adapt(bbNBT, false, structureBlock); } generate.accept(stack.getLevel(), pos); @@ -369,7 +419,7 @@ public class PlaceCommand { if (structureBlock) { createControlBlocks(stack, location, bbNBT); } - return Command.SINGLE_SUCCESS; + return bb; } }