From c6c7bd914d887966c9936c65e4e40f3401c56f34 Mon Sep 17 00:00:00 2001 From: Misode Date: Sun, 24 Dec 2023 03:14:15 +0100 Subject: [PATCH] fix bugs with dummy respawning + implement doImmediateRespawn --- .../github/misode/packtest/dummy/Dummy.java | 28 ++++++++++++----- .../packtest/mixin/PlayerListMixin.java | 31 ++++++------------- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/src/main/java/io/github/misode/packtest/dummy/Dummy.java b/src/main/java/io/github/misode/packtest/dummy/Dummy.java index 6771846..762f3e3 100644 --- a/src/main/java/io/github/misode/packtest/dummy/Dummy.java +++ b/src/main/java/io/github/misode/packtest/dummy/Dummy.java @@ -7,21 +7,24 @@ import net.minecraft.network.protocol.PacketFlow; import net.minecraft.network.protocol.game.ClientboundRotateHeadPacket; import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket; +import net.minecraft.network.protocol.game.ServerboundClientCommandPacket; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.TickTask; import net.minecraft.server.level.ClientInformation; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.CommonListenerCookie; import net.minecraft.server.players.GameProfileCache; import net.minecraft.util.RandomSource; +import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.GameRules; import net.minecraft.world.level.GameType; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.Objects; @@ -29,8 +32,7 @@ * Heavily inspired by Carpet */ public class Dummy extends ServerPlayer { - public @Nullable BlockPos origin = null; - public Runnable fixStartingPosition = () -> {}; + public Vec3 originalSpawn; public static Dummy createRandom(MinecraftServer server, ResourceKey dimensionId, Vec3 pos) { RandomSource random = server.overworld().getRandom(); @@ -58,14 +60,13 @@ public static Dummy create(String username, MinecraftServer server, ResourceKey< if (profile == null) { profile = new GameProfile(UUIDUtil.createOfflinePlayerUUID(username), username); } - Dummy dummy = new Dummy(server, level, profile, ClientInformation.createDefault()); - dummy.origin = BlockPos.containing(pos); - dummy.fixStartingPosition = () -> dummy.moveTo(pos.x, pos.y, pos.z, 0, 0); + Vec3 originalSpawn = Vec3.atBottomCenterOf(BlockPos.containing(pos)); + Dummy dummy = new Dummy(server, level, profile, ClientInformation.createDefault(), originalSpawn); server.getPlayerList().placeNewPlayer( new DummyClientConnection(PacketFlow.SERVERBOUND), dummy, new CommonListenerCookie(profile, 0, dummy.clientInformation())); - dummy.teleportTo(level, pos.x, pos.y, pos.z, 0, 0); + dummy.teleportTo(level, originalSpawn.x, originalSpawn.y, originalSpawn.z, 0, 0); dummy.setHealth(20); dummy.unsetRemoved(); dummy.gameMode.changeGameModeForPlayer(GameType.SURVIVAL); @@ -75,8 +76,9 @@ public static Dummy create(String username, MinecraftServer server, ResourceKey< return dummy; } - public Dummy(MinecraftServer server, ServerLevel level, GameProfile profile, ClientInformation cli) { + public Dummy(MinecraftServer server, ServerLevel level, GameProfile profile, ClientInformation cli, Vec3 originalSpawn) { super(server, level, profile, cli); + this.originalSpawn = originalSpawn; } public String getUsername() { @@ -104,6 +106,16 @@ public void tick() { } catch (NullPointerException ignored) {} } + @Override + public void die(DamageSource cause) { + super.die(cause); + if (this.serverLevel().getGameRules().getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN)) { + this.server.tell(new TickTask(this.server.getTickCount(), + () -> this.connection.handleClientCommand(new ServerboundClientCommandPacket(ServerboundClientCommandPacket.Action.PERFORM_RESPAWN)) + )); + } + } + @Override public void onEquipItem(final EquipmentSlot slot, final ItemStack previous, final ItemStack stack) { if (!isUsingItem()) super.onEquipItem(slot, previous, stack); diff --git a/src/main/java/io/github/misode/packtest/mixin/PlayerListMixin.java b/src/main/java/io/github/misode/packtest/mixin/PlayerListMixin.java index aeb1c3e..4510830 100644 --- a/src/main/java/io/github/misode/packtest/mixin/PlayerListMixin.java +++ b/src/main/java/io/github/misode/packtest/mixin/PlayerListMixin.java @@ -5,7 +5,6 @@ import com.llamalad7.mixinextras.sugar.Local; import com.mojang.authlib.GameProfile; import io.github.misode.packtest.dummy.Dummy; -import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ClientInformation; @@ -18,8 +17,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.Optional; - /** * Fixes starting position of dummies when they load in. * Respawns dummies and in the correct position. @@ -29,34 +26,26 @@ public class PlayerListMixin { @Inject(method = "load", at = @At(value = "RETURN", shift = At.Shift.BEFORE)) private void fixStartingPos(ServerPlayer player, CallbackInfoReturnable cir) { if (player instanceof Dummy dummy) { - dummy.fixStartingPosition.run(); + Vec3 pos = dummy.originalSpawn; + dummy.moveTo(pos.x, pos.y, pos.z, 0, 0); } } @WrapOperation(method = "respawn", 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 createDummy(MinecraftServer server, ServerLevel level, GameProfile profile, ClientInformation cli, Operation original, @Local(ordinal = 0) ServerPlayer player) { - if (player instanceof Dummy) { - return new Dummy(server, level, profile, cli); + if (player instanceof Dummy dummy) { + return new Dummy(server, level, profile, cli, dummy.originalSpawn); } else { return original.call(server, level, profile, cli); } } - @WrapOperation(method = "respawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;getRespawnPosition()Lnet/minecraft/core/BlockPos;")) - private BlockPos getRespawnBlock(ServerPlayer player, Operation original) { - if (player instanceof Dummy dummy && dummy.origin != null) { - return dummy.origin; - } else { - return original.call(player); - } - } - - @WrapOperation(method = "respawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;findRespawnPositionAndUseSpawnBlock(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;FZZ)Ljava/util/Optional;")) - private Optional getRespawnPos(ServerLevel level, BlockPos pos, float angle, boolean forced, boolean other, Operation> original, @Local(ordinal = 0) ServerPlayer player) { - if (player instanceof Dummy dummy && dummy.origin != null) { - return Optional.of(new Vec3(dummy.origin.getX() + 0.5, dummy.origin.getY(), dummy.origin.getZ() + 0.5)); - } else { - return original.call(level, pos, angle, forced, other); + @Inject(method = "respawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;restoreFrom(Lnet/minecraft/server/level/ServerPlayer;Z)V")) + private void teleportDummy(ServerPlayer serverPlayer, boolean bl, CallbackInfoReturnable cir, @Local(ordinal = 1) ServerPlayer player) { + if (player instanceof Dummy dummy) { + Vec3 pos = dummy.originalSpawn; + dummy.moveTo(pos.x, pos.y, pos.z, 0, 0); + dummy.teleportTo(dummy.serverLevel(), pos.x, pos.y, pos.z, 0, 0); } } }