diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index af9640c..7dccfef 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -24,7 +24,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-java@v1 with: - java-version: '16' + java-version: '17' - name: Cache Spigot Dependencies id: cache-spigot-dependencies @@ -45,10 +45,10 @@ jobs: docker create --name structureblocklib-dependencies-jdk8 structureblocklib-dependencies-jdk8 bash docker cp structureblocklib-dependencies-jdk8:/root/.m2/repository/org/spigotmc ~/.m2/repository/org/ docker rm -f structureblocklib-dependencies-jdk8 - docker build --target dependencies-jdk16 -t structureblocklib-dependencies-jdk16 . - docker create --name structureblocklib-dependencies-jdk16 structureblocklib-dependencies-jdk16 bash - docker cp structureblocklib-dependencies-jdk16:/root/.m2/repository/org/spigotmc ~/.m2/repository/org/ - docker rm -f structureblocklib-dependencies-jdk16 + docker build --target dependencies-jdk17 -t structureblocklib-dependencies-jdk17 . + docker create --name structureblocklib-dependencies-jdk17 structureblocklib-dependencies-jdk17 bash + docker cp structureblocklib-dependencies-jdk17:/root/.m2/repository/org/spigotmc ~/.m2/repository/org/ + docker rm -f structureblocklib-dependencies-jdk17 - name: Build Java Application run: | diff --git a/Dockerfile b/Dockerfile index a7bd743..cdf7c0b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,51 +9,52 @@ RUN java -jar BuildTools.jar --rev 1.9.4 RUN java -jar BuildTools.jar --rev 1.10 RUN java -jar BuildTools.jar --rev 1.11 RUN java -jar BuildTools.jar --rev 1.12 -RUN java -jar BuildTools.jar --rev 1.16.4 RUN java -jar BuildTools.jar --rev 1.13.2 RUN java -jar BuildTools.jar --rev 1.14.4 RUN java -jar BuildTools.jar --rev 1.15 RUN java -jar BuildTools.jar --rev 1.16.4 CMD ["sh","-c","/bin/bash"] -# 2. Resolve minecraft-dependencies for 1.17 - latest with jdk16 -FROM adoptopenjdk/openjdk16 AS dependencies-jdk16 +# 2. Resolve minecraft-dependencies for 1.17 - 1.18 - latest with jdk17 +FROM amazoncorretto:17 AS dependencies-jdk17 WORKDIR /tmp -RUN apt-get update -RUN apt-get install maven -y -RUN apt-get install wget -y -RUN apt-get install git -y +RUN yum update -y +RUN yum install maven -y +RUN yum install wget -y +RUN yum install git -y RUN wget "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar" -RUN java -jar BuildTools.jar --rev 1.17 --remapped +RUN java -jar BuildTools.jar --rev 1.17.1 --remapped +RUN java -jar BuildTools.jar --rev 1.18 --remapped -# 3. Build plugin for 1.8 - 1.17 with jdk16 -FROM adoptopenjdk/openjdk16 AS plugin-jdk16 +# 3. Build plugin for 1.8 - 1.17 with jdk17 +FROM amazoncorretto:17 AS plugin-jdk17 WORKDIR /tmp -RUN apt-get update -RUN apt-get install maven -y -RUN apt-get install dos2unix -y +RUN yum update -y +RUN yum install maven -y +RUN yum install dos2unix -y COPY --from=dependencies-jdk8 /root/.m2/repository/org/spigotmc /root/.m2/repository/org/spigotmc/ -COPY --from=dependencies-jdk16 /root/.m2/repository/org/spigotmc /root/.m2/repository/org/spigotmc/ +COPY --from=dependencies-jdk17 /root/.m2/repository/org/spigotmc /root/.m2/repository/org/spigotmc/ COPY . /tmp RUN chmod +x gradlew RUN dos2unix gradlew RUN ./gradlew build pluginJar --no-daemon -# 4. Launch a minecraft server with jdk16 and plugin -FROM adoptopenjdk/openjdk16 +# 4. Launch a minecraft server with jdk17 and plugin +FROM amazoncorretto:17 # Change to the current plugin version present in build.gradle -ENV PLUGIN_VERSION=2.2.2 +ENV PLUGIN_VERSION=2.3.0 # Change to the server version you want to test. -ENV SERVER_VERSION=1.17-R0.1-SNAPSHOT/spigot-1.17-R0.1-SNAPSHOT.jar +ENV SERVER_VERSION=spigot-1.18.jar # Port of the Minecraft Server. EXPOSE 25565 # Port for Remote Debugging EXPOSE 5005 WORKDIR /app -RUN apt-get update +RUN yum update -y RUN echo "eula=true" > eula.txt && mkdir plugins COPY ./structureblocklib-tools/world-1.14 /app/ COPY ./structureblocklib-tools/ops.json /app/ -COPY --from=dependencies-jdk16 /root/.m2/repository/org/spigotmc/spigot/$SERVER_VERSION /app/spigot.jar -COPY --from=plugin-jdk16 /tmp/structureblocklib-bukkit-sample/build/libs/structureblocklib-bukkit-sample-$PLUGIN_VERSION.jar /app/plugins/Structureblocklib.jar +# For < 1.18 COPY --from=dependencies-jdk17 /root/.m2/repository/org/spigotmc/spigot/$SERVER_VERSION /app/spigot.jar +COPY --from=dependencies-jdk17 /tmp/$SERVER_VERSION /app/spigot.jar +COPY --from=plugin-jdk17 /tmp/structureblocklib-bukkit-sample/build/libs/structureblocklib-bukkit-sample-$PLUGIN_VERSION.jar /app/plugins/Structureblocklib.jar CMD ["sh","-c","java -DIReallyKnowWhatIAmDoingISwear -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -jar spigot.jar"] diff --git a/README.md b/README.md index 870f98c..f32ebd0 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ StructureBlockLib is a bukkit API and implementation for handling structures on * API to save or load structures without an actual structure block. * Asynchronous implementation and API. * Fluent API. -* Version support 1.9.R1 - 1.17.R1 +* Version support 1.9.R1 - 1.18.R1 * Java support 8 - Latest ## Installation @@ -29,7 +29,7 @@ StructureBlockLib is a bukkit API and implementation for handling structures on com.github.shynixn.structureblocklib structureblocklib-bukkit-api - 2.2.2 + 2.3.0 provided ``` @@ -37,7 +37,7 @@ StructureBlockLib is a bukkit API and implementation for handling structures on ```xml dependencies { - compileOnly("com.github.shynixn.structureblocklib:structureblocklib-bukkit-api:2.2.2") + compileOnly("com.github.shynixn.structureblocklib:structureblocklib-bukkit-api:2.3.0") } ``` @@ -174,8 +174,8 @@ structureBlock.update(); **plugin.yml** ```yaml libraries: - - com.github.shynixn.structureblocklib:structureblocklib-bukkit-api:2.2.2 - - com.github.shynixn.structureblocklib:structureblocklib-bukkit-core:2.2.2 + - com.github.shynixn.structureblocklib:structureblocklib-bukkit-api:2.3.0 + - com.github.shynixn.structureblocklib:structureblocklib-bukkit-core:2.3.0 ``` ### For version < 1.17 @@ -194,13 +194,13 @@ go with the option above instead. There are several tutorials on spigotmc.org. com.github.shynixn.structureblocklib structureblocklib-bukkit-api - 2.2.2 + 2.3.0 compile com.github.shynixn.structureblocklib structureblocklib-bukkit-core - 2.2.2 + 2.3.0 compile ``` @@ -208,8 +208,8 @@ go with the option above instead. There are several tutorials on spigotmc.org. ```xml dependencies { - implementation("com.github.shynixn.structureblocklib:structureblocklib-bukkit-api:2.2.2") - implementation("com.github.shynixn.structureblocklib:structureblocklib-bukkit-core:2.2.2") + implementation("com.github.shynixn.structureblocklib:structureblocklib-bukkit-api:2.3.0") + implementation("com.github.shynixn.structureblocklib:structureblocklib-bukkit-core:2.3.0") } ``` @@ -217,9 +217,9 @@ dependencies { ### Setting up development environment -* Install Java 16 or higher +* Install Java 17 or higher * Fork the StructureBlockLib project on github and clone it to your local environment. -* StructureBlockLib requires spigot server implementations from 1.9.4 to 1.17 to be correctly installed in your local Maven cache. +* StructureBlockLib requires spigot server implementations from 1.9.4 to 1.18 to be correctly installed in your local Maven cache. As this requires multiple java version to build different versions, a Dockerfile is provided to build these dependencies in a docker container and then copy it to your local Maven cache. @@ -230,10 +230,10 @@ docker build --target dependencies-jdk8 -t structureblocklib-dependencies-jdk8 . docker create --name structureblocklib-dependencies-jdk8 structureblocklib-dependencies-jdk8 bash docker cp structureblocklib-dependencies-jdk8:/root/.m2/repository/org/spigotmc ~/.m2/repository/org/ docker rm -f structureblocklib-dependencies-jdk8 -docker build --target dependencies-jdk16 -t structureblocklib-dependencies-jdk16 . -docker create --name structureblocklib-dependencies-jdk16 structureblocklib-dependencies-jdk16 bash -docker cp structureblocklib-dependencies-jdk16:/root/.m2/repository/org/spigotmc ~/.m2/repository/org/ -docker rm -f structureblocklib-dependencies-jdk16 +docker build --target dependencies-jdk17 -t structureblocklib-dependencies-jdk17 . +docker create --name structureblocklib-dependencies-jdk17 structureblocklib-dependencies-jdk17 bash +docker cp structureblocklib-dependencies-jdk17:/root/.m2/repository/org/spigotmc ~/.m2/repository/org/ +docker rm -f structureblocklib-dependencies-jdk17 ```` * Open the project with an IDE, gradle sync for dependencies. diff --git a/build.gradle b/build.gradle index c5374e0..b982b47 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript { } dependencies { classpath group: 'org.jetbrains.kotlin', name: 'kotlin-gradle-plugin', version: '1.3.72' - classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.4.32" + classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.5.31" } } @@ -44,7 +44,7 @@ tasks.register("printVersion") { subprojects { group 'com.github.shynixn.structureblocklib' - version '2.2.2' + version '2.3.0' apply plugin: 'kotlin-platform-jvm' apply plugin: 'signing' diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0f80bbf..84d1f85 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle.kts b/settings.gradle.kts index 29be388..d54518e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -14,3 +14,4 @@ include("structureblocklib-bukkit-core:bukkit-nms-114R1") include("structureblocklib-bukkit-core:bukkit-nms-115R1") include("structureblocklib-bukkit-core:bukkit-nms-116R3") include("structureblocklib-bukkit-core:bukkit-nms-117R1") +include("structureblocklib-bukkit-core:bukkit-nms-118R1") diff --git a/structureblocklib-api/src/main/java/com/github/shynixn/structureblocklib/api/enumeration/Version.java b/structureblocklib-api/src/main/java/com/github/shynixn/structureblocklib/api/enumeration/Version.java index 31f3d9c..1fafdeb 100644 --- a/structureblocklib-api/src/main/java/com/github/shynixn/structureblocklib/api/enumeration/Version.java +++ b/structureblocklib-api/src/main/java/com/github/shynixn/structureblocklib/api/enumeration/Version.java @@ -57,9 +57,14 @@ public enum Version { VERSION_1_16_R3("v1_16_R3", "1.16.4", 1.164), /** - * Version 1.17.0 - 1.17.0. + * Version 1.17.0 - 1.17.1. */ - VERSION_1_17_R1("v1_17_R1", "1.17.0", 1.170); + VERSION_1_17_R1("v1_17_R1", "1.17.0", 1.170), + + /** + * Version 1.18.0 - 1.17.0. + */ + VERSION_1_18_R1("v1_18_R1", "1.18.0", 1.180); private final String bukkitId; private final String id; diff --git a/structureblocklib-bukkit-core/build.gradle.kts b/structureblocklib-bukkit-core/build.gradle.kts index b6b0ed9..b68b565 100644 --- a/structureblocklib-bukkit-core/build.gradle.kts +++ b/structureblocklib-bukkit-core/build.gradle.kts @@ -38,15 +38,26 @@ tasks.register("pluginJar", Exec::class.java) { } val shadowJar = tasks.findByName("shadowJar")!! as ShadowJar - val obfArchiveName = "${shadowJar.baseName}-${shadowJar.version}-obfuscated.${shadowJar.extension}" - val archiveName = "${shadowJar.baseName}-${shadowJar.version}.${shadowJar.extension}" val sourceJarFile = File(buildDir, "libs/" + shadowJar.archiveName) - val obfJarFile = File(buildDir, "libs/$obfArchiveName") + val archiveName = "${shadowJar.baseName}-${shadowJar.version}.${shadowJar.extension}" val targetJarFile = File(buildDir, "libs/$archiveName") - val obsMapping = - "java -jar ${file.absolutePath} -i \"$sourceJarFile\" -o \"$obfJarFile\" -m \"\$HOME/.m2/repository/org/spigotmc/minecraft-server/1.17-R0.1-SNAPSHOT/minecraft-server-1.17-R0.1-SNAPSHOT-maps-mojang.txt\" --reverse" + - "&& java -jar ${file.absolutePath} -i \"$obfJarFile\" -o \"$targetJarFile\" -m \"\$HOME/.m2/repository/org/spigotmc/minecraft-server/1.17-R0.1-SNAPSHOT/minecraft-server-1.17-R0.1-SNAPSHOT-maps-spigot.csrg\"" + var obsMapping = createCommand( + "1.17.1-R0.1-SNAPSHOT", + "com/github/shynixn/structureblocklib/bukkit/v1_17_R1", + file, + shadowJar, + sourceJarFile, + targetJarFile + ) + obsMapping = "$obsMapping && " + createCommand( + "1.18-R0.1-SNAPSHOT", + "com/github/shynixn/structureblocklib/bukkit/v1_18_R1", + file, + shadowJar, + targetJarFile, + targetJarFile + ) if (System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("windows")) { commandLine = listOf("cmd", "/c", obsMapping.replace("\$HOME", "%userprofile%")) @@ -55,6 +66,21 @@ tasks.register("pluginJar", Exec::class.java) { } } +fun createCommand( + version: String, + include: String, + file: File, + shadowJar: ShadowJar, + sourceJarFile: File, + targetJarFile: File +): String { + val obfArchiveName = "${shadowJar.baseName}-${shadowJar.version}-obfuscated.${shadowJar.extension}" + val obfJarFile = File(buildDir, "libs/$obfArchiveName") + + return "java -jar ${file.absolutePath} -i \"$sourceJarFile\" -o \"$obfJarFile\" -only \"$include\" -m \"\$HOME/.m2/repository/org/spigotmc/minecraft-server/${version}/minecraft-server-${version}-maps-mojang.txt\" --reverse" + + "&& java -jar ${file.absolutePath} -i \"$obfJarFile\" -o \"$targetJarFile\" -only \"$include\" -m \"\$HOME/.m2/repository/org/spigotmc/minecraft-server/${version}/minecraft-server-${version}-maps-spigot.csrg\"" +} + dependencies { implementation(project(":structureblocklib-api")) implementation(project(":structureblocklib-core")) @@ -68,6 +94,7 @@ dependencies { implementation(project(":structureblocklib-bukkit-core:bukkit-nms-115R1")) implementation(project(":structureblocklib-bukkit-core:bukkit-nms-116R3")) implementation(project(":structureblocklib-bukkit-core:bukkit-nms-117R1")) + implementation(project(":structureblocklib-bukkit-core:bukkit-nms-118R1")) compileOnly("org.spigotmc:spigot:1.14.4-R0.1-SNAPSHOT") testCompile("org.spigotmc:spigot:1.12-R0.1-SNAPSHOT") diff --git a/structureblocklib-bukkit-core/bukkit-nms-117R1/build.gradle.kts b/structureblocklib-bukkit-core/bukkit-nms-117R1/build.gradle.kts index 2046b07..132451e 100644 --- a/structureblocklib-bukkit-core/bukkit-nms-117R1/build.gradle.kts +++ b/structureblocklib-bukkit-core/bukkit-nms-117R1/build.gradle.kts @@ -2,6 +2,6 @@ dependencies { implementation(project(":structureblocklib-api")) implementation(project(":structureblocklib-core")) implementation(project(":structureblocklib-bukkit-api")) - compileOnly("org.spigotmc:spigot:1.17-R0.1-SNAPSHOT:remapped-mojang") - testCompile("org.spigotmc:spigot:1.17-R0.1-SNAPSHOT:remapped-mojang") + compileOnly("org.spigotmc:spigot:1.17.1-R0.1-SNAPSHOT:remapped-mojang") + testCompile("org.spigotmc:spigot:1.17.1-R0.1-SNAPSHOT:remapped-mojang") } diff --git a/structureblocklib-bukkit-core/bukkit-nms-118R1/build.gradle.kts b/structureblocklib-bukkit-core/bukkit-nms-118R1/build.gradle.kts new file mode 100644 index 0000000..d892fe4 --- /dev/null +++ b/structureblocklib-bukkit-core/bukkit-nms-118R1/build.gradle.kts @@ -0,0 +1,24 @@ +repositories { + maven(url = "https://libraries.minecraft.net") +} + +dependencies { + // Dependencies of spigot mojang want to restrict usage to only Java 16. However, we do not care + // what they want because the general compatibility of this plugin is Java 8. The plugin + // guarantees that everything works during runtime. This error is a false positive. + components { + all { + allVariants { + attributes { + attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 8) + } + } + } + } + + implementation(project(":structureblocklib-api")) + implementation(project(":structureblocklib-core")) + implementation(project(":structureblocklib-bukkit-api")) + compileOnly("org.spigotmc:spigot:1.18-R0.1-SNAPSHOT:remapped-mojang") + testCompile("org.spigotmc:spigot:1.18-R0.1-SNAPSHOT:remapped-mojang") +} diff --git a/structureblocklib-bukkit-core/bukkit-nms-118R1/src/main/java/com/github/shynixn/structureblocklib/bukkit/v1_18_R1/CraftStructureBlock.java b/structureblocklib-bukkit-core/bukkit-nms-118R1/src/main/java/com/github/shynixn/structureblocklib/bukkit/v1_18_R1/CraftStructureBlock.java new file mode 100644 index 0000000..a843071 --- /dev/null +++ b/structureblocklib-bukkit-core/bukkit-nms-118R1/src/main/java/com/github/shynixn/structureblocklib/bukkit/v1_18_R1/CraftStructureBlock.java @@ -0,0 +1,470 @@ +package com.github.shynixn.structureblocklib.bukkit.v1_18_R1; + +import com.github.shynixn.structureblocklib.api.bukkit.block.StructureBlockData; +import com.github.shynixn.structureblocklib.api.bukkit.block.StructureBlockLoad; +import com.github.shynixn.structureblocklib.api.bukkit.block.StructureBlockSave; +import com.github.shynixn.structureblocklib.api.entity.StructureLoaderAbstract; +import com.github.shynixn.structureblocklib.api.entity.StructureSaverAbstract; +import com.github.shynixn.structureblocklib.api.enumeration.StructureMirror; +import com.github.shynixn.structureblocklib.api.enumeration.StructureMode; +import com.github.shynixn.structureblocklib.api.enumeration.StructureRotation; +import com.github.shynixn.structureblocklib.api.service.TypeConversionService; +import com.github.shynixn.structureblocklib.core.block.StructureBlockAbstractImpl; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.StructureBlockEntity; +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.craftbukkit.v1_18_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_18_R1.block.CraftBlockState; +import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.Method; + +public class CraftStructureBlock extends CraftBlockState implements StructureBlockData, StructureBlockSave, StructureBlockLoad { + public StructureBlockAbstractImpl internalBlock; + public TypeConversionService conversionService; + public StructureBlockEntity tileEntityStructure; + + /** + * Creates a new instance with dependencies. + * + * @param structure dependency. + * @param block dependency. + */ + public CraftStructureBlock(StructureBlockAbstractImpl structure, TypeConversionService conversionService, Block block) { + super(block); + final CraftWorld world = (CraftWorld) block.getWorld(); + this.internalBlock = structure; + this.conversionService = conversionService; + this.tileEntityStructure = (StructureBlockEntity) world.getHandle().getBlockEntity(new BlockPos(this.getX(), this.getY(), this.getZ()), true); + + if (tileEntityStructure == null) { + throw new IllegalArgumentException("The block at " + world.getName() + " " + this.getX() + " " + this.getY() + " " + this.getZ() + " is not a StructureBlock."); + } + + CompoundTag compound = new CompoundTag(); + compound = saveCompoundTileEntityStructure(this.tileEntityStructure, compound); + this.setSaveName(compound.getString("name")); + this.setAuthor(compound.getString("author")); + this.setBlockNameMetaData(compound.getString("metadata")); + this.setStructureLocation(new Location(block.getWorld(), compound.getInt("posX"), compound.getInt("posY"), compound.getInt("posZ"))); + this.setSizeX(compound.getInt("sizeX")); + this.setSizeY(compound.getInt("sizeY")); + this.setSizeZ(compound.getInt("sizeZ")); + this.setIncludeEntities(!compound.getBoolean("ignoreEntities")); + this.setBoundingBoxVisible(compound.getBoolean("showboundingbox")); + this.setInvisibleBlocksEnabled(compound.getBoolean("showair")); + this.setIntegrity(compound.getFloat("integrity")); + this.setSeed(compound.getLong("seed")); + this.setMirrorType(conversionService.convertToStructureMirror(Mirror.valueOf(compound.getString("mirror")))); + this.setRotationType(conversionService.convertToStructureRotation(Rotation.valueOf(compound.getString("rotation")))); + this.setStructureMode(conversionService.convertToStructureMode(net.minecraft.world.level.block.state.properties.StructureMode.valueOf(compound.getString("mode")))); + } + + /** + * Updates the craft changes to the minecraft world. + * + * @param force force update. + * @param applyPhysics apply physics. + * @return success. + */ + @Override + public boolean update(boolean force, boolean applyPhysics) { + final boolean result = super.update(force, applyPhysics); + CompoundTag compound = new CompoundTag(); + compound = saveCompoundTileEntityStructure(this.tileEntityStructure, compound); + compound.putString("name", this.getSaveName()); + compound.putString("author", this.getAuthor()); + compound.putString("metadata", this.getBlockNameMetaData()); + compound.putInt("posX", this.getStructureLocation().getBlockX()); + compound.putInt("posY", this.getStructureLocation().getBlockY()); + compound.putInt("posZ", this.getStructureLocation().getBlockZ()); + compound.putInt("sizeX", this.getSizeX()); + compound.putInt("sizeY", this.getSizeY()); + compound.putInt("sizeZ", this.getSizeZ()); + compound.putBoolean("showboundingbox", this.isBoundingBoxVisible()); + compound.putBoolean("showair", this.isInvisibleBlocksEnabled()); + compound.putBoolean("ignoreEntities", !this.isIncludeEntitiesEnabled()); + compound.putFloat("integrity", this.getIntegrity()); + compound.putLong("seed", this.getSeed()); + compound.putString("rotation", conversionService.convertToRotationHandle(getRotationType()).toString()); + compound.putString("mirror", conversionService.convertToMirrorHandle(getMirrorType()).toString()); + compound.putString("mode", conversionService.convertToStructureModeHandle(getStructureMode()).toString()); + this.loadCompoundTileEntityStructure(this.tileEntityStructure, compound); + this.setChangedTileEntityStructure(this.tileEntityStructure); + + return result; + } + + + /** + * Sets the mirrorType of the structure when getting load. + * + * @param mirrorType mirrorType. + */ + @Override + public void setMirrorType(@NotNull StructureMirror mirrorType) { + this.internalBlock.setMirrorType(mirrorType); + } + + /** + * Sets the rotation of the structure when getting load. + * + * @param rotation rotation. + */ + @Override + public void setRotationType(@NotNull StructureRotation rotation) { + this.internalBlock.setRotationType(rotation); + } + + /** + * Returns the rotation of the structure when getting load. + * + * @return rotation. + */ + @Override + public @NotNull StructureRotation getRotationType() { + return internalBlock.getRotationType(); + } + + /** + * Returns the mirrorType of the structure when getting load. + * + * @return mirrorType. + */ + @Override + public @NotNull StructureMirror getMirrorType() { + return internalBlock.getMirrorType(); + } + + /** + * Sets the boundingBoxVisibility. + * + * @param visible visible. + */ + @Override + public void setBoundingBoxVisible(boolean visible) { + this.internalBlock.setBoundingBoxVisible(visible); + } + + /** + * Returns if the boundingBox is visible. + * + * @return visible. + */ + @Override + public boolean isBoundingBoxVisible() { + return this.internalBlock.isBoundingBoxVisible(); + } + + /** + * Sets the integrity of the structure. + * + * @param integrity integrity. + */ + @Override + public void setIntegrity(float integrity) { + this.internalBlock.setIntegrity(integrity); + } + + /** + * Returns the integrity of the structure. + * + * @return integrity. + */ + @Override + public float getIntegrity() { + return this.internalBlock.getIntegrity(); + } + + /** + * Sets the seed of the structure. + * + * @param seed seed. + */ + @Override + public void setSeed(long seed) { + this.internalBlock.setSeed(seed); + } + + /** + * Returns the seed of the structure. + * + * @return seed. + */ + @Override + public long getSeed() { + return internalBlock.getSeed(); + } + + /** + * Sets the author of the structure. + * + * @param author author. + */ + @Override + public void setAuthor(@Nullable String author) { + this.internalBlock.setAuthor(author); + } + + /** + * Returns the author of the structure. + * + * @return author. + */ + @Override + public @Nullable String getAuthor() { + return this.internalBlock.getAuthor(); + } + + /** + * Changes the location of the structure. + * + * @param location location. + */ + @Override + public void setStructureLocation(@Nullable Location location) { + this.internalBlock.setStructureLocation(location); + } + + /** + * Returns the location of the structure. + * + * @return location. + */ + @Nullable + @Override + public Location getStructureLocation() { + return this.internalBlock.getStructureLocation(); + } + + /** + * Should entities which may or may not be included in the + * saved file be included in the loaded/saved structure. + * Default false. + * + * @param flag flag. + */ + @Override + public void setIncludeEntities(boolean flag) { + this.internalBlock.setIncludeEntities(flag); + } + + /** + * Should entities which may or may not be included in the + * saved file be included in the loaded/saved structure. + * Default false. + * + * @return false. + */ + @Override + public boolean isIncludeEntitiesEnabled() { + return internalBlock.isIncludeEntitiesEnabled(); + } + + /** + * Changes the size of the structure in X direction. + * + * @param sizeX sizeX. + */ + @Override + public void setSizeX(int sizeX) { + this.internalBlock.setSizeX(sizeX); + } + + /** + * Changes the size of the structure in Y direction. + * + * @param sizeY sizeY. + */ + @Override + public void setSizeY(int sizeY) { + this.internalBlock.setSizeY(sizeY); + } + + /** + * Changes the size of the structure in Z direction. + * + * @param sizeZ sizeZ. + */ + @Override + public void setSizeZ(int sizeZ) { + this.internalBlock.setSizeZ(sizeZ); + } + + /** + * Returns the size of the structure in X direction. + * + * @return xSize. + */ + @Override + public int getSizeX() { + return this.internalBlock.getSizeX(); + } + + /** + * Returns the size of the structure in Y direction. + * + * @return ySize. + */ + @Override + public int getSizeY() { + return internalBlock.getSizeY(); + } + + /** + * Returns the size of the structure in Z direction. + * + * @return zSize. + */ + @Override + public int getSizeZ() { + return internalBlock.getSizeZ(); + } + + /** + * Sets the name of the save. + * + * @param name name. + */ + @Override + public void setSaveName(@Nullable String name) { + this.internalBlock.setSaveName(name); + } + + /** + * Returns the name of the save. + * + * @return name. + */ + @Override + public @Nullable String getSaveName() { + return internalBlock.getSaveName(); + } + + /** + * Sets custom meta data. Please use the minecraft documentation to find out more. + * + * @param blockNameMetaData customMeta. + */ + @Override + public void setBlockNameMetaData(@Nullable String blockNameMetaData) { + this.internalBlock.setBlockNameMetaData(blockNameMetaData); + } + + /** + * Returns the custom meta data. + * + * @return customMeta + */ + @Override + public @Nullable String getBlockNameMetaData() { + return internalBlock.getBlockNameMetaData(); + } + + /** + * Sets if invisibleBlocks should be visible. + * + * @param flag flag. + */ + @Override + public void setInvisibleBlocksEnabled(boolean flag) { + this.internalBlock.setInvisibleBlocksEnabled(flag); + } + + /** + * Returns if invisibleBlocks are visible. + * + * @return visible + */ + @Override + public boolean isInvisibleBlocksEnabled() { + return internalBlock.isInvisibleBlocksEnabled(); + } + + /** + * Changes the type of the structureBlock. + * + * @param structureMode structureMode. + */ + @Override + public void setStructureMode(@NotNull StructureMode structureMode) { + this.internalBlock.setStructureMode(structureMode); + } + + /** + * Returns the type of the structureBlock. + * + * @return structureMode. + */ + @Override + public @NotNull StructureMode getStructureMode() { + return internalBlock.getStructureMode(); + } + + /** + * Creates a new instance of {@link StructureLoaderAbstract} which + * contains the current block properties. + * + * @return New instance. + */ + @Override + public @NotNull StructureLoaderAbstract loadStructure() { + return internalBlock.loadStructure(); + } + + /** + * Creates a new instance of {@link StructureSaverAbstract} which + * contains the current block properties. + * + * @return New instance. + */ + @Override + public @NotNull StructureSaverAbstract saveStructure() { + return internalBlock.saveStructure(); + } + + /** + * The mapping for StructureBlockEntity save is broken in spigot. This is a workaround. + */ + private CompoundTag saveCompoundTileEntityStructure(StructureBlockEntity tileEntityStructure, CompoundTag compoundTag) { + try { + Method method = StructureBlockEntity.class.getDeclaredMethod("b", CompoundTag.class); + method.setAccessible(true); + method.invoke(tileEntityStructure, compoundTag); + return compoundTag; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * The mapping for StructureBlockEntity load is broken in spigot. This is a workaround. + */ + private void loadCompoundTileEntityStructure(StructureBlockEntity tileEntityStructure, CompoundTag compoundTag) { + try { + Method method = StructureBlockEntity.class.getDeclaredMethod("a", CompoundTag.class); + method.invoke(tileEntityStructure, compoundTag); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * The mapping for StructureBlockEntity setChanged is broken in spigot. This is a workaround. + */ + private void setChangedTileEntityStructure(StructureBlockEntity tileEntityStructure) { + try { + Method method = BlockEntity.class.getDeclaredMethod("e"); + method.invoke(tileEntityStructure); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/structureblocklib-bukkit-core/bukkit-nms-118R1/src/main/java/com/github/shynixn/structureblocklib/bukkit/v1_18_R1/StructureSerializationServiceImpl.java b/structureblocklib-bukkit-core/bukkit-nms-118R1/src/main/java/com/github/shynixn/structureblocklib/bukkit/v1_18_R1/StructureSerializationServiceImpl.java new file mode 100644 index 0000000..0cdfefe --- /dev/null +++ b/structureblocklib-bukkit-core/bukkit-nms-118R1/src/main/java/com/github/shynixn/structureblocklib/bukkit/v1_18_R1/StructureSerializationServiceImpl.java @@ -0,0 +1,47 @@ +package com.github.shynixn.structureblocklib.bukkit.v1_18_R1; + +import com.github.shynixn.structureblocklib.api.service.StructureSerializationService; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtIo; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * Serialization service. + */ +public class StructureSerializationServiceImpl implements StructureSerializationService { + /** + * Deserializes the {@link InputStream} to an NMS handle of StructureTemplate. + * This call is blocking. + * + * @param inputStream Opened inputStream. Does not close the stream after processing. + * @return A new NMS instance of StructureTemplate. + */ + @Override + public Object deSerialize(InputStream inputStream) throws IOException { + CompoundTag compound = NbtIo.readCompressed(inputStream); + StructureTemplate template = new StructureTemplate(); + template.load(compound); + return template; + } + + /** + * Serializes the NMS handle of StructureTemplate to an {@link OutputStream}. + * This call is blocking. + * + * @param structureTemplate NMS handle. + * @param outputStream Opened outputStream. Does not close the stream after processing. + */ + @Override + public void serialize(Object structureTemplate, OutputStream outputStream) throws IOException { + if (!(structureTemplate instanceof StructureTemplate)) { + throw new IllegalArgumentException("StructureTemplate has to be an NMS handle!"); + } + + CompoundTag compound = (((StructureTemplate) structureTemplate)).save(new CompoundTag()); + NbtIo.writeCompressed(compound, outputStream); + } +} diff --git a/structureblocklib-bukkit-core/bukkit-nms-118R1/src/main/java/com/github/shynixn/structureblocklib/bukkit/v1_18_R1/StructureWorldServiceImpl.java b/structureblocklib-bukkit-core/bukkit-nms-118R1/src/main/java/com/github/shynixn/structureblocklib/bukkit/v1_18_R1/StructureWorldServiceImpl.java new file mode 100644 index 0000000..b8b884b --- /dev/null +++ b/structureblocklib-bukkit-core/bukkit-nms-118R1/src/main/java/com/github/shynixn/structureblocklib/bukkit/v1_18_R1/StructureWorldServiceImpl.java @@ -0,0 +1,92 @@ +package com.github.shynixn.structureblocklib.bukkit.v1_18_R1; + +import com.github.shynixn.structureblocklib.api.entity.StructurePlaceMeta; +import com.github.shynixn.structureblocklib.api.entity.StructureReadMeta; +import com.github.shynixn.structureblocklib.api.service.StructureWorldService; +import com.github.shynixn.structureblocklib.api.service.TypeConversionService; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.levelgen.structure.templatesystem.BlockRotProcessor; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_18_R1.CraftWorld; + +import java.util.Random; + +/** + * Implementation to interact with structures in the world. + */ +public class StructureWorldServiceImpl implements StructureWorldService { + private final TypeConversionService conversionService; + + /** + * Creates a new service with dependencies. + * + * @param conversionService dependency. + */ + public StructureWorldServiceImpl(TypeConversionService conversionService) { + this.conversionService = conversionService; + } + + /** + * Places the blocks in the world defined by the given structure. + * + * @param meta Meta data to describe the placement. + * @param structure NMS structure. + */ + @Override + public void placeStructureToWorld(StructurePlaceMeta meta, Object structure) throws Exception { + if (!(structure instanceof StructureTemplate)) { + throw new IllegalArgumentException("StructureTemplate has to be an NMS handle!"); + } + + StructureTemplate template = (StructureTemplate) structure; + ServerLevel world = ((CraftWorld) Bukkit.getWorld(meta.getLocation().getWorldName())).getHandle(); + BlockPos cornerBlock = new BlockPos((int) meta.getLocation().getX(), (int) meta.getLocation().getY(), (int) meta.getLocation().getZ()); + StructurePlaceSettings info = new StructurePlaceSettings(); + info.setIgnoreEntities(!meta.isIncludeEntitiesEnabled()); + info.setMirror((Mirror) conversionService.convertToMirrorHandle(meta.getMirrorType())); + info.setRotation((Rotation) conversionService.convertToRotationHandle(meta.getRotationType())); + + if (meta.getIntegrity() < 1.0F) { + info.clearProcessors(); + float rotation = Mth.clamp(meta.getIntegrity(), 0.0F, 1.0F); + BlockRotProcessor rotationProcessor = new BlockRotProcessor(rotation); + Random random = new Random(); + + if (meta.getSeed() != 0L) { + random = new Random(meta.getSeed()); + } + + info.addProcessor(rotationProcessor); + info.setRandom(random); + } + + template.placeInWorld(world, cornerBlock, cornerBlock, info, new Random(), 2); + } + + /** + * Reads the blocks in the world into an NMS Structure definition. + * + * @param meta Meta data to describe the block selection. + * @return A new NMS Structure definition. + */ + @Override + public Object readStructureFromWorld(StructureReadMeta meta) throws Exception { + ServerLevel world = ((CraftWorld) Bukkit.getWorld(meta.getLocation().getWorldName())).getHandle(); + BlockPos cornerBlock = new BlockPos((int) meta.getLocation().getX(), (int) meta.getLocation().getY(), (int) meta.getLocation().getZ()); + BlockPos offsetBlock = new BlockPos((int) meta.getOffset().getX(), (int) meta.getOffset().getY(), (int) meta.getOffset().getZ()); + Block structureVoid = (Block) Blocks.class.getDeclaredField(meta.getStructureVoidTypeName()).get(null); + + StructureTemplate template = new StructureTemplate(); + template.fillFromWorld(world, cornerBlock, offsetBlock, meta.isIncludeEntitiesEnabled(), structureVoid); + template.setAuthor(meta.getAuthor()); + return template; + } +} diff --git a/structureblocklib-bukkit-core/bukkit-nms-118R1/src/main/java/com/github/shynixn/structureblocklib/bukkit/v1_18_R1/TypeConversionServiceImpl.java b/structureblocklib-bukkit-core/bukkit-nms-118R1/src/main/java/com/github/shynixn/structureblocklib/bukkit/v1_18_R1/TypeConversionServiceImpl.java new file mode 100644 index 0000000..f9830a2 --- /dev/null +++ b/structureblocklib-bukkit-core/bukkit-nms-118R1/src/main/java/com/github/shynixn/structureblocklib/bukkit/v1_18_R1/TypeConversionServiceImpl.java @@ -0,0 +1,129 @@ +package com.github.shynixn.structureblocklib.bukkit.v1_18_R1; + +import com.github.shynixn.structureblocklib.api.enumeration.StructureMirror; +import com.github.shynixn.structureblocklib.api.enumeration.StructureMode; +import com.github.shynixn.structureblocklib.api.enumeration.StructureRotation; +import com.github.shynixn.structureblocklib.api.service.TypeConversionService; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.world.level.block.Rotation; + +public class TypeConversionServiceImpl implements TypeConversionService { + /** + * Converts the given handle to a {@link StructureMode}. + * + * @param handle NMS handle. + * @return {@link StructureMode}. + */ + @Override + public StructureMode convertToStructureMode(Object handle) { + net.minecraft.world.level.block.state.properties.StructureMode usageMode = (net.minecraft.world.level.block.state.properties.StructureMode) handle; + switch (usageMode) { + case DATA: + return StructureMode.DATA; + case LOAD: + return StructureMode.LOAD; + case SAVE: + return StructureMode.SAVE; + default: + return StructureMode.CORNER; + } + } + + /** + * Converts the given handle to a {@link StructureMirror}. + * + * @param handle NMS handle. + * @return {@link StructureMirror}. + */ + @Override + public StructureMirror convertToStructureMirror(Object handle) { + Mirror mirror = (Mirror) handle; + switch (mirror) { + case FRONT_BACK: + return StructureMirror.FRONT_BACK; + case LEFT_RIGHT: + return StructureMirror.LEFT_RIGHT; + default: + return StructureMirror.NONE; + } + } + + /** + * Converts the given handle to a {@link StructureRotation}. + * + * @param handle NMS handle. + * @return {@link StructureRotation}. + */ + @Override + public StructureRotation convertToStructureRotation(Object handle) { + Rotation rotation = (Rotation) handle; + switch (rotation) { + case CLOCKWISE_90: + return StructureRotation.ROTATION_90; + case CLOCKWISE_180: + return StructureRotation.ROTATION_180; + case COUNTERCLOCKWISE_90: + return StructureRotation.ROTATION_270; + default: + return StructureRotation.NONE; + } + } + + /** + * Converts the given {@link StructureMode} to a handle. + * + * @param mode {@link StructureMode}. + * @return NMS handle. + */ + @Override + public Object convertToStructureModeHandle(StructureMode mode) { + switch (mode) { + case SAVE: + return net.minecraft.world.level.block.state.properties.StructureMode.SAVE; + case DATA: + return net.minecraft.world.level.block.state.properties.StructureMode.DATA; + case LOAD: + return net.minecraft.world.level.block.state.properties.StructureMode.LOAD; + default: + return net.minecraft.world.level.block.state.properties.StructureMode.CORNER; + } + } + + /** + * Converts the given {@link StructureMirror} to a handle. + * + * @param mirror {@link StructureMirror}. + * @return NMS handle. + */ + @Override + public Object convertToMirrorHandle(StructureMirror mirror) { + switch (mirror) { + case FRONT_BACK: + return Mirror.FRONT_BACK; + case LEFT_RIGHT: + return Mirror.LEFT_RIGHT; + default: + return Mirror.NONE; + } + } + + /** + * Converts the given {@link StructureRotation} to a handle. + * + * @param rotation {@link StructureRotation}. + * @return NMS handle. + */ + @Override + public Object convertToRotationHandle(StructureRotation rotation) { + switch (rotation) { + case ROTATION_90: + return Rotation.CLOCKWISE_90; + case ROTATION_180: + return Rotation.CLOCKWISE_180; + case ROTATION_270: + return Rotation.COUNTERCLOCKWISE_90; + default: + return Rotation.NONE; + } + } +} diff --git a/structureblocklib-bukkit-core/bukkit-nms-118R1/src/test/java/helper/MockedProxyService.java b/structureblocklib-bukkit-core/bukkit-nms-118R1/src/test/java/helper/MockedProxyService.java new file mode 100644 index 0000000..fa09db3 --- /dev/null +++ b/structureblocklib-bukkit-core/bukkit-nms-118R1/src/test/java/helper/MockedProxyService.java @@ -0,0 +1,106 @@ +package helper; + +import com.github.shynixn.structureblocklib.api.entity.Position; +import com.github.shynixn.structureblocklib.api.enumeration.Version; +import com.github.shynixn.structureblocklib.api.service.ProxyService; +import com.github.shynixn.structureblocklib.core.entity.PositionImpl; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.mockito.Mockito; + +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class MockedProxyService implements ProxyService { + private ExecutorService executor = Executors.newFixedThreadPool(1); + public Queue concurrentList = new ConcurrentLinkedQueue(); + + /** + * Converts the given position to a location. + * + * @param position position. + * @return location. + */ + @Override + public @Nullable L toLocation(@Nullable Position position) { + return (L) new Location(Mockito.mock(World.class), position.getX(), position.getY(), position.getZ()); + } + + /** + * Converts the given position to a vector. + * + * @param position position. + * @return vector. + */ + @Override + public @Nullable V toVector(@Nullable Position position) { + return (V) new Vector(position.getX(), position.getY(), position.getZ()); + } + + /** + * Converts the given location to a position. + * + * @param location Location. + * @return position. + */ + @Override + public @Nullable Position toPosition(@Nullable L location) { + if (location == null) { + return null; + } + + Position position = new PositionImpl(); + + if (location instanceof Location) { + Location l = (Location) location; + position.setWorldName(l.getWorld().getName()); + position.setX(l.getX()); + position.setY(l.getY()); + position.setZ(l.getZ()); + } + + if (location instanceof Vector) { + Vector l = (Vector) location; + position.setX(l.getX()); + position.setY(l.getY()); + position.setZ(l.getZ()); + } + + return position; + } + + /** + * Runs an async task. + * + * @param runnable Runnable. + */ + @Override + public void runAsyncTask(@NotNull Runnable runnable) { + executor.submit(runnable); + } + + /** + * Runs a sync task. + * + * @param runnable Runnable. + */ + @Override + public void runSyncTask(@NotNull Runnable runnable) { + concurrentList.add(runnable); + } + + /** + * Gets the running minecraft version. + * + * @return version. + */ + @Override + public Version getServerVersion() { + return Version.VERSION_UNKNOWN; + } +} diff --git a/structureblocklib-bukkit-core/bukkit-nms-118R1/src/test/java/helper/MockedStructureWorldService.java b/structureblocklib-bukkit-core/bukkit-nms-118R1/src/test/java/helper/MockedStructureWorldService.java new file mode 100644 index 0000000..dcecc3a --- /dev/null +++ b/structureblocklib-bukkit-core/bukkit-nms-118R1/src/test/java/helper/MockedStructureWorldService.java @@ -0,0 +1,29 @@ +package helper; + +import com.github.shynixn.structureblocklib.api.entity.StructurePlaceMeta; +import com.github.shynixn.structureblocklib.api.entity.StructureReadMeta; +import com.github.shynixn.structureblocklib.api.service.StructureWorldService; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; + +public class MockedStructureWorldService implements StructureWorldService { + /** + * Places the blocks in the world defined by the given structure. + * + * @param meta Meta data to describe the placement. + * @param structure NMS structure. + */ + @Override + public void placeStructureToWorld(StructurePlaceMeta meta, Object structure) throws Exception { + } + + /** + * Reads the blocks in the world into an NMS Structure definition. + * + * @param meta Meta data to describe the block selection. + * @return A new NMS Structure definition. + */ + @Override + public Object readStructureFromWorld(StructureReadMeta meta) throws Exception { + return new StructureTemplate(); + } +} diff --git a/structureblocklib-bukkit-core/bukkit-nms-118R1/src/test/java/unittest/TStructureSerializationServiceImpl.java b/structureblocklib-bukkit-core/bukkit-nms-118R1/src/test/java/unittest/TStructureSerializationServiceImpl.java new file mode 100644 index 0000000..ec8711c --- /dev/null +++ b/structureblocklib-bukkit-core/bukkit-nms-118R1/src/test/java/unittest/TStructureSerializationServiceImpl.java @@ -0,0 +1,63 @@ +package unittest; + +import com.github.shynixn.structureblocklib.bukkit.v1_18_R1.StructureSerializationServiceImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +public class TStructureSerializationServiceImpl { + /** + * Given a valid defined Structure + * when serialize is called + * then the content should be written to the output stream. + */ + @Test + public void serialize_ValidDefinedStructure_ShouldCorrectlySerialize() { + // Arrange + StructureSerializationServiceImpl classUnderTest = createWithDependencies(); + StructureTemplate definedStructure = Mockito.mock(StructureTemplate.class); + Mockito.when(definedStructure.save(Mockito.any(CompoundTag.class))) + .thenReturn(new CompoundTag()); + byte[] expected = new byte[]{ + 31, -117, 8, 0, 0, 0, 0, 0, 0, -1, -29, 98, 96, 96, 0, 0, 120, 63, -7, 78, 4, 0, 0, 0 + }; + + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + // Act + classUnderTest.serialize(definedStructure, outputStream); + byte[] actual = outputStream.toByteArray(); + + // Assert. + Assertions.assertArrayEquals(expected, actual); + } catch (IOException e) { + Assertions.fail(e); + } + } + + /** + * Given a invalid defined Structure + * when serialize is called + * then an exception should be thrown. + */ + @Test + public void seSerialize_InvalidDefinedStructure_ShouldThrowException() { + // Arrange + StructureSerializationServiceImpl classUnderTest = createWithDependencies(); + StructureTemplate definedStructure = Mockito.mock(StructureTemplate.class); + Mockito.when(definedStructure.save(Mockito.any(CompoundTag.class))) + .thenReturn(new CompoundTag()); + + Assertions.assertThrows(IllegalArgumentException.class, () -> { + classUnderTest.serialize("NotReal", new ByteArrayOutputStream()); + }); + } + + private StructureSerializationServiceImpl createWithDependencies() { + return new StructureSerializationServiceImpl(); + } +} diff --git a/structureblocklib-bukkit-core/bukkit-nms-118R1/src/test/java/unittest/TTypeConversionServiceImpl.java b/structureblocklib-bukkit-core/bukkit-nms-118R1/src/test/java/unittest/TTypeConversionServiceImpl.java new file mode 100644 index 0000000..7fe3082 --- /dev/null +++ b/structureblocklib-bukkit-core/bukkit-nms-118R1/src/test/java/unittest/TTypeConversionServiceImpl.java @@ -0,0 +1,78 @@ +package unittest; + +import com.github.shynixn.structureblocklib.api.enumeration.StructureMirror; +import com.github.shynixn.structureblocklib.api.enumeration.StructureMode; +import com.github.shynixn.structureblocklib.api.enumeration.StructureRotation; +import com.github.shynixn.structureblocklib.api.service.TypeConversionService; +import com.github.shynixn.structureblocklib.bukkit.v1_18_R1.TypeConversionServiceImpl; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.world.level.block.Rotation; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class TTypeConversionServiceImpl { + /** + * Given StructureMirror + * when convert is called + * then value should be correctly converted. + */ + @Test + public void convert_StructureMirror_ShouldCorrectlyConvert() { + // Arrange + TypeConversionService conversionService = createWithDependencies(); + + // Assert + Assertions.assertEquals(Mirror.LEFT_RIGHT, conversionService.convertToMirrorHandle(StructureMirror.LEFT_RIGHT)); + Assertions.assertEquals(Mirror.FRONT_BACK, conversionService.convertToMirrorHandle(StructureMirror.FRONT_BACK)); + Assertions.assertEquals(Mirror.NONE, conversionService.convertToMirrorHandle(StructureMirror.NONE)); + Assertions.assertEquals(StructureMirror.LEFT_RIGHT, conversionService.convertToStructureMirror(Mirror.LEFT_RIGHT)); + Assertions.assertEquals(StructureMirror.FRONT_BACK, conversionService.convertToStructureMirror(Mirror.FRONT_BACK)); + Assertions.assertEquals(StructureMirror.NONE, conversionService.convertToStructureMirror(Mirror.NONE)); + } + + /** + * Given StructureRotation + * when convert is called + * then value should be correctly converted. + */ + @Test + public void convert_StructureRotation_ShouldCorrectlyConvert() { + // Arrange + TypeConversionService conversionService = createWithDependencies(); + + // Assert + Assertions.assertEquals(Rotation.CLOCKWISE_90, conversionService.convertToRotationHandle(StructureRotation.ROTATION_90)); + Assertions.assertEquals(Rotation.CLOCKWISE_180, conversionService.convertToRotationHandle(StructureRotation.ROTATION_180)); + Assertions.assertEquals(Rotation.COUNTERCLOCKWISE_90, conversionService.convertToRotationHandle(StructureRotation.ROTATION_270)); + Assertions.assertEquals(Rotation.NONE, conversionService.convertToRotationHandle(StructureRotation.NONE)); + Assertions.assertEquals(StructureRotation.ROTATION_90, conversionService.convertToStructureRotation(Rotation.CLOCKWISE_90)); + Assertions.assertEquals(StructureRotation.ROTATION_180, conversionService.convertToStructureRotation(Rotation.CLOCKWISE_180)); + Assertions.assertEquals(StructureRotation.ROTATION_270, conversionService.convertToStructureRotation(Rotation.COUNTERCLOCKWISE_90)); + Assertions.assertEquals(StructureRotation.NONE, conversionService.convertToStructureRotation(Rotation.NONE)); + } + + /** + * Given StructureMode + * when convert is called + * then value should be correctly converted. + */ + @Test + public void convert_StructureMode_ShouldCorrectlyConvert() { + // Arrange + TypeConversionService conversionService = createWithDependencies(); + + // Assert + Assertions.assertEquals(net.minecraft.world.level.block.state.properties.StructureMode.CORNER, conversionService.convertToStructureModeHandle(StructureMode.CORNER)); + Assertions.assertEquals(net.minecraft.world.level.block.state.properties.StructureMode.SAVE, conversionService.convertToStructureModeHandle(StructureMode.SAVE)); + Assertions.assertEquals(net.minecraft.world.level.block.state.properties.StructureMode.DATA, conversionService.convertToStructureModeHandle(StructureMode.DATA)); + Assertions.assertEquals(net.minecraft.world.level.block.state.properties.StructureMode.LOAD, conversionService.convertToStructureModeHandle(StructureMode.LOAD)); + Assertions.assertEquals(StructureMode.CORNER, conversionService.convertToStructureMode(net.minecraft.world.level.block.state.properties.StructureMode.CORNER)); + Assertions.assertEquals(StructureMode.DATA, conversionService.convertToStructureMode(net.minecraft.world.level.block.state.properties.StructureMode.DATA)); + Assertions.assertEquals(StructureMode.SAVE, conversionService.convertToStructureMode(net.minecraft.world.level.block.state.properties.StructureMode.SAVE)); + Assertions.assertEquals(StructureMode.LOAD, conversionService.convertToStructureMode(net.minecraft.world.level.block.state.properties.StructureMode.LOAD)); + } + + private TypeConversionService createWithDependencies() { + return new TypeConversionServiceImpl(); + } +} diff --git a/structureblocklib-bukkit-plugin/build.gradle.kts b/structureblocklib-bukkit-plugin/build.gradle.kts index d696045..130b61e 100644 --- a/structureblocklib-bukkit-plugin/build.gradle.kts +++ b/structureblocklib-bukkit-plugin/build.gradle.kts @@ -38,15 +38,26 @@ tasks.register("pluginJar", Exec::class.java) { } val shadowJar = tasks.findByName("shadowJar")!! as ShadowJar - val obfArchiveName = "${shadowJar.baseName}-${shadowJar.version}-obfuscated.${shadowJar.extension}" - val archiveName = "${shadowJar.baseName}-${shadowJar.version}.${shadowJar.extension}" val sourceJarFile = File(buildDir, "libs/" + shadowJar.archiveName) - val obfJarFile = File(buildDir, "libs/$obfArchiveName") + val archiveName = "${shadowJar.baseName}-${shadowJar.version}.${shadowJar.extension}" val targetJarFile = File(buildDir, "libs/$archiveName") - val obsMapping = - "java -jar ${file.absolutePath} -i \"$sourceJarFile\" -o \"$obfJarFile\" -m \"\$HOME/.m2/repository/org/spigotmc/minecraft-server/1.17-R0.1-SNAPSHOT/minecraft-server-1.17-R0.1-SNAPSHOT-maps-mojang.txt\" --reverse" + - "&& java -jar ${file.absolutePath} -i \"$obfJarFile\" -o \"$targetJarFile\" -m \"\$HOME/.m2/repository/org/spigotmc/minecraft-server/1.17-R0.1-SNAPSHOT/minecraft-server-1.17-R0.1-SNAPSHOT-maps-spigot.csrg\"" + var obsMapping = createCommand( + "1.17.1-R0.1-SNAPSHOT", + "com/github/shynixn/structureblocklib/bukkit/v1_17_R1", + file, + shadowJar, + sourceJarFile, + targetJarFile + ) + obsMapping = "$obsMapping && " + createCommand( + "1.18-R0.1-SNAPSHOT", + "com/github/shynixn/structureblocklib/bukkit/v1_18_R1", + file, + shadowJar, + targetJarFile, + targetJarFile + ) if (System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("windows")) { commandLine = listOf("cmd", "/c", obsMapping.replace("\$HOME", "%userprofile%")) @@ -55,6 +66,21 @@ tasks.register("pluginJar", Exec::class.java) { } } +fun createCommand( + version: String, + include: String, + file: File, + shadowJar: ShadowJar, + sourceJarFile: File, + targetJarFile: File +): String { + val obfArchiveName = "${shadowJar.baseName}-${shadowJar.version}-obfuscated.${shadowJar.extension}" + val obfJarFile = File(buildDir, "libs/$obfArchiveName") + + return "java -jar ${file.absolutePath} -i \"$sourceJarFile\" -o \"$obfJarFile\" -only \"$include\" -m \"\$HOME/.m2/repository/org/spigotmc/minecraft-server/${version}/minecraft-server-${version}-maps-mojang.txt\" --reverse" + + "&& java -jar ${file.absolutePath} -i \"$obfJarFile\" -o \"$targetJarFile\" -only \"$include\" -m \"\$HOME/.m2/repository/org/spigotmc/minecraft-server/${version}/minecraft-server-${version}-maps-spigot.csrg\"" +} + dependencies { implementation(project(":structureblocklib-api")) implementation(project(":structureblocklib-core")) diff --git a/structureblocklib-bukkit-plugin/src/main/resources/plugin.yml b/structureblocklib-bukkit-plugin/src/main/resources/plugin.yml index 0228bc2..e54a14d 100644 --- a/structureblocklib-bukkit-plugin/src/main/resources/plugin.yml +++ b/structureblocklib-bukkit-plugin/src/main/resources/plugin.yml @@ -1,4 +1,4 @@ name: StructureBlockLib -version: 2.2.2 +version: 2.3.0 author: Shynixn main: com.github.shynixn.structureblocklib.bukkit.plugin.StructureBlockLibPlugin diff --git a/structureblocklib-bukkit-sample/build.gradle.kts b/structureblocklib-bukkit-sample/build.gradle.kts index dac7eff..6296c3c 100644 --- a/structureblocklib-bukkit-sample/build.gradle.kts +++ b/structureblocklib-bukkit-sample/build.gradle.kts @@ -42,15 +42,26 @@ tasks.register("pluginJar", Exec::class.java) { } val shadowJar = tasks.findByName("shadowJar")!! as ShadowJar - val obfArchiveName = "${shadowJar.baseName}-${shadowJar.version}-obfuscated.${shadowJar.extension}" - val archiveName = "${shadowJar.baseName}-${shadowJar.version}.${shadowJar.extension}" val sourceJarFile = File(buildDir, "libs/" + shadowJar.archiveName) - val obfJarFile = File(buildDir, "libs/$obfArchiveName") + val archiveName = "${shadowJar.baseName}-${shadowJar.version}.${shadowJar.extension}" val targetJarFile = File(destinationDir, archiveName) - val obsMapping = - "java -jar ${file.absolutePath} -i \"$sourceJarFile\" -o \"$obfJarFile\" -m \"\$HOME/.m2/repository/org/spigotmc/minecraft-server/1.17-R0.1-SNAPSHOT/minecraft-server-1.17-R0.1-SNAPSHOT-maps-mojang.txt\" --reverse" + - "&& java -jar ${file.absolutePath} -i \"$obfJarFile\" -o \"$targetJarFile\" -m \"\$HOME/.m2/repository/org/spigotmc/minecraft-server/1.17-R0.1-SNAPSHOT/minecraft-server-1.17-R0.1-SNAPSHOT-maps-spigot.csrg\"" + var obsMapping = createCommand( + "1.17.1-R0.1-SNAPSHOT", + "com/github/shynixn/structureblocklib/bukkit/v1_17_R1", + file, + shadowJar, + sourceJarFile, + targetJarFile + ) + obsMapping = "$obsMapping && " + createCommand( + "1.18-R0.1-SNAPSHOT", + "com/github/shynixn/structureblocklib/bukkit/v1_18_R1", + file, + shadowJar, + targetJarFile, + targetJarFile + ) if (System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("windows")) { commandLine = listOf("cmd", "/c", obsMapping.replace("\$HOME", "%userprofile%")) @@ -59,6 +70,21 @@ tasks.register("pluginJar", Exec::class.java) { } } +fun createCommand( + version: String, + include: String, + file: File, + shadowJar: ShadowJar, + sourceJarFile: File, + targetJarFile: File +): String { + val obfArchiveName = "${shadowJar.baseName}-${shadowJar.version}-obfuscated.${shadowJar.extension}" + val obfJarFile = File(buildDir, "libs/$obfArchiveName") + + return "java -jar ${file.absolutePath} -i \"$sourceJarFile\" -o \"$obfJarFile\" -only \"$include\" -m \"\$HOME/.m2/repository/org/spigotmc/minecraft-server/${version}/minecraft-server-${version}-maps-mojang.txt\" --reverse" + + "&& java -jar ${file.absolutePath} -i \"$obfJarFile\" -o \"$targetJarFile\" -only \"$include\" -m \"\$HOME/.m2/repository/org/spigotmc/minecraft-server/${version}/minecraft-server-${version}-maps-spigot.csrg\"" +} + dependencies { implementation(project(":structureblocklib-api")) implementation(project(":structureblocklib-core")) diff --git a/structureblocklib-bukkit-sample/src/main/resources/plugin.yml b/structureblocklib-bukkit-sample/src/main/resources/plugin.yml index 78dc7ab..4c7313d 100644 --- a/structureblocklib-bukkit-sample/src/main/resources/plugin.yml +++ b/structureblocklib-bukkit-sample/src/main/resources/plugin.yml @@ -1,5 +1,5 @@ name: StructureBlockLibSample -version: 2.2.2 +version: 2.3.0 author: Shynixn main: com.github.shynixn.structureblocklib.bukkit.plugin.StructureBlockLibSamplePlugin commands: diff --git a/structureblocklib-core/src/main/java/com/github/shynixn/structureblocklib/core/entity/StructureSaverAbstractImpl.java b/structureblocklib-core/src/main/java/com/github/shynixn/structureblocklib/core/entity/StructureSaverAbstractImpl.java index 3a194db..de71b13 100644 --- a/structureblocklib-core/src/main/java/com/github/shynixn/structureblocklib/core/entity/StructureSaverAbstractImpl.java +++ b/structureblocklib-core/src/main/java/com/github/shynixn/structureblocklib/core/entity/StructureSaverAbstractImpl.java @@ -46,7 +46,9 @@ public StructureSaverAbstractImpl(ProxyService proxyService, StructureSerializat this.serializationService = serializationService; this.worldService = worldService; - if (proxyService.getServerVersion().isVersionSameOrGreaterThan(Version.VERSION_1_17_R1)) { + if (proxyService.getServerVersion().isVersionSameOrGreaterThan(Version.VERSION_1_18_R1)) { + structureVoid = "b"; + } else if (proxyService.getServerVersion().isVersionSameOrGreaterThan(Version.VERSION_1_17_R1)) { structureVoid = "jb"; } else if (proxyService.getServerVersion().isVersionSameOrGreaterThan(Version.VERSION_1_13_R2)) { structureVoid = "STRUCTURE_VOID";