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";