diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..ab8c3f8 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,35 @@ +on: + push: + paths: + - 'src/**' + - 'pom.xml' + pull_request: + paths: + - 'src/**' + - 'pom.xml' + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - id: vars + run: | + echo "JAVA=$(mvn help:evaluate -Dexpression=maven.compiler.release -q -DforceStdout)" >> "$GITHUB_OUTPUT" + echo "VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" >> "$GITHUB_OUTPUT" + - uses: actions/setup-java@v5 + with: + distribution: liberica + java-version: ${{ steps.vars.outputs.JAVA }} + - run: ./src/build/scripts/TestCode.sh + - run: mvn -B package -DskipTests + - uses: actions/upload-artifact@v7 + with: + name: wlib-${{ steps.vars.outputs.VERSION }} + path: target/wlib-${{ steps.vars.outputs.VERSION }}.jar + if-no-files-found: error diff --git a/.gitignore b/.gitignore index 9aefad5..4b3f348 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ **/.DS_Store -/dependency-reduced-pom.xml \ No newline at end of file +/dependency-reduced-pom.xml + +.vscode \ No newline at end of file diff --git a/src/build/scripts/TestCode.bat b/src/build/scripts/TestCode.bat new file mode 100644 index 0000000..76feb23 --- /dev/null +++ b/src/build/scripts/TestCode.bat @@ -0,0 +1,2 @@ +@echo off +mvn test %* diff --git a/src/build/scripts/TestCode.sh b/src/build/scripts/TestCode.sh new file mode 100755 index 0000000..dd05d8f --- /dev/null +++ b/src/build/scripts/TestCode.sh @@ -0,0 +1 @@ +mvn test $@ diff --git a/src/main/java/xyz/webmc/wlib/api/command/WCommand.java b/src/main/java/xyz/webmc/wlib/api/command/WCommand.java index 31bf1d9..c92eb6b 100644 --- a/src/main/java/xyz/webmc/wlib/api/command/WCommand.java +++ b/src/main/java/xyz/webmc/wlib/api/command/WCommand.java @@ -67,11 +67,11 @@ public final void sendPermissionMessage(CommandSender sender, String alias) { } public final void sendUsageMessage(CommandSender sender) { - sendUsageMessage(sender, ""); + this.sendUsageMessage(sender, ""); } public final void sendPermissionMessage(CommandSender sender) { - sendPermissionMessage(sender, ""); + this.sendPermissionMessage(sender, ""); } protected final boolean checkIsPlayer(CommandSender sender) { @@ -92,6 +92,27 @@ protected final boolean checkHasPermission(CommandSender sender, String perm) { } } + public static void sendUnknownCommandMessage(CommandSender sender) { + boolean bool = true; + + final Class clazz = MirrorSafe.getClass("org.spigotmc.SpigotConfig"); + if (clazz != null) { + final String msg = MirrorSafe.getFieldValue(clazz, "unknownCommandMessage"); + if (msg != null) { + sender.sendMessage(msg); + bool = false; + } + } + + if (bool) { + sender.sendMessage(ChatColor.RED + "Unknown command."); + } + } + + public static void sendOnlyPlayersMessage(CommandSender sender) { + sender.sendMessage(ChatColor.RED + "This command can only be used by players."); + } + private void showStack(CommandSender sender, Throwable t) { final String stack = ExceptionStacker.getFullStackString(t); @@ -121,25 +142,4 @@ private String replaceUsedAlias(String str, String alias) { return str; } } - - public static void sendUnknownCommandMessage(CommandSender sender) { - boolean bool = true; - - final Class clazz = MirrorSafe.getClass("org.spigotmc.SpigotConfig"); - if (clazz != null) { - final String msg = MirrorSafe.getFieldValue(clazz, "unknownCommandMessage"); - if (msg != null) { - sender.sendMessage(msg); - bool = false; - } - } - - if (bool) { - sender.sendMessage(ChatColor.RED + "Unknown command."); - } - } - - public static void sendOnlyPlayersMessage(CommandSender sender) { - sender.sendMessage(ChatColor.RED + "This command can only be used by players."); - } } diff --git a/src/main/java/xyz/webmc/wlib/api/structure/AbsoluteStructure.java b/src/main/java/xyz/webmc/wlib/api/structure/AbsoluteStructure.java new file mode 100644 index 0000000..0f1a55c --- /dev/null +++ b/src/main/java/xyz/webmc/wlib/api/structure/AbsoluteStructure.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2026 Colbster937 + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * See the LICENSE file for details. + */ + +package xyz.webmc.wlib.api.structure; + +import xyz.webmc.wlib.api.structure.placeable.AbsolutePlaceableStructure; + +import org.bukkit.Location; + +public abstract class AbsoluteStructure implements BaseStructure { + public abstract AbsolutePlaceableStructure build(Location loc); + + @Override + public final void place(Location loc, Object... chunks) { + if (chunks.length > 0) { + final AbsolutePlaceableStructure builder = this.build(loc); + for (Object chk: chunks){ + builder.place(chk); + } + } else { + this.build(loc).place(); + } + } +} diff --git a/src/main/java/xyz/webmc/wlib/api/structure/AbstractBaseSchemStructure.java b/src/main/java/xyz/webmc/wlib/api/structure/AbstractBaseSchemStructure.java index b64ece7..5fac7f6 100644 --- a/src/main/java/xyz/webmc/wlib/api/structure/AbstractBaseSchemStructure.java +++ b/src/main/java/xyz/webmc/wlib/api/structure/AbstractBaseSchemStructure.java @@ -13,14 +13,20 @@ package xyz.webmc.wlib.api.structure; +import xyz.webmc.wlib.api.WLIB; + import java.io.IOException; import java.io.InputStream; import net.sandrohc.schematic4j.exception.ParsingException; +@SuppressWarnings({ "removal" }) +@Deprecated(forRemoval = true) public abstract class AbstractBaseSchemStructure extends AbstractBaseStructure { + @Deprecated(forRemoval = true) public AbstractBaseSchemStructure(String name, String resource) throws IOException, ParsingException { super(name); + WLIB.warnDeprecatedUsage(); try (InputStream is = this.getClass().getResourceAsStream(resource)) { super.loadSchematic(is); diff --git a/src/main/java/xyz/webmc/wlib/api/structure/AbstractBaseStructure.java b/src/main/java/xyz/webmc/wlib/api/structure/AbstractBaseStructure.java index 087644b..80e63f3 100644 --- a/src/main/java/xyz/webmc/wlib/api/structure/AbstractBaseStructure.java +++ b/src/main/java/xyz/webmc/wlib/api/structure/AbstractBaseStructure.java @@ -13,10 +13,8 @@ package xyz.webmc.wlib.api.structure; -import xyz.webmc.wlib.api.structure.block.BlockRelative; -import xyz.webmc.wlib.api.structure.iface.TestStructure; +import xyz.webmc.wlib.api.WLIB; import xyz.webmc.wlib.api.util.SchemUtil; -import xyz.webmc.wlib.internal.util.TestStructureUtil; import java.io.File; import java.io.FileInputStream; @@ -35,45 +33,62 @@ import net.sandrohc.schematic4j.schematic.types.SchematicBlockPos; import org.bukkit.Location; -@SuppressWarnings({ "unchecked" }) +@SuppressWarnings({ "unchecked", "removal" }) +@Deprecated(forRemoval = true) public abstract class AbstractBaseStructure { private static final Map, AbstractBaseStructure> INSTANCES = new HashMap<>(); private final List blocks = new ArrayList<>(); private final String name; + @Deprecated(forRemoval = true) protected AbstractBaseStructure(String name) { + WLIB.warnDeprecatedUsage(); this.name = name; } + @Deprecated(forRemoval = true) public final void place(Location loc) { + WLIB.warnDeprecatedUsage(); final Location offset = loc.clone().add(this.getOffsetX(), this.getOffsetY(), this.getOffsetZ()); for (BlockRelative blk : blocks) { blk.place(offset); } } + @Deprecated(forRemoval = true) public final String getName() { + WLIB.warnDeprecatedUsage(); return this.name; } + @Deprecated(forRemoval = true) public int getOffsetX() { + WLIB.warnDeprecatedUsage(); return 0; } + @Deprecated(forRemoval = true) public int getOffsetY() { + WLIB.warnDeprecatedUsage(); return 0; } + @Deprecated(forRemoval = true) public int getOffsetZ() { + WLIB.warnDeprecatedUsage(); return 0; } + @Deprecated(forRemoval = true) protected final void addBlock(BlockRelative blk) { + WLIB.warnDeprecatedUsage(); this.blocks.add(blk); } + @Deprecated(forRemoval = true) protected final void loadSchematic(InputStream is) throws IOException, ParsingException { + WLIB.warnDeprecatedUsage(); try (is) { final Schematic schematic = SchemUtil.readSchematic(is); @@ -111,19 +126,20 @@ protected final void loadSchematic(InputStream is) throws IOException, ParsingEx } } + @Deprecated(forRemoval = true) protected final void loadSchematic(File file) throws IOException, ParsingException { + WLIB.warnDeprecatedUsage(); loadSchematic(new FileInputStream(file)); } - public static T getInstance(Class clazz, Object... params) { + @Deprecated(forRemoval = true) + public static final T getInstance(Class clazz, Object... params) { + WLIB.warnDeprecatedUsage(); AbstractBaseStructure structure = INSTANCES.get(clazz); if (structure == null) { structure = MirrorSafe.invokeConstructor(clazz, params); INSTANCES.put(clazz, structure); - if (structure instanceof TestStructure) { - TestStructureUtil.register(structure); - } } return (T) structure; diff --git a/src/main/java/xyz/webmc/wlib/api/structure/iface/TestStructure.java b/src/main/java/xyz/webmc/wlib/api/structure/BaseStructure.java similarity index 63% rename from src/main/java/xyz/webmc/wlib/api/structure/iface/TestStructure.java rename to src/main/java/xyz/webmc/wlib/api/structure/BaseStructure.java index f83ebf2..a682987 100644 --- a/src/main/java/xyz/webmc/wlib/api/structure/iface/TestStructure.java +++ b/src/main/java/xyz/webmc/wlib/api/structure/BaseStructure.java @@ -11,7 +11,14 @@ * See the LICENSE file for details. */ -package xyz.webmc.wlib.api.structure.iface; +package xyz.webmc.wlib.api.structure; -public interface TestStructure { +import org.bukkit.Location; + +public interface BaseStructure { + void place(Location loc, Object... chunks); + + default String getName() { + return this.getClass().getSimpleName(); + } } diff --git a/src/main/java/xyz/webmc/wlib/api/structure/BlockRelative.java b/src/main/java/xyz/webmc/wlib/api/structure/BlockRelative.java index 48245ac..fb2347f 100644 --- a/src/main/java/xyz/webmc/wlib/api/structure/BlockRelative.java +++ b/src/main/java/xyz/webmc/wlib/api/structure/BlockRelative.java @@ -13,40 +13,131 @@ package xyz.webmc.wlib.api.structure; +import xyz.webmc.wlib.api.WLIB; + import com.cryptomorin.xseries.XMaterial; +import dev.colbster937.reflect.MirrorSafe; +import org.bukkit.Bukkit; +import org.bukkit.Location; import org.bukkit.Material; - -import static xyz.webmc.wlib.api.WLIB.warnDeprecatedUsage; +import org.bukkit.block.Block; @Deprecated(forRemoval = true) -public class BlockRelative extends xyz.webmc.wlib.api.structure.block.BlockRelative { +public class BlockRelative { + private final int x; + private final int y; + private final int z; + + private final XMaterial mat; + private final String dataModern; + private final byte dataLegacy; + + @Deprecated(forRemoval = true) + private BlockRelative(int x, int y, int z, XMaterial mat, String dataModern, byte dataLegacy) { + WLIB.warnDeprecatedUsage(); + this.x = x; + this.y = y; + this.z = z; + this.mat = mat; + this.dataModern = dataModern; + this.dataLegacy = dataLegacy; + } + + @Deprecated(forRemoval = true) public BlockRelative(int x, int y, int z, XMaterial mat) { - super(x, y, z, mat, null, (byte) 0); - warnDeprecatedUsage(); + this(x, y, z, mat, null, (byte) 0); + WLIB.warnDeprecatedUsage(); } + @Deprecated(forRemoval = true) public BlockRelative(int x, int y, int z, Material mat) { - super(x, y, z, XMaterial.matchXMaterial(mat)); - warnDeprecatedUsage(); + this(x, y, z, XMaterial.matchXMaterial(mat)); + WLIB.warnDeprecatedUsage(); } + @Deprecated(forRemoval = true) public BlockRelative(int x, int y, int z, XMaterial mat, String dataModern) { - super(x, y, z, mat, dataModern, (byte) 0); - warnDeprecatedUsage(); + this(x, y, z, mat, dataModern, (byte) 0); + WLIB.warnDeprecatedUsage(); } + @Deprecated(forRemoval = true) public BlockRelative(int x, int y, int z, Material mat, String dataModern) { - super(x, y, z, XMaterial.matchXMaterial(mat), dataModern); - warnDeprecatedUsage(); + this(x, y, z, XMaterial.matchXMaterial(mat), dataModern); + WLIB.warnDeprecatedUsage(); } + @Deprecated(forRemoval = true) public BlockRelative(int x, int y, int z, XMaterial mat, byte dataLegacy) { - super(x, y, z, mat, null, dataLegacy); - warnDeprecatedUsage(); + this(x, y, z, mat, null, dataLegacy); + WLIB.warnDeprecatedUsage(); } + @Deprecated(forRemoval = true) public BlockRelative(int x, int y, int z, Material mat, byte dataLegacy) { - super(x, y, z, XMaterial.matchXMaterial(mat), dataLegacy); - warnDeprecatedUsage(); + this(x, y, z, XMaterial.matchXMaterial(mat), dataLegacy); + WLIB.warnDeprecatedUsage(); + } + + @Deprecated(forRemoval = true) + public void place(Location loc) { + WLIB.warnDeprecatedUsage(); + final Location rel = loc.clone().add(this.x, this.y, this.z); + final Block blk = rel.getBlock(); + final Material _mat = this.mat.parseMaterial(); + + if (mat != null && blk != null) { + if (WLIB.getIsModernServer() && this.dataModern != null && _mat != null) { + final Object data = MirrorSafe.invokeMethod(Bukkit.class, "createBlockData", new Object[] { "minecraft:" + _mat.name().toLowerCase() + this.dataModern }); + MirrorSafe.invokeMethod(Block.class, blk, "setBlockData", data, false); + } else { + blk.setType(_mat, false); + if (this.dataLegacy != 0) { + blk.setData(this.dataLegacy); + } + } + } + } + + @Deprecated(forRemoval = true) + public final int getX() { + WLIB.warnDeprecatedUsage(); + return x; + } + + @Deprecated(forRemoval = true) + public final int getY() { + WLIB.warnDeprecatedUsage(); + return y; + } + + @Deprecated(forRemoval = true) + public final int getZ() { + WLIB.warnDeprecatedUsage(); + return z; + } + + @Deprecated(forRemoval = true) + public final XMaterial getMaterial() { + WLIB.warnDeprecatedUsage(); + return mat; + } + + @Deprecated(forRemoval = true) + public final Material getBukkitMaterial() { + WLIB.warnDeprecatedUsage(); + return mat.parseMaterial(); + } + + @Deprecated(forRemoval = true) + public final String getDataModern() { + WLIB.warnDeprecatedUsage(); + return dataModern; + } + + @Deprecated(forRemoval = true) + public final byte getDataLegacy() { + WLIB.warnDeprecatedUsage(); + return dataLegacy; } } diff --git a/src/main/java/xyz/webmc/wlib/api/structure/BuilderChunk.java b/src/main/java/xyz/webmc/wlib/api/structure/BuilderChunk.java new file mode 100644 index 0000000..5963361 --- /dev/null +++ b/src/main/java/xyz/webmc/wlib/api/structure/BuilderChunk.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2026 Colbster937 + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * See the LICENSE file for details. + */ + +package xyz.webmc.wlib.api.structure; + +import xyz.webmc.wlib.internal.util.ModernServerUtil; + +public record BuilderChunk(Object chunkData, int x, int z) { + public BuilderChunk { + ModernServerUtil.requireModernServer(); + } +} diff --git a/src/main/java/xyz/webmc/wlib/api/structure/GenerableStructure.java b/src/main/java/xyz/webmc/wlib/api/structure/GenerableStructure.java new file mode 100644 index 0000000..15632a6 --- /dev/null +++ b/src/main/java/xyz/webmc/wlib/api/structure/GenerableStructure.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2026 Colbster937 + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * See the LICENSE file for details. + */ + +package xyz.webmc.wlib.api.structure; + +import org.bukkit.Chunk; +import org.bukkit.Location; + +public interface GenerableStructure extends BaseStructure { + int SEARCH_RADIUS = 64; + + boolean canGenerate(Location loc); + boolean canGenerate(Chunk chunk); + boolean canGenerate(BuilderChunk chk); +} diff --git a/src/main/java/xyz/webmc/wlib/api/structure/RelativeStructure.java b/src/main/java/xyz/webmc/wlib/api/structure/RelativeStructure.java new file mode 100644 index 0000000..604ff17 --- /dev/null +++ b/src/main/java/xyz/webmc/wlib/api/structure/RelativeStructure.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2026 Colbster937 + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * See the LICENSE file for details. + */ + +package xyz.webmc.wlib.api.structure; + +import xyz.webmc.wlib.api.structure.placeable.RelativePlaceableStructure; + +import org.bukkit.Location; + +public abstract class RelativeStructure implements BaseStructure { + public abstract RelativePlaceableStructure build(); + + @Override + public final void place(Location loc, Object... chunks) { + if (chunks.length > 0) { + final RelativePlaceableStructure builder = this.build(); + for (Object chk: chunks){ + builder.place(loc, chk); + } + } else { + this.build().place(loc); + } + } +} diff --git a/src/main/java/xyz/webmc/wlib/api/structure/WeightedStructure.java b/src/main/java/xyz/webmc/wlib/api/structure/WeightedStructure.java index 76e764e..0236250 100644 --- a/src/main/java/xyz/webmc/wlib/api/structure/WeightedStructure.java +++ b/src/main/java/xyz/webmc/wlib/api/structure/WeightedStructure.java @@ -13,10 +13,16 @@ package xyz.webmc.wlib.api.structure; +import xyz.webmc.wlib.api.WLIB; + import dev.colbster937.util.WeightedObject; +@SuppressWarnings({ "removal" }) +@Deprecated(forRemoval = true) public final class WeightedStructure extends WeightedObject { + @Deprecated(forRemoval = true) public WeightedStructure(AbstractBaseStructure structure, int weight) { super(structure, weight); + WLIB.warnDeprecatedUsage(); } } diff --git a/src/main/java/xyz/webmc/wlib/api/structure/WeightedStructureTable.java b/src/main/java/xyz/webmc/wlib/api/structure/WeightedStructureTable.java index 9fd6ec2..f6affa8 100644 --- a/src/main/java/xyz/webmc/wlib/api/structure/WeightedStructureTable.java +++ b/src/main/java/xyz/webmc/wlib/api/structure/WeightedStructureTable.java @@ -13,6 +13,7 @@ package xyz.webmc.wlib.api.structure; +import xyz.webmc.wlib.api.WLIB; import xyz.webmc.wlib.api.util.RNGUtil; import java.util.ArrayList; @@ -22,30 +23,43 @@ import dev.colbster937.util.WeightedObjectTable; import org.bukkit.Location; +@SuppressWarnings({ "removal" }) +@Deprecated(forRemoval = true) public final class WeightedStructureTable extends WeightedObjectTable { + @Deprecated(forRemoval = true) public WeightedStructureTable(long seed, WeightedStructure... structures) { super(seed, structures); + WLIB.warnDeprecatedUsage(); } + @Deprecated(forRemoval = true) public WeightedStructureTable(WeightedStructure... structures) { this(RNGUtil.getRandomSeed(), structures); + WLIB.warnDeprecatedUsage(); } @SafeVarargs + @Deprecated(forRemoval = true) public WeightedStructureTable(long seed, Class... structures) { this(seed, weigh(structures)); + WLIB.warnDeprecatedUsage(); } @SafeVarargs + @Deprecated(forRemoval = true) public WeightedStructureTable(Class... structures) { this(weigh(structures)); + WLIB.warnDeprecatedUsage(); } + @Deprecated(forRemoval = true) public void place(Location loc) { + WLIB.warnDeprecatedUsage(); this.computeRandomObject().place(loc); } @SafeVarargs + @Deprecated(forRemoval = true) private static WeightedStructure[] weigh(Class... structures) { final List lst = new ArrayList<>(); final int chance = 100 / structures.length; diff --git a/src/main/java/xyz/webmc/wlib/api/structure/block/AbsoluteBlock.java b/src/main/java/xyz/webmc/wlib/api/structure/block/AbsoluteBlock.java new file mode 100644 index 0000000..fdb585f --- /dev/null +++ b/src/main/java/xyz/webmc/wlib/api/structure/block/AbsoluteBlock.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2026 Colbster937 + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * See the LICENSE file for details. + */ + +package xyz.webmc.wlib.api.structure.block; + +import com.cryptomorin.xseries.XMaterial; +import org.bukkit.Location; +import org.bukkit.Material; + +public non-sealed class AbsoluteBlock extends AbstractBlockBase { + private final Location loc; + + public AbsoluteBlock(Location loc, XMaterial mat, String dataModern, byte dataLegacy) { + super(mat, dataModern, dataLegacy); + this.loc = loc; + } + + public AbsoluteBlock(int x, int y, int z, XMaterial mat) { + this(new Location(null, x, y, z), mat, null, (byte) 0); + } + + public AbsoluteBlock(int x, int y, int z, Material mat) { + this(x, y, z, XMaterial.matchXMaterial(mat)); + } + + public AbsoluteBlock(int x, int y, int z, XMaterial mat, String dataModern) { + this(new Location(null, x, y, z), mat, dataModern, (byte) 0); + } + + public AbsoluteBlock(int x, int y, int z, Material mat, String dataModern) { + this(x, y, z, XMaterial.matchXMaterial(mat), dataModern); + } + + public AbsoluteBlock(int x, int y, int z, XMaterial mat, byte dataLegacy) { + this(new Location(null, x, y, z), mat, null, dataLegacy); + } + + public AbsoluteBlock(int x, int y, int z, Material mat, byte dataLegacy) { + this(x, y, z, XMaterial.matchXMaterial(mat), dataLegacy); + } + + public final int getX() { + return this.loc.getBlockX(); + } + + public final int getY() { + return this.loc.getBlockY(); + } + + public final int getZ() { + return this.loc.getBlockZ(); + } + + public final Location getLocation() { + return this.loc; + } + + public void place() { + super.place(this.loc); + } + + public void place(Object chunk) { + super.place(this.loc, chunk); + } + + public final RelativeBlock toRelative(Location newRelativeOrigin) { + return new RelativeBlock( + this.loc.getBlockX() - newRelativeOrigin.getBlockX(), + this.loc.getBlockY() - newRelativeOrigin.getBlockY(), + this.loc.getBlockZ() - newRelativeOrigin.getBlockZ(), + this.mat, + this.dataModern, + this.dataLegacy); + } +} diff --git a/src/main/java/xyz/webmc/wlib/api/structure/block/AbstractBlockBase.java b/src/main/java/xyz/webmc/wlib/api/structure/block/AbstractBlockBase.java index e3c85c2..752e6f7 100644 --- a/src/main/java/xyz/webmc/wlib/api/structure/block/AbstractBlockBase.java +++ b/src/main/java/xyz/webmc/wlib/api/structure/block/AbstractBlockBase.java @@ -14,17 +14,23 @@ package xyz.webmc.wlib.api.structure.block; import xyz.webmc.wlib.api.WLIB; +import xyz.webmc.wlib.api.structure.BuilderChunk; import com.cryptomorin.xseries.XMaterial; +import dev.colbster937.reflect.MirrorSafe; +import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.block.Block; -public abstract sealed class AbstractBlockBase permits BlockRelative { + +public abstract sealed class AbstractBlockBase permits AbsoluteBlock, BlockRelative, RelativeBlock { protected final XMaterial mat; protected final String dataModern; protected final byte dataLegacy; protected AbstractBlockBase(XMaterial mat, String dataModern, byte dataLegacy) { + WLIB.warnDeprecatedUsage(); this.mat = mat; this.dataModern = dataModern; this.dataLegacy = dataLegacy; @@ -32,33 +38,92 @@ protected AbstractBlockBase(XMaterial mat, String dataModern, byte dataLegacy) { protected AbstractBlockBase(XMaterial mat, String data) { this(mat, data, (byte) 0); + WLIB.warnDeprecatedUsage(); } protected AbstractBlockBase(XMaterial mat, byte data) { this(mat, null, data); + WLIB.warnDeprecatedUsage(); } - protected abstract void place(Location loc); + protected void place(Location loc) { + final Material material = this.getBukkitMaterial(); + if (material == null) { + return; + } + + final Block block = loc.getBlock(); + if (WLIB.getIsModernServer() && this.dataModern != null) { + final Object data = MirrorSafe.invokeMethod(Bukkit.class, "createBlockData", + new Object[] { "minecraft:" + material.name().toLowerCase() + this.dataModern }); + MirrorSafe.invokeMethod(Block.class, block, "setBlockData", data, false); + } else { + block.setType(material, false); + if (this.dataLegacy != 0) { + block.setData(this.dataLegacy); + } + } + } + + protected void place(Location loc, Object chunk) { + if (chunk instanceof org.bukkit.Chunk liveChunk) { + if (loc.getWorld() == liveChunk.getWorld() + && loc.getBlockX() >> 4 == liveChunk.getX() + && loc.getBlockZ() >> 4 == liveChunk.getZ()) { + this.place(loc); + } + return; + } + + if (chunk instanceof BuilderChunk builderChunk) { + if (loc.getBlockX() >> 4 != builderChunk.x() + || loc.getBlockZ() >> 4 != builderChunk.z()) { + return; + } + + final Material material = this.getBukkitMaterial(); + if (material == null) { + return; + } + + final int x = loc.getBlockX() - (builderChunk.x() << 4); + final int y = loc.getBlockY(); + final int z = loc.getBlockZ() - (builderChunk.z() << 4); + if (this.dataModern != null) { + final Object data = MirrorSafe.invokeMethod(Bukkit.class, "createBlockData", + new Object[] { "minecraft:" + material.name().toLowerCase() + this.dataModern }); + MirrorSafe.invokeMethod(builderChunk.chunkData().getClass(), builderChunk.chunkData(), "setBlockData", x, y, z, data); + } else { + MirrorSafe.invokeMethod(builderChunk.chunkData().getClass(), builderChunk.chunkData(), "setBlock", x, y, z, material); + } + return; + } + + throw new IllegalArgumentException("Unsupported chunk type: " + chunk); + } public final XMaterial getXMaterial() { + WLIB.warnDeprecatedUsage(); return this.mat; } - @Deprecated(forRemoval = true) public final XMaterial getMaterial() { WLIB.warnDeprecatedUsage(); return this.getXMaterial(); } public final Material getBukkitMaterial() { - return this.mat.get(); + WLIB.warnDeprecatedUsage(); + return this.mat == null ? null : this.mat.get(); } public final String getDataModern() { + WLIB.warnDeprecatedUsage(); return this.dataModern; } public final byte getDataLegacy() { + WLIB.warnDeprecatedUsage(); return this.dataLegacy; } } diff --git a/src/main/java/xyz/webmc/wlib/api/structure/block/BlockRelative.java b/src/main/java/xyz/webmc/wlib/api/structure/block/BlockRelative.java index ed58e53..9fa1cce 100644 --- a/src/main/java/xyz/webmc/wlib/api/structure/block/BlockRelative.java +++ b/src/main/java/xyz/webmc/wlib/api/structure/block/BlockRelative.java @@ -16,78 +16,83 @@ import xyz.webmc.wlib.api.WLIB; import com.cryptomorin.xseries.XMaterial; -import dev.colbster937.reflect.MirrorSafe; -import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.block.Block; -@SuppressWarnings({ "deprecation" }) +@SuppressWarnings({ "removal" }) +@Deprecated(forRemoval = true) public non-sealed class BlockRelative extends AbstractBlockBase { private final int x; private final int y; private final int z; + @Deprecated(forRemoval = true) protected BlockRelative(int x, int y, int z, XMaterial mat, String dataModern, byte dataLegacy) { super(mat, dataModern, dataLegacy); + WLIB.warnDeprecatedUsage(); this.x = x; this.y = y; this.z = z; } + @Deprecated(forRemoval = true) public BlockRelative(int x, int y, int z, XMaterial mat) { this(x, y, z, mat, null, (byte) 0); + WLIB.warnDeprecatedUsage(); } + @Deprecated(forRemoval = true) public BlockRelative(int x, int y, int z, Material mat) { this(x, y, z, XMaterial.matchXMaterial(mat)); + WLIB.warnDeprecatedUsage(); } + @Deprecated(forRemoval = true) public BlockRelative(int x, int y, int z, XMaterial mat, String dataModern) { this(x, y, z, mat, dataModern, (byte) 0); + WLIB.warnDeprecatedUsage(); } + @Deprecated(forRemoval = true) public BlockRelative(int x, int y, int z, Material mat, String dataModern) { this(x, y, z, XMaterial.matchXMaterial(mat), dataModern); + WLIB.warnDeprecatedUsage(); } + @Deprecated(forRemoval = true) public BlockRelative(int x, int y, int z, XMaterial mat, byte dataLegacy) { this(x, y, z, mat, null, dataLegacy); + WLIB.warnDeprecatedUsage(); } + @Deprecated(forRemoval = true) public BlockRelative(int x, int y, int z, Material mat, byte dataLegacy) { this(x, y, z, XMaterial.matchXMaterial(mat), dataLegacy); + WLIB.warnDeprecatedUsage(); } + @Deprecated(forRemoval = true) @Override public void place(Location loc) { - if (this.mat != null) { - final Location rel = loc.clone().add(this.x, this.y, this.z); - final Block blk = rel.getBlock(); - final Material _mat = this.getBukkitMaterial(); - if (_mat != null) { - if (WLIB.getIsModernServer() && this.dataModern != null) { - final Object data = MirrorSafe.invokeMethod(Bukkit.class, "createBlockData", new Object[] { "minecraft:" + _mat.name().toLowerCase() + this.dataModern }); - MirrorSafe.invokeMethod(Block.class, blk, "setBlockData", data, false); - } else { - blk.setType(_mat, false); - if (this.dataLegacy != 0) { - blk.setData(this.dataLegacy); - } - } - } - } + WLIB.warnDeprecatedUsage(); + super.place(loc.clone().add(this.x, this.y, this.z)); } + @Deprecated(forRemoval = true) public final int getX() { + WLIB.warnDeprecatedUsage(); return this.x; } + @Deprecated(forRemoval = true) public final int getY() { + WLIB.warnDeprecatedUsage(); return this.y; } + @Deprecated(forRemoval = true) public final int getZ() { + WLIB.warnDeprecatedUsage(); return this.z; } } diff --git a/src/main/java/xyz/webmc/wlib/api/structure/block/RelativeBlock.java b/src/main/java/xyz/webmc/wlib/api/structure/block/RelativeBlock.java new file mode 100644 index 0000000..968ca8f --- /dev/null +++ b/src/main/java/xyz/webmc/wlib/api/structure/block/RelativeBlock.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2026 Colbster937 + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * See the LICENSE file for details. + */ + +package xyz.webmc.wlib.api.structure.block; + +import com.cryptomorin.xseries.XMaterial; +import org.bukkit.Location; +import org.bukkit.Material; + +public non-sealed class RelativeBlock extends AbstractBlockBase { + private final int x; + private final int y; + private final int z; + + public RelativeBlock(int x, int y, int z, XMaterial mat, String dataModern, byte dataLegacy) { + super(mat, dataModern, dataLegacy); + this.x = x; + this.y = y; + this.z = z; + } + + public RelativeBlock(int x, int y, int z, XMaterial mat) { + this(x, y, z, mat, null, (byte) 0); + } + + public RelativeBlock(int x, int y, int z, Material mat) { + this(x, y, z, XMaterial.matchXMaterial(mat)); + } + + public RelativeBlock(int x, int y, int z, XMaterial mat, String dataModern) { + this(x, y, z, mat, dataModern, (byte) 0); + } + + public RelativeBlock(int x, int y, int z, Material mat, String dataModern) { + this(x, y, z, XMaterial.matchXMaterial(mat), dataModern); + } + + public RelativeBlock(int x, int y, int z, XMaterial mat, byte dataLegacy) { + this(x, y, z, mat, null, dataLegacy); + } + + public RelativeBlock(int x, int y, int z, Material mat, byte dataLegacy) { + this(x, y, z, XMaterial.matchXMaterial(mat), dataLegacy); + } + + public final int getX() { + return this.x; + } + + public final int getY() { + return this.y; + } + + public final int getZ() { + return this.z; + } + + @Override + public void place(Location loc) { + super.place(loc.clone().add(this.x, this.y, this.z)); + } + + public void place(Location loc, Object chunk) { + super.place(loc.clone().add(this.x, this.y, this.z), chunk); + } + + public final AbsoluteBlock toAbsolute(Location relativeOrigin) { + return new AbsoluteBlock( + relativeOrigin.clone().add(this.x, this.y, this.z), + this.mat, + this.dataModern, + this.dataLegacy); + } +} diff --git a/src/main/java/xyz/webmc/wlib/api/structure/blocks/AbsoluteBlock.java b/src/main/java/xyz/webmc/wlib/api/structure/blocks/AbsoluteBlock.java new file mode 100644 index 0000000..dfe8a9f --- /dev/null +++ b/src/main/java/xyz/webmc/wlib/api/structure/blocks/AbsoluteBlock.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2026 Colbster937 + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * See the LICENSE file for details. + */ + +package xyz.webmc.wlib.api.structure.blocks; + +import com.cryptomorin.xseries.XMaterial; +import org.bukkit.Location; +import org.bukkit.Material; + +public class AbsoluteBlock extends AbstractBlockBase { + private final Location loc; + + public AbsoluteBlock(Location loc, XMaterial mat, String dataModern, byte dataLegacy) { + super(mat, dataModern, dataLegacy); + this.loc = loc; + } + + public AbsoluteBlock(int x, int y, int z, XMaterial mat) { + this(new Location(null, x, y, z), mat, null, (byte) 0); + } + + public AbsoluteBlock(int x, int y, int z, Material mat) { + this(x, y, z, XMaterial.matchXMaterial(mat)); + } + + public AbsoluteBlock(int x, int y, int z, XMaterial mat, String dataModern) { + this(new Location(null, x, y, z), mat, dataModern, (byte) 0); + } + + public AbsoluteBlock(int x, int y, int z, Material mat, String dataModern) { + this(x, y, z, XMaterial.matchXMaterial(mat), dataModern); + } + + public AbsoluteBlock(int x, int y, int z, XMaterial mat, byte dataLegacy) { + this(new Location(null, x, y, z), mat, null, dataLegacy); + } + + public AbsoluteBlock(int x, int y, int z, Material mat, byte dataLegacy) { + this(x, y, z, XMaterial.matchXMaterial(mat), dataLegacy); + } + + public final int getX() { + return this.loc.getBlockX(); + } + + public final int getY() { + return this.loc.getBlockY(); + } + + public final int getZ() { + return this.loc.getBlockZ(); + } + + public final Location getLocation() { + return this.loc; + } + + public void place() { + super.place(this.loc); + } + + public void place(Object chunk) { + super.place(this.loc, chunk); + } + + public final RelativeBlock toRelative(Location newRelativeOrigin) { + return new RelativeBlock( + this.loc.getBlockX() - newRelativeOrigin.getBlockX(), + this.loc.getBlockY() - newRelativeOrigin.getBlockY(), + this.loc.getBlockZ() - newRelativeOrigin.getBlockZ(), + this.mat, + this.dataModern, + this.dataLegacy); + } +} diff --git a/src/main/java/xyz/webmc/wlib/api/structure/blocks/AbstractBlockBase.java b/src/main/java/xyz/webmc/wlib/api/structure/blocks/AbstractBlockBase.java new file mode 100644 index 0000000..d20f508 --- /dev/null +++ b/src/main/java/xyz/webmc/wlib/api/structure/blocks/AbstractBlockBase.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2026 Colbster937 + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * See the LICENSE file for details. + */ + +package xyz.webmc.wlib.api.structure.blocks; + +import xyz.webmc.wlib.api.WLIB; +import xyz.webmc.wlib.api.structure.BuilderChunk; + +import com.cryptomorin.xseries.XMaterial; +import dev.colbster937.reflect.MirrorSafe; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; + +public abstract class AbstractBlockBase { + protected final XMaterial mat; + protected final String dataModern; + protected final byte dataLegacy; + + protected AbstractBlockBase(XMaterial mat, String dataModern, byte dataLegacy) { + this.mat = mat; + this.dataModern = dataModern; + this.dataLegacy = dataLegacy; + } + + protected void place(Location loc) { + final Block blk = loc.getBlock(); + final Material _mat = this.mat.get(); + + if (this.mat != null) { + if (WLIB.getIsModernServer() && this.dataModern != null && _mat != null) { + final Object data = MirrorSafe.invokeMethod(Bukkit.class, "createBlockData", new Object[] { "minecraft:" + _mat.name().toLowerCase() + this.dataModern }); + MirrorSafe.invokeMethod(Block.class, blk, "setBlockData", data, false); + } else { + blk.setType(_mat, false); + } + } + } + + protected void place(Location loc, Object chunk) { + if (chunk instanceof org.bukkit.Chunk liveChunk) { + if (!isInChunk(loc, liveChunk)) { + return; + } + + this.place(loc); + return; + } + + if (chunk instanceof BuilderChunk builderChunk) { + if (!isInChunk(loc, builderChunk)) { + return; + } + + final int x = loc.getBlockX() - (builderChunk.x() << 4); + final int y = loc.getBlockY(); + final int z = loc.getBlockZ() - (builderChunk.z() << 4); + final Material material = this.mat.get(); + + if (material == null) { + return; + } + + if (this.dataModern != null) { + final Object data = MirrorSafe.invokeMethod(Bukkit.class, "createBlockData", + new Object[] { "minecraft:" + material.name().toLowerCase() + this.dataModern }); + MirrorSafe.invokeMethod(builderChunk.chunkData().getClass(), builderChunk.chunkData(), "setBlockData", x, y, z, data); + } else { + MirrorSafe.invokeMethod(builderChunk.chunkData().getClass(), builderChunk.chunkData(), "setBlock", x, y, z, material); + } + return; + } + + throw new IllegalArgumentException("Unsupported chunk type: " + chunk); + } + + public final XMaterial getMaterial() { + return this.mat; + } + + public final Material getBukkitMaterial() { + return this.mat.get(); + } + + public final String getDataModern() { + return this.dataModern; + } + + public final byte getDataLegacy() { + return this.dataLegacy; + } + + private static boolean isInChunk(Location location, org.bukkit.Chunk chunk) { + return location.getWorld() == chunk.getWorld() + && location.getBlockX() >> 4 == chunk.getX() + && location.getBlockZ() >> 4 == chunk.getZ(); + } + + private static boolean isInChunk(Location location, BuilderChunk chunk) { + return location.getBlockX() >> 4 == chunk.x() + && location.getBlockZ() >> 4 == chunk.z(); + } +} diff --git a/src/main/java/xyz/webmc/wlib/api/structure/blocks/RelativeBlock.java b/src/main/java/xyz/webmc/wlib/api/structure/blocks/RelativeBlock.java new file mode 100644 index 0000000..30726e8 --- /dev/null +++ b/src/main/java/xyz/webmc/wlib/api/structure/blocks/RelativeBlock.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2026 Colbster937 + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * See the LICENSE file for details. + */ + +package xyz.webmc.wlib.api.structure.blocks; + +import com.cryptomorin.xseries.XMaterial; + +import org.bukkit.Location; +import org.bukkit.Material; + +public class RelativeBlock extends AbstractBlockBase { + private final int x; + private final int y; + private final int z; + + public RelativeBlock(int x, int y, int z, XMaterial mat, String dataModern, + byte dataLegacy) { + super(mat, dataModern, dataLegacy); + this.x = x; + this.y = y; + this.z = z; + } + + public RelativeBlock(int x, int y, int z, XMaterial mat) { + this(x, y, z, mat, null, (byte) 0); + } + + public RelativeBlock(int x, int y, int z, Material mat) { + this(x, y, z, XMaterial.matchXMaterial(mat)); + } + + public RelativeBlock(int x, int y, int z, XMaterial mat, String dataModern) { + this(x, y, z, mat, dataModern, (byte) 0); + } + + public RelativeBlock(int x, int y, int z, Material mat, String dataModern) { + this(x, y, z, XMaterial.matchXMaterial(mat), dataModern); + } + + public RelativeBlock(int x, int y, int z, XMaterial mat, byte dataLegacy) { + this(x, y, z, mat, null, dataLegacy); + } + + public RelativeBlock(int x, int y, int z, Material mat, byte dataLegacy) { + this(x, y, z, XMaterial.matchXMaterial(mat), dataLegacy); + } + + public final int getX() { + return this.x; + } + + public final int getY() { + return this.y; + } + + public final int getZ() { + return this.z; + } + + @Override + public void place(Location loc) { + super.place(loc.clone().add(this.x, this.y, this.z)); + } + + public void place(Location loc, Object chunk) { + super.place(loc.clone().add(this.x, this.y, this.z), chunk); + } + + public final AbsoluteBlock toAbsolute(Location relativeOrigin) { + return new AbsoluteBlock( + relativeOrigin.clone().add(this.x, this.y, this.z), + this.mat, + this.dataModern, + this.dataLegacy); + } +} diff --git a/src/main/java/xyz/webmc/wlib/api/structure/placeable/AbsolutePlaceableStructure.java b/src/main/java/xyz/webmc/wlib/api/structure/placeable/AbsolutePlaceableStructure.java new file mode 100644 index 0000000..14036e6 --- /dev/null +++ b/src/main/java/xyz/webmc/wlib/api/structure/placeable/AbsolutePlaceableStructure.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2026 Colbster937 + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * See the LICENSE file for details. + */ + +package xyz.webmc.wlib.api.structure.placeable; + +import xyz.webmc.wlib.api.structure.BuilderChunk; +import xyz.webmc.wlib.api.structure.block.AbsoluteBlock; +import xyz.webmc.wlib.api.structure.block.RelativeBlock; +import xyz.webmc.wlib.api.util.SchemUtil; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Map; + +import com.cryptomorin.xseries.XMaterial; +import net.sandrohc.schematic4j.schematic.Schematic; +import net.sandrohc.schematic4j.schematic.types.SchematicBlock; +import net.sandrohc.schematic4j.schematic.types.SchematicBlockPos; +import org.bukkit.Chunk; +import org.bukkit.Location; + +public class AbsolutePlaceableStructure extends AbstractPlaceableStructureBase { + private final Location location; + + public AbsolutePlaceableStructure(Location location) { + super(new ArrayList<>()); + this.location = location; + } + + public void place() { + for (final AbsoluteBlock block : this.blocks) { + block.place(); + } + } + + public void place(Object chunk) { + for (final AbsoluteBlock block : this.blocks) { + final Location blockLocation = block.getLocation(); + if (isInChunk(blockLocation, chunk)) { + block.place(chunk); + } + } + } + + @Override + public void loadSchematic(InputStream stream, int offsetx, int offsety, int offsetz) { + try (stream) { + final Schematic schematic = SchemUtil.readSchematic(stream); + final SchematicBlockPos offset = schematic.offset(); + + for (int y = 0; y < schematic.height(); y++) { + for (int z = 0; z < schematic.length(); z++) { + for (int x = 0; x < schematic.width(); x++) { + final SchematicBlock block = schematic.block(x, y, z); + if (block != SchematicBlock.AIR) { + final XMaterial material = XMaterial.matchXMaterial(block.block().replace("minecraft:", "")).orElse(XMaterial.AIR); + final StringBuilder data = new StringBuilder(); + + for (final Map.Entry entry : block.states().entrySet()) { + if (data.length() > 0) { + data.append(","); + } + + data.append(entry.getKey()).append("=").append(entry.getValue()); + } + + final RelativeBlock relativeBlock = new RelativeBlock( + x - offset.x + offsetx, + y - offset.y + offsety, + z - offset.z + offsetz, + material, + "[" + data + "]"); + this.blocks.add(relativeBlock.toAbsolute(this.location)); + } + } + } + } + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + private static boolean isInChunk(Location location, Object chunk) { + if (chunk instanceof Chunk liveChunk) { + return location.getWorld() == liveChunk.getWorld() + && location.getBlockX() >> 4 == liveChunk.getX() + && location.getBlockZ() >> 4 == liveChunk.getZ(); + } + + if (chunk instanceof BuilderChunk builderChunk) { + return location.getBlockX() >> 4 == builderChunk.x() + && location.getBlockZ() >> 4 == builderChunk.z(); + } + + throw new IllegalArgumentException("Unsupported chunk type: " + chunk); + } +} diff --git a/src/main/java/xyz/webmc/wlib/api/structure/placeable/AbstractPlaceableStructureBase.java b/src/main/java/xyz/webmc/wlib/api/structure/placeable/AbstractPlaceableStructureBase.java new file mode 100644 index 0000000..d1e12f9 --- /dev/null +++ b/src/main/java/xyz/webmc/wlib/api/structure/placeable/AbstractPlaceableStructureBase.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2026 Colbster937 + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * See the LICENSE file for details. + */ + +package xyz.webmc.wlib.api.structure.placeable; + +import xyz.webmc.wlib.api.structure.block.AbstractBlockBase; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +@SuppressWarnings({ "unchecked" }) +public abstract class AbstractPlaceableStructureBase { + protected List blocks = new ArrayList<>(); + + public abstract void loadSchematic(InputStream stream, int offsetx, int offsety, int offsetz); + + protected AbstractPlaceableStructureBase(List blocks) { + this.blocks = blocks; + } + + public final void loadSchematic(File file, int offsetx, int offsety, int offsetz) { + try (final FileInputStream fis = new FileInputStream(file)) { + this.loadSchematic(fis, offsetx, offsety, offsetz); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + public final void loadSchematic(InputStream stream) { + this.loadSchematic(stream, 0, 0, 0); + } + + public final void loadSchematic(File file) { + this.loadSchematic(file, 0, 0, 0); + } + + public final void addBlock(B blk) { + this.blocks.add(blk); + } + + public final void addBlocks(Collection blks) { + this.blocks.addAll(blks); + } + + public final void addBlocks(B... blks) { + this.blocks.addAll(List.of(blks)); + } +} diff --git a/src/main/java/xyz/webmc/wlib/api/structure/placeable/RelativePlaceableStructure.java b/src/main/java/xyz/webmc/wlib/api/structure/placeable/RelativePlaceableStructure.java new file mode 100644 index 0000000..07b98c0 --- /dev/null +++ b/src/main/java/xyz/webmc/wlib/api/structure/placeable/RelativePlaceableStructure.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2026 Colbster937 + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * See the LICENSE file for details. + */ + +package xyz.webmc.wlib.api.structure.placeable; + +import xyz.webmc.wlib.api.structure.BuilderChunk; +import xyz.webmc.wlib.api.structure.block.RelativeBlock; +import xyz.webmc.wlib.api.util.SchemUtil; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Map; + +import com.cryptomorin.xseries.XMaterial; +import net.sandrohc.schematic4j.schematic.Schematic; +import net.sandrohc.schematic4j.schematic.types.SchematicBlock; +import net.sandrohc.schematic4j.schematic.types.SchematicBlockPos; +import org.bukkit.Chunk; +import org.bukkit.Location; + +public class RelativePlaceableStructure extends AbstractPlaceableStructureBase { + public RelativePlaceableStructure() { + super(new ArrayList<>()); + } + + public void place(Location loc) { + for (final RelativeBlock block : this.blocks) { + block.place(loc); + } + } + + public void place(Location loc, Object chunk) { + for (final RelativeBlock block : this.blocks) { + final Location blockLocation = loc.clone().add(block.getX(), block.getY(), block.getZ()); + if (isInChunk(blockLocation, chunk)) { + block.place(loc, chunk); + } + } + } + + @Override + public final void loadSchematic(InputStream stream, int offsetx, int offsety, int offsetz) { + try (stream) { + final Schematic schematic = SchemUtil.readSchematic(stream); + final SchematicBlockPos offset = schematic.offset(); + + for (int y = 0; y < schematic.height(); y++) { + for (int z = 0; z < schematic.length(); z++) { + for (int x = 0; x < schematic.width(); x++) { + final SchematicBlock block = schematic.block(x, y, z); + if (block != SchematicBlock.AIR) { + final XMaterial material = XMaterial.matchXMaterial(block.block().replace("minecraft:", "")).orElse(XMaterial.AIR); + final StringBuilder data = new StringBuilder(); + + for (final Map.Entry entry : block.states().entrySet()) { + if (data.length() > 0) { + data.append(","); + } + + data.append(entry.getKey()).append("=").append(entry.getValue()); + } + + this.blocks.add(new RelativeBlock( + x - offset.x + offsetx, + y - offset.y + offsety, + z - offset.z + offsetz, + material, + "[" + data + "]")); + } + } + } + } + } catch (Exception ex) { + throw new RuntimeException(); + } + } + + private static boolean isInChunk(Location location, Object chunk) { + if (chunk instanceof Chunk liveChunk) { + return location.getWorld() == liveChunk.getWorld() + && location.getBlockX() >> 4 == liveChunk.getX() + && location.getBlockZ() >> 4 == liveChunk.getZ(); + } + + if (chunk instanceof BuilderChunk builderChunk) { + return location.getBlockX() >> 4 == builderChunk.x() + && location.getBlockZ() >> 4 == builderChunk.z(); + } + + throw new IllegalArgumentException("Unsupported chunk type: " + chunk); + } +} diff --git a/src/main/java/xyz/webmc/wlib/api/util/GenerableStructuresUtils.java b/src/main/java/xyz/webmc/wlib/api/util/GenerableStructuresUtils.java new file mode 100644 index 0000000..3512de1 --- /dev/null +++ b/src/main/java/xyz/webmc/wlib/api/util/GenerableStructuresUtils.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2026 Colbster937 + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * See the LICENSE file for details. + */ + +package xyz.webmc.wlib.api.util; + +import xyz.webmc.wlib.api.structure.GenerableStructure; +import xyz.webmc.wlib.internal.util.TestStructureUtil; + +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.World; + +public final class GenerableStructuresUtils { + + public static Location locateNearest(GenerableStructure structure, Location pos) { + Location ret = null; + + if (structure != null && pos != null && pos.getWorld() != null) { + final int centerChunkX = pos.getChunk().getX(); + final int centerChunkZ = pos.getChunk().getZ(); + final int searchRadius = GenerableStructure.SEARCH_RADIUS; + + search: + for (int radius = 0; radius <= searchRadius; radius++) { + final int minX = centerChunkX - radius; + final int maxX = centerChunkX + radius; + final int minZ = centerChunkZ - radius; + final int maxZ = centerChunkZ + radius; + + for (int chunkX = minX; chunkX <= maxX; chunkX++) { + for (final int chunkZ : new int[] { minZ, maxZ }) { + final Location loc = createLocation(pos.getWorld(), chunkX, chunkZ); + if (structure.canGenerate(loc)) { + ret = loc; + break search; + } + } + } + + for (int chunkZ = minZ + 1; chunkZ < maxZ; chunkZ++) { + for (final int chunkX : new int[] { minX, maxX }) { + final Location loc = createLocation(pos.getWorld(), chunkX, chunkZ); + if (structure.canGenerate(loc)) { + ret = loc; + break search; + } + } + } + } + } + + return ret; + } + + public static void generateChunk(T structure, Chunk chunk) { + if (structure == null || chunk == null) { + return; + } + + final Location loc = locateNearest(structure, chunk.getBlock(0, 65, 0).getLocation()); + if (loc != null) { + structure.place(loc, chunk); + } + } + + public static void generateChunk(Class structureClass, + Chunk chunk) { + if (structureClass != null) { + generateChunk(TestStructureUtil.getInstance(structureClass), chunk); + } + } + + private static Location createLocation(World world, int chunkX, int chunkZ) { + return new Location(world, chunkX << 4, 65, chunkZ << 4); + } + +} diff --git a/src/main/java/xyz/webmc/wlib/api/util/SchedulerUtil.java b/src/main/java/xyz/webmc/wlib/api/util/SchedulerUtil.java index e376606..9cf5220 100644 --- a/src/main/java/xyz/webmc/wlib/api/util/SchedulerUtil.java +++ b/src/main/java/xyz/webmc/wlib/api/util/SchedulerUtil.java @@ -121,7 +121,7 @@ public static CompletableFuture runAtLocation(Location loc, Runnable task) } public static ScheduledTask runAtLocationLater(Plugin plugin, Location loc, Runnable task, - final long delayTicks) { + long delayTicks) { return task(plugin, sch.runAtLocationLater(loc, task, delayTicks)); } diff --git a/src/main/java/xyz/webmc/wlib/internal/command/WLIBCommand.java b/src/main/java/xyz/webmc/wlib/internal/command/WLIBCommand.java index 894edac..c7a2b65 100644 --- a/src/main/java/xyz/webmc/wlib/internal/command/WLIBCommand.java +++ b/src/main/java/xyz/webmc/wlib/internal/command/WLIBCommand.java @@ -15,7 +15,7 @@ import xyz.webmc.wlib.api.WLIB; import xyz.webmc.wlib.api.command.WCommand; -import xyz.webmc.wlib.api.structure.AbstractBaseStructure; +import xyz.webmc.wlib.api.structure.BaseStructure; import xyz.webmc.wlib.api.util.CommandUtil; import xyz.webmc.wlib.api.util.SchedulerUtil; import xyz.webmc.wlib.api.util.TextUtil; @@ -47,27 +47,32 @@ public boolean run(CommandSender sender, String label, String[] args) { if ((arg.equals("plugins") || arg.equals("pl")) && (bool2 = sender.hasPermission("wlib.command.plugins"))) { TextUtil.sendStringListMessageType3(sender, "WLIB Plugins", WLIB.getWLIBPluginNames()); bool1 = false; - } else if ((arg.equals("version") || arg.equals("ver")) && (bool2 = sender.hasPermission("wlib.command.version"))) { + } else if ((arg.equals("version") || arg.equals("ver")) + && (bool2 = sender.hasPermission("wlib.command.version"))) { sender.sendMessage("Running WLIB Version " + ChatColor.BLUE + WLIB.getWLIBVersionString()); bool1 = false; } else if (args.length > 1) { - /* if (arg.equals("alerts") && (bool2 = sender.hasPermission("wlib.alerts"))) { - final String ctx = args[1].trim(); - final int ret = PermissionUtil.toggleUserPermissionC(sender, "wlib.alerts.muted." + ctx); - bool1 = ret < 0; - - if (!bool1) { - final String state; - - if (ret > 0) { - state = ChatColor.RED + "DISABLED"; - } else { - state = ChatColor.GREEN + "ENABLED"; - } - - sender.sendMessage(state + ChatColor.RESET + " alerts for " + ChatColor.AQUA + ctx); - } - } else */ + /* + * if (arg.equals("alerts") && (bool2 = sender.hasPermission("wlib.alerts"))) { + * final String ctx = args[1].trim(); + * final int ret = PermissionUtil.toggleUserPermissionC(sender, + * "wlib.alerts.muted." + ctx); + * bool1 = ret < 0; + * + * if (!bool1) { + * final String state; + * + * if (ret > 0) { + * state = ChatColor.RED + "DISABLED"; + * } else { + * state = ChatColor.GREEN + "ENABLED"; + * } + * + * sender.sendMessage(state + ChatColor.RESET + " alerts for " + ChatColor.AQUA + * + ctx); + * } + * } else + */ if (arg.equals("debug") && (bool2 = sender.hasPermission("wlib.command.debug"))) { final String act = args[1].trim(); if (act.equals("throw")) { @@ -77,12 +82,13 @@ public boolean run(CommandSender sender, String label, String[] args) { bool1 = false; if (sender instanceof Player plr) { final String struct = args[2].trim(); - final AbstractBaseStructure structure = TestStructureUtil.getTestStructure(struct); + final BaseStructure structure = TestStructureUtil.getTestStructure(struct); if (structure != null) { final Location loc = plr.getLocation(); structure.place(loc.clone()); - SchedulerUtil.teleportAsync(plr, loc.clone().add(1, 1, 0).getBlock().getLocation().clone().add(0.5D, 0, 0.5D)); + SchedulerUtil.teleportAsync(plr, + loc.clone().add(1, 1, 0).getBlock().getLocation().clone().add(0.5D, 0, 0.5D)); sender.sendMessage(ChatColor.GREEN + "Placed structure " + structure.getName()); } else { bool3 = true; @@ -128,45 +134,53 @@ public boolean run(CommandSender sender, String label, String[] args) { @Override public List tab(CommandSender sender, String label, String[] args) { - if (args.length > 0) { - final List ret = new ArrayList<>(); + final List ret = new ArrayList<>(); - if (args.length == 1) { - if (sender.hasPermission("wlib.command.plugins")) { - ret.add("plugins"); - } - - if (sender.hasPermission("wlib.command.version")) { - ret.add("version"); - } + if (args.length == 1) { + if (sender.hasPermission("wlib.command.plugins")) { + ret.add("plugins"); + } - /* if (sender.hasPermission("wlib.alerts")) { - ret.add("alerts"); - } */ + if (sender.hasPermission("wlib.command.version")) { + ret.add("version"); + } - if (sender.hasPermission("wlib.command.debug")) { - ret.add("debug"); - } - } else if (args.length == 2) { - if (args[0].equals("debug") && sender.hasPermission("wlib.command.debug")) { - ret.add("throw"); + /* + * if (sender.hasPermission("wlib.alerts")) { + * ret.add("alerts"); + * } + */ - if (CommandUtil.isPlayer(sender)) { - ret.add("place"); - } + if (sender.hasPermission("wlib.command.debug")) { + ret.add("debug"); + } + } else if (args.length == 2) { + if (args[0].equals("debug") && sender.hasPermission("wlib.command.debug")) { + ret.add("throw"); - ret.add("alert"); - ret.add("deprecation"); + if (CommandUtil.isPlayer(sender)) { + ret.add("place"); } - } else if (args.length == 3) { - if (args[0].equals("debug") && args[1].equals("place") && CommandUtil.isPlayer(sender) && sender.hasPermission("wlib.command.debug")) { - ret.addAll(TestStructureUtil.getStructureNames()); + + ret.add("alert"); + ret.add("deprecation"); + } + } else if (args.length == 3) { + if (args[0].equals("debug") && args[1].equals("place") && CommandUtil.isPlayer(sender) + && sender.hasPermission("wlib.command.debug")) { + ret.addAll(TestStructureUtil.getStructureNames()); + if (args[0].equals("debug") && args[1].equals("place") && sender.hasPermission("wlib.debug")) { + ret.add("shrine"); + ret.add("rick"); + ret.add("coord"); } } return ret; } else { - return List.of(); + return ret; } + + return List.of(); } } diff --git a/src/main/java/xyz/webmc/wlib/internal/structure/CoordinateStructure.java b/src/main/java/xyz/webmc/wlib/internal/structure/CoordinateStructure.java new file mode 100644 index 0000000..28a2b3e --- /dev/null +++ b/src/main/java/xyz/webmc/wlib/internal/structure/CoordinateStructure.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2026 Colbster937 + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * See the LICENSE file for details. + */ + +package xyz.webmc.wlib.internal.structure; + +import xyz.webmc.wlib.api.structure.AbsoluteStructure; +import xyz.webmc.wlib.api.structure.block.AbsoluteBlock; +import xyz.webmc.wlib.api.structure.placeable.AbsolutePlaceableStructure; +import xyz.webmc.wlib.internal.util.TestStructureUtil; + +import com.cryptomorin.xseries.XMaterial; +import org.bukkit.Location; + +public final class CoordinateStructure extends AbsoluteStructure { + @Override + public AbsolutePlaceableStructure build(Location loc) { + final AbsolutePlaceableStructure structure = new AbsolutePlaceableStructure(loc); + final int x = loc.getBlockX(); + final int z = loc.getBlockZ(); + final int y = loc.getBlockY(); + + final int maxBits = Math.max(1, Integer.SIZE - Integer.numberOfLeadingZeros(Math.max(Math.abs(x), Math.abs(z)))); + for (int bit = 0; bit < maxBits; bit++) { + final int xBit = (x >> bit) & 1; + final int zBit = (z >> bit) & 1; + + structure.addBlock(new AbsoluteBlock(x + 1 + bit, y, z, bitToMaterial(xBit))); + structure.addBlock(new AbsoluteBlock(x, y, z + 1 + bit, bitToMaterial(zBit))); + } + + return structure; + } + + private static XMaterial bitToMaterial(int bit) { + return bit == 0 ? XMaterial.WHITE_CONCRETE : XMaterial.BLACK_CONCRETE; + } + + public static CoordinateStructure getInstance() { + return TestStructureUtil.getInstance(CoordinateStructure.class); + } + + static { + TestStructureUtil.registerInstance(CoordinateStructure.class); + } +} diff --git a/src/main/java/xyz/webmc/wlib/internal/structure/HerobrineShrineTestStructure.java b/src/main/java/xyz/webmc/wlib/internal/structure/HerobrineShrineTestStructure.java index d2e2394..73dd8f4 100644 --- a/src/main/java/xyz/webmc/wlib/internal/structure/HerobrineShrineTestStructure.java +++ b/src/main/java/xyz/webmc/wlib/internal/structure/HerobrineShrineTestStructure.java @@ -13,32 +13,63 @@ package xyz.webmc.wlib.internal.structure; -import xyz.webmc.wlib.api.structure.AbstractBaseStructure; -import xyz.webmc.wlib.api.structure.block.BlockRelative; -import xyz.webmc.wlib.api.structure.iface.TestStructure; +import xyz.webmc.wlib.api.structure.BuilderChunk; +import xyz.webmc.wlib.api.structure.GenerableStructure; +import xyz.webmc.wlib.api.structure.RelativeStructure; +import xyz.webmc.wlib.api.structure.block.RelativeBlock; +import xyz.webmc.wlib.api.structure.placeable.RelativePlaceableStructure; +import xyz.webmc.wlib.internal.util.TestStructureUtil; import com.cryptomorin.xseries.XMaterial; +import org.bukkit.Chunk; +import org.bukkit.Location; -public final class HerobrineShrineTestStructure extends AbstractBaseStructure implements TestStructure { - public HerobrineShrineTestStructure() { - super("herobrine_shrine"); +public final class HerobrineShrineTestStructure extends RelativeStructure implements GenerableStructure { + @Override + public boolean canGenerate(Location loc) { + return true; + } + + @Override + public boolean canGenerate(Chunk chunk) { + return true; + } + + @Override + public boolean canGenerate(BuilderChunk chunk) { + return true; + } + + @Override + public RelativePlaceableStructure build() { + final RelativePlaceableStructure structure = new RelativePlaceableStructure(); for (int y = 0; y < 3; y++) { for (int x = -1; x < 2; x++) { for (int z = -1; z < 2; z++) { if (y == 0) { - super.addBlock(new BlockRelative(x, y, z, XMaterial.GOLD_BLOCK)); + structure.addBlock(new RelativeBlock(x, y, z, XMaterial.GOLD_BLOCK)); } else if (y == 1) { if (x != z && x + z != 0) { - super.addBlock(new BlockRelative(x, y, z, XMaterial.REDSTONE_TORCH)); + structure.addBlock(new RelativeBlock(x, y, z, XMaterial.REDSTONE_TORCH)); } else if (x == 0 && z == 0) { - super.addBlock(new BlockRelative(x, y, z, XMaterial.NETHERRACK)); + structure.addBlock(new RelativeBlock(x, y, z, XMaterial.NETHERRACK)); } } else if (y == 2 && x == 0 && z == 0) { - super.addBlock(new BlockRelative(x, y, z, XMaterial.FIRE)); + structure.addBlock(new RelativeBlock(x, y, z, XMaterial.FIRE)); } } } } + + return structure; + } + + public static HerobrineShrineTestStructure getInstance() { + return TestStructureUtil.getInstance(HerobrineShrineTestStructure.class); + } + + static { + TestStructureUtil.registerInstance(HerobrineShrineTestStructure.class); } } diff --git a/src/main/java/xyz/webmc/wlib/internal/structure/RickQRCodeTestSchemStructure.java b/src/main/java/xyz/webmc/wlib/internal/structure/RickQRCodeTestSchemStructure.java deleted file mode 100644 index 0d5e8b4..0000000 --- a/src/main/java/xyz/webmc/wlib/internal/structure/RickQRCodeTestSchemStructure.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2026 Colbster937 - * - * SPDX-License-Identifier: AGPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * See the LICENSE file for details. - */ - -package xyz.webmc.wlib.internal.structure; - -import xyz.webmc.wlib.api.structure.AbstractBaseSchemStructure; -import xyz.webmc.wlib.api.structure.iface.TestStructure; - -import java.io.IOException; - -import net.sandrohc.schematic4j.exception.ParsingException; - -public final class RickQRCodeTestSchemStructure extends AbstractBaseSchemStructure implements TestStructure { - public RickQRCodeTestSchemStructure() throws IOException, ParsingException { - super("rick_qr", "/schematics/rick.schem"); - } -} diff --git a/src/main/java/xyz/webmc/wlib/internal/structure/RickQRCodeTestStructure.java b/src/main/java/xyz/webmc/wlib/internal/structure/RickQRCodeTestStructure.java new file mode 100644 index 0000000..97565d4 --- /dev/null +++ b/src/main/java/xyz/webmc/wlib/internal/structure/RickQRCodeTestStructure.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2026 Colbster937 + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * See the LICENSE file for details. + */ + +package xyz.webmc.wlib.internal.structure; + +import xyz.webmc.wlib.api.structure.RelativeStructure; +import xyz.webmc.wlib.api.structure.placeable.RelativePlaceableStructure; +import xyz.webmc.wlib.internal.util.TestStructureUtil; + +import java.io.InputStream; + +public final class RickQRCodeTestStructure extends RelativeStructure { + @Override + public RelativePlaceableStructure build() { + final RelativePlaceableStructure structure = new RelativePlaceableStructure(); + final InputStream stream = RickQRCodeTestStructure.class.getResourceAsStream("/schematics/rick.schem"); + structure.loadSchematic(stream); + return structure; + } + + public static RickQRCodeTestStructure getInstance() { + return TestStructureUtil.getInstance(RickQRCodeTestStructure.class); + } + + static { + TestStructureUtil.registerInstance(RickQRCodeTestStructure.class); + } +} diff --git a/src/main/java/xyz/webmc/wlib/internal/util/BuildUtil.java b/src/main/java/xyz/webmc/wlib/internal/util/BuildUtil.java index 8f7bd93..7b8f1da 100644 --- a/src/main/java/xyz/webmc/wlib/internal/util/BuildUtil.java +++ b/src/main/java/xyz/webmc/wlib/internal/util/BuildUtil.java @@ -20,7 +20,7 @@ public final class BuildUtil { private static final Properties properties = new Properties(); - public static String getProperty(final String key) { + public static String getProperty(String key) { return properties.getProperty(key).trim(); } diff --git a/src/main/java/xyz/webmc/wlib/internal/util/TestStructureUtil.java b/src/main/java/xyz/webmc/wlib/internal/util/TestStructureUtil.java index d252bd3..bbcdd40 100644 --- a/src/main/java/xyz/webmc/wlib/internal/util/TestStructureUtil.java +++ b/src/main/java/xyz/webmc/wlib/internal/util/TestStructureUtil.java @@ -13,9 +13,10 @@ package xyz.webmc.wlib.internal.util; -import xyz.webmc.wlib.api.structure.AbstractBaseStructure; +import xyz.webmc.wlib.api.structure.BaseStructure; +import xyz.webmc.wlib.internal.structure.CoordinateStructure; import xyz.webmc.wlib.internal.structure.HerobrineShrineTestStructure; -import xyz.webmc.wlib.internal.structure.RickQRCodeTestSchemStructure; +import xyz.webmc.wlib.internal.structure.RickQRCodeTestStructure; import java.util.HashSet; import java.util.Set; @@ -23,52 +24,71 @@ import dev.colbster937.reflect.MirrorSafe; public final class TestStructureUtil { - private static final Set> WLIB_TEST_STRUCTURES = Set.of( - HerobrineShrineTestStructure.class, - RickQRCodeTestSchemStructure.class - ); + private static final Set> WLIB_TEST_STRUCTURES = Set.of( + HerobrineShrineTestStructure.class, + RickQRCodeTestStructure.class, + CoordinateStructure.class); - private static final Set STRUCTURES = new HashSet<>(); + private static final Set STRUCTURES = new HashSet<>(); public static void _init() { - for (Class clazz : WLIB_TEST_STRUCTURES) { - AbstractBaseStructure.getInstance(clazz); + for (Class clazz : WLIB_TEST_STRUCTURES) { + getInstance(clazz); } } - public static void register(AbstractBaseStructure structure) { + public static T getInstance(Class clazz, Object... params) { + for (BaseStructure structure : STRUCTURES) { + if (structure.getClass().equals(clazz)) { + return clazz.cast(structure); + } + } + + T structure = MirrorSafe.invokeConstructor(clazz, params); + registerInstance(structure); + return structure; + } + + public static void registerInstance(Class clazz, Object... params) { + getInstance(clazz, params); + } + + private static void registerInstance(BaseStructure structure) { STRUCTURES.add(structure); } - public static AbstractBaseStructure getTestStructure(String name) { - return getTestStructure(name, "getName"); + public static BaseStructure getTestStructure(String name) { + for (BaseStructure structure : getStructures()) { + if (structure.getName().equals(name)) { + return structure; + } + } + + return null; } - public static AbstractBaseStructure getTestStructure(Class clazz) { - return getTestStructure(clazz, "getClass"); + public static BaseStructure getTestStructure(Class clazz) { + for (BaseStructure structure : getStructures()) { + if (structure.getClass().equals(clazz)) { + return structure; + } + } + + return null; } - public static Set getStructures() { + public static Set getStructures() { return STRUCTURES; } public static Set getStructureNames() { - final Set names = new HashSet<>(); + Set names = new HashSet<>(); - for (AbstractBaseStructure structure : getStructures()) { + for (BaseStructure structure : getStructures()) { names.add(structure.getName()); } return names; } - private static AbstractBaseStructure getTestStructure(T obj, String method) { - for (AbstractBaseStructure structure : getStructures()) { - if (MirrorSafe.invokeMethod(structure, method).equals(obj)) { - return structure; - } - } - - return null; - } }