Files
TiedUp-/src/main/java/com/tiedup/remake/commands/subcommands/MasterTestSubCommand.java
NotEvil a71093ba9c Remove internal phase comments and format code
Strip all Phase references, TODO/FUTURE roadmap notes, and internal
planning comments from the codebase. Run Prettier for consistent
formatting across all Java files.
2026-04-12 01:25:55 +02:00

253 lines
8.0 KiB
Java

package com.tiedup.remake.commands.subcommands;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.tiedup.remake.commands.CommandHelper;
import com.tiedup.remake.entities.EntityMaster;
import com.tiedup.remake.entities.ModEntities;
import com.tiedup.remake.entities.ai.master.MasterState;
import com.tiedup.remake.state.PlayerBindState;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.MobSpawnType;
/**
* Master/pet-play test sub-commands for /tiedup.
* Handles: mastertest, masterchair, mastertask
*/
@SuppressWarnings("null")
public class MasterTestSubCommand {
public static void register(
LiteralArgumentBuilder<CommandSourceStack> root
) {
// /tiedup mastertest
root.then(
Commands.literal("mastertest")
.requires(CommandHelper.REQUIRES_OP)
.executes(MasterTestSubCommand::mastertest)
);
// /tiedup masterchair
root.then(
Commands.literal("masterchair")
.requires(CommandHelper.REQUIRES_OP)
.executes(MasterTestSubCommand::masterchair)
);
// /tiedup mastertask <task>
root.then(
Commands.literal("mastertask")
.requires(CommandHelper.REQUIRES_OP)
.then(
Commands.argument("task", StringArgumentType.word())
.suggests((ctx, builder) -> {
for (MasterState s : MasterState.values()) {
builder.suggest(s.name().toLowerCase());
}
return builder.buildFuture();
})
.executes(MasterTestSubCommand::mastertask)
)
);
}
// Command Implementations
/**
* /tiedup mastertest
*
* Spawn a Master NPC nearby and immediately become its pet.
* For testing the pet play system without going through capture.
*/
private static int mastertest(CommandContext<CommandSourceStack> context)
throws CommandSyntaxException {
ServerPlayer player = context.getSource().getPlayerOrException();
ServerLevel level = context.getSource().getLevel();
double x = player.getX() + player.getLookAngle().x * 2;
double y = player.getY();
double z = player.getZ() + player.getLookAngle().z * 2;
EntityMaster master = ModEntities.MASTER.get().create(level);
if (master == null) {
context
.getSource()
.sendFailure(
Component.literal("Failed to create Master entity")
);
return 0;
}
master.moveTo(x, y, z, player.getYRot() + 180F, 0.0F);
master.finalizeSpawn(
level,
level.getCurrentDifficultyAt(master.blockPosition()),
MobSpawnType.COMMAND,
null,
null
);
level.addFreshEntity(master);
master.setPetPlayer(player);
master.putPetCollar(player);
CommandHelper.syncPlayerState(
player,
PlayerBindState.getInstance(player)
);
String masterName = master.getNpcName();
if (masterName == null || masterName.isEmpty()) masterName = "Master";
String finalName = masterName;
context
.getSource()
.sendSuccess(
() ->
Component.literal(
"Spawned Master '" +
finalName +
"' \u2014 you are now their pet."
),
true
);
return 1;
}
/**
* /tiedup masterchair
*
* Force the nearest Master NPC into HUMAN_CHAIR state.
* Requires the player to be that Master's pet.
*/
private static int masterchair(CommandContext<CommandSourceStack> context)
throws CommandSyntaxException {
ServerPlayer player = context.getSource().getPlayerOrException();
EntityMaster master = findNearestMaster(player);
if (master == null) {
context
.getSource()
.sendFailure(
Component.literal("No Master NPC found within 20 blocks")
);
return 0;
}
if (!master.hasPet()) {
master.setPetPlayer(player);
master.putPetCollar(player);
CommandHelper.syncPlayerState(
player,
PlayerBindState.getInstance(player)
);
}
master.setMasterState(MasterState.HUMAN_CHAIR);
String masterName = master.getNpcName();
if (masterName == null || masterName.isEmpty()) masterName = "Master";
String finalName = masterName;
context
.getSource()
.sendSuccess(
() ->
Component.literal(
"Forced " + finalName + " into HUMAN_CHAIR state"
),
true
);
return 1;
}
/**
* /tiedup mastertask <state>
*
* Force the nearest Master NPC into any MasterState.
* Useful for testing specific master behaviors.
*/
private static int mastertask(CommandContext<CommandSourceStack> context)
throws CommandSyntaxException {
ServerPlayer player = context.getSource().getPlayerOrException();
String taskName = StringArgumentType.getString(context, "task");
MasterState targetState;
try {
targetState = MasterState.valueOf(taskName.toUpperCase());
} catch (IllegalArgumentException e) {
context
.getSource()
.sendFailure(
Component.literal("Unknown MasterState: " + taskName)
);
return 0;
}
EntityMaster master = findNearestMaster(player);
if (master == null) {
context
.getSource()
.sendFailure(
Component.literal("No Master NPC found within 20 blocks")
);
return 0;
}
if (!master.hasPet()) {
master.setPetPlayer(player);
master.putPetCollar(player);
CommandHelper.syncPlayerState(
player,
PlayerBindState.getInstance(player)
);
}
master.setMasterState(targetState);
String masterName = master.getNpcName();
if (masterName == null || masterName.isEmpty()) masterName = "Master";
String finalName = masterName;
context
.getSource()
.sendSuccess(
() ->
Component.literal(
"Forced " +
finalName +
" into " +
targetState.name() +
" state"
),
true
);
return 1;
}
/**
* Find the nearest EntityMaster within 20 blocks of a player.
*/
@javax.annotation.Nullable
private static EntityMaster findNearestMaster(ServerPlayer player) {
var masters = player
.level()
.getEntitiesOfClass(
EntityMaster.class,
player.getBoundingBox().inflate(20.0),
m -> m.isAlive()
);
if (masters.isEmpty()) return null;
return masters
.stream()
.min((a, b) ->
Double.compare(a.distanceToSqr(player), b.distanceToSqr(player))
)
.orElse(null);
}
}