diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index 99dc37247..e827c664c 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -154,7 +154,7 @@ jobs:
run: cd BuildTools && java -jar BuildTools.jar --rev 1.18.2 --remapped
# Build 1.19.2 NMS
- wild_1_19:
+ wild_1_19_2:
runs-on: ubuntu-latest
steps:
- name: Set up JDK 17 # 1.19.2 can only be built with Java 17
@@ -163,7 +163,7 @@ jobs:
distribution: 'temurin'
java-version: '17'
- name: Cache 1.19.2 Maven package
- id: cacheWild
+ id: cacheWild_r1
uses: actions/cache@v2
with:
path: |
@@ -195,78 +195,130 @@ jobs:
if: steps.wild.outputs.sucess != 'true' || steps.wildMojang.outputs.sucess != 'true' || steps.wildObf.outputs.sucess != 'true'
run: cd BuildTools && java -jar BuildTools.jar --rev 1.19.2 --remapped
+ # Build 1.19.3 NMS
+ wild_1_19_3:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Set up JDK 17 # 1.19.3 can only be built with Java 17
+ uses: actions/setup-java@v2
+ with:
+ distribution: 'temurin'
+ java-version: '17'
+ - name: Cache 1.19.3 Maven package
+ id: cacheWild_r2
+ uses: actions/cache@v2
+ with:
+ path: |
+ ~/.m2/repository/org/spigotmc/spigot/1.19.3-R0.1-SNAPSHOT/
+ ~/.m2/repository/org/spigotmc/spigot-parent/
+ ~/.m2/repository/org/spigotmc/minecraft-server/
+ key: ${{ runner.os }}-spigot-1.19.3-all
+ restore-keys: ${{ runner.os }}-spigot-1.19.3-all
+ - name: Cache Maven packages
+ id: cacheMain
+ uses: actions/cache@v2
+ with:
+ path: ~/.m2
+ key: ${{ runner.os }}-m2_1.19.3
+ restore-keys: ${{ runner.os }}-m2_1.19.3
+
+ - name: Setup BuildTools
+ run: mkdir BuildTools && wget -O BuildTools/BuildTools.jar https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar
+ - name: Check 1.19.3 Spigot
+ id: wild
+ run: test -f ~/.m2/repository/org/spigotmc/spigot/1.19.3-R0.1-SNAPSHOT/spigot-1.19.3-R0.1-SNAPSHOT.jar && echo "::set-output name=sucess::true" || echo "::set-output name=sucess::false"
+ - name: Check 1.19.3 Spigot (Mojang)
+ id: wildMojang
+ run: test -f ~/.m2/repository/org/spigotmc/spigot/1.19.3-R0.1-SNAPSHOT/spigot-1.19.3-R0.1-SNAPSHOT-remapped-mojang.jar && echo "::set-output name=sucess::true" || echo "::set-output name=sucess::false"
+ - name: Check 1.19.3 Spigot (Obf)
+ id: wildObf
+ run: test -f ~/.m2/repository/org/spigotmc/spigot/1.19.3-R0.1-SNAPSHOT/spigot-1.19.3-R0.1-SNAPSHOT-remapped-obf.jar && echo "::set-output name=sucess::true" || echo "::set-output name=sucess::false"
+ - name: Build 1.19.3
+ if: steps.wild.outputs.sucess != 'true' || steps.wildMojang.outputs.sucess != 'true' || steps.wildObf.outputs.sucess != 'true'
+ run: cd BuildTools && java -jar BuildTools.jar --rev 1.19.3 --remapped
+
# Build Movecraft
build:
runs-on: ubuntu-latest
- needs: [pillage_1_14, nether_1_16, goats_1_17, caves_1_18, wild_1_19]
+ needs: [pillage_1_14, nether_1_16, goats_1_17, caves_1_18, wild_1_19_2, wild_1_19_3]
steps:
- - name: Checkout Movecraft
- uses: actions/checkout@v1
- - name: Set up JDK 17
- uses: actions/setup-java@v2
- with:
- distribution: 'temurin'
- java-version: '17'
- - name: Cache Maven packages
- id: cacheMain
- uses: actions/cache@v2
- with:
- path: ~/.m2
- key: ${{ runner.os }}-m2
- restore-keys: ${{ runner.os }}-m2
- - name: Cache 1.14.4 Maven package
- id: cachePillage
- uses: actions/cache@v2
- with:
- path: ~/.m2/repository/org/bukkit/craftbukkit/1.14.4-R0.1-SNAPSHOT/
- key: ${{ runner.os }}-1.14.4
- restore-keys: ${{ runner.os }}-1.14.4
- - name: Cache 1.16.5 Maven package
- id: cacheNether
- uses: actions/cache@v2
- with:
- path: ~/.m2/repository/org/bukkit/craftbukkit/1.16.5-R0.1-SNAPSHOT/
- key: ${{ runner.os }}-1.16.5
- restore-keys: ${{ runner.os }}-1.16.5
- - name: Cache 1.17.1 Maven package
- id: cacheGoats
- uses: actions/cache@v2
- with:
- path: |
- ~/.m2/repository/org/spigotmc/spigot/1.17.1-R0.1-SNAPSHOT/
- ~/.m2/repository/org/spigotmc/spigot-parent/
- ~/.m2/repository/org/spigotmc/minecraft-server/
- key: ${{ runner.os }}-spigot-1.17.1-all
- restore-keys: ${{ runner.os }}-spigot-1.17.1-all
- - name: Cache 1.18.2 Maven package
- id: cacheCaves
- uses: actions/cache@v2
- with:
- path: |
- ~/.m2/repository/org/spigotmc/spigot/1.18.2-R0.1-SNAPSHOT/
- ~/.m2/repository/org/spigotmc/spigot-parent/
- ~/.m2/repository/org/spigotmc/minecraft-server/
- key: ${{ runner.os }}-spigot-1.18.2-all
- restore-keys: ${{ runner.os }}-spigot-1.18.2-all
- - name: Cache 1.19.2 Maven package
- id: cacheWild
- uses: actions/cache@v2
- with:
- path: |
- ~/.m2/repository/org/spigotmc/spigot/1.19.2-R0.1-SNAPSHOT/
- ~/.m2/repository/org/spigotmc/spigot-parent/
- ~/.m2/repository/org/spigotmc/minecraft-server/
- key: ${{ runner.os }}-spigot-1.19.2-all
- restore-keys: ${{ runner.os }}-spigot-1.19.2-all
+ - name: Checkout Movecraft
+ uses: actions/checkout@v1
+ - name: Set up JDK 17
+ uses: actions/setup-java@v2
+ with:
+ distribution: 'temurin'
+ java-version: '17'
+ - name: Cache Maven packages
+ id: cacheMain
+ uses: actions/cache@v2
+ with:
+ path: ~/.m2
+ key: ${{ runner.os }}-m2
+ restore-keys: ${{ runner.os }}-m2
+ - name: Cache 1.14.4 Maven package
+ id: cachePillage
+ uses: actions/cache@v2
+ with:
+ path: ~/.m2/repository/org/bukkit/craftbukkit/1.14.4-R0.1-SNAPSHOT/
+ key: ${{ runner.os }}-1.14.4
+ restore-keys: ${{ runner.os }}-1.14.4
+ - name: Cache 1.16.5 Maven package
+ id: cacheNether
+ uses: actions/cache@v2
+ with:
+ path: ~/.m2/repository/org/bukkit/craftbukkit/1.16.5-R0.1-SNAPSHOT/
+ key: ${{ runner.os }}-1.16.5
+ restore-keys: ${{ runner.os }}-1.16.5
+ - name: Cache 1.17.1 Maven package
+ id: cacheGoats
+ uses: actions/cache@v2
+ with:
+ path: |
+ ~/.m2/repository/org/spigotmc/spigot/1.17.1-R0.1-SNAPSHOT/
+ ~/.m2/repository/org/spigotmc/spigot-parent/
+ ~/.m2/repository/org/spigotmc/minecraft-server/
+ key: ${{ runner.os }}-spigot-1.17.1-all
+ restore-keys: ${{ runner.os }}-spigot-1.17.1-all
+ - name: Cache 1.18.2 Maven package
+ id: cacheCaves
+ uses: actions/cache@v2
+ with:
+ path: |
+ ~/.m2/repository/org/spigotmc/spigot/1.18.2-R0.1-SNAPSHOT/
+ ~/.m2/repository/org/spigotmc/spigot-parent/
+ ~/.m2/repository/org/spigotmc/minecraft-server/
+ key: ${{ runner.os }}-spigot-1.18.2-all
+ restore-keys: ${{ runner.os }}-spigot-1.18.2-all
+ - name: Cache 1.19.2 Maven package
+ id: cacheWild_r1
+ uses: actions/cache@v2
+ with:
+ path: |
+ ~/.m2/repository/org/spigotmc/spigot/1.19.2-R0.1-SNAPSHOT/
+ ~/.m2/repository/org/spigotmc/spigot-parent/
+ ~/.m2/repository/org/spigotmc/minecraft-server/
+ key: ${{ runner.os }}-spigot-1.19.2-all
+ restore-keys: ${{ runner.os }}-spigot-1.19.2-all
+ - name: Cache 1.19.3 Maven package
+ id: cacheWild_r2
+ uses: actions/cache@v2
+ with:
+ path: |
+ ~/.m2/repository/org/spigotmc/spigot/1.19.3-R0.1-SNAPSHOT/
+ ~/.m2/repository/org/spigotmc/spigot-parent/
+ ~/.m2/repository/org/spigotmc/minecraft-server/
+ key: ${{ runner.os }}-spigot-1.19.3-all
+ restore-keys: ${{ runner.os }}-spigot-1.19.3-all
- - name: Build with Maven
- run: mvn -T 1C -B package --file pom.xml
+ - name: Build with Maven
+ run: mvn -T 1C -B package --file pom.xml
- - name: Stage jar
- run: mkdir staging && cp target/Movecraft.jar staging && mv staging/Movecraft.jar staging/Movecraft_$GITHUB_SHA.jar
- - name: Upload jar
- uses: actions/upload-artifact@v2
- with:
- name: Movecraft_Dev-Build
- path: staging/Movecraft_*.jar
+ - name: Stage jar
+ run: mkdir staging && cp target/Movecraft.jar staging && mv staging/Movecraft.jar staging/Movecraft_$GITHUB_SHA.jar
+ - name: Upload jar
+ uses: actions/upload-artifact@v2
+ with:
+ name: Movecraft_Dev-Build
+ path: staging/Movecraft_*.jar
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 0fc825ace..1e39add12 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -157,7 +157,7 @@ jobs:
run: cd BuildTools && java -jar BuildTools.jar --rev 1.18.2 --remapped
# Build 1.19.2 NMS
- wild_1_19:
+ wild_1_19_2:
runs-on: ubuntu-latest
steps:
- name: Set up JDK 17 # 1.19.2 can only be built with Java 17
@@ -166,7 +166,7 @@ jobs:
distribution: 'temurin'
java-version: '17'
- name: Cache 1.19.2 Maven package
- id: cacheWild
+ id: cacheWild_r1
uses: actions/cache@v2
with:
path: |
@@ -198,10 +198,52 @@ jobs:
if: steps.wild.outputs.sucess != 'true' || steps.wildMojang.outputs.sucess != 'true' || steps.wildObf.outputs.sucess != 'true'
run: cd BuildTools && java -jar BuildTools.jar --rev 1.19.2 --remapped
+ # Build 1.19.3 NMS
+ wild_1_19_3:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Set up JDK 17 # 1.19.3 can only be built with Java 17
+ uses: actions/setup-java@v2
+ with:
+ distribution: 'temurin'
+ java-version: '17'
+ - name: Cache 1.19.3 Maven package
+ id: cacheWild_r2
+ uses: actions/cache@v2
+ with:
+ path: |
+ ~/.m2/repository/org/spigotmc/spigot/1.19.3-R0.1-SNAPSHOT/
+ ~/.m2/repository/org/spigotmc/spigot-parent/
+ ~/.m2/repository/org/spigotmc/minecraft-server/
+ key: ${{ runner.os }}-spigot-1.19.3-all
+ restore-keys: ${{ runner.os }}-spigot-1.19.3-all
+ - name: Cache Maven packages
+ id: cacheMain
+ uses: actions/cache@v2
+ with:
+ path: ~/.m2
+ key: ${{ runner.os }}-m2_1.19.3
+ restore-keys: ${{ runner.os }}-m2_1.19.3
+
+ - name: Setup BuildTools
+ run: mkdir BuildTools && wget -O BuildTools/BuildTools.jar https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar
+ - name: Check 1.19.3 Spigot
+ id: wild
+ run: test -f ~/.m2/repository/org/spigotmc/spigot/1.19.3-R0.1-SNAPSHOT/spigot-1.19.3-R0.1-SNAPSHOT.jar && echo "::set-output name=sucess::true" || echo "::set-output name=sucess::false"
+ - name: Check 1.19.3 Spigot (Mojang)
+ id: wildMojang
+ run: test -f ~/.m2/repository/org/spigotmc/spigot/1.19.3-R0.1-SNAPSHOT/spigot-1.19.3-R0.1-SNAPSHOT-remapped-mojang.jar && echo "::set-output name=sucess::true" || echo "::set-output name=sucess::false"
+ - name: Check 1.19.3 Spigot (Obf)
+ id: wildObf
+ run: test -f ~/.m2/repository/org/spigotmc/spigot/1.19.3-R0.1-SNAPSHOT/spigot-1.19.3-R0.1-SNAPSHOT-remapped-obf.jar && echo "::set-output name=sucess::true" || echo "::set-output name=sucess::false"
+ - name: Build 1.19.3
+ if: steps.wild.outputs.sucess != 'true' || steps.wildMojang.outputs.sucess != 'true' || steps.wildObf.outputs.sucess != 'true'
+ run: cd BuildTools && java -jar BuildTools.jar --rev 1.19.3 --remapped
+
# Build Movecraft
publish:
runs-on: ubuntu-latest
- needs: [pillage_1_14, nether_1_16, goats_1_17, caves_1_18, wild_1_19]
+ needs: [pillage_1_14, nether_1_16, goats_1_17, caves_1_18, wild_1_19_2, wild_1_19_3]
permissions:
contents: read
packages: write
@@ -256,7 +298,7 @@ jobs:
key: ${{ runner.os }}-spigot-1.18.2-all
restore-keys: ${{ runner.os }}-spigot-1.18.2-all
- name: Cache 1.19.2 Maven package
- id: cacheWild
+ id: cacheWild_r1
uses: actions/cache@v2
with:
path: |
@@ -265,6 +307,16 @@ jobs:
~/.m2/repository/org/spigotmc/minecraft-server/
key: ${{ runner.os }}-spigot-1.19.2-all
restore-keys: ${{ runner.os }}-spigot-1.19.2-all
+ - name: Cache 1.19.3 Maven package
+ id: cacheWild_r2
+ uses: actions/cache@v2
+ with:
+ path: |
+ ~/.m2/repository/org/spigotmc/spigot/1.19.3-R0.1-SNAPSHOT/
+ ~/.m2/repository/org/spigotmc/spigot-parent/
+ ~/.m2/repository/org/spigotmc/minecraft-server/
+ key: ${{ runner.os }}-spigot-1.19.3-all
+ restore-keys: ${{ runner.os }}-spigot-1.19.3-all
- name: Build with Maven
run: mvn -T 1C -B package --file pom.xml
diff --git a/modules/Movecraft/pom.xml b/modules/Movecraft/pom.xml
index 2ee267887..af49fdd1e 100644
--- a/modules/Movecraft/pom.xml
+++ b/modules/Movecraft/pom.xml
@@ -68,6 +68,12 @@
${revision}
jar
+
+ net.countercraft
+ movecraft-v1_19_r2
+ ${revision}
+ jar
+
net.countercraft
movecraft-api
@@ -83,18 +89,7 @@
org.yaml
snakeyaml
- 1.32
-
-
- org.jetbrains
- annotations-java5
- 22.0.0
-
-
- it.unimi.dsi
- fastutil
- 8.5.8
- compile
+ 1.33
@@ -188,6 +183,10 @@
net.kyori
net.countercraft.movecraft.libs.net.kyori
+
+ org.roaringbitmap
+ net.countercraft.movecraft.libs.org.roaringbitmap
+
true
false
@@ -222,6 +221,12 @@
**
+
+ net.countercraft:movecraft-v1_19_r2
+
+ **
+
+
net.countercraft:datapack
diff --git a/modules/Movecraft/src/main/java/net/countercraft/movecraft/Movecraft.java b/modules/Movecraft/src/main/java/net/countercraft/movecraft/Movecraft.java
index 9e2407397..0a911405f 100644
--- a/modules/Movecraft/src/main/java/net/countercraft/movecraft/Movecraft.java
+++ b/modules/Movecraft/src/main/java/net/countercraft/movecraft/Movecraft.java
@@ -55,6 +55,8 @@
import net.countercraft.movecraft.sign.StatusSign;
import net.countercraft.movecraft.sign.SubcraftRotateSign;
import net.countercraft.movecraft.sign.TeleportSign;
+import net.countercraft.movecraft.util.BukkitTeleport;
+import net.countercraft.movecraft.util.Tags;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.Bukkit;
import org.bukkit.Material;
@@ -67,6 +69,7 @@
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
import java.util.logging.Logger;
public class Movecraft extends JavaPlugin {
@@ -76,6 +79,7 @@ public class Movecraft extends JavaPlugin {
private Logger logger;
private boolean shuttingDown;
private WorldHandler worldHandler;
+ private SmoothTeleport smoothTeleport;
private AsyncManager asyncManager;
public static synchronized Movecraft getInstance() {
@@ -84,7 +88,7 @@ public static synchronized Movecraft getInstance() {
@NotNull
public static BukkitAudiences getAdventure() {
- if(adventure == null)
+ if (adventure == null)
throw new IllegalStateException("Tried to access Adventure when the plugin was disabled!");
return adventure;
@@ -93,7 +97,7 @@ public static BukkitAudiences getAdventure() {
@Override
public void onDisable() {
shuttingDown = true;
- if(adventure != null) {
+ if (adventure != null) {
adventure.close();
adventure = null;
}
@@ -108,39 +112,58 @@ public void onEnable() {
Settings.DisableIceForm = getConfig().getBoolean("DisableIceForm", true);
String[] localisations = {"en", "cz", "nl", "fr"};
- for(String s : localisations) {
- if(!new File(getDataFolder()
+ for (String s : localisations) {
+ if (!new File(getDataFolder()
+ "/localisation/movecraftlang_" + s + ".properties").exists()) {
saveResource("localisation/movecraftlang_" + s + ".properties", false);
}
}
I18nSupport.init();
-
-
+
+
// if the PilotTool is specified in the config.yml file, use it
String pilotTool = getConfig().getString("PilotTool");
- if(pilotTool != null) {
+ if (pilotTool != null) {
Material material = Material.getMaterial(pilotTool);
- if(material != null) {
+ if (material != null) {
logger.info(I18nSupport.getInternationalisedString("Startup - Recognized Pilot Tool")
+ pilotTool);
Settings.PilotTool = material;
}
- else
+ else {
logger.info(I18nSupport.getInternationalisedString("Startup - No Pilot Tool"));
+ }
}
- else
+ else {
logger.info(I18nSupport.getInternationalisedString("Startup - No Pilot Tool"));
+ }
String packageName = getServer().getClass().getPackage().getName();
String version = packageName.substring(packageName.lastIndexOf('.') + 1);
try {
- final Class> clazz = Class.forName("net.countercraft.movecraft.compat." + version + ".IWorldHandler");
+ final Class> worldHandlerClazz = Class.forName("net.countercraft.movecraft.compat." + version + ".IWorldHandler");
// Check if we have a NMSHandler class at that location.
- if (WorldHandler.class.isAssignableFrom(clazz)) // Make sure it actually implements NMS
- worldHandler = (WorldHandler) clazz.getConstructor().newInstance(); // Set our handler
+ if (WorldHandler.class.isAssignableFrom(worldHandlerClazz)) { // Make sure it actually implements NMS
+ worldHandler = (WorldHandler) worldHandlerClazz.getConstructor().newInstance(); // Set our handler
+
+ // Try to setup the smooth teleport handler
+ try {
+ final Class> smoothTeleportClazz = Class.forName("net.countercraft.movecraft.support." + version + ".ISmoothTeleport");
+ if (SmoothTeleport.class.isAssignableFrom(smoothTeleportClazz)) {
+ smoothTeleport = (SmoothTeleport) smoothTeleportClazz.getConstructor().newInstance();
+ }
+ else {
+ smoothTeleport = new BukkitTeleport(); // Fall back to bukkit teleportation
+ getLogger().warning("Falling back to bukkit teleportation provider.");
+ }
+ }
+ catch (ReflectiveOperationException ignored) {
+ smoothTeleport = new BukkitTeleport(); // Fall back to bukkit teleportation
+ getLogger().warning("Falling back to bukkit teleportation provider.");
+ }
+ }
}
- catch(final Exception e) {
+ catch (final Exception e) {
e.printStackTrace();
getLogger().severe(I18nSupport.getInternationalisedString("Startup - Version Not Supported"));
setEnabled(false);
@@ -162,17 +185,13 @@ public void onEnable() {
Settings.FadeWrecksAfter = getConfig().getInt("FadeWrecksAfter", 0);
Settings.FadeTickCooldown = getConfig().getInt("FadeTickCooldown", 20);
Settings.FadePercentageOfWreckPerCycle = getConfig().getDouble("FadePercentageOfWreckPerCycle", 10.0);
- if(getConfig().contains("ExtraFadeTimePerBlock")) {
+ if (getConfig().contains("ExtraFadeTimePerBlock")) {
Map temp = getConfig().getConfigurationSection("ExtraFadeTimePerBlock").getValues(false);
- for(String str : temp.keySet()) {
- Material type;
- try {
- type = Material.getMaterial(str);
- }
- catch(NumberFormatException e) {
- type = Material.getMaterial(str);
+ for (String str : temp.keySet()) {
+ Set materials = Tags.parseMaterials(str);
+ for (Material m : materials) {
+ Settings.ExtraFadeTimePerBlock.put(m, (Integer) temp.get(str));
}
- Settings.ExtraFadeTimePerBlock.put(type, (Integer) temp.get(str));
}
}
@@ -331,6 +350,9 @@ public WorldHandler getWorldHandler(){
return worldHandler;
}
+ public SmoothTeleport getSmoothTeleport() {
+ return smoothTeleport;
+ }
+
public AsyncManager getAsyncManager(){return asyncManager;}
}
-
diff --git a/modules/Movecraft/src/main/java/net/countercraft/movecraft/commands/ManOverboardCommand.java b/modules/Movecraft/src/main/java/net/countercraft/movecraft/commands/ManOverboardCommand.java
index b06e93dcd..e3118c255 100644
--- a/modules/Movecraft/src/main/java/net/countercraft/movecraft/commands/ManOverboardCommand.java
+++ b/modules/Movecraft/src/main/java/net/countercraft/movecraft/commands/ManOverboardCommand.java
@@ -1,14 +1,14 @@
package net.countercraft.movecraft.commands;
+import net.countercraft.movecraft.Movecraft;
import net.countercraft.movecraft.config.Settings;
import net.countercraft.movecraft.craft.Craft;
import net.countercraft.movecraft.craft.CraftManager;
-import net.countercraft.movecraft.craft.PilotedCraft;
import net.countercraft.movecraft.craft.SinkingCraft;
import net.countercraft.movecraft.events.ManOverboardEvent;
import net.countercraft.movecraft.localisation.I18nSupport;
import net.countercraft.movecraft.util.MathUtils;
-import net.countercraft.movecraft.util.teleport.TeleportUtils;
+import net.countercraft.movecraft.util.ReflectUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.command.Command;
@@ -73,7 +73,7 @@ public boolean onCommand(CommandSender commandSender, Command command, String s,
player.setVelocity(new Vector(0, 0, 0));
player.setFallDistance(0);
- TeleportUtils.teleport(player, telPoint, 0, 0);
+ Movecraft.getInstance().getSmoothTeleport().teleport(player, telPoint, 0, 0);
return true;
}
diff --git a/modules/Movecraft/src/main/java/net/countercraft/movecraft/mapUpdater/update/EntityUpdateCommand.java b/modules/Movecraft/src/main/java/net/countercraft/movecraft/mapUpdater/update/EntityUpdateCommand.java
index 853fde2f1..c334f4e5b 100644
--- a/modules/Movecraft/src/main/java/net/countercraft/movecraft/mapUpdater/update/EntityUpdateCommand.java
+++ b/modules/Movecraft/src/main/java/net/countercraft/movecraft/mapUpdater/update/EntityUpdateCommand.java
@@ -17,7 +17,8 @@
package net.countercraft.movecraft.mapUpdater.update;
-import net.countercraft.movecraft.util.teleport.TeleportUtils;
+import net.countercraft.movecraft.Movecraft;
+import net.countercraft.movecraft.util.ReflectUtils;
import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.World;
@@ -89,7 +90,7 @@ public void doUpdate() {
return;
}
Location location = new Location(world, playerLoc.getX() + x, playerLoc.getY() + y, playerLoc.getZ() + z);
- TeleportUtils.teleport((Player) entity, location, yaw, pitch);
+ Movecraft.getInstance().getSmoothTeleport().teleport((Player) entity, location, yaw, pitch);
if (sound != null) {
((Player) entity).playSound(location, sound, volume, 1.0f);
}
diff --git a/modules/Movecraft/src/main/java/net/countercraft/movecraft/util/teleport/AbstractTeleport.java b/modules/Movecraft/src/main/java/net/countercraft/movecraft/util/teleport/AbstractTeleport.java
deleted file mode 100644
index 90c15055f..000000000
--- a/modules/Movecraft/src/main/java/net/countercraft/movecraft/util/teleport/AbstractTeleport.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package net.countercraft.movecraft.util.teleport;
-
-import org.bukkit.Location;
-import org.bukkit.entity.Player;
-import org.jetbrains.annotations.NotNull;
-
-public abstract class AbstractTeleport {
-
- public static boolean initialize() {
- return false;
- }
-
- public static void teleport(Player player, @NotNull Location location, float yawChange, float pitchChange) { }
-}
diff --git a/modules/Movecraft/src/main/java/net/countercraft/movecraft/util/teleport/SpigotMappedTeleport.java b/modules/Movecraft/src/main/java/net/countercraft/movecraft/util/teleport/SpigotMappedTeleport.java
deleted file mode 100644
index 855a62cee..000000000
--- a/modules/Movecraft/src/main/java/net/countercraft/movecraft/util/teleport/SpigotMappedTeleport.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package net.countercraft.movecraft.util.teleport;
-
-import org.bukkit.Location;
-import org.bukkit.entity.Player;
-import org.jetbrains.annotations.NotNull;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.Set;
-
-/**
- * Code taken with permission from MicleBrick
- * https://www.spigotmc.org/threads/teleport-player-smoothly.317416/
- * Used for 1.14.4 to 1.16.5
- */
-public class SpigotMappedTeleport extends AbstractTeleport {
- private static Set
net.countercraft
diff --git a/modules/v1_18_R2/src/main/java/net/countercraft/movecraft/compat/v1_18_R2/IWorldHandler.java b/modules/v1_18_R2/src/main/java/net/countercraft/movecraft/compat/v1_18_R2/IWorldHandler.java
index 505833525..1d70ba93a 100644
--- a/modules/v1_18_R2/src/main/java/net/countercraft/movecraft/compat/v1_18_R2/IWorldHandler.java
+++ b/modules/v1_18_R2/src/main/java/net/countercraft/movecraft/compat/v1_18_R2/IWorldHandler.java
@@ -52,12 +52,6 @@ public IWorldHandler() {
throw new IllegalStateException("Movecraft is not compatible with this version of Minecraft 1.18: " + mappings);
}
-// @Override
-// public void addPlayerLocation(Player player, double x, double y, double z, float yaw, float pitch){
-// ServerPlayer ePlayer = ((CraftPlayer) player).getHandle();
-// ePlayer.connection.teleport(x, y, z, yaw, pitch, EnumSet.allOf(ClientboundPlayerPositionPacket.RelativeArgument.class));
-// }
-
@Override
public void rotateCraft(@NotNull Craft craft, @NotNull MovecraftLocation originPoint, @NotNull MovecraftRotation rotation) {
//*******************************************
diff --git a/modules/v1_18_R2/src/main/java/net/countercraft/movecraft/support/v1_18_R2/ISmoothTeleport.java b/modules/v1_18_R2/src/main/java/net/countercraft/movecraft/support/v1_18_R2/ISmoothTeleport.java
new file mode 100644
index 000000000..3f123aec3
--- /dev/null
+++ b/modules/v1_18_R2/src/main/java/net/countercraft/movecraft/support/v1_18_R2/ISmoothTeleport.java
@@ -0,0 +1,100 @@
+package net.countercraft.movecraft.support.v1_18_R2;
+
+import net.countercraft.movecraft.SmoothTeleport;
+import net.countercraft.movecraft.util.ReflectUtils;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Set;
+
+/**
+ * Code derived from code taken with permission from MicleBrick
+ * https://www.spigotmc.org/threads/teleport-player-smoothly.317416/
+ * Used for 1.18.2
+ */
+public class ISmoothTeleport extends SmoothTeleport {
+ private final Set teleportFlags;
+
+ private final Method positionMethod;
+ private final Method sendMethod;
+
+ private final Constructor> vec3Constructor;
+ private final Constructor> packetConstructor;
+
+ private final Field connectionField;
+ private final Field teleportPosField;
+ private final Field teleportAwaitField;
+ private final Field awaitingTeleportTimeField;
+ private final Field tickCountField;
+ private final Field yawField;
+ private final Field pitchField;
+
+ private static @NotNull Class> getNmClass(String name) throws ClassNotFoundException {
+ return Class.forName("net.minecraft." + name);
+ }
+
+ private void sendPacket(Object packet, Player p) {
+ try {
+ Object handle = ReflectUtils.getHandle(p);
+ Object pConnection = connectionField.get(handle);
+ sendMethod.invoke(pConnection, packet);
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public ISmoothTeleport() throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException {
+ Class> packetClass = getNmClass("network.protocol.Packet");
+ Class> positionPacketClass = getNmClass("network.protocol.game.PacketPlayOutPosition"); // ClientboundPlayerPositionPacket
+ Class> entityClass = getNmClass("world.entity.Entity");
+ Class> playerClass = getNmClass("server.level.EntityPlayer"); // ServerPlayer
+ Class> connectionClass = getNmClass("server.network.PlayerConnection"); // ServerGamePacketListenerImpl
+ Class> vectorClass = getNmClass("world.phys.Vec3D"); // Vec3
+
+ Object[] flags = getNmClass("network.protocol.game.PacketPlayOutPosition$EnumPlayerTeleportFlags").getEnumConstants(); // $RelativeArgument
+ teleportFlags = Set.of(flags[4], flags[3]); // X_ROT, Y_ROT
+
+ positionMethod = entityClass.getDeclaredMethod("a", Double.TYPE, Double.TYPE, Double.TYPE, Float.TYPE, Float.TYPE); // absMoveTo
+ sendMethod = connectionClass.getMethod("a", packetClass); // send
+
+ vec3Constructor = vectorClass.getConstructor(Double.TYPE, Double.TYPE, Double.TYPE);
+ packetConstructor = positionPacketClass.getConstructor(Double.TYPE, Double.TYPE, Double.TYPE, Float.TYPE, Float.TYPE, Set.class, Integer.TYPE, Boolean.TYPE);
+
+ connectionField = ReflectUtils.getField(playerClass, "b"); // connection
+ teleportPosField = ReflectUtils.getField(connectionClass, "y"); // awaitingPositionFromClient
+ teleportAwaitField = ReflectUtils.getField(connectionClass, "z"); // awaitingTeleport
+ awaitingTeleportTimeField = ReflectUtils.getField(connectionClass, "A"); // awaitingTeleportTime
+ tickCountField = ReflectUtils.getField(connectionClass, "f"); // tickCount
+ yawField = ReflectUtils.getField(entityClass, "aB"); // xRot
+ pitchField = ReflectUtils.getField(entityClass, "aA"); // yRot
+ }
+
+ public void teleport(Player player, @NotNull Location location, float yawChange, float pitchChange) {
+ double x = location.getX();
+ double y = location.getY();
+ double z = location.getZ();
+ Object handle = ReflectUtils.getHandle(player);
+ try {
+ positionMethod.invoke(handle, x, y, z, yawField.get(handle), pitchField.get(handle));
+ Object connection = connectionField.get(handle);
+ teleportPosField.set(connection, vec3Constructor.newInstance(x, y, z));
+ int teleportAwait = teleportAwaitField.getInt(connection) + 1;
+ if (teleportAwait == Integer.MAX_VALUE)
+ teleportAwait = 0;
+ teleportAwaitField.setInt(connection, teleportAwait);
+ awaitingTeleportTimeField.set(connection, tickCountField.get(connection));
+
+ Object packet = packetConstructor.newInstance(x, y, z, yawChange, pitchChange, teleportFlags, teleportAwait, false);
+ sendPacket(packet, player);
+ }
+ catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/modules/v1_19_R1/pom.xml b/modules/v1_19_R1/pom.xml
index 2bc1384a7..faea18a95 100644
--- a/modules/v1_19_R1/pom.xml
+++ b/modules/v1_19_R1/pom.xml
@@ -20,6 +20,7 @@
1.19.2-R0.1-SNAPSHOT
remapped-mojang
provided
+
net.countercraft
diff --git a/modules/v1_19_R1/src/main/java/net/countercraft/movecraft/compat/v1_19_R1/IWorldHandler.java b/modules/v1_19_R1/src/main/java/net/countercraft/movecraft/compat/v1_19_R1/IWorldHandler.java
index 1530bf7aa..e8dcad3df 100644
--- a/modules/v1_19_R1/src/main/java/net/countercraft/movecraft/compat/v1_19_R1/IWorldHandler.java
+++ b/modules/v1_19_R1/src/main/java/net/countercraft/movecraft/compat/v1_19_R1/IWorldHandler.java
@@ -52,12 +52,6 @@ public IWorldHandler() {
throw new IllegalStateException("Movecraft is not compatible with this version of Minecraft 1.19: " + mappings);
}
-// @Override
-// public void addPlayerLocation(Player player, double x, double y, double z, float yaw, float pitch){
-// ServerPlayer ePlayer = ((CraftPlayer) player).getHandle();
-// ePlayer.connection.teleport(x, y, z, yaw, pitch, EnumSet.allOf(ClientboundPlayerPositionPacket.RelativeArgument.class));
-// }
-
@Override
public void rotateCraft(@NotNull Craft craft, @NotNull MovecraftLocation originPoint, @NotNull MovecraftRotation rotation) {
//*******************************************
diff --git a/modules/v1_19_R1/src/main/java/net/countercraft/movecraft/support/v1_19_R1/ISmoothTeleport.java b/modules/v1_19_R1/src/main/java/net/countercraft/movecraft/support/v1_19_R1/ISmoothTeleport.java
new file mode 100644
index 000000000..20345a457
--- /dev/null
+++ b/modules/v1_19_R1/src/main/java/net/countercraft/movecraft/support/v1_19_R1/ISmoothTeleport.java
@@ -0,0 +1,100 @@
+package net.countercraft.movecraft.support.v1_19_R1;
+
+import net.countercraft.movecraft.SmoothTeleport;
+import net.countercraft.movecraft.util.ReflectUtils;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Set;
+
+/**
+ * Code derived from code taken with permission from MicleBrick
+ * https://www.spigotmc.org/threads/teleport-player-smoothly.317416/
+ * Used for 1.19.2
+ */
+public class ISmoothTeleport extends SmoothTeleport {
+ private final Set teleportFlags;
+
+ private final Method positionMethod;
+ private final Method sendMethod;
+
+ private final Constructor> vec3Constructor;
+ private final Constructor> packetConstructor;
+
+ private final Field connectionField;
+ private final Field teleportPosField;
+ private final Field teleportAwaitField;
+ private final Field awaitingTeleportTimeField;
+ private final Field tickCountField;
+ private final Field yawField;
+ private final Field pitchField;
+
+ private static @NotNull Class> getNmClass(String name) throws ClassNotFoundException {
+ return Class.forName("net.minecraft." + name);
+ }
+
+ private void sendPacket(Object packet, Player p) {
+ try {
+ Object handle = ReflectUtils.getHandle(p);
+ Object pConnection = connectionField.get(handle);
+ sendMethod.invoke(pConnection, packet);
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public ISmoothTeleport() throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException {
+ Class> packetClass = getNmClass("network.protocol.Packet");
+ Class> positionPacketClass = getNmClass("network.protocol.game.PacketPlayOutPosition"); // ClientboundPlayerPositionPacket
+ Class> entityClass = getNmClass("world.entity.Entity");
+ Class> playerClass = getNmClass("server.level.EntityPlayer"); // ServerPlayer
+ Class> connectionClass = getNmClass("server.network.PlayerConnection"); // ServerGamePacketListenerImpl
+ Class> vectorClass = getNmClass("world.phys.Vec3D"); // Vec3
+
+ Object[] flags = getNmClass("network.protocol.game.PacketPlayOutPosition$EnumPlayerTeleportFlags").getEnumConstants(); // $RelativeArgument
+ teleportFlags = Set.of(flags[4], flags[3]); // X_ROT, Y_ROT
+
+ positionMethod = entityClass.getDeclaredMethod("a", Double.TYPE, Double.TYPE, Double.TYPE, Float.TYPE, Float.TYPE); // absMoveTo
+ sendMethod = connectionClass.getMethod("a", packetClass); // send
+
+ vec3Constructor = vectorClass.getConstructor(Double.TYPE, Double.TYPE, Double.TYPE);
+ packetConstructor = positionPacketClass.getConstructor(Double.TYPE, Double.TYPE, Double.TYPE, Float.TYPE, Float.TYPE, Set.class, Integer.TYPE, Boolean.TYPE);
+
+ connectionField = ReflectUtils.getField(playerClass, "b"); // connection
+ teleportPosField = ReflectUtils.getField(connectionClass, "C"); // awaitingPositionFromClient
+ teleportAwaitField = ReflectUtils.getField(connectionClass, "D"); // awaitingTeleport
+ awaitingTeleportTimeField = ReflectUtils.getField(connectionClass, "E"); // awaitingTeleportTime
+ tickCountField = ReflectUtils.getField(connectionClass, "i"); // tickCount
+ yawField = ReflectUtils.getField(entityClass, "aB"); // xRot
+ pitchField = ReflectUtils.getField(entityClass, "aA"); // yRot
+ }
+
+ public void teleport(Player player, @NotNull Location location, float yawChange, float pitchChange) {
+ double x = location.getX();
+ double y = location.getY();
+ double z = location.getZ();
+ Object handle = ReflectUtils.getHandle(player);
+ try {
+ positionMethod.invoke(handle, x, y, z, yawField.get(handle), pitchField.get(handle));
+ Object connection = connectionField.get(handle);
+ teleportPosField.set(connection, vec3Constructor.newInstance(x, y, z));
+ int teleportAwait = teleportAwaitField.getInt(connection) + 1;
+ if (teleportAwait == Integer.MAX_VALUE)
+ teleportAwait = 0;
+ teleportAwaitField.setInt(connection, teleportAwait);
+ awaitingTeleportTimeField.set(connection, tickCountField.get(connection));
+
+ Object packet = packetConstructor.newInstance(x, y, z, yawChange, pitchChange, teleportFlags, teleportAwait, false);
+ sendPacket(packet, player);
+ }
+ catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/modules/v1_19_R2/pom.xml b/modules/v1_19_R2/pom.xml
new file mode 100644
index 000000000..10bd81f4e
--- /dev/null
+++ b/modules/v1_19_R2/pom.xml
@@ -0,0 +1,95 @@
+
+
+
+ movecraft-parent
+ net.countercraft
+ ${revision}
+ ../../pom.xml
+
+ 4.0.0
+
+ movecraft-v1_19_r2
+ Movecraft-v1_19_R2
+ jar
+
+
+ org.spigotmc
+ spigot
+ 1.19.3-R0.1-SNAPSHOT
+ remapped-mojang
+ provided
+
+
+
+ net.countercraft
+ movecraft-api
+ ${revision}
+ jar
+
+
+
+ src/main/java
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+
+ net/countercraft/movecraft/compat/v1_19_R2/**
+ net/countercraft/movecraft/support/v1_19_R2/**
+
+
+ 13
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 2.4
+
+
+ net/countercraft/movecraft/compat/v1_19_R2/**
+ net/countercraft/movecraft/support/v1_19_R2/**
+
+
+
+
+ net.md-5
+ specialsource-maven-plugin
+ 1.2.2
+
+
+ package
+
+ remap
+
+ remap-obf
+
+ org.spigotmc:minecraft-server:1.19.3-R0.1-SNAPSHOT:txt:maps-mojang
+ true
+ org.spigotmc:spigot:1.19.3-R0.1-SNAPSHOT:jar:remapped-mojang
+ true
+ remapped-obf
+
+
+
+ package
+
+ remap
+
+ remap-spigot
+
+ ${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar
+ org.spigotmc:minecraft-server:1.19.3-R0.1-SNAPSHOT:csrg:maps-spigot
+ org.spigotmc:spigot:1.19.3-R0.1-SNAPSHOT:jar:remapped-obf
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/v1_19_R2/src/main/java/net/countercraft/movecraft/compat/v1_19_R2/IWorldHandler.java b/modules/v1_19_R2/src/main/java/net/countercraft/movecraft/compat/v1_19_R2/IWorldHandler.java
new file mode 100644
index 000000000..fdaaf94d6
--- /dev/null
+++ b/modules/v1_19_R2/src/main/java/net/countercraft/movecraft/compat/v1_19_R2/IWorldHandler.java
@@ -0,0 +1,299 @@
+package net.countercraft.movecraft.compat.v1_19_R2;
+
+import net.countercraft.movecraft.MovecraftLocation;
+import net.countercraft.movecraft.MovecraftRotation;
+import net.countercraft.movecraft.WorldHandler;
+import net.countercraft.movecraft.craft.Craft;
+import net.countercraft.movecraft.util.CollectionUtils;
+import net.countercraft.movecraft.util.MathUtils;
+import net.countercraft.movecraft.util.UnsafeUtils;
+import net.minecraft.core.BlockPos;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.world.level.Level;
+import net.minecraft.world.level.block.Block;
+import net.minecraft.world.level.block.Blocks;
+import net.minecraft.world.level.block.Rotation;
+import net.minecraft.world.level.block.entity.BlockEntity;
+import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.world.level.chunk.LevelChunk;
+import net.minecraft.world.level.chunk.LevelChunkSection;
+import net.minecraft.world.ticks.ScheduledTick;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.block.data.BlockData;
+import org.bukkit.craftbukkit.v1_19_R2.CraftWorld;
+import org.bukkit.craftbukkit.v1_19_R2.block.data.CraftBlockData;
+import org.bukkit.craftbukkit.v1_19_R2.util.CraftMagicNumbers;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@SuppressWarnings("unused")
+public class IWorldHandler extends WorldHandler {
+ private static final Rotation ROTATION[];
+
+ static {
+ ROTATION = new Rotation[3];
+ ROTATION[MovecraftRotation.NONE.ordinal()] = Rotation.NONE;
+ ROTATION[MovecraftRotation.CLOCKWISE.ordinal()] = Rotation.CLOCKWISE_90;
+ ROTATION[MovecraftRotation.ANTICLOCKWISE.ordinal()] = Rotation.COUNTERCLOCKWISE_90;
+ }
+
+ private final NextTickProvider tickProvider = new NextTickProvider();
+
+ public IWorldHandler() {
+ String mappings = ((CraftMagicNumbers) CraftMagicNumbers.INSTANCE).getMappingsVersion();
+ if (!mappings.equals("1afe2ffe8a9d7fc510442a168b3d4338"))
+ throw new IllegalStateException("Movecraft is not compatible with this version of Minecraft 1.19: " + mappings);
+ }
+
+ @Override
+ public void rotateCraft(@NotNull Craft craft, @NotNull MovecraftLocation originPoint, @NotNull MovecraftRotation rotation) {
+ //*******************************************
+ //* Step one: Convert to Positions *
+ //*******************************************
+ HashMap rotatedPositions = new HashMap<>();
+ MovecraftRotation counterRotation = rotation == MovecraftRotation.CLOCKWISE ? MovecraftRotation.ANTICLOCKWISE : MovecraftRotation.CLOCKWISE;
+ for (MovecraftLocation newLocation : craft.getHitBox()) {
+ rotatedPositions.put(locationToPosition(MathUtils.rotateVec(counterRotation, newLocation.subtract(originPoint)).add(originPoint)), locationToPosition(newLocation));
+ }
+ //*******************************************
+ //* Step two: Get the tiles *
+ //*******************************************
+ ServerLevel nativeWorld = ((CraftWorld) craft.getWorld()).getHandle();
+ List tiles = new ArrayList<>();
+ //get the tiles
+ for (BlockPos position : rotatedPositions.keySet()) {
+ //BlockEntity tile = nativeWorld.removeBlockEntity(position);
+ BlockEntity tile = removeBlockEntity(nativeWorld, position);
+ if (tile == null)
+ continue;
+// tile.a(ROTATION[rotation.ordinal()]);
+ //get the nextTick to move with the tile
+ tiles.add(new TileHolder(tile, tickProvider.getNextTick(nativeWorld, position), position));
+ }
+
+ //*******************************************
+ //* Step three: Translate all the blocks *
+ //*******************************************
+ // blockedByWater=false means an ocean-going vessel
+ //TODO: Simplify
+ //TODO: go by chunks
+ //TODO: Don't move unnecessary blocks
+ //get the blocks and rotate them
+ HashMap blockData = new HashMap<>();
+ for (BlockPos position : rotatedPositions.keySet()) {
+ blockData.put(position, nativeWorld.getBlockState(position).rotate(ROTATION[rotation.ordinal()]));
+ }
+ //create the new block
+ for (Map.Entry entry : blockData.entrySet()) {
+ setBlockFast(nativeWorld, rotatedPositions.get(entry.getKey()), entry.getValue());
+ }
+
+
+ //*******************************************
+ //* Step four: replace all the tiles *
+ //*******************************************
+ //TODO: go by chunks
+ for (TileHolder tileHolder : tiles) {
+ moveBlockEntity(nativeWorld, rotatedPositions.get(tileHolder.getTilePosition()), tileHolder.getTile());
+ if (tileHolder.getNextTick() == null)
+ continue;
+ final long currentTime = nativeWorld.N.getGameTime(); // N is obfuscated serverLevelData
+ nativeWorld.getBlockTicks().schedule(new ScheduledTick<>((Block) tileHolder.getNextTick().type(), rotatedPositions.get(tileHolder.getNextTick().pos()), tileHolder.getNextTick().triggerTick() - currentTime, tileHolder.getNextTick().priority(), tileHolder.getNextTick().subTickOrder()));
+ }
+
+ //*******************************************
+ //* Step five: Destroy the leftovers *
+ //*******************************************
+ //TODO: add support for pass-through
+ Collection deletePositions = CollectionUtils.filter(rotatedPositions.keySet(), rotatedPositions.values());
+ for (BlockPos position : deletePositions) {
+ setBlockFast(nativeWorld, position, Blocks.AIR.defaultBlockState());
+ }
+ }
+
+ @Override
+ public void translateCraft(@NotNull Craft craft, @NotNull MovecraftLocation displacement, @NotNull org.bukkit.World world) {
+ //TODO: Add support for rotations
+ //A craftTranslateCommand should only occur if the craft is moving to a valid position
+ //*******************************************
+ //* Step one: Convert to Positions *
+ //*******************************************
+ BlockPos translateVector = locationToPosition(displacement);
+ List positions = new ArrayList<>(craft.getHitBox().size());
+ craft.getHitBox().forEach((movecraftLocation) -> positions.add(locationToPosition((movecraftLocation)).subtract(translateVector)));
+ ServerLevel oldNativeWorld = ((CraftWorld) craft.getWorld()).getHandle();
+ ServerLevel nativeWorld = ((CraftWorld) world).getHandle();
+ //*******************************************
+ //* Step two: Get the tiles *
+ //*******************************************
+ List tiles = new ArrayList<>();
+ //get the tiles
+ for (int i = 0, positionsSize = positions.size(); i < positionsSize; i++) {
+ BlockPos position = positions.get(i);
+ if (oldNativeWorld.getBlockState(position) == Blocks.AIR.defaultBlockState())
+ continue;
+ //BlockEntity tile = nativeWorld.removeBlockEntity(position);
+ BlockEntity tile = removeBlockEntity(oldNativeWorld, position);
+ if (tile == null)
+ continue;
+ //get the nextTick to move with the tile
+
+ //nativeWorld.capturedTileEntities.remove(position);
+ //nativeWorld.getChunkAtWorldCoords(position).getTileEntities().remove(position);
+ tiles.add(new TileHolder(tile, tickProvider.getNextTick(oldNativeWorld, position), position));
+
+ }
+ //*******************************************
+ //* Step three: Translate all the blocks *
+ //*******************************************
+ // blockedByWater=false means an ocean-going vessel
+ //TODO: Simplify
+ //TODO: go by chunks
+ //TODO: Don't move unnecessary blocks
+ //get the blocks and translate the positions
+ List blockData = new ArrayList<>();
+ List newPositions = new ArrayList<>();
+ for (int i = 0, positionsSize = positions.size(); i < positionsSize; i++) {
+ BlockPos position = positions.get(i);
+ blockData.add(oldNativeWorld.getBlockState(position));
+ newPositions.add(position.offset(translateVector));
+ }
+ //create the new block
+ for (int i = 0, positionSize = newPositions.size(); i < positionSize; i++) {
+ setBlockFast(nativeWorld, newPositions.get(i), blockData.get(i));
+ }
+ //*******************************************
+ //* Step four: replace all the tiles *
+ //*******************************************
+ //TODO: go by chunks
+ for (int i = 0, tilesSize = tiles.size(); i < tilesSize; i++) {
+ TileHolder tileHolder = tiles.get(i);
+ moveBlockEntity(nativeWorld, tileHolder.getTilePosition().offset(translateVector), tileHolder.getTile());
+ if (tileHolder.getNextTick() == null)
+ continue;
+ final long currentTime = nativeWorld.getGameTime();
+ nativeWorld.getBlockTicks().schedule(new ScheduledTick<>((Block) tileHolder.getNextTick().type(), tileHolder.getTilePosition().offset(translateVector), tileHolder.getNextTick().triggerTick() - currentTime, tileHolder.getNextTick().priority(), tileHolder.getNextTick().subTickOrder()));
+ }
+ //*******************************************
+ //* Step five: Destroy the leftovers *
+ //*******************************************
+ List deletePositions = positions;
+ if (oldNativeWorld == nativeWorld)
+ deletePositions = CollectionUtils.filter(positions, newPositions);
+ for (int i = 0, deletePositionsSize = deletePositions.size(); i < deletePositionsSize; i++) {
+ BlockPos position = deletePositions.get(i);
+ setBlockFast(oldNativeWorld, position, Blocks.AIR.defaultBlockState());
+ }
+ }
+
+ @Nullable
+ private BlockEntity removeBlockEntity(@NotNull Level world, @NotNull BlockPos position) {
+ return world.getChunkAt(position).blockEntities.remove(position);
+ }
+
+ @NotNull
+ private BlockPos locationToPosition(@NotNull MovecraftLocation loc) {
+ return new BlockPos(loc.getX(), loc.getY(), loc.getZ());
+ }
+
+ private void setBlockFast(@NotNull Level world, @NotNull BlockPos position, @NotNull BlockState data) {
+ LevelChunk chunk = world.getChunkAt(position);
+ int chunkSection = (position.getY() >> 4) - chunk.getMinSection();
+ LevelChunkSection section = chunk.getSections()[chunkSection];
+ if (section == null) {
+ // Put a GLASS block to initialize the section. It will be replaced next with the real block.
+ chunk.setBlockState(position, Blocks.GLASS.defaultBlockState(), false);
+ section = chunk.getSections()[chunkSection];
+ }
+ if (section.getBlockState(position.getX() & 15, position.getY() & 15, position.getZ() & 15).equals(data)) {
+ //Block is already of correct type and data, don't overwrite
+ return;
+ }
+ section.setBlockState(position.getX() & 15, position.getY() & 15, position.getZ() & 15, data);
+ world.sendBlockUpdated(position, data, data, 3);
+ world.getLightEngine().checkBlock(position); // boolean corresponds to if chunk section empty
+ chunk.setUnsaved(true);
+ }
+
+ @Override
+ public void setBlockFast(@NotNull Location location, @NotNull BlockData data) {
+ setBlockFast(location, MovecraftRotation.NONE, data);
+ }
+
+ @Override
+ public void setBlockFast(@NotNull Location location, @NotNull MovecraftRotation rotation, @NotNull BlockData data) {
+ BlockState blockData;
+ if (data instanceof CraftBlockData) {
+ blockData = ((CraftBlockData) data).getState();
+ }
+ else {
+ blockData = (BlockState) data;
+ }
+ blockData = blockData.rotate(ROTATION[rotation.ordinal()]);
+ Level world = ((CraftWorld) (location.getWorld())).getHandle();
+ BlockPos BlockPos = locationToPosition(MathUtils.bukkit2MovecraftLoc(location));
+ setBlockFast(world, BlockPos, blockData);
+ }
+
+ @Override
+ public void disableShadow(@NotNull Material type) {
+ // Disabled
+ }
+
+ private void moveBlockEntity(@NotNull Level nativeWorld, @NotNull BlockPos newPosition, @NotNull BlockEntity tile) {
+ LevelChunk chunk = nativeWorld.getChunkAt(newPosition);
+ try {
+ var positionField = BlockEntity.class.getDeclaredField("o"); // o is obfuscated worldPosition
+ UnsafeUtils.setField(positionField, tile, newPosition);
+ }
+ catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ }
+ tile.setLevel(nativeWorld);
+ tile.clearRemoved();
+ if (nativeWorld.captureBlockStates) {
+ nativeWorld.capturedTileEntities.put(newPosition, tile);
+ return;
+ }
+ chunk.setBlockEntity(tile);
+ chunk.blockEntities.put(newPosition, tile);
+ }
+
+ private static class TileHolder {
+ @NotNull
+ private final BlockEntity tile;
+ @Nullable
+ private final ScheduledTick> nextTick;
+ @NotNull
+ private final BlockPos tilePosition;
+
+ public TileHolder(@NotNull BlockEntity tile, @Nullable ScheduledTick> nextTick, @NotNull BlockPos tilePosition) {
+ this.tile = tile;
+ this.nextTick = nextTick;
+ this.tilePosition = tilePosition;
+ }
+
+
+ @NotNull
+ public BlockEntity getTile() {
+ return tile;
+ }
+
+ @Nullable
+ public ScheduledTick> getNextTick() {
+ return nextTick;
+ }
+
+ @NotNull
+ public BlockPos getTilePosition() {
+ return tilePosition;
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/v1_19_R2/src/main/java/net/countercraft/movecraft/compat/v1_19_R2/NextTickProvider.java b/modules/v1_19_R2/src/main/java/net/countercraft/movecraft/compat/v1_19_R2/NextTickProvider.java
new file mode 100644
index 000000000..06f40c453
--- /dev/null
+++ b/modules/v1_19_R2/src/main/java/net/countercraft/movecraft/compat/v1_19_R2/NextTickProvider.java
@@ -0,0 +1,44 @@
+package net.countercraft.movecraft.compat.v1_19_R2;
+
+import net.minecraft.core.BlockPos;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.world.level.block.Block;
+import net.minecraft.world.level.levelgen.structure.BoundingBox;
+import net.minecraft.world.ticks.LevelTicks;
+import net.minecraft.world.ticks.ScheduledTick;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.Queue;
+
+public class NextTickProvider {
+
+ @Nullable
+ public ScheduledTick> getNextTick(@NotNull ServerLevel world, @NotNull BlockPos position){
+ LevelTicks tickList = world.getBlockTicks();
+ var box = BoundingBox.encapsulatingPositions(List.of(position));
+ if(box.isEmpty()){
+ return null;
+ }
+ Queue> toRunThisTick;
+ try {
+ Field toRunThisTickField = LevelTicks.class.getDeclaredField("g");
+ toRunThisTickField.setAccessible(true);
+ toRunThisTick = (Queue>) toRunThisTickField.get(tickList);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ e.printStackTrace();
+ return null;
+ }
+ for (var iter = toRunThisTick.iterator(); iter.hasNext(); ) {
+ var next = iter.next();
+ if (!next.pos().equals(position)) {
+ continue;
+ }
+ iter.remove();
+ return next;
+ }
+ return null;
+ }
+}
diff --git a/modules/v1_19_R2/src/main/java/net/countercraft/movecraft/support/v1_19_R2/IAsyncChunk.java b/modules/v1_19_R2/src/main/java/net/countercraft/movecraft/support/v1_19_R2/IAsyncChunk.java
new file mode 100644
index 000000000..d6cc3a737
--- /dev/null
+++ b/modules/v1_19_R2/src/main/java/net/countercraft/movecraft/support/v1_19_R2/IAsyncChunk.java
@@ -0,0 +1,57 @@
+package net.countercraft.movecraft.support.v1_19_R2;
+
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import net.countercraft.movecraft.MovecraftLocation;
+import net.countercraft.movecraft.processing.WorldManager;
+import net.countercraft.movecraft.support.AsyncChunk;
+import net.minecraft.core.BlockPos;
+import org.bukkit.Chunk;
+import org.bukkit.Material;
+import org.bukkit.block.BlockState;
+import org.bukkit.block.data.BlockData;
+import org.bukkit.craftbukkit.v1_19_R2.CraftChunk;
+import org.bukkit.craftbukkit.v1_19_R2.block.data.CraftBlockData;
+import org.jetbrains.annotations.NotNull;
+
+@SuppressWarnings("unused")
+public class IAsyncChunk extends AsyncChunk {
+
+ private final @NotNull LoadingCache stateCache = CacheBuilder.newBuilder().maximumSize(1000).build(new CacheLoader<>() {
+ @Override
+ public BlockState load(@NotNull MovecraftLocation movecraftLocation) {
+ var block = chunk.getBlock(movecraftLocation.getX(), movecraftLocation.getY(), movecraftLocation.getZ());
+ return WorldManager.INSTANCE.executeMain(block::getState);
+ }
+ });
+
+ public IAsyncChunk(@NotNull Chunk chunk) {
+ super(chunk);
+ }
+
+ @NotNull
+ @Override
+ protected CraftChunk adapt(@NotNull org.bukkit.Chunk chunk) {
+ return (CraftChunk) chunk;
+ }
+
+ @NotNull
+ @Override
+ public BlockState getState(@NotNull MovecraftLocation location) {
+ return stateCache.getUnchecked(location);
+ }
+
+ @Override
+ @NotNull
+ public Material getType(@NotNull MovecraftLocation location){
+ return this.getData(location).getMaterial();
+ }
+
+ @Override
+ @NotNull
+ public BlockData getData(@NotNull MovecraftLocation location){
+ return CraftBlockData.fromData(chunk.getHandle().getBlockState(new BlockPos(location.getX(), location.getY(), location.getZ())));
+ }
+
+}
diff --git a/modules/v1_19_R2/src/main/java/net/countercraft/movecraft/support/v1_19_R2/ISmoothTeleport.java b/modules/v1_19_R2/src/main/java/net/countercraft/movecraft/support/v1_19_R2/ISmoothTeleport.java
new file mode 100644
index 000000000..9b82d8ec8
--- /dev/null
+++ b/modules/v1_19_R2/src/main/java/net/countercraft/movecraft/support/v1_19_R2/ISmoothTeleport.java
@@ -0,0 +1,100 @@
+package net.countercraft.movecraft.support.v1_19_R2;
+
+import net.countercraft.movecraft.SmoothTeleport;
+import net.countercraft.movecraft.util.ReflectUtils;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Set;
+
+/**
+ * Code derived from code taken with permission from MicleBrick
+ * https://www.spigotmc.org/threads/teleport-player-smoothly.317416/
+ * Used for 1.19.3
+ */
+public class ISmoothTeleport extends SmoothTeleport {
+ private final Set teleportFlags;
+
+ private final Method positionMethod;
+ private final Method sendMethod;
+
+ private final Constructor> vec3Constructor;
+ private final Constructor> packetConstructor;
+
+ private final Field connectionField;
+ private final Field teleportPosField;
+ private final Field teleportAwaitField;
+ private final Field awaitingTeleportTimeField;
+ private final Field tickCountField;
+ private final Field yawField;
+ private final Field pitchField;
+
+ private static @NotNull Class> getNmClass(String name) throws ClassNotFoundException {
+ return Class.forName("net.minecraft." + name);
+ }
+
+ private void sendPacket(Object packet, Player p) {
+ try {
+ Object handle = ReflectUtils.getHandle(p);
+ Object pConnection = connectionField.get(handle);
+ sendMethod.invoke(pConnection, packet);
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public ISmoothTeleport() throws NoSuchFieldException, NoSuchMethodException, ClassNotFoundException {
+ Class> packetClass = getNmClass("network.protocol.Packet");
+ Class> positionPacketClass = getNmClass("network.protocol.game.PacketPlayOutPosition"); // ClientboundPlayerPositionPacket
+ Class> entityClass = getNmClass("world.entity.Entity");
+ Class> playerClass = getNmClass("server.level.EntityPlayer"); // ServerPlayer
+ Class> connectionClass = getNmClass("server.network.PlayerConnection"); // ServerGamePacketListenerImpl
+ Class> vectorClass = getNmClass("world.phys.Vec3D"); // Vec3
+
+ Object[] flags = getNmClass("network.protocol.game.PacketPlayOutPosition$EnumPlayerTeleportFlags").getEnumConstants(); // $RelativeArgument
+ teleportFlags = Set.of(flags[4], flags[3]); // X_ROT, Y_ROT
+
+ positionMethod = entityClass.getDeclaredMethod("a", Double.TYPE, Double.TYPE, Double.TYPE, Float.TYPE, Float.TYPE); // absMoveTo
+ sendMethod = connectionClass.getMethod("a", packetClass); // send
+
+ vec3Constructor = vectorClass.getConstructor(Double.TYPE, Double.TYPE, Double.TYPE);
+ packetConstructor = positionPacketClass.getConstructor(Double.TYPE, Double.TYPE, Double.TYPE, Float.TYPE, Float.TYPE, Set.class, Integer.TYPE, Boolean.TYPE);
+
+ connectionField = ReflectUtils.getField(playerClass, "b"); // connection
+ teleportPosField = ReflectUtils.getField(connectionClass, "D"); // awaitingPositionFromClient
+ teleportAwaitField = ReflectUtils.getField(connectionClass, "E"); // awaitingTeleport
+ awaitingTeleportTimeField = ReflectUtils.getField(connectionClass, "F"); // awaitingTeleportTime
+ tickCountField = ReflectUtils.getField(connectionClass, "j"); // tickCount
+ yawField = ReflectUtils.getField(entityClass, "aB"); // xRot
+ pitchField = ReflectUtils.getField(entityClass, "aA"); // yRot
+ }
+
+ public void teleport(Player player, @NotNull Location location, float yawChange, float pitchChange) {
+ double x = location.getX();
+ double y = location.getY();
+ double z = location.getZ();
+ Object handle = ReflectUtils.getHandle(player);
+ try {
+ positionMethod.invoke(handle, x, y, z, yawField.get(handle), pitchField.get(handle));
+ Object connection = connectionField.get(handle);
+ teleportPosField.set(connection, vec3Constructor.newInstance(x, y, z));
+ int teleportAwait = teleportAwaitField.getInt(connection) + 1;
+ if (teleportAwait == Integer.MAX_VALUE)
+ teleportAwait = 0;
+ teleportAwaitField.setInt(connection, teleportAwait);
+ awaitingTeleportTimeField.set(connection, tickCountField.get(connection));
+
+ Object packet = packetConstructor.newInstance(x, y, z, yawChange, pitchChange, teleportFlags, teleportAwait, false);
+ sendPacket(packet, player);
+ }
+ catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/pom.xml b/pom.xml
index 64b7236ed..a0fdb4a8c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
http://github.com/apdevteam/Movecraft
UTF-8
- 8.0.0-a.9
+ 8.0.0-a.10-dev
@@ -19,6 +19,7 @@
modules/v1_17_R1
modules/v1_18_R2
modules/v1_19_R1
+ modules/v1_19_R2
modules/datapack
modules/Movecraft
diff --git a/setup.sh b/setup.sh
index 327b4c1e5..63f69f1a3 100755
--- a/setup.sh
+++ b/setup.sh
@@ -40,13 +40,6 @@ else
/usr/lib/jvm/temurin-11-jdk-amd64/bin/java -jar BuildTools.jar --rev 1.16.5 --compile craftbukkit
fi
-# Build 1.17.1
-if [ -f ~/.m2/repository/org/spigotmc/spigot/1.17.1-R0.1-SNAPSHOT/spigot-1.17.1-R0.1-SNAPSHOT.jar ]; then
- echo "1.17.1 already exists, skipping build"
-else
- java -jar BuildTools.jar --rev 1.17.1 --remapped
-fi
-
# Build 1.18.2
if [ -f ~/.m2/repository/org/spigotmc/spigot/1.18.2-R0.1-SNAPSHOT/spigot-1.18.2-R0.1-SNAPSHOT.jar ]; then
echo "1.18.2 already exists, skipping build"
@@ -54,13 +47,20 @@ else
java -jar BuildTools.jar --rev 1.18.2 --remapped
fi
-# Build 1.19.1
-if [ -f ~/.m2/repository/org/spigotmc/spigot/1.19-R0.1-SNAPSHOT/spigot-1.19.2-R0.1-SNAPSHOT.jar ]; then
+# Build 1.19.2
+if [ -f ~/.m2/repository/org/spigotmc/spigot/1.19.2-R0.1-SNAPSHOT/spigot-1.19.2-R0.1-SNAPSHOT.jar ]; then
echo "1.19.2 already exists, skipping build"
else
java -jar BuildTools.jar --rev 1.19.2 --remapped
fi
+# Build 1.19.3
+if [ -f ~/.m2/repository/org/spigotmc/spigot/1.19.3-R0.1-SNAPSHOT/spigot-1.19.3-R0.1-SNAPSHOT.jar ]; then
+ echo "1.19.3 already exists, skipping build"
+else
+ java -jar BuildTools.jar --rev 1.19.3 --remapped
+fi
+
# Restore git information
git config --global user.name "$git_name"
git config --global user.email "$git_email"