Strip all Phase references, TODO/FUTURE roadmap notes, and internal planning comments from the codebase. Run Prettier for consistent formatting across all Java files.
253 lines
8.0 KiB
Java
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);
|
|
}
|
|
}
|