From 6cf300a6ce4f7975f337b2df49d22c5bf618e47b Mon Sep 17 00:00:00 2001 From: GoldenGamerLP <65727384+GoldenGamerLP@users.noreply.github.com> Date: Sat, 29 Oct 2022 16:49:11 +0200 Subject: [PATCH 1/5] !Reformat Code by IntelliJ Added version properties in all build.gradle.kts for easier maintaining --- .github/ISSUE_TEMPLATE/bug_report.md | 17 +++-- .github/workflows/codeql.yml | 68 +++++++++---------- README.md | 36 ++++++---- build.gradle.kts | 13 ++++ core/build.gradle.kts | 12 ++-- .../dev/hypera/scaffolding/Scaffolding.java | 33 ++------- .../instance/SchematicChunkLoader.java | 17 +++-- .../dev/hypera/scaffolding/region/Region.java | 18 +++-- .../scaffolding/schematic/LegacyLookup.java | 14 ++-- .../schematic/NBTSchematicReader.java | 12 +--- .../scaffolding/schematic/Schematic.java | 15 +--- .../readers/MCEditSchematicReader.java | 9 +-- .../readers/SpongeSchematicReader.java | 14 ++-- docs/content/.vitepress/config.js | 66 +++++++++--------- docs/content/index.md | 1 + docs/content/setup/getting-started.md | 16 ++++- docs/content/usage/read.md | 2 + editor/README.md | 1 + editor/build.gradle.kts | 2 +- .../scaffolding/editor/ScaffoldingEditor.java | 13 ++-- .../editor/commands/LoadCommand.java | 9 +-- gradle/wrapper/gradle-wrapper.properties | 2 +- 22 files changed, 193 insertions(+), 197 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index dd84ea7..3205926 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -12,6 +12,7 @@ A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: + 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' @@ -24,15 +25,17 @@ A clear and concise description of what you expected to happen. If applicable, add screenshots to help explain your problem. **Desktop (please complete the following information):** - - OS: [e.g. iOS] - - Browser [e.g. chrome, safari] - - Version [e.g. 22] + +- OS: [e.g. iOS] +- Browser [e.g. chrome, safari] +- Version [e.g. 22] **Smartphone (please complete the following information):** - - Device: [e.g. iPhone6] - - OS: [e.g. iOS8.1] - - Browser [e.g. stock browser, safari] - - Version [e.g. 22] + +- Device: [e.g. iPhone6] +- OS: [e.g. iOS8.1] +- Browser [e.g. stock browser, safari] +- Version [e.g. 22] **Additional context** Add any other context about the problem here. diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 7ce3e3b..d3faf4d 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -25,43 +25,43 @@ jobs: # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Setup Java JDK - uses: actions/setup-java@v3.3.0 - with: - distribution: temurin - java-version: 17 - cache: maven + - name: Checkout repository + uses: actions/checkout@v3 - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality + - name: Setup Java JDK + uses: actions/setup-java@v3.3.0 + with: + distribution: temurin + java-version: 17 + cache: maven - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. - # ℹ️ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/README.md b/README.md index 5474407..48cf719 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,42 @@ # Scaffolding + Scaffolding is a library for Minestom that allows you to load and place schematics. -> This library is still under heavy development and has too many bugs to count. For your own safety, this should not be used in a production environment. +> This library is still under heavy development and has too many bugs to count. For your own safety, this should not be +> used in a production environment. > This library's API is likely to change a lot as this project works towards a stable 1.0.0 release. ## Usage + ```java // Load a schematic from File. -public void method1() { - Schematic schematic = Scaffolding.fromFile(new File("schematics/my_schematic.schematic")); -} +public void method1(){ + Schematic schematic=Scaffolding.fromFile(new File("schematics/my_schematic.schematic")); + } -public void method2() { - Schematic schematic = new SpongeSchematic(); - schematic.read(new FileInputStream(new File("schematics/my_schematic.schematic"))); -} +public void method2(){ + Schematic schematic=new SpongeSchematic(); + schematic.read(new FileInputStream(new File("schematics/my_schematic.schematic"))); + } ``` + ```java // Place a schematic at a location. -Instance instance = player.getInstance(); -Pos position = player.getPosition(); -schematic.build(instance, position).thenRun(() -> player.sendMessage("Schematic placed!")); +Instance instance=player.getInstance(); + Pos position=player.getPosition(); + schematic.build(instance,position).thenRun(()->player.sendMessage("Schematic placed!")); ``` + ```java // Write a schematic (Soon:tm:) -Region region = new Region(new Pos(0, 0, 0), new Pos(10, 10, 10)); -Schematic schematic = new SpongeSchematic(); -schematic.write(new FileOutputStream("schematics/my_schematic.schematic"), region); +Region region=new Region(new Pos(0,0,0),new Pos(10,10,10)); + Schematic schematic=new SpongeSchematic(); + schematic.write(new FileOutputStream("schematics/my_schematic.schematic"),region); ``` ## Dependency ### Gradle (Kotlin) + Add Scaffolding as a dependency in your `build.gradle.kts` file. ```kt @@ -44,6 +50,7 @@ dependencies { ``` ### Gradle (Groovy) + Add Scaffolding as a dependency in your `build.gradle` file. ```groovy @@ -57,6 +64,7 @@ dependencies { ``` ### Maven + Add Scaffolding as a dependency in your `pom.xml` file. ```xml diff --git a/build.gradle.kts b/build.gradle.kts index f75bff5..2c1bbb2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -23,6 +23,19 @@ group = "dev.hypera" version = "0.2.0-SNAPSHOT" +//Minestom +val minestomVersion by extra("7be96b7679") + +//Gson +val gsonVersion by extra("2.9.0") + +//Fast Utililities +val fastUtilVersion by extra("2.0.1") + +//Jupiter Testing +val jupiterAPIVersion by extra("5.8.2") +val jupiterEngineVersion by extra("5.8.2") + allprojects { repositories { mavenCentral() diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 6719cdf..87544f9 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -32,13 +32,13 @@ java { } dependencies { - compileOnlyApi("com.github.Minestom:Minestom:7be96b7679") - compileOnly("space.vectrix.flare:flare-fastutil:2.0.1") - compileOnly("com.google.code.gson:gson:2.9.0") + compileOnlyApi("com.github.Minestom:Minestom:${rootProject.extra["minestomVersion"]}") + compileOnly("space.vectrix.flare:flare-fastutil:${rootProject.extra["fastUtilVersion"]}") + compileOnly("com.google.code.gson:gson:${rootProject.extra["gsonVersion"]}") - testImplementation("com.github.Minestom:Minestom:7be96b7679") - testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.2") - testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.2") + testImplementation("com.github.Minestom:Minestom:${rootProject.extra["minestomVersion"]}") + testImplementation("org.junit.jupiter:junit-jupiter-api:${rootProject.extra["jupiterAPIVersion"]}") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${rootProject.extra["jupiterEngineVersion"]}") } publishing { diff --git a/core/src/main/java/dev/hypera/scaffolding/Scaffolding.java b/core/src/main/java/dev/hypera/scaffolding/Scaffolding.java index 6953ffa..c919336 100644 --- a/core/src/main/java/dev/hypera/scaffolding/Scaffolding.java +++ b/core/src/main/java/dev/hypera/scaffolding/Scaffolding.java @@ -26,20 +26,17 @@ import dev.hypera.scaffolding.schematic.Schematic; import dev.hypera.scaffolding.schematic.readers.MCEditSchematicReader; import dev.hypera.scaffolding.schematic.readers.SpongeSchematicReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.concurrent.CompletableFuture; import org.jetbrains.annotations.NotNull; import org.jglrxavpok.hephaistos.nbt.CompressedProcesser; import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTException; import org.jglrxavpok.hephaistos.nbt.NBTReader; +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.concurrent.CompletableFuture; + /** * A static utility class primarily used to parse schematics. */ @@ -49,14 +46,14 @@ public final class Scaffolding { private static final @NotNull NBTSchematicReader MC_EDIT_SCHEMATIC_READER = new MCEditSchematicReader(); private static final @NotNull NBTSchematicReader SPONGE_SCHEMATIC_READER = new SpongeSchematicReader(); - private Scaffolding() {} + private Scaffolding() { + } /** * Automatically detects the type of schematic and parses the file. * * @param path Schematic path - * * @return parsed schematic * @throws IOException if the file is invalid * @throws NBTException if the schematic is invalid @@ -69,7 +66,6 @@ private Scaffolding() {} /** * @param path the {@link Path} to read from * @param schematic the {@link Schematic} to load the data into - * * @return a {@link CompletableFuture} that will be completed when the schematic is loaded * @throws IOException if the file is invalid * @throws NBTException if the NBT tag is invalid @@ -84,7 +80,6 @@ private Scaffolding() {} * Automatically detects the type of schematic and parses the file. * * @param file Schematic file - * * @return parsed schematic * @throws IOException if the file is invalid * @throws NBTException if the schematic is invalid @@ -97,7 +92,6 @@ private Scaffolding() {} /** * @param file the {@link File} to read from * @param schematic the {@link Schematic} to load the data into - * * @return a {@link CompletableFuture} that will be completed when the schematic is loaded * @throws IOException if the file is invalid * @throws NBTException if the NBT tag is invalid @@ -112,7 +106,6 @@ private Scaffolding() {} * Automatically detects the type of schematic and parses the input stream * * @param inputStream Schematic input - * * @return a {@link CompletableFuture} that will contain the schematic once loaded * @throws IOException if the input stream is invalid * @throws NBTException if the schematic is invalid @@ -125,7 +118,6 @@ private Scaffolding() {} /** * @param inputStream the {@link InputStream} to read from * @param schematic the {@link Schematic} to load the data into - * * @return a {@link CompletableFuture} that will be completed when the schematic is loaded * @throws IOException if the input stream is invalid * @throws NBTException if the NBT tag is invalid @@ -139,7 +131,6 @@ private Scaffolding() {} * Automatically detects the schematic format from the provided {@link NBTCompound} and parses it. * * @param nbtTag The {@link NBTCompound} to read from - * * @return A {@link CompletableFuture} that will complete with the schematic once it's loaded * @throws NBTException If the NBT tag is invalid */ @@ -150,7 +141,6 @@ private Scaffolding() {} /** * @param nbtTag The NBT tag to parse * @param schematic The {@link Schematic} to load the data into - * * @return a {@link CompletableFuture} that will be completed when the schematic is loaded * @throws NBTException if the NBT tag is invalid */ @@ -165,10 +155,8 @@ private Scaffolding() {} } - /** * @param path The {@link Path} to read from - * * @return The parsed {@link Schematic} * @throws IOException if the file is invalid * @throws NBTException if the schematic is invalid @@ -181,7 +169,6 @@ private Scaffolding() {} /** * @param path the {@link Path} to read from * @param schematic the {@link Schematic} to load the data into - * * @return the parsed {@link Schematic} * @throws IOException if the file is invalid * @throws NBTException if the NBT tag is invalid @@ -193,7 +180,6 @@ private Scaffolding() {} /** * @param file The {@link File} to read from - * * @return The parsed {@link Schematic} * @throws IOException if the file is invalid * @throws NBTException if the schematic is invalid @@ -206,7 +192,6 @@ private Scaffolding() {} /** * @param file the {@link File} to read from * @param schematic the {@link Schematic} to load the data into - * * @return the parsed {@link Schematic} * @throws IOException if the file is invalid * @throws NBTException if the NBT tag is invalid @@ -220,7 +205,6 @@ private Scaffolding() {} * Automatically detects the schematic format from the provided {@link NBTCompound} and parses it synchronously. * * @param nbtTag the {@link NBTCompound} to read from - * * @return the parsed {@link Schematic} * @throws NBTException if the NBT tag is invalid * @throws IllegalArgumentException if the schematic is neither an MCEdit nor a Sponge schematic @@ -232,7 +216,6 @@ private Scaffolding() {} /** * @param nbtTag The NBT tag to parse * @param schematic The {@link Schematic} to load the data into - * * @return the parsed {@link Schematic} * @throws NBTException if the NBT tag is invalid */ @@ -243,7 +226,6 @@ private Scaffolding() {} /** * @param inputStream The {@link InputStream} to read from - * * @return The parsed {@link Schematic} * @throws IOException if the input stream is invalid * @throws NBTException if the schematic is invalid @@ -256,7 +238,6 @@ private Scaffolding() {} /** * @param inputStream the {@link InputStream} to read from * @param schematic the {@link Schematic} to load the data into - * * @return the parsed {@link Schematic} * @throws IOException if the input stream is invalid * @throws NBTException if the NBT tag is invalid diff --git a/core/src/main/java/dev/hypera/scaffolding/instance/SchematicChunkLoader.java b/core/src/main/java/dev/hypera/scaffolding/instance/SchematicChunkLoader.java index 9ca78aa..dc6638d 100644 --- a/core/src/main/java/dev/hypera/scaffolding/instance/SchematicChunkLoader.java +++ b/core/src/main/java/dev/hypera/scaffolding/instance/SchematicChunkLoader.java @@ -24,11 +24,6 @@ import dev.hypera.scaffolding.schematic.Schematic; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.function.Function; import net.minestom.server.coordinate.Vec; import net.minestom.server.instance.Chunk; import net.minestom.server.instance.DynamicChunk; @@ -42,6 +37,12 @@ import org.jetbrains.annotations.Nullable; import space.vectrix.flare.fastutil.Long2ObjectSyncMap; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; + // TODO: Entities? @SuppressWarnings("UnstableApiUsage") public class SchematicChunkLoader implements IChunkLoader { @@ -114,7 +115,8 @@ public static class Builder { private int yOffset; private int zOffset; - private Builder() {} + private Builder() { + } /** * Adds a schematic to this chunk loader. @@ -124,7 +126,6 @@ private Builder() {} * This means that the last added schematic is the only schematic that is guaranteed to have all its data. * * @param schematic The schematic to add. - * * @return This builder. */ // TODO: Add a way to position schematics within the instance. @@ -140,7 +141,6 @@ private Builder() {} * @param x The x offset. * @param y The y offset. * @param z The z offset. - * * @return This builder. */ @Contract("_,_,_ -> this") @@ -155,7 +155,6 @@ private Builder() {} * Specifies the handler to use to save the chunks. * * @param handler The handler. - * * @return This builder. */ @Contract("_ -> this") diff --git a/core/src/main/java/dev/hypera/scaffolding/region/Region.java b/core/src/main/java/dev/hypera/scaffolding/region/Region.java index f81c82a..8c5a442 100644 --- a/core/src/main/java/dev/hypera/scaffolding/region/Region.java +++ b/core/src/main/java/dev/hypera/scaffolding/region/Region.java @@ -22,18 +22,17 @@ */ package dev.hypera.scaffolding.region; -import dev.hypera.scaffolding.schematic.LegacyLookup; -import java.util.Objects; -import java.util.concurrent.CompletableFuture; -import java.util.function.BiFunction; import net.minestom.server.coordinate.Point; import net.minestom.server.coordinate.Vec; import net.minestom.server.instance.Chunk; import net.minestom.server.instance.Instance; -import org.jetbrains.annotations.ApiStatus.Internal; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; + /** * Represents a rectangle 3 dimensional region of blocks within an {@link Instance}. */ @@ -57,7 +56,6 @@ public Region(@NotNull Instance instance, @NotNull Point p1, @NotNull Point p2) } - /** * Force loads all {@link Chunk}s this region. * @@ -187,10 +185,10 @@ public int hashCode() { @Override public boolean equals(Object obj) { return obj == this || ( - obj instanceof Region region - && Objects.equals(this.instance, region.getInstance()) - && Objects.equals(this.lower, region.getLower()) - && Objects.equals(this.upper, region.getUpper()) + obj instanceof Region region + && Objects.equals(this.instance, region.getInstance()) + && Objects.equals(this.lower, region.getLower()) + && Objects.equals(this.upper, region.getUpper()) ); } diff --git a/core/src/main/java/dev/hypera/scaffolding/schematic/LegacyLookup.java b/core/src/main/java/dev/hypera/scaffolding/schematic/LegacyLookup.java index b37f5f8..bf7f46c 100644 --- a/core/src/main/java/dev/hypera/scaffolding/schematic/LegacyLookup.java +++ b/core/src/main/java/dev/hypera/scaffolding/schematic/LegacyLookup.java @@ -22,11 +22,13 @@ */ package dev.hypera.scaffolding.schematic; -import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import dev.hypera.scaffolding.Scaffolding; -import dev.hypera.scaffolding.region.Region; +import org.jetbrains.annotations.ApiStatus.Internal; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + import java.io.BufferedReader; import java.io.IOException; import java.net.URISyntaxException; @@ -35,12 +37,6 @@ import java.util.HashMap; import java.util.Map; import java.util.Objects; -import java.util.concurrent.CompletableFuture; -import net.minestom.server.instance.Chunk; -import net.minestom.server.instance.Instance; -import org.jetbrains.annotations.ApiStatus.Internal; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; /** * A static utility class containing useful methods used throughout Scaffolding. @@ -69,7 +65,6 @@ private LegacyLookup() { /** * @param legacyBlockId The legacy block ID * @param legacyBlockData The legacy block data - * * @return The modern state ID for the given legacy block ID and data */ public static short stateIdFromLegacy(int legacyBlockId, byte legacyBlockData) { @@ -82,7 +77,6 @@ public static short stateIdFromLegacy(int legacyBlockId, byte legacyBlockData) { * * @param legacyBlockId the legacy block ID * @param legacyBlockData the legacy block data - * * @return the lookup ID */ @Contract(pure = true) diff --git a/core/src/main/java/dev/hypera/scaffolding/schematic/NBTSchematicReader.java b/core/src/main/java/dev/hypera/scaffolding/schematic/NBTSchematicReader.java index 7781432..51038f6 100644 --- a/core/src/main/java/dev/hypera/scaffolding/schematic/NBTSchematicReader.java +++ b/core/src/main/java/dev/hypera/scaffolding/schematic/NBTSchematicReader.java @@ -22,12 +22,13 @@ */ package dev.hypera.scaffolding.schematic; -import java.util.concurrent.CompletableFuture; import org.jetbrains.annotations.NotNull; import org.jglrxavpok.hephaistos.collections.ImmutableByteArray; import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTException; +import java.util.concurrent.CompletableFuture; + /** * A parser for schematics that uses NBT to store data. */ @@ -35,6 +36,7 @@ public abstract class NBTSchematicReader { /** * Checks if the provided NBT tag can be read by this reader. + * * @param compound The {@link NBTCompound} to check * @return whether this reader can read the provided tag. */ @@ -45,7 +47,6 @@ public abstract class NBTSchematicReader { * * @param compound The {@link NBTCompound} to read from * @param schematic The {@link Schematic} to read into - * * @return a {@link CompletableFuture} that will be completed with the {@link Schematic} * @throws NBTException If the provided NBT tag is invalid */ @@ -55,7 +56,6 @@ public abstract class NBTSchematicReader { * @param compound The {@link NBTCompound} to read from * @param key The key to look for * @param exceptionMessage The exception message to throw if the key is not found - * * @return The value of the key * @throws NBTException If the provided NBT tag is invalid */ @@ -72,7 +72,6 @@ protected final int getInteger(@NotNull NBTCompound compound, @NotNull String ke * @param compound The {@link NBTCompound} to read from * @param key The key to look for * @param exceptionMessage The exception message to throw if the key is not found - * * @return The value of the key * @throws NBTException If the provided NBT tag is invalid */ @@ -89,7 +88,6 @@ protected final short getShort(@NotNull NBTCompound compound, @NotNull String ke * @param compound The {@link NBTCompound} to read from * @param key The key to look for * @param exceptionMessage The exception message to throw if the key is not found - * * @return The value of the key * @throws NBTException If the provided NBT tag is invalid */ @@ -106,7 +104,6 @@ protected final NBTCompound getCompound(@NotNull NBTCompound compound, @NotNull * @param compound The {@link NBTCompound} to read from * @param key The key to look for * @param exceptionMessage The exception message to throw if the key is not found - * * @return The value of the key * @throws NBTException If the provided NBT tag is invalid */ @@ -123,7 +120,6 @@ protected final byte getByte(@NotNull NBTCompound compound, @NotNull String key, * @param compound The {@link NBTCompound} to read from * @param key The key to look for * @param exceptionMessage The exception message to throw if the key is not found - * * @return The value of the key * @throws NBTException If the provided NBT tag is invalid */ @@ -140,7 +136,6 @@ protected final byte[] getByteArray(@NotNull NBTCompound compound, @NotNull Stri * @param compound The {@link NBTCompound} to read from * @param key The key to look for * @param exceptionMessage The exception message to throw if the key is not found - * * @return The value of the key * @throws NBTException If the provided NBT tag is invalid */ @@ -157,7 +152,6 @@ protected final boolean getBoolean(@NotNull NBTCompound compound, @NotNull Strin * @param compound The {@link NBTCompound} to read from * @param key The key to look for * @param exceptionMessage The exception message to throw if the key is not found - * * @return The value of the key * @throws NBTException If the provided NBT tag is invalid */ diff --git a/core/src/main/java/dev/hypera/scaffolding/schematic/Schematic.java b/core/src/main/java/dev/hypera/scaffolding/schematic/Schematic.java index 1b44302..c861385 100644 --- a/core/src/main/java/dev/hypera/scaffolding/schematic/Schematic.java +++ b/core/src/main/java/dev/hypera/scaffolding/schematic/Schematic.java @@ -23,10 +23,8 @@ package dev.hypera.scaffolding.schematic; import dev.hypera.scaffolding.region.Region; -import java.util.concurrent.CompletableFuture; import net.minestom.server.coordinate.Point; import net.minestom.server.coordinate.Vec; -import net.minestom.server.instance.Chunk; import net.minestom.server.instance.Instance; import net.minestom.server.instance.batch.AbsoluteBlockBatch; import net.minestom.server.instance.block.Block; @@ -36,10 +34,12 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.concurrent.CompletableFuture; + /** * A parsed schematic. */ -@SuppressWarnings({ "unused", "UnstableApiUsage" }) +@SuppressWarnings({"unused", "UnstableApiUsage"}) public final class Schematic implements Block.Setter { private short[] blocks; @@ -74,7 +74,6 @@ public void reset() { * Copies blocks from the given region into this schematic. * * @param region the {@link Region} to copy from - * * @return a {@link CompletableFuture} that will complete once all blocks have been copied */ public @NotNull CompletableFuture copy(@NotNull Region region) { @@ -131,7 +130,6 @@ public void setSize(int width, int height, int length) { * @param x block x coordinate * @param y block y coordinate * @param z block z coordinate - * * @return the index of the block at the given coordinates */ public int getBlockIndex(int x, int y, int z) { @@ -143,7 +141,6 @@ public int getBlockIndex(int x, int y, int z) { * * @param instance the {@link Instance} to build this schematic in * @param position the {@link Point} to build this schematic at (note: the schematics offset will be applied to this position to get the lower corner) - * * @return a {@link CompletableFuture} that will complete once the schematic has been built */ public @NotNull CompletableFuture build(@NotNull Instance instance, @NotNull Point position) { @@ -158,7 +155,6 @@ public int getBlockIndex(int x, int y, int z) { * @param flipX whether to flip the schematic along the X axis * @param flipY whether to flip the schematic along the Y axis * @param flipZ whether to flip the schematic along the Z axis - * * @return a {@link CompletableFuture} that will complete once the schematic has been built */ public @NotNull CompletableFuture build(@NotNull Instance instance, @NotNull Point position, boolean flipX, boolean flipY, boolean flipZ) { @@ -184,7 +180,6 @@ public int getBlockIndex(int x, int y, int z) { /** * @param instance the {@link Instance} to check * @param position the {@link Point} to check - * * @return the {@link Region} that this schematic would take up if placed at the given position */ public @NotNull Region getContainingRegion(@NotNull Instance instance, @NotNull Point position) { @@ -202,7 +197,6 @@ private boolean isPlaceable(@NotNull Region region) { * Applies the schematic to the given block setter. * * @param setter the block setter - * * @deprecated See {@link Schematic#apply(Point, boolean, boolean, boolean, Setter)} */ @Deprecated @@ -247,7 +241,6 @@ public void apply(@NotNull Point position, boolean flipX, boolean flipY, boolean * @param x block x coordinate * @param y block y coordinate * @param z block z coordinate - * * @return the block at the given coordinates */ @Nullable @@ -259,7 +252,6 @@ public Block getBlock(int x, int y, int z) { * @param x block x coordinate * @param y block y coordinate * @param z block z coordinate - * * @return the state ID at the given coordinates */ public short getStateId(int x, int y, int z) { @@ -407,7 +399,6 @@ public void setOffset(int x, int y, int z) { /** * @param instance the {@link Instance} to check * @param position the {@link Point} to check - * * @return {@code true} if the given position is within the bounds of the given instance, {@code false} otherwise. If either the instance or the position is null, false is returned. */ public boolean isPlaceable(@Nullable Instance instance, @Nullable Point position) { diff --git a/core/src/main/java/dev/hypera/scaffolding/schematic/readers/MCEditSchematicReader.java b/core/src/main/java/dev/hypera/scaffolding/schematic/readers/MCEditSchematicReader.java index 1bf1cc0..28720d2 100644 --- a/core/src/main/java/dev/hypera/scaffolding/schematic/readers/MCEditSchematicReader.java +++ b/core/src/main/java/dev/hypera/scaffolding/schematic/readers/MCEditSchematicReader.java @@ -22,16 +22,17 @@ */ package dev.hypera.scaffolding.schematic.readers; -import dev.hypera.scaffolding.schematic.NBTSchematicReader; import dev.hypera.scaffolding.schematic.LegacyLookup; +import dev.hypera.scaffolding.schematic.NBTSchematicReader; import dev.hypera.scaffolding.schematic.Schematic; -import java.util.Objects; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; import org.jetbrains.annotations.NotNull; import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTException; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; + /** * A parser for MCEdit schematics. (.schematic files) * diff --git a/core/src/main/java/dev/hypera/scaffolding/schematic/readers/SpongeSchematicReader.java b/core/src/main/java/dev/hypera/scaffolding/schematic/readers/SpongeSchematicReader.java index ec67f37..f803a56 100644 --- a/core/src/main/java/dev/hypera/scaffolding/schematic/readers/SpongeSchematicReader.java +++ b/core/src/main/java/dev/hypera/scaffolding/schematic/readers/SpongeSchematicReader.java @@ -24,14 +24,6 @@ import dev.hypera.scaffolding.schematic.NBTSchematicReader; import dev.hypera.scaffolding.schematic.Schematic; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; import net.minestom.server.instance.block.Block; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,6 +31,10 @@ import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTException; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; + /** * A parser for Sponge schematics. (.schem files) * @@ -103,7 +99,7 @@ private void readBlockPalette(@NotNull Schematic schematic, @NotNull NBTCompound } Map palette = unsortedPalette.entrySet().stream().sorted(Map.Entry.comparingByValue()) - .collect(LinkedHashMap::new, (map, entry) -> map.put(entry.getKey(), entry.getValue()), LinkedHashMap::putAll); + .collect(LinkedHashMap::new, (map, entry) -> map.put(entry.getKey(), entry.getValue()), LinkedHashMap::putAll); ImmutableByteArray blocksData = nbtTag.getByteArray("BlockData"); if (blocksData == null || blocksData.getSize() == 0) { diff --git a/docs/content/.vitepress/config.js b/docs/content/.vitepress/config.js index f860c0c..66ac952 100644 --- a/docs/content/.vitepress/config.js +++ b/docs/content/.vitepress/config.js @@ -24,42 +24,42 @@ import {defineConfig} from 'vitepress' export default defineConfig({ - title: 'Scaffolding', - description: 'Schematic library for Minestom', + title: 'Scaffolding', + description: 'Schematic library for Minestom', - themeConfig: { - sidebar: { - '/': getSidebar() + themeConfig: { + sidebar: { + '/': getSidebar() + } } - } }) function getSidebar() { - return [ - { - text: 'Introduction', - link: '/' - }, - { - text: 'Setup', - children: [ - { text: 'Getting Started', link: '/setup/getting-started' }, - ] - }, - { - text: 'Using Schematics', - children: [ - { text: 'Load', link: '/usage/read' }, - { text: 'Copy', link: '/usage/copy' }, - { text: 'Build', link: '/usage/build ' }, - { text: 'Write', link: '/usage/write ' }, - ] - }, - { - text: 'Utilities', - children: [ - { text: 'Region', link: '/utilities/region' }, - ] - }, - ] + return [ + { + text: 'Introduction', + link: '/' + }, + { + text: 'Setup', + children: [ + {text: 'Getting Started', link: '/setup/getting-started'}, + ] + }, + { + text: 'Using Schematics', + children: [ + {text: 'Load', link: '/usage/read'}, + {text: 'Copy', link: '/usage/copy'}, + {text: 'Build', link: '/usage/build '}, + {text: 'Write', link: '/usage/write '}, + ] + }, + { + text: 'Utilities', + children: [ + {text: 'Region', link: '/utilities/region'}, + ] + }, + ] } diff --git a/docs/content/index.md b/docs/content/index.md index d1759c3..f8a32db 100644 --- a/docs/content/index.md +++ b/docs/content/index.md @@ -1,2 +1,3 @@ # Introduction + Scaffolding is a library for interacting with schematics for the [Minestom](https://minestom.net/) framework. \ No newline at end of file diff --git a/docs/content/setup/getting-started.md b/docs/content/setup/getting-started.md index 1eab389..25dd3bd 100644 --- a/docs/content/setup/getting-started.md +++ b/docs/content/setup/getting-started.md @@ -3,16 +3,18 @@ This guide describes how to setup Scaffolding as a dependency for your project. ::: info -Scaffolding is intended to be used as a library for the Minestom framework. You can learn how to setup Minestom [here](https://wiki.minestom.net/setup/dependencies/). +Scaffolding is intended to be used as a library for the Minestom framework. You can learn how to setup +Minestom [here](https://wiki.minestom.net/setup/dependencies/). ::: - ## Repository As with Minestom, Scaffolding uses JitPack to distribute releases. ### Gradle (Kotlin) + Add JitPack as a repository to your ```build.gradle.kts``` file. + ```kotlin{2} repositories { maven(url = "https://jitpack.io") @@ -20,7 +22,9 @@ repositories { ``` ### Gradle (Groovy) + Add JitPack as a repository to your ```build.gradle``` file. + ```groovy{2} repositories { maven { url 'https://jitpack.io' } @@ -28,7 +32,9 @@ repositories { ``` ### Maven + Add JitPack as a repository to your ```pom.xml``` file. + ```xml{2-5} @@ -43,7 +49,9 @@ Add JitPack as a repository to your ```pom.xml``` file. Keep an eye out for new releases on [Jitpack](https://jitpack.io/#CrystalGamesMc/scaffolding). ### Gradle (Kotlin) + Add Scaffolding as a dependency in your ```build.gradle.kts``` file. + ```kts{2} dependencies { implementation("com.github.CrystalGamesMc:scaffolding:Tag") @@ -51,7 +59,9 @@ dependencies { ``` ### Gradle (Groovy) + Add Scaffolding as a dependency in your ```build.gradle``` file. + ```groovy{2} dependencies { implementation 'com.github.CrystalGamesMc:scaffolding:Tag' @@ -59,7 +69,9 @@ dependencies { ``` ### Maven + Add Scaffolding as a dependency in your ```pom.xml``` file. + ```xml{2-6} diff --git a/docs/content/usage/read.md b/docs/content/usage/read.md index 77876db..f44327d 100644 --- a/docs/content/usage/read.md +++ b/docs/content/usage/read.md @@ -1,7 +1,9 @@ # Loading Schematics + Scaffolding offers many ways to load schematics. ## Automatically parsing type + ```java File file = new File("schematics/your_schematic.schematic"); Schematic schematic = Scaffolding.fromFileSync(file); diff --git a/editor/README.md b/editor/README.md index 0e2af61..e4d2d91 100644 --- a/editor/README.md +++ b/editor/README.md @@ -1,2 +1,3 @@ # Scaffolding Editor + Scaffolding Editor is by no means production-ready. Currently, this is just a test environment for Scaffolding's core. \ No newline at end of file diff --git a/editor/build.gradle.kts b/editor/build.gradle.kts index e34efa4..2c37331 100644 --- a/editor/build.gradle.kts +++ b/editor/build.gradle.kts @@ -35,5 +35,5 @@ java { dependencies { implementation(project(":core")) - implementation("com.github.Minestom:Minestom:7be96b7679") + implementation("com.github.Minestom:Minestom:${rootProject.extra["minestomVersion"]}") } \ No newline at end of file diff --git a/editor/src/main/java/dev/hypera/scaffolding/editor/ScaffoldingEditor.java b/editor/src/main/java/dev/hypera/scaffolding/editor/ScaffoldingEditor.java index fc524d0..cc06581 100644 --- a/editor/src/main/java/dev/hypera/scaffolding/editor/ScaffoldingEditor.java +++ b/editor/src/main/java/dev/hypera/scaffolding/editor/ScaffoldingEditor.java @@ -26,11 +26,6 @@ import dev.hypera.scaffolding.editor.commands.LoadCommand; import dev.hypera.scaffolding.editor.commands.PasteCommand; import dev.hypera.scaffolding.editor.features.SelectionFeature; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.HashMap; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.minestom.server.MinecraftServer; @@ -50,6 +45,12 @@ import net.minestom.server.utils.NamespaceID; import net.minestom.server.world.DimensionType; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; + public class ScaffoldingEditor { public static final Path SCHEMATICS_PATH = Paths.get("schematics"); @@ -86,7 +87,7 @@ public static void main(String[] args) throws IOException { ItemStack wand = ItemStack.builder(Material.WOODEN_AXE) .amount(1) - .displayName(Component.text("Selection Tool", NamedTextColor.WHITE)) + .displayName(Component.text("Selection Tool", NamedTextColor.GOLD)) .lore( Component.text("Use this to edit the world.", NamedTextColor.GRAY), Component.empty(), Clipboard.FIRST_POINT_COMPONENT.append(Component.text(" - left click", NamedTextColor.GRAY)), diff --git a/editor/src/main/java/dev/hypera/scaffolding/editor/commands/LoadCommand.java b/editor/src/main/java/dev/hypera/scaffolding/editor/commands/LoadCommand.java index bcf7ed0..d69c099 100644 --- a/editor/src/main/java/dev/hypera/scaffolding/editor/commands/LoadCommand.java +++ b/editor/src/main/java/dev/hypera/scaffolding/editor/commands/LoadCommand.java @@ -25,10 +25,6 @@ import dev.hypera.scaffolding.Scaffolding; import dev.hypera.scaffolding.editor.Clipboard; import dev.hypera.scaffolding.editor.ScaffoldingEditor; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.stream.Stream; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.minestom.server.command.builder.Command; @@ -38,6 +34,11 @@ import net.minestom.server.entity.Player; import org.jglrxavpok.hephaistos.nbt.NBTException; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.stream.Stream; + public class LoadCommand extends Command { public LoadCommand() { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f5589ad..2010eb1 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -20,9 +20,9 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # - distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists +org.gradle.jvmargs=-Dfile.encoding=UTF-8 From bcfebddd1087bad54e2243ec2016fe528cd0d7d9 Mon Sep 17 00:00:00 2001 From: GoldenGamerLP <65727384+GoldenGamerLP@users.noreply.github.com> Date: Sat, 29 Oct 2022 17:31:32 +0200 Subject: [PATCH 2/5] Updated Minestom Version Updated codeql --- .github/workflows/codeql.yml | 2 +- build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index d3faf4d..9bc5ec9 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -33,7 +33,7 @@ jobs: with: distribution: temurin java-version: 17 - cache: maven + cache: gradle # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/build.gradle.kts b/build.gradle.kts index 2c1bbb2..da0956b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -24,7 +24,7 @@ group = "dev.hypera" version = "0.2.0-SNAPSHOT" //Minestom -val minestomVersion by extra("7be96b7679") +val minestomVersion by extra("-SNAPSHOT") //Gson val gsonVersion by extra("2.9.0") From cbf96de5d52f5f03e9cf746d998883ff3221d35f Mon Sep 17 00:00:00 2001 From: GoldenGamerLP <65727384+GoldenGamerLP@users.noreply.github.com> Date: Sun, 30 Oct 2022 14:17:16 +0100 Subject: [PATCH 3/5] Fixed compile error with UTF-8 and the license header in class SchematicChunkLoader.java Fixed not finding legacy data file, imporved read speeds in LegacyLookup.java Added version lookup into SpongeSchematicReader.java check Added UTF-8 java compile option too --- build.gradle.kts | 13 ++++++ core/build.gradle.kts | 6 +++ .../scaffolding/schematic/LegacyLookup.java | 43 +++++++++++++------ .../scaffolding/schematic/Schematic.java | 17 +++++--- .../readers/SpongeSchematicReader.java | 3 +- editor/build.gradle.kts | 5 +++ .../editor/commands/LoadCommand.java | 10 +++-- 7 files changed, 73 insertions(+), 24 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index da0956b..12313ae 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -36,9 +36,22 @@ val fastUtilVersion by extra("2.0.1") val jupiterAPIVersion by extra("5.8.2") val jupiterEngineVersion by extra("5.8.2") +plugins { + `java-library` +} + allprojects { repositories { mavenCentral() maven("https://jitpack.io/") } + + + +} + +tasks { + compileJava { + options.encoding = "UTF-8" + } } \ No newline at end of file diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 87544f9..462263c 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -41,6 +41,12 @@ dependencies { testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${rootProject.extra["jupiterEngineVersion"]}") } +tasks { + compileJava { + options.encoding = "UTF-8" + } +} + publishing { publications.create("maven") { from(components["java"]) diff --git a/core/src/main/java/dev/hypera/scaffolding/schematic/LegacyLookup.java b/core/src/main/java/dev/hypera/scaffolding/schematic/LegacyLookup.java index bf7f46c..23971e2 100644 --- a/core/src/main/java/dev/hypera/scaffolding/schematic/LegacyLookup.java +++ b/core/src/main/java/dev/hypera/scaffolding/schematic/LegacyLookup.java @@ -22,16 +22,22 @@ */ package dev.hypera.scaffolding.schematic; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; +import com.google.gson.*; +import com.google.gson.stream.JsonReader; import dev.hypera.scaffolding.Scaffolding; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.io.FastBufferedInputStream; import org.jetbrains.annotations.ApiStatus.Internal; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import java.io.BufferedReader; -import java.io.IOException; +import java.io.*; import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.HashMap; @@ -44,17 +50,28 @@ @Internal public final class LegacyLookup { - private static final @NotNull String LEGACY_FILE_NAME = "legacy.json"; - private static final @NotNull Map LEGACY_LOOKUP = new HashMap<>(); + private static final @NotNull String LEGACY_FILE_NAME = "/legacy.json"; + private static final @NotNull Int2ObjectMap LEGACY_LOOKUP = new Int2ObjectOpenHashMap<>(); + private static final @NotNull Logger LOGGER = LoggerFactory.getLogger(LegacyLookup.class); static { - try (BufferedReader reader = Files.newBufferedReader(Path.of(Objects.requireNonNull(Scaffolding.class.getClassLoader().getResource(LEGACY_FILE_NAME)).toURI()))) { - JsonParser.parseReader(reader).getAsJsonArray().forEach(data -> { - JsonObject object = data.getAsJsonObject(); - LEGACY_LOOKUP.put(getLookupId(object.get("block").getAsInt(), object.get("data").getAsByte()), object.get("state").getAsShort()); - }); - } catch (IOException | URISyntaxException ex) { - ex.printStackTrace(); + LOGGER.info(LegacyLookup.class.getResource(LEGACY_FILE_NAME).getFile()); + try(BufferedReader reader = new BufferedReader(new InputStreamReader(LegacyLookup.class.getResourceAsStream(LEGACY_FILE_NAME), StandardCharsets.UTF_8))) { + JsonArray obj = JsonParser.parseReader(reader).getAsJsonArray(); + + + for (JsonElement jsonElement : obj) { + JsonObject object = jsonElement.getAsJsonObject(); + + LEGACY_LOOKUP.computeIfAbsent( + getLookupId(object.get("block").getAsInt(), object.get("data").getAsByte() + ), + integer -> object.get("state").getAsShort() + ); + } + LOGGER.info("Loaded legacy data."); + } catch (IOException e) { + LOGGER.error("Error while initializing Legacy data", e); } } diff --git a/core/src/main/java/dev/hypera/scaffolding/schematic/Schematic.java b/core/src/main/java/dev/hypera/scaffolding/schematic/Schematic.java index c861385..b9682d9 100644 --- a/core/src/main/java/dev/hypera/scaffolding/schematic/Schematic.java +++ b/core/src/main/java/dev/hypera/scaffolding/schematic/Schematic.java @@ -35,6 +35,8 @@ import org.jetbrains.annotations.Nullable; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.LockSupport; /** * A parsed schematic. @@ -48,7 +50,8 @@ public final class Schematic implements Block.Setter { private int offsetX, offsetY, offsetZ; private int area; - private boolean locked; + private final AtomicBoolean locked = new AtomicBoolean(); + /** * Constructs a new schematic. The schematic will be locked and have an area of 0. @@ -103,7 +106,7 @@ public void reset() { } } - locked = false; + locked.set(false); return this; }); } @@ -158,7 +161,7 @@ public int getBlockIndex(int x, int y, int z) { * @return a {@link CompletableFuture} that will complete once the schematic has been built */ public @NotNull CompletableFuture build(@NotNull Instance instance, @NotNull Point position, boolean flipX, boolean flipY, boolean flipZ) { - if (locked) { + if (locked.get()) { throw new IllegalStateException("Cannot build a locked schematic."); } @@ -214,7 +217,7 @@ public void apply(@NotNull Block.Setter setter) { * @param setter the {@link Block.Setter} to apply this schematic to */ public void apply(@NotNull Point position, boolean flipX, boolean flipY, boolean flipZ, @NotNull Block.Setter setter) { - if (locked) { + if (locked.get()) { throw new IllegalStateException("Cannot apply a locked schematic."); } @@ -266,7 +269,7 @@ public short getStateId(int x, int y, int z) { * @param flipZ whether to flip the schematic along the Z axis */ public void fork(@NotNull GenerationUnit unit, @NotNull Point position, boolean flipX, boolean flipY, boolean flipZ) { - if (locked) { + if (locked.get()) { throw new IllegalStateException("Cannot fork a locked schematic."); } @@ -366,7 +369,7 @@ public int getArea() { * @return true if this schematic is locked, false otherwise */ public boolean isLocked() { - return locked; + return locked.getAcquire(); } /** @@ -375,7 +378,7 @@ public boolean isLocked() { * @param locked whether to lock this schematic */ public void setLocked(boolean locked) { - this.locked = locked; + this.locked.setRelease(locked); } /** diff --git a/core/src/main/java/dev/hypera/scaffolding/schematic/readers/SpongeSchematicReader.java b/core/src/main/java/dev/hypera/scaffolding/schematic/readers/SpongeSchematicReader.java index f803a56..231e34f 100644 --- a/core/src/main/java/dev/hypera/scaffolding/schematic/readers/SpongeSchematicReader.java +++ b/core/src/main/java/dev/hypera/scaffolding/schematic/readers/SpongeSchematicReader.java @@ -46,7 +46,8 @@ public class SpongeSchematicReader extends NBTSchematicReader { @Override public boolean isReadable(@NotNull NBTCompound compound) { // TODO: Improve this - return compound.contains("Palette"); + int version = compound.contains("Version") ? compound.getAsInt("Version") : 0; + return compound.contains("Palette") || version < 2; } @Override diff --git a/editor/build.gradle.kts b/editor/build.gradle.kts index 2c37331..7b763bb 100644 --- a/editor/build.gradle.kts +++ b/editor/build.gradle.kts @@ -31,6 +31,11 @@ java { targetCompatibility = JavaVersion.VERSION_17 } +tasks { + compileJava { + options.encoding = "UTF-8" + } +} dependencies { implementation(project(":core")) diff --git a/editor/src/main/java/dev/hypera/scaffolding/editor/commands/LoadCommand.java b/editor/src/main/java/dev/hypera/scaffolding/editor/commands/LoadCommand.java index d69c099..fb0591c 100644 --- a/editor/src/main/java/dev/hypera/scaffolding/editor/commands/LoadCommand.java +++ b/editor/src/main/java/dev/hypera/scaffolding/editor/commands/LoadCommand.java @@ -37,6 +37,9 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.stream.Stream; public class LoadCommand extends Command { @@ -65,9 +68,10 @@ public LoadCommand() { Scaffolding.fromFile(ScaffoldingEditor.SCHEMATICS_PATH.resolve(schematicName).toFile(), clipboard.getSchematic()).thenRun(() -> { player.sendMessage(Component.text("Loaded schematic " + schematicName, NamedTextColor.GRAY)); - }); - } catch (IOException | NBTException e) { - player.sendMessage("Failed to load schematic"); + }).get(2, TimeUnit.SECONDS); + } catch (IOException | NBTException | ExecutionException | InterruptedException | TimeoutException e) { + player.sendMessage("Failed to load schematic" + e.getLocalizedMessage()); + e.printStackTrace(); } } }, nameArgument); From d2bdc7657fab54dddaf84c57ad0482b1cb7b15e8 Mon Sep 17 00:00:00 2001 From: GoldenGamerLP <65727384+GoldenGamerLP@users.noreply.github.com> Date: Sun, 30 Oct 2022 14:33:05 +0100 Subject: [PATCH 4/5] Hot fix, removed logger for file path --- .../instance/SchematicChunkLoader.java | 25 ++----------------- .../scaffolding/schematic/LegacyLookup.java | 1 - 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/core/src/main/java/dev/hypera/scaffolding/instance/SchematicChunkLoader.java b/core/src/main/java/dev/hypera/scaffolding/instance/SchematicChunkLoader.java index dc6638d..8e7c875 100644 --- a/core/src/main/java/dev/hypera/scaffolding/instance/SchematicChunkLoader.java +++ b/core/src/main/java/dev/hypera/scaffolding/instance/SchematicChunkLoader.java @@ -1,25 +1,3 @@ -/* - * Scaffolding - Schematic library for Minestom - * Copyright (c) 2022-latest The Scaffolding Library Authors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the “Software”), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ package dev.hypera.scaffolding.instance; import dev.hypera.scaffolding.schematic.Schematic; @@ -44,6 +22,7 @@ import java.util.function.Function; // TODO: Entities? +//Todo: Implement a working save handler @SuppressWarnings("UnstableApiUsage") public class SchematicChunkLoader implements IChunkLoader { @@ -170,4 +149,4 @@ private Builder() { } -} +} \ No newline at end of file diff --git a/core/src/main/java/dev/hypera/scaffolding/schematic/LegacyLookup.java b/core/src/main/java/dev/hypera/scaffolding/schematic/LegacyLookup.java index 23971e2..a48cbb6 100644 --- a/core/src/main/java/dev/hypera/scaffolding/schematic/LegacyLookup.java +++ b/core/src/main/java/dev/hypera/scaffolding/schematic/LegacyLookup.java @@ -55,7 +55,6 @@ public final class LegacyLookup { private static final @NotNull Logger LOGGER = LoggerFactory.getLogger(LegacyLookup.class); static { - LOGGER.info(LegacyLookup.class.getResource(LEGACY_FILE_NAME).getFile()); try(BufferedReader reader = new BufferedReader(new InputStreamReader(LegacyLookup.class.getResourceAsStream(LEGACY_FILE_NAME), StandardCharsets.UTF_8))) { JsonArray obj = JsonParser.parseReader(reader).getAsJsonArray(); From 3878e09494c2fbf38d26d4ab85945101951523a8 Mon Sep 17 00:00:00 2001 From: GoldenGamerLP <65727384+GoldenGamerLP@users.noreply.github.com> Date: Wed, 9 Nov 2022 19:21:09 +0100 Subject: [PATCH 5/5] Updated comments/java docs Updated README.md Looked through some files and updated them --- README.md | 46 ++++-- build.gradle.kts | 3 - .../dev/hypera/scaffolding/Scaffolding.java | 45 ++++-- .../instance/SchematicChunkLoader.java | 3 + .../dev/hypera/scaffolding/region/Region.java | 15 ++ .../scaffolding/schematic/LegacyLookup.java | 28 ++-- .../schematic/NBTSchematicReader.java | 11 +- .../scaffolding/schematic/Schematic.java | 32 +++- .../readers/MCEditSchematicReader.java | 1 - .../readers/SpongeSchematicReader.java | 2 +- .../hypera/scaffolding/editor/Clipboard.java | 147 ++++++++++++++---- .../scaffolding/editor/ScaffoldingEditor.java | 4 +- .../editor/commands/LoadCommand.java | 24 ++- .../editor/commands/PasteCommand.java | 20 ++- .../editor/commands/SaveCommand.java | 77 +++++++++ gradle.properties | 8 + 16 files changed, 379 insertions(+), 87 deletions(-) create mode 100644 editor/src/main/java/dev/hypera/scaffolding/editor/commands/SaveCommand.java create mode 100644 gradle.properties diff --git a/README.md b/README.md index 48cf719..fad72be 100644 --- a/README.md +++ b/README.md @@ -8,29 +8,41 @@ Scaffolding is a library for Minestom that allows you to load and place schemati ## Usage ```java -// Load a schematic from File. -public void method1(){ - Schematic schematic=Scaffolding.fromFile(new File("schematics/my_schematic.schematic")); - } -public void method2(){ - Schematic schematic=new SpongeSchematic(); +//Load Schematics +public class LoadASchematic { + public void method1(){ + Schematic schematic = Scaffolding.fromFile(new File("schematics/my_schematic.schematic")); + } + + + public void method2(){ + Schematic schematic = new Schematic(); schematic.read(new FileInputStream(new File("schematics/my_schematic.schematic"))); - } -``` + } +} -```java -// Place a schematic at a location. -Instance instance=player.getInstance(); - Pos position=player.getPosition(); - schematic.build(instance,position).thenRun(()->player.sendMessage("Schematic placed!")); ``` ```java -// Write a schematic (Soon:tm:) -Region region=new Region(new Pos(0,0,0),new Pos(10,10,10)); - Schematic schematic=new SpongeSchematic(); - schematic.write(new FileOutputStream("schematics/my_schematic.schematic"),region); + +public class LoadAndPasteSchematicOrSaveIt { + + // Place a schematic at a location. + public void method1() { + Instance instance = player.getInstance(); + Pos position = player.getPosition(); + schematic.build(instance, position).thenRun(() -> player.sendMessage("Schematic placed!")); + } + + + //Select a region and save it to a schematic (Soon TM) + public void method2() { + Region region = new Region(new Pos(0, 0, 0), new Pos(10, 10, 10)); + Schematic schematic = new SpongeSchematic(); + schematic.write(new FileOutputStream("schematics/my_schematic.schematic"), region); + } +} ``` ## Dependency diff --git a/build.gradle.kts b/build.gradle.kts index 12313ae..d27c43b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -45,9 +45,6 @@ allprojects { mavenCentral() maven("https://jitpack.io/") } - - - } tasks { diff --git a/core/src/main/java/dev/hypera/scaffolding/Scaffolding.java b/core/src/main/java/dev/hypera/scaffolding/Scaffolding.java index c919336..e06eedc 100644 --- a/core/src/main/java/dev/hypera/scaffolding/Scaffolding.java +++ b/core/src/main/java/dev/hypera/scaffolding/Scaffolding.java @@ -26,6 +26,7 @@ import dev.hypera.scaffolding.schematic.Schematic; import dev.hypera.scaffolding.schematic.readers.MCEditSchematicReader; import dev.hypera.scaffolding.schematic.readers.SpongeSchematicReader; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.NotNull; import org.jglrxavpok.hephaistos.nbt.CompressedProcesser; import org.jglrxavpok.hephaistos.nbt.NBTCompound; @@ -35,6 +36,7 @@ import java.io.*; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Optional; import java.util.concurrent.CompletableFuture; /** @@ -42,9 +44,15 @@ */ @SuppressWarnings("unused") public final class Scaffolding { + private static final ObjectArrayList MC_SCHEMATIC_READERS; - private static final @NotNull NBTSchematicReader MC_EDIT_SCHEMATIC_READER = new MCEditSchematicReader(); - private static final @NotNull NBTSchematicReader SPONGE_SCHEMATIC_READER = new SpongeSchematicReader(); + + static { + MC_SCHEMATIC_READERS = new ObjectArrayList<>(); + + MC_SCHEMATIC_READERS.add(new MCEditSchematicReader()); + MC_SCHEMATIC_READERS.add(new SpongeSchematicReader()); + } private Scaffolding() { } @@ -58,6 +66,7 @@ private Scaffolding() { * @throws IOException if the file is invalid * @throws NBTException if the schematic is invalid * @throws IllegalArgumentException if the schematic is neither an MCEdit nor a Sponge schematic + * */ public static @NotNull CompletableFuture fromPath(@NotNull Path path) throws IOException, NBTException, IllegalArgumentException { return fromPath(path, new Schematic()); @@ -69,6 +78,7 @@ private Scaffolding() { * @return a {@link CompletableFuture} that will be completed when the schematic is loaded * @throws IOException if the file is invalid * @throws NBTException if the NBT tag is invalid + * */ public static @NotNull CompletableFuture fromPath(@NotNull Path path, @NotNull Schematic schematic) throws IOException, NBTException { if (!Files.exists(path)) throw new FileNotFoundException("Invalid Schematic: File does not exist"); @@ -84,6 +94,7 @@ private Scaffolding() { * @throws IOException if the file is invalid * @throws NBTException if the schematic is invalid * @throws IllegalArgumentException if the schematic is neither an MCEdit nor a Sponge schematic + * */ public static @NotNull CompletableFuture fromFile(@NotNull File file) throws IOException, NBTException, IllegalArgumentException { return fromFile(file, new Schematic()); @@ -95,6 +106,7 @@ private Scaffolding() { * @return a {@link CompletableFuture} that will be completed when the schematic is loaded * @throws IOException if the file is invalid * @throws NBTException if the NBT tag is invalid + * */ public static @NotNull CompletableFuture fromFile(@NotNull File file, @NotNull Schematic schematic) throws IOException, NBTException { if (!file.exists()) throw new FileNotFoundException("Invalid Schematic: File does not exist"); @@ -110,6 +122,7 @@ private Scaffolding() { * @throws IOException if the input stream is invalid * @throws NBTException if the schematic is invalid * @throws IllegalArgumentException if the schematic is neither an MCEdit nor a Sponge schematic + * */ public static @NotNull CompletableFuture fromStream(@NotNull InputStream inputStream) throws IOException, NBTException, IllegalArgumentException { return fromStream(inputStream, new Schematic()); @@ -121,6 +134,7 @@ private Scaffolding() { * @return a {@link CompletableFuture} that will be completed when the schematic is loaded * @throws IOException if the input stream is invalid * @throws NBTException if the NBT tag is invalid + * */ public static @NotNull CompletableFuture fromStream(@NotNull InputStream inputStream, @NotNull Schematic schematic) throws IOException, NBTException { return fromNBT((NBTCompound) new NBTReader(inputStream, CompressedProcesser.GZIP).read(), schematic); @@ -133,6 +147,7 @@ private Scaffolding() { * @param nbtTag The {@link NBTCompound} to read from * @return A {@link CompletableFuture} that will complete with the schematic once it's loaded * @throws NBTException If the NBT tag is invalid + * */ public static @NotNull CompletableFuture fromNBT(@NotNull NBTCompound nbtTag) throws NBTException, IllegalArgumentException { return fromNBT(nbtTag, new Schematic()); @@ -143,15 +158,17 @@ private Scaffolding() { * @param schematic The {@link Schematic} to load the data into * @return a {@link CompletableFuture} that will be completed when the schematic is loaded * @throws NBTException if the NBT tag is invalid + * */ public static @NotNull CompletableFuture fromNBT(@NotNull NBTCompound nbtTag, @NotNull Schematic schematic) throws NBTException { - if (MC_EDIT_SCHEMATIC_READER.isReadable(nbtTag)) { - return MC_EDIT_SCHEMATIC_READER.read(nbtTag, schematic); - } else if (SPONGE_SCHEMATIC_READER.isReadable(nbtTag)) { - return SPONGE_SCHEMATIC_READER.read(nbtTag, schematic); - } else { - throw new IllegalArgumentException("Unknown schematic type"); - } + Optional reader = MC_SCHEMATIC_READERS + .stream() + .filter(nbtSchematicReader -> nbtSchematicReader.isReadable(nbtTag)) + .findFirst(); + + if (reader.isPresent()) return reader.get().read(nbtTag, schematic); + + throw new NBTException("No valid schematic-reader found."); } @@ -161,6 +178,7 @@ private Scaffolding() { * @throws IOException if the file is invalid * @throws NBTException if the schematic is invalid * @throws IllegalArgumentException if the schematic is neither an MCEdit nor a Sponge schematic + * */ public static @NotNull Schematic fromPathSync(@NotNull Path path) throws IOException, NBTException, IllegalArgumentException { return fromPath(path).join(); @@ -172,6 +190,7 @@ private Scaffolding() { * @return the parsed {@link Schematic} * @throws IOException if the file is invalid * @throws NBTException if the NBT tag is invalid + * */ public static @NotNull Schematic fromPathSync(@NotNull Path path, @NotNull Schematic schematic) throws IOException, NBTException { return fromPath(path, schematic).join(); @@ -184,6 +203,7 @@ private Scaffolding() { * @throws IOException if the file is invalid * @throws NBTException if the schematic is invalid * @throws IllegalArgumentException if the schematic is neither an MCEdit nor a Sponge schematic + * */ public static @NotNull Schematic fromFileSync(@NotNull File file) throws IOException, NBTException, IllegalArgumentException { return fromFile(file).join(); @@ -195,6 +215,7 @@ private Scaffolding() { * @return the parsed {@link Schematic} * @throws IOException if the file is invalid * @throws NBTException if the NBT tag is invalid + * */ public static @NotNull Schematic fromFileSync(@NotNull File file, @NotNull Schematic schematic) throws IOException, NBTException { return fromFile(file, schematic).join(); @@ -208,6 +229,7 @@ private Scaffolding() { * @return the parsed {@link Schematic} * @throws NBTException if the NBT tag is invalid * @throws IllegalArgumentException if the schematic is neither an MCEdit nor a Sponge schematic + * */ public static @NotNull Schematic fromNBTSync(@NotNull NBTCompound nbtTag) throws NBTException, IllegalArgumentException { return fromNBT(nbtTag).join(); @@ -218,6 +240,7 @@ private Scaffolding() { * @param schematic The {@link Schematic} to load the data into * @return the parsed {@link Schematic} * @throws NBTException if the NBT tag is invalid + * */ public static @NotNull Schematic fromNBTSync(@NotNull NBTCompound nbtTag, @NotNull Schematic schematic) throws NBTException { return fromNBT(nbtTag, schematic).join(); @@ -230,6 +253,7 @@ private Scaffolding() { * @throws IOException if the input stream is invalid * @throws NBTException if the schematic is invalid * @throws IllegalArgumentException if the schematic is neither an MCEdit nor a Sponge schematic + * */ public static @NotNull Schematic fromStreamSync(@NotNull InputStream inputStream) throws IOException, NBTException, IllegalArgumentException { return fromStream(inputStream).join(); @@ -241,9 +265,10 @@ private Scaffolding() { * @return the parsed {@link Schematic} * @throws IOException if the input stream is invalid * @throws NBTException if the NBT tag is invalid + * */ public static @NotNull Schematic fromStreamSync(@NotNull InputStream inputStream, @NotNull Schematic schematic) throws IOException, NBTException { return fromStream(inputStream, schematic).join(); } -} +} \ No newline at end of file diff --git a/core/src/main/java/dev/hypera/scaffolding/instance/SchematicChunkLoader.java b/core/src/main/java/dev/hypera/scaffolding/instance/SchematicChunkLoader.java index 8e7c875..026ab99 100644 --- a/core/src/main/java/dev/hypera/scaffolding/instance/SchematicChunkLoader.java +++ b/core/src/main/java/dev/hypera/scaffolding/instance/SchematicChunkLoader.java @@ -106,6 +106,7 @@ private Builder() { * * @param schematic The schematic to add. * @return This builder. + * */ // TODO: Add a way to position schematics within the instance. @Contract("_ -> this") @@ -121,6 +122,7 @@ private Builder() { * @param y The y offset. * @param z The z offset. * @return This builder. + * */ @Contract("_,_,_ -> this") public @NotNull Builder offset(int x, int y, int z) { @@ -135,6 +137,7 @@ private Builder() { * * @param handler The handler. * @return This builder. + * */ @Contract("_ -> this") public @NotNull Builder saveHandler(@NotNull Function<@NotNull Chunk, @NotNull CompletableFuture> handler) { diff --git a/core/src/main/java/dev/hypera/scaffolding/region/Region.java b/core/src/main/java/dev/hypera/scaffolding/region/Region.java index 8c5a442..2372d87 100644 --- a/core/src/main/java/dev/hypera/scaffolding/region/Region.java +++ b/core/src/main/java/dev/hypera/scaffolding/region/Region.java @@ -35,6 +35,7 @@ /** * Represents a rectangle 3 dimensional region of blocks within an {@link Instance}. + * */ public final class Region { @@ -48,6 +49,7 @@ public final class Region { * @param instance The instance that the region is in. * @param p1 The first point of the region. * @param p2 The second point of the region. + * */ public Region(@NotNull Instance instance, @NotNull Point p1, @NotNull Point p2) { this.instance = Objects.requireNonNull(instance); @@ -60,6 +62,7 @@ public Region(@NotNull Instance instance, @NotNull Point p1, @NotNull Point p2) * Force loads all {@link Chunk}s this region. * * @return a {@link CompletableFuture} that will complete once all chunks in the region have been loaded. The future will give the region as the result so that you can chain it. + * */ public @NotNull CompletableFuture loadChunks() { int lengthX = getUpperChunkX() - getLowerChunkX() + 1; @@ -80,6 +83,7 @@ public Region(@NotNull Instance instance, @NotNull Point p1, @NotNull Point p2) /** * @return the width of this region. + * */ public int getWidth() { return (upper.blockX() - lower.blockX()) + 1; @@ -87,6 +91,7 @@ public int getWidth() { /** * @return the height of this region. + * */ public int getHeight() { return (upper.blockY() - lower.blockY()) + 1; @@ -94,6 +99,7 @@ public int getHeight() { /** * @return the length of this region. + * */ public int getLength() { return (upper.blockZ() - lower.blockZ()) + 1; @@ -101,6 +107,7 @@ public int getLength() { /** * @return the x coordinate of the upper {@link Chunk} of this region. + * */ @Contract(pure = true) public int getUpperChunkX() { @@ -109,6 +116,7 @@ public int getUpperChunkX() { /** * @return the z coordinate of the upper {@link Chunk} of this region. + * */ @Contract(pure = true) public int getUpperChunkZ() { @@ -117,6 +125,7 @@ public int getUpperChunkZ() { /** * @return the x coordinate of the lower {@link Chunk} of this region. + * */ @Contract(pure = true) public int getLowerChunkX() { @@ -125,6 +134,7 @@ public int getLowerChunkX() { /** * @return the z coordinate of the lower {@link Chunk} of this region. + * */ @Contract(pure = true) public int getLowerChunkZ() { @@ -133,6 +143,7 @@ public int getLowerChunkZ() { /** * @return the number of {@link Chunk}s along the x coordinate of this region. + * */ @Contract(pure = true) public int getChunkSizeX() { @@ -141,6 +152,7 @@ public int getChunkSizeX() { /** * @return the number of {@link Chunk}s along the z coordinate of this region. + * */ @Contract(pure = true) public int getChunkSizeZ() { @@ -149,6 +161,7 @@ public int getChunkSizeZ() { /** * @return the instance that this region is in + * */ @Contract(pure = true) public @NotNull Instance getInstance() { @@ -157,6 +170,7 @@ public int getChunkSizeZ() { /** * @return the upper {@link Point} of this region. + * */ @Contract(pure = true) public @NotNull Point getUpper() { @@ -165,6 +179,7 @@ public int getChunkSizeZ() { /** * @return the lower {@link Point} of this region. + * */ @Contract(pure = true) public @NotNull Point getLower() { diff --git a/core/src/main/java/dev/hypera/scaffolding/schematic/LegacyLookup.java b/core/src/main/java/dev/hypera/scaffolding/schematic/LegacyLookup.java index a48cbb6..3c6f48d 100644 --- a/core/src/main/java/dev/hypera/scaffolding/schematic/LegacyLookup.java +++ b/core/src/main/java/dev/hypera/scaffolding/schematic/LegacyLookup.java @@ -22,27 +22,22 @@ */ package dev.hypera.scaffolding.schematic; -import com.google.gson.*; -import com.google.gson.stream.JsonReader; -import dev.hypera.scaffolding.Scaffolding; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.io.FastBufferedInputStream; import org.jetbrains.annotations.ApiStatus.Internal; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.*; -import java.net.URISyntaxException; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; /** * A static utility class containing useful methods used throughout Scaffolding. @@ -54,8 +49,10 @@ public final class LegacyLookup { private static final @NotNull Int2ObjectMap LEGACY_LOOKUP = new Int2ObjectOpenHashMap<>(); private static final @NotNull Logger LOGGER = LoggerFactory.getLogger(LegacyLookup.class); + // Loading data on access + // TODO: Maybe loading data on program start for faster schematic loading static { - try(BufferedReader reader = new BufferedReader(new InputStreamReader(LegacyLookup.class.getResourceAsStream(LEGACY_FILE_NAME), StandardCharsets.UTF_8))) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(LegacyLookup.class.getResourceAsStream(LEGACY_FILE_NAME), StandardCharsets.UTF_8))) { JsonArray obj = JsonParser.parseReader(reader).getAsJsonArray(); @@ -74,7 +71,9 @@ public final class LegacyLookup { } } + private LegacyLookup() { + throw new UnsupportedOperationException(); } @@ -82,7 +81,9 @@ private LegacyLookup() { * @param legacyBlockId The legacy block ID * @param legacyBlockData The legacy block data * @return The modern state ID for the given legacy block ID and data + * */ + public static short stateIdFromLegacy(int legacyBlockId, byte legacyBlockData) { return LEGACY_LOOKUP.get(getLookupId(legacyBlockId, legacyBlockData)); } @@ -94,6 +95,7 @@ public static short stateIdFromLegacy(int legacyBlockId, byte legacyBlockData) { * @param legacyBlockId the legacy block ID * @param legacyBlockData the legacy block data * @return the lookup ID + * */ @Contract(pure = true) private static int getLookupId(int legacyBlockId, byte legacyBlockData) { diff --git a/core/src/main/java/dev/hypera/scaffolding/schematic/NBTSchematicReader.java b/core/src/main/java/dev/hypera/scaffolding/schematic/NBTSchematicReader.java index 51038f6..fc4a9d8 100644 --- a/core/src/main/java/dev/hypera/scaffolding/schematic/NBTSchematicReader.java +++ b/core/src/main/java/dev/hypera/scaffolding/schematic/NBTSchematicReader.java @@ -39,6 +39,7 @@ public abstract class NBTSchematicReader { * * @param compound The {@link NBTCompound} to check * @return whether this reader can read the provided tag. + * */ public abstract boolean isReadable(@NotNull NBTCompound compound); @@ -49,6 +50,7 @@ public abstract class NBTSchematicReader { * @param schematic The {@link Schematic} to read into * @return a {@link CompletableFuture} that will be completed with the {@link Schematic} * @throws NBTException If the provided NBT tag is invalid + * */ public abstract CompletableFuture read(@NotNull NBTCompound compound, @NotNull Schematic schematic) throws NBTException; @@ -58,6 +60,7 @@ public abstract class NBTSchematicReader { * @param exceptionMessage The exception message to throw if the key is not found * @return The value of the key * @throws NBTException If the provided NBT tag is invalid + * */ protected final int getInteger(@NotNull NBTCompound compound, @NotNull String key, String exceptionMessage) throws NBTException { Integer value = compound.getInt(key); @@ -74,6 +77,7 @@ protected final int getInteger(@NotNull NBTCompound compound, @NotNull String ke * @param exceptionMessage The exception message to throw if the key is not found * @return The value of the key * @throws NBTException If the provided NBT tag is invalid + * */ protected final short getShort(@NotNull NBTCompound compound, @NotNull String key, String exceptionMessage) throws NBTException { Short value = compound.getShort(key); @@ -90,6 +94,7 @@ protected final short getShort(@NotNull NBTCompound compound, @NotNull String ke * @param exceptionMessage The exception message to throw if the key is not found * @return The value of the key * @throws NBTException If the provided NBT tag is invalid + * */ protected final NBTCompound getCompound(@NotNull NBTCompound compound, @NotNull String key, String exceptionMessage) throws NBTException { NBTCompound value = compound.getCompound(key); @@ -106,6 +111,7 @@ protected final NBTCompound getCompound(@NotNull NBTCompound compound, @NotNull * @param exceptionMessage The exception message to throw if the key is not found * @return The value of the key * @throws NBTException If the provided NBT tag is invalid + * */ protected final byte getByte(@NotNull NBTCompound compound, @NotNull String key, String exceptionMessage) throws NBTException { Byte value = compound.getByte(key); @@ -122,6 +128,7 @@ protected final byte getByte(@NotNull NBTCompound compound, @NotNull String key, * @param exceptionMessage The exception message to throw if the key is not found * @return The value of the key * @throws NBTException If the provided NBT tag is invalid + * */ protected final byte[] getByteArray(@NotNull NBTCompound compound, @NotNull String key, String exceptionMessage) throws NBTException { ImmutableByteArray value = compound.getByteArray(key); @@ -138,6 +145,7 @@ protected final byte[] getByteArray(@NotNull NBTCompound compound, @NotNull Stri * @param exceptionMessage The exception message to throw if the key is not found * @return The value of the key * @throws NBTException If the provided NBT tag is invalid + * */ protected final boolean getBoolean(@NotNull NBTCompound compound, @NotNull String key, String exceptionMessage) throws NBTException { Boolean value = compound.getBoolean(key); @@ -154,6 +162,7 @@ protected final boolean getBoolean(@NotNull NBTCompound compound, @NotNull Strin * @param exceptionMessage The exception message to throw if the key is not found * @return The value of the key * @throws NBTException If the provided NBT tag is invalid + * */ protected final String getString(@NotNull NBTCompound compound, @NotNull String key, String exceptionMessage) throws NBTException { String value = compound.getString(key); @@ -164,4 +173,4 @@ protected final String getString(@NotNull NBTCompound compound, @NotNull String return value; } -} +} \ No newline at end of file diff --git a/core/src/main/java/dev/hypera/scaffolding/schematic/Schematic.java b/core/src/main/java/dev/hypera/scaffolding/schematic/Schematic.java index b9682d9..5d889fb 100644 --- a/core/src/main/java/dev/hypera/scaffolding/schematic/Schematic.java +++ b/core/src/main/java/dev/hypera/scaffolding/schematic/Schematic.java @@ -36,7 +36,6 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.locks.LockSupport; /** * A parsed schematic. @@ -44,16 +43,15 @@ @SuppressWarnings({"unused", "UnstableApiUsage"}) public final class Schematic implements Block.Setter { + private final AtomicBoolean locked = new AtomicBoolean(); private short[] blocks; - private int width, height, length; private int offsetX, offsetY, offsetZ; private int area; - private final AtomicBoolean locked = new AtomicBoolean(); - /** + * * Constructs a new schematic. The schematic will be locked and have an area of 0. */ public Schematic() { @@ -64,6 +62,7 @@ public Schematic() { * Resets this schematic to its original state. This is useful if you want to reuse a schematic multiple times. *

* The schematic will be locked after this method is called. + * */ public void reset() { width = height = length = 0; @@ -78,6 +77,7 @@ public void reset() { * * @param region the {@link Region} to copy from * @return a {@link CompletableFuture} that will complete once all blocks have been copied + * */ public @NotNull CompletableFuture copy(@NotNull Region region) { reset(); @@ -117,6 +117,7 @@ public void reset() { * @param width new width * @param height new height * @param length new length + * */ public void setSize(int width, int height, int length) { this.width = width; @@ -134,6 +135,7 @@ public void setSize(int width, int height, int length) { * @param y block y coordinate * @param z block z coordinate * @return the index of the block at the given coordinates + * */ public int getBlockIndex(int x, int y, int z) { return y * width * length + z * width + x; @@ -145,6 +147,7 @@ public int getBlockIndex(int x, int y, int z) { * @param instance the {@link Instance} to build this schematic in * @param position the {@link Point} to build this schematic at (note: the schematics offset will be applied to this position to get the lower corner) * @return a {@link CompletableFuture} that will complete once the schematic has been built + * */ public @NotNull CompletableFuture build(@NotNull Instance instance, @NotNull Point position) { return build(instance, position, false, false, false); @@ -159,6 +162,7 @@ public int getBlockIndex(int x, int y, int z) { * @param flipY whether to flip the schematic along the Y axis * @param flipZ whether to flip the schematic along the Z axis * @return a {@link CompletableFuture} that will complete once the schematic has been built + * */ public @NotNull CompletableFuture build(@NotNull Instance instance, @NotNull Point position, boolean flipX, boolean flipY, boolean flipZ) { if (locked.get()) { @@ -184,6 +188,7 @@ public int getBlockIndex(int x, int y, int z) { * @param instance the {@link Instance} to check * @param position the {@link Point} to check * @return the {@link Region} that this schematic would take up if placed at the given position + * */ public @NotNull Region getContainingRegion(@NotNull Instance instance, @NotNull Point position) { return new Region(instance, position.add(offsetX, offsetY, offsetZ), position.add(offsetX + width, offsetY + height, offsetZ + length)); @@ -201,6 +206,7 @@ private boolean isPlaceable(@NotNull Region region) { * * @param setter the block setter * @deprecated See {@link Schematic#apply(Point, boolean, boolean, boolean, Setter)} + * */ @Deprecated public void apply(@NotNull Block.Setter setter) { @@ -215,6 +221,7 @@ public void apply(@NotNull Block.Setter setter) { * @param flipY whether to flip the schematic along the Y axis * @param flipZ whether to flip the schematic along the Z axis * @param setter the {@link Block.Setter} to apply this schematic to + * */ public void apply(@NotNull Point position, boolean flipX, boolean flipY, boolean flipZ, @NotNull Block.Setter setter) { if (locked.get()) { @@ -245,6 +252,7 @@ public void apply(@NotNull Point position, boolean flipX, boolean flipY, boolean * @param y block y coordinate * @param z block z coordinate * @return the block at the given coordinates + * */ @Nullable public Block getBlock(int x, int y, int z) { @@ -267,6 +275,7 @@ public short getStateId(int x, int y, int z) { * @param flipX whether to flip the schematic along the X axis * @param flipY whether to flip the schematic along the Y axis * @param flipZ whether to flip the schematic along the Z axis + * */ public void fork(@NotNull GenerationUnit unit, @NotNull Point position, boolean flipX, boolean flipY, boolean flipZ) { if (locked.get()) { @@ -281,6 +290,7 @@ public void fork(@NotNull GenerationUnit unit, @NotNull Point position, boolean /** * @param position the {@link Point} of the block to set * @param block the {@link Block} to set + * */ public void setBlock(@NotNull Point position, @NotNull Block block) { setBlock(position.blockX(), position.blockY(), position.blockZ(), block); @@ -295,6 +305,7 @@ public void setBlock(int x, int y, int z, @NotNull Block block) { * @param y the Y coordinate * @param z the Z coordinate * @param stateId the state ID + * */ public void setBlock(int x, int y, int z, short stateId) { blocks[getBlockIndex(x, y, z)] = stateId; @@ -303,6 +314,7 @@ public void setBlock(int x, int y, int z, short stateId) { /** * @param position the {@link Point} to place the block at * @param stateId the state id of the block to place. + * */ public void setBlock(@NotNull Point position, short stateId) { setBlock(position.blockX(), position.blockY(), position.blockZ(), stateId); @@ -310,6 +322,7 @@ public void setBlock(@NotNull Point position, short stateId) { /** * @return the width of this schematic + * */ public int getWidth() { return width; @@ -317,6 +330,7 @@ public int getWidth() { /** * @return the height of this schematic + * */ public int getHeight() { return height; @@ -324,6 +338,7 @@ public int getHeight() { /** * @return the length of the schematic + * */ public int getLength() { return length; @@ -333,6 +348,7 @@ public int getLength() { * Gets the offset in the x-axis used when {@link #build(Instance, Point)} or {@link #apply(Point, boolean, boolean, boolean, Block.Setter)} are called. * * @return the x offset + * */ public int getOffsetX() { return offsetX; @@ -342,6 +358,7 @@ public int getOffsetX() { * Gets the offset in the y-axis used when {@link #build(Instance, Point)} or {@link #apply(Point, boolean, boolean, boolean, Block.Setter)} are called. * * @return the y offset + * */ public int getOffsetY() { return offsetY; @@ -351,6 +368,7 @@ public int getOffsetY() { * Gets the offset in the z-axis used when {@link #build(Instance, Point)} or {@link #apply(Point, boolean, boolean, boolean, Block.Setter)} are called. * * @return the z offset + * */ public int getOffsetZ() { return offsetZ; @@ -360,6 +378,7 @@ public int getOffsetZ() { * Gets the area of this schematic. ({@code width} * {@code height} * {@code length}) * * @return the area of this schematic + * */ public int getArea() { return area; @@ -367,6 +386,7 @@ public int getArea() { /** * @return true if this schematic is locked, false otherwise + * */ public boolean isLocked() { return locked.getAcquire(); @@ -376,6 +396,7 @@ public boolean isLocked() { * Sets the locked state of this schematic. Locked schematics can't be built, applied or forked, or saved. * * @param locked whether to lock this schematic + * */ public void setLocked(boolean locked) { this.locked.setRelease(locked); @@ -383,6 +404,7 @@ public void setLocked(boolean locked) { /** * @param offset the {@link Point} to offset this schematic by + * */ public void setOffset(@NotNull Point offset) { setOffset(offset.blockX(), offset.blockY(), offset.blockZ()); @@ -392,6 +414,7 @@ public void setOffset(@NotNull Point offset) { * @param x new x offset * @param y new y offset * @param z new z offset + * */ public void setOffset(int x, int y, int z) { offsetX = x; @@ -403,6 +426,7 @@ public void setOffset(int x, int y, int z) { * @param instance the {@link Instance} to check * @param position the {@link Point} to check * @return {@code true} if the given position is within the bounds of the given instance, {@code false} otherwise. If either the instance or the position is null, false is returned. + * */ public boolean isPlaceable(@Nullable Instance instance, @Nullable Point position) { if (instance == null || position == null) { diff --git a/core/src/main/java/dev/hypera/scaffolding/schematic/readers/MCEditSchematicReader.java b/core/src/main/java/dev/hypera/scaffolding/schematic/readers/MCEditSchematicReader.java index 28720d2..7f7b0d9 100644 --- a/core/src/main/java/dev/hypera/scaffolding/schematic/readers/MCEditSchematicReader.java +++ b/core/src/main/java/dev/hypera/scaffolding/schematic/readers/MCEditSchematicReader.java @@ -128,5 +128,4 @@ private void readBlocksData(@NotNull Schematic schematic, @NotNull NBTCompound n } } } - } diff --git a/core/src/main/java/dev/hypera/scaffolding/schematic/readers/SpongeSchematicReader.java b/core/src/main/java/dev/hypera/scaffolding/schematic/readers/SpongeSchematicReader.java index 231e34f..7a47a0b 100644 --- a/core/src/main/java/dev/hypera/scaffolding/schematic/readers/SpongeSchematicReader.java +++ b/core/src/main/java/dev/hypera/scaffolding/schematic/readers/SpongeSchematicReader.java @@ -176,4 +176,4 @@ private short getStateId(@NotNull String input) { return Block.fromNamespaceId(input.split("\\[")[0]); } -} +} \ No newline at end of file diff --git a/editor/src/main/java/dev/hypera/scaffolding/editor/Clipboard.java b/editor/src/main/java/dev/hypera/scaffolding/editor/Clipboard.java index 6ae4b32..edb692a 100644 --- a/editor/src/main/java/dev/hypera/scaffolding/editor/Clipboard.java +++ b/editor/src/main/java/dev/hypera/scaffolding/editor/Clipboard.java @@ -38,24 +38,28 @@ import net.minestom.server.particle.ParticleCreator; import net.minestom.server.timer.Task; import net.minestom.server.utils.time.TimeUnit; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.logging.Logger; + public class Clipboard { public static final Component FIRST_POINT_COMPONENT = Component.text("First point", NamedTextColor.GOLD); public static final Component SECOND_POINT_COMPONENT = Component.text("Second point", NamedTextColor.AQUA); private final Player player; + private final Task drawParticlesTask; private final Schematic schematic = new Schematic(); - private Point firstPoint, secondPoint; + private Point firstPoint, secondPoint, firstPointSet, secondPointSet; private Hologram firstPointHologram, secondPointHologram; public Clipboard(Player player) { this.player = player; - drawParticlesTask = MinecraftServer.getSchedulerManager().buildTask(this::drawSelection).repeat(50, TimeUnit.MILLISECOND).schedule(); + this.drawParticlesTask = MinecraftServer.getSchedulerManager().buildTask(this::drawSelection).repeat(150, TimeUnit.MILLISECOND).schedule(); } public boolean hasValidSelection() { @@ -72,7 +76,9 @@ public boolean hasValidSelection() { public void drawSelection() { Region region = createRegionFromSelection(); - if (region == null) return; + if (region == null) { + return; + } Point lower = region.getLower(); Point upper = region.getUpper().add(1); @@ -87,20 +93,23 @@ public void drawSelection() { Vec p7 = new Vec(upper.x(), upper.y(), upper.z()); Vec p8 = new Vec(lower.x(), upper.y(), upper.z()); - drawLine(player, Particle.CRIT, p1, p2); - drawLine(player, Particle.CRIT, p2, p3); - drawLine(player, Particle.CRIT, p3, p4); - drawLine(player, Particle.CRIT, p4, p1); + Particle p = Particle.REVERSE_PORTAL; + - drawLine(player, Particle.CRIT, p5, p6); - drawLine(player, Particle.CRIT, p6, p7); - drawLine(player, Particle.CRIT, p7, p8); - drawLine(player, Particle.CRIT, p8, p5); + drawLine(player, p, p1, p2); + drawLine(player, p, p2, p3); + drawLine(player, p, p3, p4); + drawLine(player, p, p4, p1); - drawLine(player, Particle.CRIT, p1, p5); - drawLine(player, Particle.CRIT, p2, p6); - drawLine(player, Particle.CRIT, p3, p7); - drawLine(player, Particle.CRIT, p4, p8); + drawLine(player, p, p5, p6); + drawLine(player, p, p6, p7); + drawLine(player, p, p7, p8); + drawLine(player, p, p8, p5); + + drawLine(player, p, p1, p5); + drawLine(player, p, p2, p6); + drawLine(player, p, p3, p7); + drawLine(player, p, p4, p8); } private void drawLine(Player player, Particle particle, Point p1, Point p2) { @@ -108,8 +117,9 @@ private void drawLine(Player player, Particle particle, Point p1, Point p2) { final Vec v2 = Vec.fromPoint(p2); Vec direction = v2.sub(v1).normalize(); + double repeat = v1.distance(v2) / 4; - for (Vec position = v1; position.sub(v2).dot(direction) < 0; position = position.add(direction.mul(0.2d))) { + for (Vec position = v1; position.sub(v2).dot(direction) < 0; position = position.add(direction.mul(repeat))) { ParticlePacket packet = ParticleCreator.createParticlePacket(particle, true, position.x(), position.y(), position.z(), 0, 0, 0, 0, 1, null); player.sendPacket(packet); } @@ -120,12 +130,98 @@ public Point getFirstPoint() { } public void setFirstPoint(Point firstPoint) { - this.firstPoint = firstPoint; + boolean isOverride = this.firstPointSet != null && this.firstPointSet.samePoint(firstPoint); + this.firstPointSet = firstPoint; + + //Setting + if(this.firstPoint == null) { + //set + this.firstPoint = firstPoint; + + //Creating hologram + if (firstPointHologram != null) firstPointHologram.remove(); + firstPointHologram = createHologram(firstPoint, FIRST_POINT_COMPONENT); + + //Starting animation + this.drawParticlesTask.unpark(); + + + player.sendMessage("Setzen"); + return; + } + if(this.firstPoint.samePoint(firstPoint)) { + //Entfernen + if (firstPointHologram != null) firstPointHologram.remove(); + this.firstPoint = null; + + player.sendMessage("entfernen"); + return; + } + //Replace + if(this.firstPoint != null) { + player.sendMessage("Double click the same location for override"); + + //Double clicked location + if(isOverride) { + player.sendMessage("Overriden!"); + this.firstPoint = firstPoint; + + //Create hologram + if (firstPointHologram != null) firstPointHologram.remove(); + firstPointHologram = createHologram(firstPoint, FIRST_POINT_COMPONENT); + + //Start animation + this.drawParticlesTask.unpark(); + } + } + } + + public void setSecondPoint(Point secondPoint) { + boolean isOverride = this.secondPointSet != null && this.secondPointSet.samePoint(secondPoint); + this.secondPointSet = secondPoint; + + //Setting + if(this.secondPoint == null) { + //set + this.secondPoint = secondPoint; - if (firstPointHologram != null) firstPointHologram.remove(); - firstPointHologram = createHologram(firstPoint, FIRST_POINT_COMPONENT); + //Creating hologram + if (secondPointHologram != null) secondPointHologram.remove(); + secondPointHologram = createHologram(secondPoint, SECOND_POINT_COMPONENT); + + //Starting animation + if(this.drawParticlesTask != null) { + this.drawParticlesTask.unpark(); + } + + player.sendMessage("Setzen"); + return; + } + if(this.secondPoint.samePoint(secondPoint)) { + //Entfernen + if (secondPointHologram != null) secondPointHologram.remove(); + this.secondPoint = null; - player.sendMessage(Component.text("Set ", NamedTextColor.GRAY).append(FIRST_POINT_COMPONENT)); + player.sendMessage("entfernen"); + return; + } + //Replace + if(this.secondPoint != null) { + player.sendMessage("Double click the same location for override"); + + //Double clicked location + if(isOverride) { + player.sendMessage("Overriden!"); + this.secondPoint = secondPoint; + + //Create hologram + if (secondPointHologram != null) secondPointHologram.remove(); + secondPointHologram = createHologram(secondPoint, SECOND_POINT_COMPONENT); + + //Start animation + this.drawParticlesTask.unpark(); + } + } } private Hologram createHologram(Point position, Component text) { @@ -139,20 +235,11 @@ public Point getSecondPoint() { return secondPoint; } - public void setSecondPoint(Point secondPoint) { - this.secondPoint = secondPoint; - - if (secondPointHologram != null) secondPointHologram.remove(); - secondPointHologram = createHologram(secondPoint, SECOND_POINT_COMPONENT); - - player.sendMessage(Component.text("Set ", NamedTextColor.GRAY).append(SECOND_POINT_COMPONENT)); - } - public Schematic getSchematic() { return schematic; } public void cleanup() { - drawParticlesTask.cancel(); + this.drawParticlesTask.cancel(); } } diff --git a/editor/src/main/java/dev/hypera/scaffolding/editor/ScaffoldingEditor.java b/editor/src/main/java/dev/hypera/scaffolding/editor/ScaffoldingEditor.java index cc06581..0efc1da 100644 --- a/editor/src/main/java/dev/hypera/scaffolding/editor/ScaffoldingEditor.java +++ b/editor/src/main/java/dev/hypera/scaffolding/editor/ScaffoldingEditor.java @@ -25,6 +25,7 @@ import dev.hypera.scaffolding.editor.commands.CopyCommand; import dev.hypera.scaffolding.editor.commands.LoadCommand; import dev.hypera.scaffolding.editor.commands.PasteCommand; +import dev.hypera.scaffolding.editor.commands.SaveCommand; import dev.hypera.scaffolding.editor.features.SelectionFeature; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -72,12 +73,13 @@ public static void main(String[] args) throws IOException { commandManager.register(new LoadCommand()); commandManager.register(new CopyCommand()); commandManager.register(new PasteCommand()); + commandManager.register(new SaveCommand()); GlobalEventHandler globalEventHandler = MinecraftServer.getGlobalEventHandler(); globalEventHandler.addListener(PlayerLoginEvent.class, event -> { Player player = event.getPlayer(); - clipboards.put(player, new Clipboard(player)); + clipboards.computeIfAbsent(player,Clipboard::new); player.setRespawnPoint(new Pos(0, 6, 0)); event.setSpawningInstance(instance); }); diff --git a/editor/src/main/java/dev/hypera/scaffolding/editor/commands/LoadCommand.java b/editor/src/main/java/dev/hypera/scaffolding/editor/commands/LoadCommand.java index fb0591c..511625f 100644 --- a/editor/src/main/java/dev/hypera/scaffolding/editor/commands/LoadCommand.java +++ b/editor/src/main/java/dev/hypera/scaffolding/editor/commands/LoadCommand.java @@ -25,6 +25,7 @@ import dev.hypera.scaffolding.Scaffolding; import dev.hypera.scaffolding.editor.Clipboard; import dev.hypera.scaffolding.editor.ScaffoldingEditor; +import dev.hypera.scaffolding.schematic.Schematic; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.minestom.server.command.builder.Command; @@ -37,6 +38,9 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.text.DecimalFormat; +import java.time.format.DateTimeFormatter; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -59,17 +63,27 @@ public LoadCommand() { } }); + addSyntax((sender, context) -> { if (sender instanceof Player player) { try { String schematicName = context.get(nameArgument); - Clipboard clipboard = ScaffoldingEditor.getClipboard(player); + CompletableFuture ms = CompletableFuture.completedFuture(System.currentTimeMillis()); - Scaffolding.fromFile(ScaffoldingEditor.SCHEMATICS_PATH.resolve(schematicName).toFile(), clipboard.getSchematic()).thenRun(() -> { - player.sendMessage(Component.text("Loaded schematic " + schematicName, NamedTextColor.GRAY)); - }).get(2, TimeUnit.SECONDS); - } catch (IOException | NBTException | ExecutionException | InterruptedException | TimeoutException e) { + CompletableFuture cmp = Scaffolding.fromFile(ScaffoldingEditor.SCHEMATICS_PATH.resolve(schematicName).toFile(), clipboard.getSchematic()); + cmp.whenCompleteAsync((schematic, throwable) -> { + if(throwable != null) { + player.sendMessage(Component.text("Error while loading schematic: " + throwable.getLocalizedMessage())); + throwable.printStackTrace(); + return; + } + String formatted = DecimalFormat.getInstance().format((System.currentTimeMillis() - ms.join()) / 1000.0); + player.sendMessage(Component + .text("Loaded schematic " + schematicName + " with size of blocks: " + clipboard.getSchematic().getArea() + " in seconds: " + formatted, NamedTextColor.GRAY) + ); + }); + } catch (IOException | NBTException e) { player.sendMessage("Failed to load schematic" + e.getLocalizedMessage()); e.printStackTrace(); } diff --git a/editor/src/main/java/dev/hypera/scaffolding/editor/commands/PasteCommand.java b/editor/src/main/java/dev/hypera/scaffolding/editor/commands/PasteCommand.java index 9469949..868b31f 100644 --- a/editor/src/main/java/dev/hypera/scaffolding/editor/commands/PasteCommand.java +++ b/editor/src/main/java/dev/hypera/scaffolding/editor/commands/PasteCommand.java @@ -25,11 +25,16 @@ import dev.hypera.scaffolding.editor.Clipboard; import dev.hypera.scaffolding.editor.ScaffoldingEditor; import dev.hypera.scaffolding.schematic.Schematic; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import net.minestom.server.command.builder.Command; import net.minestom.server.coordinate.Pos; import net.minestom.server.entity.Player; import net.minestom.server.instance.Instance; +import java.text.DecimalFormat; +import java.util.concurrent.CompletableFuture; + public class PasteCommand extends Command { public PasteCommand() { @@ -37,12 +42,14 @@ public PasteCommand() { setDefaultExecutor((sender, context) -> { if ((sender instanceof Player player)) { + CompletableFuture ms = CompletableFuture.completedFuture(System.currentTimeMillis()); Clipboard clipboard = ScaffoldingEditor.getClipboard(player); Schematic schematic = clipboard.getSchematic(); Instance instance = player.getInstance(); Pos placementPosition = player.getPosition(); + if (instance == null) { player.sendMessage("You are not in an instance. This should probably not happen..."); return; @@ -58,7 +65,18 @@ public PasteCommand() { return; } - schematic.build(instance, placementPosition).thenRunAsync(() -> player.sendMessage("Schematic pasted")); + schematic.build(instance, placementPosition).whenCompleteAsync((region, throwable) -> { + if(throwable != null) { + player.sendMessage(Component.text("Error while pasting schematic: " + throwable.getLocalizedMessage())); + throwable.printStackTrace(); + return; + } + + String formatted = DecimalFormat.getInstance().format((System.currentTimeMillis() - ms.join()) / 1000.0); + player.sendMessage(Component + .text("Pasted schematic with blocks: " + clipboard.getSchematic().getArea() + " in seconds: " + formatted, NamedTextColor.GRAY) + ); + }); } }); } diff --git a/editor/src/main/java/dev/hypera/scaffolding/editor/commands/SaveCommand.java b/editor/src/main/java/dev/hypera/scaffolding/editor/commands/SaveCommand.java new file mode 100644 index 0000000..c10bfda --- /dev/null +++ b/editor/src/main/java/dev/hypera/scaffolding/editor/commands/SaveCommand.java @@ -0,0 +1,77 @@ +package dev.hypera.scaffolding.editor.commands; + +import com.google.gson.Gson; +import com.google.gson.stream.JsonWriter; +import dev.hypera.scaffolding.Scaffolding; +import dev.hypera.scaffolding.editor.Clipboard; +import dev.hypera.scaffolding.editor.ScaffoldingEditor; +import dev.hypera.scaffolding.schematic.Schematic; +import net.kyori.adventure.text.Component; +import net.minestom.server.MinecraftServer; +import net.minestom.server.command.builder.Command; +import net.minestom.server.command.builder.arguments.ArgumentType; +import net.minestom.server.command.builder.arguments.ArgumentWord; +import net.minestom.server.command.builder.suggestion.SuggestionEntry; +import net.minestom.server.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.stream.Stream; + +public class SaveCommand extends Command { + + public SaveCommand() { + super("save"); + + ArgumentWord nameArgument = ArgumentType.Word("nameArgument"); + nameArgument.setSuggestionCallback((sender, context, suggestion) -> { + try (Stream paths = Files.walk(ScaffoldingEditor.SCHEMATICS_PATH)) { + paths.filter(Files::isRegularFile).forEach(path -> { + String file = path.getFileName().toString(); + suggestion.addEntry(new SuggestionEntry(file, Component.text("Test"))); + }); + } catch (Exception e) { + e.printStackTrace(); + } + }); + + this.addSyntax((sender, context) -> { + if(sender instanceof Player player) { + String schematicName = context.get(nameArgument); + Clipboard clipboard = ScaffoldingEditor.getClipboard(player); + + if(!clipboard.hasValidSelection()) { + player.sendMessage("No selection to save."); + return; + } + + if(clipboard.getSchematic() == null) { + player.sendMessage("Not schematic"); + return; + } + + File file = new File(ScaffoldingEditor.SCHEMATICS_PATH + "/" + schematicName); + if(file.exists()) { + player.sendMessage("You cannot override schematics."); + return; + } + + try { + file.createNewFile(); + player.sendMessage(clipboard.getSchematic().toString()); + FileWriter writer = new FileWriter(file); + writer.write(new Gson().toJson(clipboard.getSchematic())); + writer.flush(); + writer.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + player.sendMessage("Saved to file" + file); + } + + }, nameArgument); + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..2d720b9 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,8 @@ +forceSign=true + +# Gradle +org.gradle.jvmargs=-Xmx4G +org.gradle.parallel=true +org.gradle.daemon=true +org.gradle.configureondemand=true +org.gradle.caching=true \ No newline at end of file