Skip to content

Commit

Permalink
fix bugs with dummy respawning + implement doImmediateRespawn
Browse files Browse the repository at this point in the history
  • Loading branch information
misode committed Dec 24, 2023
1 parent a2fc111 commit c6c7bd9
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 29 deletions.
28 changes: 20 additions & 8 deletions src/main/java/io/github/misode/packtest/dummy/Dummy.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,32 @@
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;

/**
* Heavily inspired by <a href="https://github.com/gnembon/fabric-carpet/blob/master/src/main/java/carpet/patches/EntityPlayerMPFake.java">Carpet</a>
*/
public class Dummy extends ServerPlayer {
public @Nullable BlockPos origin = null;
public Runnable fixStartingPosition = () -> {};
public Vec3 originalSpawn;

public static Dummy createRandom(MinecraftServer server, ResourceKey<Level> dimensionId, Vec3 pos) {
RandomSource random = server.overworld().getRandom();
Expand Down Expand Up @@ -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);
Expand All @@ -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() {
Expand Down Expand Up @@ -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);
Expand Down
31 changes: 10 additions & 21 deletions src/main/java/io/github/misode/packtest/mixin/PlayerListMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
Expand All @@ -29,34 +26,26 @@ public class PlayerListMixin {
@Inject(method = "load", at = @At(value = "RETURN", shift = At.Shift.BEFORE))
private void fixStartingPos(ServerPlayer player, CallbackInfoReturnable<CompoundTag> 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<ServerPlayer> 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<BlockPos> 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<Vec3> getRespawnPos(ServerLevel level, BlockPos pos, float angle, boolean forced, boolean other, Operation<Optional<Vec3>> 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<ServerPlayer> 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);
}
}
}

0 comments on commit c6c7bd9

Please sign in to comment.