From 2da32bb9b1b489dc26a2d16251bd363cabd1bc3b Mon Sep 17 00:00:00 2001 From: DoggySazHi Date: Thu, 20 Jun 2024 00:15:02 -0700 Subject: [PATCH] Proper mixin without breaking the ServerPlayer object (TrainCarts) --- .github/workflows/build-commit.yml | 47 ++++++++++ .../gensoujank/GensouJank.java | 4 +- .../gensoujank/TouhouHitboxes.java | 87 ++++++++----------- .../gensoujankmod/ITouhouPlayer.java | 23 ----- .../gensoujankmod/TouhouPlayer.java | 52 +++-------- .../gensoujankmod/TouhouPlayers.java | 10 +++ .../mixin/core/MixinPlayerList.java | 21 ----- .../mixin/core/MixinServerPlayer.java | 46 ++++++++++ .../mixin/core/MixinSpongeSIMD.java | 19 ---- GensouJankMod/src/main/resources/mixins.json | 3 +- 10 files changed, 153 insertions(+), 159 deletions(-) create mode 100644 .github/workflows/build-commit.yml delete mode 100644 GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/ITouhouPlayer.java create mode 100644 GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/TouhouPlayers.java delete mode 100644 GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/mixin/core/MixinPlayerList.java create mode 100644 GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/mixin/core/MixinServerPlayer.java delete mode 100644 GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/mixin/core/MixinSpongeSIMD.java diff --git a/.github/workflows/build-commit.yml b/.github/workflows/build-commit.yml new file mode 100644 index 0000000..0c3afe5 --- /dev/null +++ b/.github/workflows/build-commit.yml @@ -0,0 +1,47 @@ +# Used when a commit is pushed to the repository +# This makes use of caching for faster builds and uploads the resulting artifacts +name: build-commit + +on: [ push, workflow_dispatch ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Extract current branch name + shell: bash + # bash pattern expansion to grab branch name without slashes + run: ref="${GITHUB_REF#refs/heads/}" && echo "branch=${ref////-}" >> $GITHUB_OUTPUT + id: ref + - name: Checkout sources + uses: actions/checkout@v3 + - name: Set up JDK + uses: actions/setup-java@v2 + with: + distribution: 'temurin' + java-version: 21 + - name: Initialize caches + uses: actions/cache@v3 + with: + path: | + ~/.gradle/caches + ~/.gradle/loom-cache + ~/.gradle/wrapper + key: ${{ runner.os }}-build-commit-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-build-commit- + - name: Gradle deez + uses: gradle/gradle-build-action@v3 + - name: Build artifacts + run: ./gradlew clean :build-logic:build GensouJankMod:build GensouJank:build + - name: Upload artifacts + uses: actions/upload-artifact@v2 + with: + name: gensoujank-artifacts-${{ steps.ref.outputs.branch }} + path: build/libs/*.jar +# - name: Reposilite upload +# run: ./gradlew publish +# env: +# USERNAME: ${{ secrets.ORG_GRADLE_PROJECT_GENSOREPOUSERNAME }} +# TOKEN: ${{ secrets.ORG_GRADLE_PROJECT_GENSOREPOPASSWORD }} \ No newline at end of file diff --git a/GensouJank/src/main/java/net/gensokyoreimagined/gensoujank/GensouJank.java b/GensouJank/src/main/java/net/gensokyoreimagined/gensoujank/GensouJank.java index a771ad5..2cc7e60 100644 --- a/GensouJank/src/main/java/net/gensokyoreimagined/gensoujank/GensouJank.java +++ b/GensouJank/src/main/java/net/gensokyoreimagined/gensoujank/GensouJank.java @@ -1,7 +1,7 @@ package net.gensokyoreimagined.gensoujank; -import net.gensokyoreimagined.gensoujankmod.ITouhouPlayer; import net.gensokyoreimagined.gensoujankmod.TouhouPlayer; +import net.gensokyoreimagined.gensoujankmod.TouhouPlayers; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.event.Listener; import org.bukkit.plugin.java.JavaPlugin; @@ -26,7 +26,7 @@ public void onEnable(){ config.options().copyDefaults(true); saveConfig(); - TouhouPlayer.setAdjustY(config.getDouble("hitbox-y-offset")); + TouhouPlayers.defaultAdjustY = config.getDouble("hitbox-y-offset"); TouhouHitboxes touhouHitboxes = new TouhouHitboxes(); TouhouHitboxesTabCompleter touhouHitboxesTabCompleter = new TouhouHitboxesTabCompleter(); diff --git a/GensouJank/src/main/java/net/gensokyoreimagined/gensoujank/TouhouHitboxes.java b/GensouJank/src/main/java/net/gensokyoreimagined/gensoujank/TouhouHitboxes.java index 7b7627b..cc43022 100644 --- a/GensouJank/src/main/java/net/gensokyoreimagined/gensoujank/TouhouHitboxes.java +++ b/GensouJank/src/main/java/net/gensokyoreimagined/gensoujank/TouhouHitboxes.java @@ -1,59 +1,39 @@ package net.gensokyoreimagined.gensoujank; import com.mojang.math.Transformation; -import net.gensokyoreimagined.gensoujankmod.TouhouPlayer; -import net.gensokyoreimagined.gensoujankmod.ITouhouPlayer; +import net.gensokyoreimagined.gensoujankmod.TouhouPlayers; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.*; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; -import org.bukkit.command.TabCompleter; import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.craftbukkit.entity.CraftBlockDisplay; import org.bukkit.entity.EntityType; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.joml.Vector3f; -import java.util.List; - public class TouhouHitboxes implements CommandExecutor, Listener { - @EventHandler - public void onPlayerLogin(PlayerJoinEvent event) { - var player = (CraftPlayer) event.getPlayer(); - - if (!(player.getHandle() instanceof ITouhouPlayer)) { - Bukkit.getLogger().warning("[GensouJank] Player " + player.getName() + " is not a TouhouPlayer, but " + player.getHandle().getClass()); - } - } - @EventHandler public void onPlayerQuit(PlayerQuitEvent event) { var player = (CraftPlayer) event.getPlayer(); - if (player.getHandle() instanceof ITouhouPlayer touhouPlayer) { - if (touhouPlayer.getDebugTask() != null) { - touhouPlayer.getDebugTask().cancel(); - touhouPlayer.setDebugTask(null); - } + var query = TouhouPlayers.players.get(player.getUniqueId()); - if (touhouPlayer.getHitboxDisplay() != null) { - touhouPlayer.getHitboxDisplay().remove(); - touhouPlayer.setHitboxDisplay(null); + if (query != null) { + if (query.debugTask != null) { + query.debugTask.cancel(); } - if (touhouPlayer.isBossMode()) { - // Log out and fix collision box - touhouPlayer.setBossMode(false); + if (query.hitbox != null) { + query.hitbox.remove(); } - } else { - Bukkit.getLogger().warning("[GensouJank] Player " + player.getName() + " is not a TouhouPlayer, but " + player.getHandle().getClass()); + + TouhouPlayers.players.remove(player.getUniqueId()); } } @@ -85,18 +65,20 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command return true; } - if(player.getHandle() instanceof ITouhouPlayer touhouPlayer) { - touhouPlayer.setBossMode(args[1].equalsIgnoreCase("true")); + var query = TouhouPlayers.players.get(player.getUniqueId()); + + if (query != null) { + query.bossMode = (args[1].equalsIgnoreCase("true")); if (args.length > 2) { - if (args[2].equalsIgnoreCase("true") && touhouPlayer.getDebugTask() == null) { + if (args[2].equalsIgnoreCase("true") && query.debugTask == null) { // Debug mode: show hitbox using a block display entity (glass block) var world = player.getWorld(); var box = player.getBoundingBox(); var hitboxLocation = new Location(world, box.getMinX(), box.getMinY(), box.getMinZ()); var hitbox = (CraftBlockDisplay) world.spawnEntity(hitboxLocation, EntityType.BLOCK_DISPLAY); - touhouPlayer.setHitboxDisplay(hitbox); + query.hitbox = hitbox; hitbox.setVisibleByDefault(false); hitbox.setTeleportDuration(1); @@ -112,9 +94,9 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command null )); - var debugTask = Bukkit.getScheduler().runTaskTimer(GensouJank.getInstance(), () -> { + query.debugTask = Bukkit.getScheduler().runTaskTimer(GensouJank.getInstance(), () -> { var timerBox = player.getBoundingBox(); - var tHitBox = touhouPlayer.getHitboxDisplay(); + var tHitBox = query.hitbox; tHitBox.getHandle().setTransformation(new Transformation( null, @@ -125,31 +107,29 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command var onGround = player.isOnGround(); // compensate for player movement - step one tick ahead - var velocityX = touhouPlayer.getLastBoundingBox() == null ? 0 : timerBox.getMinX() - touhouPlayer.getLastBoundingBox().getMinX(); - var velocityY = touhouPlayer.getLastBoundingBox() == null ? 0 : timerBox.getMinY() - touhouPlayer.getLastBoundingBox().getMinY(); - var velocityZ = touhouPlayer.getLastBoundingBox() == null ? 0 : timerBox.getMinZ() - touhouPlayer.getLastBoundingBox().getMinZ(); + var velocityX = query.lastBoundingBox == null ? 0 : timerBox.getMinX() - query.lastBoundingBox.getMinX(); + var velocityY = query.lastBoundingBox == null ? 0 : timerBox.getMinY() - query.lastBoundingBox.getMinY(); + var velocityZ = query.lastBoundingBox == null ? 0 : timerBox.getMinZ() - query.lastBoundingBox.getMinZ(); - touhouPlayer.getHitboxDisplay().teleport(new Location( - touhouPlayer.getBukkitEntity().getWorld(), timerBox.getMinX() + 1 * velocityX, timerBox.getMinY() + (onGround ? 0 : 1 * velocityY), timerBox.getMinZ() + 1 * velocityZ + query.hitbox.teleport(new Location( + player.getWorld(), timerBox.getMinX() + 1 * velocityX, timerBox.getMinY() + (onGround ? 0 : 1 * velocityY), timerBox.getMinZ() + 1 * velocityZ )); - touhouPlayer.setLastBoundingBox(timerBox); + query.lastBoundingBox = timerBox; // Bukkit.getLogger().info("[GensouJank] " + player.getName() + " position: " + player.getLocation()); }, 0L, 1L); - - touhouPlayer.setDebugTask(debugTask); - } else if (args[2].equalsIgnoreCase("false") && touhouPlayer.getDebugTask() != null) { - touhouPlayer.getDebugTask().cancel(); - touhouPlayer.setDebugTask(null); - touhouPlayer.getHitboxDisplay().remove(); - touhouPlayer.setHitboxDisplay(null); + } else if (args[2].equalsIgnoreCase("false") && query.debugTask != null) { + query.debugTask.cancel(); + query.debugTask = null; + query.hitbox.remove(); + query.hitbox = null; } } if (args.length > 3) { try { - TouhouPlayer.setAdjustY(Double.parseDouble(args[3])); + query.adjustY = Double.parseDouble(args[3]); } catch (NumberFormatException e) { sender.sendMessage( Component @@ -172,7 +152,14 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command .build() ); } else { - throw new IllegalStateException("Player is " + player.getHandle().getClass()+ " instead of TouhouPlayer"); + sender.sendMessage( + Component + .text() + .append(Component.text().color(NamedTextColor.RED).content("Player ")) + .append(Component.text().color(NamedTextColor.WHITE).content(player.getName())) + .append(Component.text().color(NamedTextColor.RED).content(" not found")) + .build() + ); } return true; diff --git a/GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/ITouhouPlayer.java b/GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/ITouhouPlayer.java deleted file mode 100644 index 5be13fe..0000000 --- a/GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/ITouhouPlayer.java +++ /dev/null @@ -1,23 +0,0 @@ -package net.gensokyoreimagined.gensoujankmod; - -import org.bukkit.craftbukkit.entity.CraftBlockDisplay; -import org.bukkit.craftbukkit.entity.CraftPlayer; -import org.bukkit.scheduler.BukkitTask; -import org.bukkit.util.BoundingBox; - -public interface ITouhouPlayer { - - public boolean isBossMode(); - public void setBossMode(boolean bossMode); - - public BukkitTask getDebugTask(); - public void setDebugTask(BukkitTask debugTask); - - public BoundingBox getLastBoundingBox(); - public void setLastBoundingBox(BoundingBox lastBoundingBox); - - public CraftBlockDisplay getHitboxDisplay(); - public void setHitboxDisplay(CraftBlockDisplay hitbox); - - public CraftPlayer getBukkitEntity(); -} diff --git a/GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/TouhouPlayer.java b/GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/TouhouPlayer.java index db45ab2..4880f80 100644 --- a/GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/TouhouPlayer.java +++ b/GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/TouhouPlayer.java @@ -1,54 +1,22 @@ package net.gensokyoreimagined.gensoujankmod; -import com.mojang.authlib.GameProfile; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ClientInformation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Pose; -import net.minecraft.world.phys.AABB; import org.bukkit.craftbukkit.entity.CraftBlockDisplay; import org.bukkit.scheduler.BukkitTask; import org.bukkit.util.BoundingBox; -import org.jetbrains.annotations.NotNull; +import java.util.UUID; -public class TouhouPlayer extends ServerPlayer implements ITouhouPlayer { - /** - * The Y coordinate of the player's hitbox is adjusted by this amount when boss mode is enabled. - */ - private static double adjustY = 1.2; - public static void setAdjustY(double adjustY) { TouhouPlayer.adjustY = adjustY; } - public void setAdjustYY(double adjustY) { TouhouPlayer.adjustY = adjustY; } - /** - * Whether to enable the smaller hitbox. - */ - private boolean bossMode = false; - public boolean isBossMode() { return bossMode; } - public void setBossMode(boolean bossMode) { this.bossMode = bossMode; } +public class TouhouPlayer { + public UUID uuid; - /** - * The task upon debug mode to reveal the hitbox. - */ - private BukkitTask debugTask = null; - public BukkitTask getDebugTask() { return debugTask; } - public void setDebugTask(BukkitTask debugTask) { this.debugTask = debugTask; } + public double adjustY = TouhouPlayers.defaultAdjustY; + public boolean bossMode = false; + public BukkitTask debugTask; + public BoundingBox lastBoundingBox; + public CraftBlockDisplay hitbox; - private BoundingBox lastBoundingBox = null; - public BoundingBox getLastBoundingBox() { return lastBoundingBox; } - public void setLastBoundingBox(BoundingBox lastBoundingBox) { this.lastBoundingBox = lastBoundingBox; } - - private CraftBlockDisplay hitbox = null; - public CraftBlockDisplay getHitboxDisplay() { return hitbox; } - public void setHitboxDisplay(CraftBlockDisplay hitbox) { this.hitbox = hitbox; } - - public TouhouPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ClientInformation clientOptions) { - super(server, world, profile, clientOptions); - } - - @Override - protected @NotNull AABB makeBoundingBox() { - return bossMode ? getDimensions(Pose.SWIMMING).makeBoundingBox(this.position().add(0, adjustY, 0)) : super.makeBoundingBox(); + public TouhouPlayer(UUID uuid) { + this.uuid = uuid; } } diff --git a/GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/TouhouPlayers.java b/GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/TouhouPlayers.java new file mode 100644 index 0000000..aa7f805 --- /dev/null +++ b/GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/TouhouPlayers.java @@ -0,0 +1,10 @@ +package net.gensokyoreimagined.gensoujankmod; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class TouhouPlayers { + public static double defaultAdjustY = 1.2; + public static Map players = new HashMap<>(); +} diff --git a/GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/mixin/core/MixinPlayerList.java b/GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/mixin/core/MixinPlayerList.java deleted file mode 100644 index f0042c2..0000000 --- a/GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/mixin/core/MixinPlayerList.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.gensokyoreimagined.gensoujankmod.mixin.core; - -import com.mojang.authlib.GameProfile; -import net.gensokyoreimagined.gensoujankmod.TouhouPlayer; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ClientInformation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.players.PlayerList; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(PlayerList.class) -public abstract class MixinPlayerList { - @Redirect(method = "canPlayerLogin", at = @At(value = "NEW", target = "(Lnet/minecraft/server/MinecraftServer;Lnet/minecraft/server/level/ServerLevel;Lcom/mojang/authlib/GameProfile;Lnet/minecraft/server/level/ClientInformation;)Lnet/minecraft/server/level/ServerPlayer;")) - private ServerPlayer onCanPlayerLogin(MinecraftServer server, ServerLevel world, GameProfile profile, ClientInformation clientOptions) { - System.out.println("Substituted TouhouPlayer successfully!"); - return new TouhouPlayer(server, world, profile, clientOptions); - } -} \ No newline at end of file diff --git a/GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/mixin/core/MixinServerPlayer.java b/GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/mixin/core/MixinServerPlayer.java new file mode 100644 index 0000000..1023ed1 --- /dev/null +++ b/GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/mixin/core/MixinServerPlayer.java @@ -0,0 +1,46 @@ +package net.gensokyoreimagined.gensoujankmod.mixin.core; + +import net.gensokyoreimagined.gensoujankmod.TouhouPlayer; +import net.gensokyoreimagined.gensoujankmod.TouhouPlayers; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.Pose; +import net.minecraft.world.phys.AABB; +import org.bukkit.Bukkit; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(Entity.class) +public class MixinServerPlayer { + @Unique + private TouhouPlayer gensouJank$instance; + + @Inject(method = "makeBoundingBox", at = @At("HEAD"), cancellable = true) + private void makeBoundingBox(CallbackInfoReturnable cir) { + var entity = (Entity) (Object) this; + + if (entity instanceof ServerPlayer player) { + var uuid = player.getUUID(); + + if (gensouJank$instance == null) { + Bukkit.getLogger().info("[GensouJank] Creating new TouhouPlayer instance for " + uuid + "..."); + gensouJank$instance = TouhouPlayers.players.computeIfAbsent(uuid, o -> new TouhouPlayer(uuid)); + TouhouPlayers.players.put(uuid, gensouJank$instance); + } else if (!gensouJank$instance.uuid.equals(uuid)) { + Bukkit.getLogger().info("[GensouJank] Updating TouhouPlayer instance " + gensouJank$instance.uuid + " -> " + uuid + "..."); + TouhouPlayers.players.remove(gensouJank$instance.uuid); + TouhouPlayers.players.put(uuid, gensouJank$instance); + gensouJank$instance.uuid = uuid; + } + + if (gensouJank$instance.bossMode) { + var boundingBox = entity.getDimensions(Pose.SWIMMING).makeBoundingBox(entity.position().add(0, gensouJank$instance.adjustY, 0)); + cir.setReturnValue(boundingBox); + cir.cancel(); + } + } + } +} diff --git a/GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/mixin/core/MixinSpongeSIMD.java b/GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/mixin/core/MixinSpongeSIMD.java deleted file mode 100644 index d1280d4..0000000 --- a/GensouJankMod/src/main/java/net/gensokyoreimagined/gensoujankmod/mixin/core/MixinSpongeSIMD.java +++ /dev/null @@ -1,19 +0,0 @@ -package net.gensokyoreimagined.gensoujankmod.mixin.core; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(targets = "gg.pufferfish.pufferfish.simd.SIMDDetection") -public abstract class MixinSpongeSIMD { - @Inject(method = "getJavaVersion", at = @At("RETURN"), cancellable = true) - private static void loadPufferfishConfig(CallbackInfoReturnable callback) { - // We troll the Pufferfish developers by changing the return value of the method - // System.out.println("Thought that it was " + callback.getReturnValue() + " for java version"); - if (callback.getReturnValue() == 21) { - System.out.println("Successfully trolled Pufferfish into thinking we're on Java 19!"); - callback.setReturnValue(19); - } - } -} diff --git a/GensouJankMod/src/main/resources/mixins.json b/GensouJankMod/src/main/resources/mixins.json index 0f1dfca..f5ad99b 100644 --- a/GensouJankMod/src/main/resources/mixins.json +++ b/GensouJankMod/src/main/resources/mixins.json @@ -6,7 +6,6 @@ "target": "@env(DEFAULT)", "compatibilityLevel": "JAVA_17", "server": [ - "MixinPlayerList", - "MixinSpongeSIMD" + "MixinServerPlayer" ] }