Skip to content

Commit

Permalink
Rename /player to /dummy
Browse files Browse the repository at this point in the history
  • Loading branch information
misode committed Dec 21, 2023
1 parent b3e7667 commit cc3ab21
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 81 deletions.
4 changes: 2 additions & 2 deletions src/main/java/io/github/misode/packtest/PackTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import io.github.misode.packtest.commands.AssertCommand;
import io.github.misode.packtest.commands.FailCommand;
import io.github.misode.packtest.commands.SucceedCommand;
import io.github.misode.packtest.commands.PlayerCommand;
import io.github.misode.packtest.commands.DummyCommand;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.minecraft.core.BlockPos;
Expand Down Expand Up @@ -31,7 +31,7 @@ public void onInitialize() {
CommandRegistrationCallback.EVENT.register((dispatcher, buildContext, environment) -> {
AssertCommand.register(dispatcher, buildContext);
FailCommand.register(dispatcher);
PlayerCommand.register(dispatcher);
DummyCommand.register(dispatcher);
SucceedCommand.register(dispatcher, buildContext);
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import io.github.misode.packtest.fake.FakePlayer;
import io.github.misode.packtest.dummy.Dummy;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;
Expand All @@ -22,57 +22,57 @@
import static net.minecraft.commands.Commands.argument;
import static net.minecraft.commands.Commands.literal;

public class PlayerCommand {
public class DummyCommand {

public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
dispatcher.register(literal("player")
dispatcher.register(literal("dummy")
.then(literal("spawn")
.executes(PlayerCommand::spawnRandomName)
.then(argument("player", StringArgumentType.word())
.executes(PlayerCommand::spawnFixedName)))
.executes(DummyCommand::spawnRandomName)
.then(argument("name", StringArgumentType.word())
.executes(DummyCommand::spawnFixedName)))
.then(literal("leave")
.then(playerArgument()
.executes(PlayerCommand::leave)))
.then(dummyName()
.executes(DummyCommand::leave)))
.then(literal("respawn")
.then(playerArgument()
.executes(PlayerCommand::respawn)))
.then(dummyName()
.executes(DummyCommand::respawn)))
.then(literal("jump")
.then(playerArgument()
.executes(PlayerCommand::jump)))
.then(dummyName()
.executes(DummyCommand::jump)))
.then(literal("sneak")
.then(playerArgument()
.then(dummyName()
.then(argument("active", BoolArgumentType.bool())
.executes(PlayerCommand::sneak))))
.executes(DummyCommand::sneak))))
.then(literal("sprint")
.then(playerArgument()
.then(dummyName()
.then(argument("active", BoolArgumentType.bool())
.executes(PlayerCommand::sprint))))
.executes(DummyCommand::sprint))))
);
}

private static RequiredArgumentBuilder<CommandSourceStack, String> playerArgument() {
return argument("player", StringArgumentType.word())
private static RequiredArgumentBuilder<CommandSourceStack, String> dummyName() {
return argument("name", StringArgumentType.word())
.suggests((ctx, builder) -> {
PlayerList playerList = ctx.getSource().getServer().getPlayerList();
playerList.getPlayers().forEach(player -> {
if (player instanceof FakePlayer) {
if (player instanceof Dummy) {
builder.suggest(player.getName().getString());
}
});
return builder.buildFuture();
});
}

private static FakePlayer getPlayer(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
String playerName = StringArgumentType.getString(ctx, "player");
return getPlayer(playerName, ctx).orElseThrow(() -> new SimpleCommandExceptionType(() -> "Fake player " + playerName + " does not exist").create());
private static Dummy getDummy(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
String playerName = StringArgumentType.getString(ctx, "name");
return getDummy(playerName, ctx).orElseThrow(() -> new SimpleCommandExceptionType(() -> "Dummy " + playerName + " does not exist").create());
}

private static Optional<FakePlayer> getPlayer(String playerName, CommandContext<CommandSourceStack> ctx) {
private static Optional<Dummy> getDummy(String playerName, CommandContext<CommandSourceStack> ctx) {
MinecraftServer server = ctx.getSource().getServer();
ServerPlayer player = server.getPlayerList().getPlayerByName(playerName);
if (player instanceof FakePlayer fakePlayer) {
return Optional.of(fakePlayer);
if (player instanceof Dummy testPlayer) {
return Optional.of(testPlayer);
}
return Optional.empty();
}
Expand All @@ -81,73 +81,73 @@ private static int spawnRandomName(CommandContext<CommandSourceStack> ctx) {
int tries = 0;
while (tries++ < 10) {
RandomSource random = ctx.getSource().getLevel().getRandom();
String playerName = "Tester" + random.nextInt(100, 1000);
if (getPlayer(playerName, ctx).isEmpty()) {
String playerName = "Dummy" + random.nextInt(100, 1000);
if (getDummy(playerName, ctx).isEmpty()) {
return spawn(playerName, ctx);
}
}
ctx.getSource().sendFailure(Component.literal("Failed to spawn player with a random name"));
ctx.getSource().sendFailure(Component.literal("Failed to spawn dummy with a random name"));
return 0;
}

private static int spawnFixedName(CommandContext<CommandSourceStack> ctx) {
String playerName = StringArgumentType.getString(ctx, "player");
String playerName = StringArgumentType.getString(ctx, "name");
return spawn(playerName, ctx);
}

private static int spawn(String playerName, CommandContext<CommandSourceStack> ctx) {
private static int spawn(String name, CommandContext<CommandSourceStack> ctx) {
CommandSourceStack source = ctx.getSource();
MinecraftServer server = source.getServer();
if (getPlayer(playerName, ctx).isPresent()) {
source.sendFailure(Component.literal("Player " + playerName + " is already logged on"));
if (getDummy(name, ctx).isPresent()) {
source.sendFailure(Component.literal("Dummy " + name + " is already logged on"));
return 0;
}
ResourceKey<Level> dimension = source.getLevel().dimension();
FakePlayer.create(playerName, server, dimension, source.getPosition());
Dummy.create(name, server, dimension, source.getPosition());
return 1;
}

private static int leave(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
FakePlayer player = getPlayer(ctx);
player.leave(Component.literal("Forced to leave"));
Dummy dummy = getDummy(ctx);
dummy.leave(Component.literal("Forced to leave"));
return 1;
}

private static int respawn(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
FakePlayer player = getPlayer(ctx);
player.respawn();
Dummy dummy = getDummy(ctx);
dummy.respawn();
return 1;
}

private static int jump(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
FakePlayer player = getPlayer(ctx);
if (player.onGround()) {
player.jumpFromGround();
Dummy dummy = getDummy(ctx);
if (dummy.onGround()) {
dummy.jumpFromGround();
return 1;
}
ctx.getSource().sendFailure(Component.literal("Player is not on the ground"));
ctx.getSource().sendFailure(Component.literal("Dummy is not on the ground"));
return 0;
}

private static int sneak(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
FakePlayer player = getPlayer(ctx);
Dummy dummy = getDummy(ctx);
boolean toggle = BoolArgumentType.getBool(ctx, "active");
if (player.isShiftKeyDown() != toggle) {
player.setShiftKeyDown(toggle);
if (dummy.isShiftKeyDown() != toggle) {
dummy.setShiftKeyDown(toggle);
return 1;
}
ctx.getSource().sendFailure(Component.literal(toggle ? "Player is already sneaking" : "Player is already not sneaking"));
ctx.getSource().sendFailure(Component.literal(toggle ? "Dummy is already sneaking" : "Dummy is already not sneaking"));
return 0;
}

private static int sprint(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
FakePlayer player = getPlayer(ctx);
Dummy dummy = getDummy(ctx);
boolean toggle = BoolArgumentType.getBool(ctx, "active");
if (player.isSprinting() != toggle) {
player.setSprinting(toggle);
if (dummy.isSprinting() != toggle) {
dummy.setSprinting(toggle);
return 1;
}
ctx.getSource().sendFailure(Component.literal(toggle ? "Player is already sprinting" : "Player is already not sprinting"));
ctx.getSource().sendFailure(Component.literal(toggle ? "Dummy is already sprinting" : "Dummy is already not sprinting"));
return 0;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.github.misode.packtest.fake;
package io.github.misode.packtest.dummy;

import com.mojang.authlib.GameProfile;
import net.minecraft.core.BlockPos;
Expand Down Expand Up @@ -27,7 +27,7 @@
/**
* Heavily inspired by <a href="https://github.com/gnembon/fabric-carpet/blob/master/src/main/java/carpet/patches/EntityPlayerMPFake.java">Carpet</a>
*/
public class FakePlayer extends ServerPlayer {
public class Dummy extends ServerPlayer {
public @Nullable BlockPos origin = null;
public Runnable fixStartingPosition = () -> {};

Expand All @@ -45,23 +45,23 @@ public static void create(String username, MinecraftServer server, ResourceKey<L
if (profile == null) {
profile = new GameProfile(UUIDUtil.createOfflinePlayerUUID(username), username);
}
FakePlayer instance = new FakePlayer(server, level, profile, ClientInformation.createDefault());
instance.origin = BlockPos.containing(pos);
instance.fixStartingPosition = () -> instance.moveTo(pos.x, pos.y, pos.z, 0, 0);
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);
server.getPlayerList().placeNewPlayer(
new FakeClientConnection(PacketFlow.SERVERBOUND),
instance,
new CommonListenerCookie(profile, 0, instance.clientInformation()));
instance.teleportTo(level, pos.x, pos.y, pos.z, 0, 0);
instance.setHealth(20);
instance.unsetRemoved();
instance.gameMode.changeGameModeForPlayer(GameType.SURVIVAL);
server.getPlayerList().broadcastAll(new ClientboundRotateHeadPacket(instance, (byte) (instance.yHeadRot * 256 / 360)), dimensionId);
server.getPlayerList().broadcastAll(new ClientboundTeleportEntityPacket(instance), dimensionId);
instance.entityData.set(DATA_PLAYER_MODE_CUSTOMISATION, (byte) 0x7f);
new DummyClientConnection(PacketFlow.SERVERBOUND),
dummy,
new CommonListenerCookie(profile, 0, dummy.clientInformation()));
dummy.teleportTo(level, pos.x, pos.y, pos.z, 0, 0);
dummy.setHealth(20);
dummy.unsetRemoved();
dummy.gameMode.changeGameModeForPlayer(GameType.SURVIVAL);
server.getPlayerList().broadcastAll(new ClientboundRotateHeadPacket(dummy, (byte) (dummy.yHeadRot * 256 / 360)), dimensionId);
server.getPlayerList().broadcastAll(new ClientboundTeleportEntityPacket(dummy), dimensionId);
dummy.entityData.set(DATA_PLAYER_MODE_CUSTOMISATION, (byte) 0x7f);
}

public FakePlayer(MinecraftServer server, ServerLevel level, GameProfile profile, ClientInformation cli) {
public Dummy(MinecraftServer server, ServerLevel level, GameProfile profile, ClientInformation cli) {
super(server, level, profile, cli);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package io.github.misode.packtest.fake;
package io.github.misode.packtest.dummy;

import net.minecraft.network.Connection;
import net.minecraft.network.PacketListener;
import net.minecraft.network.protocol.PacketFlow;

public class FakeClientConnection extends Connection {
public class DummyClientConnection extends Connection {

public FakeClientConnection(PacketFlow flow) {
public DummyClientConnection(PacketFlow flow) {
super(flow);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.github.misode.packtest.mixin;

import io.github.misode.packtest.dummy.Dummy;
import net.minecraft.core.BlockPos;
import net.minecraft.gametest.framework.GameTestRunner;
import net.minecraft.gametest.framework.GameTestTicker;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
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.CallbackInfo;

import java.util.List;

/**
* Remove all test players when running <code>/test clearall</code>.
*/
@Mixin(GameTestRunner.class)
public class GameTestRunnerMixin {

@Inject(method = "clearAllTests", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/BlockPos;betweenClosedStream(Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/BlockPos;)Ljava/util/stream/Stream;", shift = At.Shift.AFTER))
private static void clearTestPlayers(ServerLevel level, BlockPos pos, GameTestTicker ticker, int radius, CallbackInfo ci) {
List<Dummy> testPlayers = level.getServer().getPlayerList().getPlayers().stream()
.filter(p -> p instanceof Dummy && p.distanceToSqr(pos.getCenter()) <= radius)
.map(p -> (Dummy)p)
.toList();
testPlayers.forEach(p -> p.leave(Component.literal("Cleared tests")));
}
}
22 changes: 11 additions & 11 deletions src/main/java/io/github/misode/packtest/mixin/PlayerListMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import com.mojang.authlib.GameProfile;
import io.github.misode.packtest.fake.FakePlayer;
import io.github.misode.packtest.dummy.Dummy;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.MinecraftServer;
Expand All @@ -21,40 +21,40 @@
import java.util.Optional;

/**
* Fixes starting position of fake players when they load in.
* Respawns fake players and in the correct position.
* Fixes starting position of test players when they load in.
* Respawns test players and in the correct position.
*/
@Mixin(PlayerList.class)
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 FakePlayer) {
((FakePlayer) player).fixStartingPosition.run();
if (player instanceof Dummy) {
((Dummy) player).fixStartingPosition.run();
}
}

@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 createPlayer(MinecraftServer server, ServerLevel level, GameProfile profile, ClientInformation cli, Operation<ServerPlayer> original, @Local(ordinal = 0) ServerPlayer player) {
if (player instanceof FakePlayer) {
return new FakePlayer(server, level, profile, cli);
if (player instanceof Dummy) {
return new Dummy(server, level, profile, cli);
} 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 FakePlayer fakePlayer && fakePlayer.origin != null) {
return fakePlayer.origin;
if (player instanceof Dummy testPlayer && testPlayer.origin != null) {
return testPlayer.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 FakePlayer fakePlayer && fakePlayer.origin != null) {
return Optional.of(new Vec3(fakePlayer.origin.getX() + 0.5, fakePlayer.origin.getY(), fakePlayer.origin.getZ() + 0.5));
if (player instanceof Dummy testPlayer && testPlayer.origin != null) {
return Optional.of(new Vec3(testPlayer.origin.getX() + 0.5, testPlayer.origin.getY(), testPlayer.origin.getZ() + 0.5));
} else {
return original.call(level, pos, angle, forced, other);
}
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/packtest.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"GameTestHelperMixin",
"GameTestInfoMixin",
"GameTestRegistryMixin",
"GameTestRunnerMixin",
"GameTestServerMixin",
"LogTestReporterMixin",
"MinecraftServerMixin",
Expand Down

0 comments on commit cc3ab21

Please sign in to comment.