Remove build artifacts, dev tool configs, unused dependencies, and third-party source dumps. Add proper README, update .gitignore, clean up Makefile.
312 lines
10 KiB
Java
312 lines
10 KiB
Java
package com.tiedup.remake.commands;
|
|
|
|
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.items.clothes.GenericClothes;
|
|
import net.minecraft.commands.CommandSourceStack;
|
|
import net.minecraft.commands.Commands;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.server.level.ServerPlayer;
|
|
import net.minecraft.world.item.ItemStack;
|
|
|
|
/**
|
|
* Command handler for clothes configuration.
|
|
*
|
|
* Subcommands:
|
|
* /tiedup clothes url set <url> - Set dynamic texture URL on held clothes
|
|
* /tiedup clothes url reset - Remove dynamic texture URL
|
|
* /tiedup clothes fullskin - Toggle full-skin mode
|
|
* /tiedup clothes smallarms - Toggle small arms forcing
|
|
* /tiedup clothes keephead - Toggle keep head mode (preserves wearer's head)
|
|
* /tiedup clothes layer <part> - Toggle layer visibility
|
|
*
|
|
* All commands operate on the clothes item held in main hand.
|
|
*/
|
|
public class ClothesCommand {
|
|
|
|
/**
|
|
* Create the /tiedup clothes ... command tree.
|
|
*
|
|
* @return The command builder
|
|
*/
|
|
public static LiteralArgumentBuilder<
|
|
CommandSourceStack
|
|
> createClothesCommand() {
|
|
return Commands.literal("clothes")
|
|
// /tiedup clothes url set <url>
|
|
// /tiedup clothes url reset
|
|
.then(
|
|
Commands.literal("url")
|
|
.then(
|
|
Commands.literal("set").then(
|
|
Commands.argument(
|
|
"url",
|
|
StringArgumentType.greedyString()
|
|
).executes(ClothesCommand::setUrl)
|
|
)
|
|
)
|
|
.then(
|
|
Commands.literal("reset").executes(
|
|
ClothesCommand::resetUrl
|
|
)
|
|
)
|
|
)
|
|
// /tiedup clothes fullskin
|
|
.then(
|
|
Commands.literal("fullskin").executes(
|
|
ClothesCommand::toggleFullSkin
|
|
)
|
|
)
|
|
// /tiedup clothes smallarms
|
|
.then(
|
|
Commands.literal("smallarms").executes(
|
|
ClothesCommand::toggleSmallArms
|
|
)
|
|
)
|
|
// /tiedup clothes keephead
|
|
.then(
|
|
Commands.literal("keephead").executes(
|
|
ClothesCommand::toggleKeepHead
|
|
)
|
|
)
|
|
// /tiedup clothes layer <part>
|
|
.then(
|
|
Commands.literal("layer").then(
|
|
Commands.argument("part", StringArgumentType.word())
|
|
.suggests((ctx, builder) -> {
|
|
builder.suggest("head");
|
|
builder.suggest("body");
|
|
builder.suggest("leftarm");
|
|
builder.suggest("rightarm");
|
|
builder.suggest("leftleg");
|
|
builder.suggest("rightleg");
|
|
return builder.buildFuture();
|
|
})
|
|
.executes(ClothesCommand::toggleLayer)
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get the clothes ItemStack from player's main hand.
|
|
* Returns null and sends error message if not holding clothes.
|
|
*/
|
|
private static ItemStack getHeldClothes(
|
|
CommandContext<CommandSourceStack> ctx
|
|
) throws CommandSyntaxException {
|
|
ServerPlayer player = ctx.getSource().getPlayerOrException();
|
|
ItemStack held = player.getMainHandItem();
|
|
|
|
if (held.isEmpty() || !(held.getItem() instanceof GenericClothes)) {
|
|
ctx
|
|
.getSource()
|
|
.sendFailure(
|
|
Component.translatable("command.tiedup.clothes.not_holding")
|
|
);
|
|
return null;
|
|
}
|
|
return held;
|
|
}
|
|
|
|
/**
|
|
* /tiedup clothes url set <url>
|
|
*/
|
|
private static int setUrl(CommandContext<CommandSourceStack> ctx)
|
|
throws CommandSyntaxException {
|
|
ItemStack clothes = getHeldClothes(ctx);
|
|
if (clothes == null) return 0;
|
|
|
|
String url = StringArgumentType.getString(ctx, "url");
|
|
|
|
// Basic URL validation
|
|
if (!url.startsWith("https://")) {
|
|
ctx
|
|
.getSource()
|
|
.sendFailure(
|
|
Component.translatable(
|
|
"command.tiedup.clothes.url_must_https"
|
|
)
|
|
);
|
|
return 0;
|
|
}
|
|
|
|
// Check URL length
|
|
if (url.length() > 2048) {
|
|
ctx
|
|
.getSource()
|
|
.sendFailure(
|
|
Component.translatable(
|
|
"command.tiedup.clothes.url_too_long"
|
|
)
|
|
);
|
|
return 0;
|
|
}
|
|
|
|
GenericClothes item = (GenericClothes) clothes.getItem();
|
|
item.setDynamicTextureUrl(clothes, url);
|
|
|
|
ctx
|
|
.getSource()
|
|
.sendSuccess(
|
|
() -> Component.translatable("command.tiedup.clothes.url_set"),
|
|
false
|
|
);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* /tiedup clothes url reset
|
|
*/
|
|
private static int resetUrl(CommandContext<CommandSourceStack> ctx)
|
|
throws CommandSyntaxException {
|
|
ItemStack clothes = getHeldClothes(ctx);
|
|
if (clothes == null) return 0;
|
|
|
|
GenericClothes item = (GenericClothes) clothes.getItem();
|
|
item.removeDynamicTextureUrl(clothes);
|
|
|
|
ctx
|
|
.getSource()
|
|
.sendSuccess(
|
|
() ->
|
|
Component.translatable("command.tiedup.clothes.url_reset"),
|
|
false
|
|
);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* /tiedup clothes fullskin
|
|
*/
|
|
private static int toggleFullSkin(CommandContext<CommandSourceStack> ctx)
|
|
throws CommandSyntaxException {
|
|
ItemStack clothes = getHeldClothes(ctx);
|
|
if (clothes == null) return 0;
|
|
|
|
GenericClothes item = (GenericClothes) clothes.getItem();
|
|
boolean newState = !item.isFullSkinEnabled(clothes);
|
|
item.setFullSkinEnabled(clothes, newState);
|
|
|
|
String stateKey = newState ? "enabled" : "disabled";
|
|
ctx
|
|
.getSource()
|
|
.sendSuccess(
|
|
() ->
|
|
Component.translatable(
|
|
"command.tiedup.clothes.fullskin_" + stateKey
|
|
),
|
|
false
|
|
);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* /tiedup clothes smallarms
|
|
*/
|
|
private static int toggleSmallArms(CommandContext<CommandSourceStack> ctx)
|
|
throws CommandSyntaxException {
|
|
ItemStack clothes = getHeldClothes(ctx);
|
|
if (clothes == null) return 0;
|
|
|
|
GenericClothes item = (GenericClothes) clothes.getItem();
|
|
boolean newState = !item.shouldForceSmallArms(clothes);
|
|
item.setForceSmallArms(clothes, newState);
|
|
|
|
String stateKey = newState ? "enabled" : "disabled";
|
|
ctx
|
|
.getSource()
|
|
.sendSuccess(
|
|
() ->
|
|
Component.translatable(
|
|
"command.tiedup.clothes.smallarms_" + stateKey
|
|
),
|
|
false
|
|
);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* /tiedup clothes keephead
|
|
* When enabled, the wearer's head/hat is preserved instead of being replaced by clothes.
|
|
*/
|
|
private static int toggleKeepHead(CommandContext<CommandSourceStack> ctx)
|
|
throws CommandSyntaxException {
|
|
ItemStack clothes = getHeldClothes(ctx);
|
|
if (clothes == null) return 0;
|
|
|
|
GenericClothes item = (GenericClothes) clothes.getItem();
|
|
boolean newState = !item.isKeepHeadEnabled(clothes);
|
|
item.setKeepHeadEnabled(clothes, newState);
|
|
|
|
String stateKey = newState ? "enabled" : "disabled";
|
|
ctx
|
|
.getSource()
|
|
.sendSuccess(
|
|
() ->
|
|
Component.translatable(
|
|
"command.tiedup.clothes.keephead_" + stateKey
|
|
),
|
|
false
|
|
);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* /tiedup clothes layer <part>
|
|
*/
|
|
private static int toggleLayer(CommandContext<CommandSourceStack> ctx)
|
|
throws CommandSyntaxException {
|
|
ItemStack clothes = getHeldClothes(ctx);
|
|
if (clothes == null) return 0;
|
|
|
|
String part = StringArgumentType.getString(ctx, "part").toLowerCase();
|
|
String layerKey = mapPartToLayerKey(part);
|
|
|
|
if (layerKey == null) {
|
|
ctx
|
|
.getSource()
|
|
.sendFailure(
|
|
Component.translatable(
|
|
"command.tiedup.clothes.unknown_layer",
|
|
part
|
|
)
|
|
);
|
|
return 0;
|
|
}
|
|
|
|
GenericClothes item = (GenericClothes) clothes.getItem();
|
|
boolean newState = !item.isLayerEnabled(clothes, layerKey);
|
|
item.setLayerEnabled(clothes, layerKey, newState);
|
|
|
|
String stateKey = newState ? "visible" : "hidden";
|
|
ctx
|
|
.getSource()
|
|
.sendSuccess(
|
|
() ->
|
|
Component.translatable(
|
|
"command.tiedup.clothes.layer_" + stateKey,
|
|
part
|
|
),
|
|
false
|
|
);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* Map user-friendly part name to NBT layer key.
|
|
*/
|
|
private static String mapPartToLayerKey(String part) {
|
|
return switch (part) {
|
|
case "head" -> GenericClothes.LAYER_HEAD;
|
|
case "body" -> GenericClothes.LAYER_BODY;
|
|
case "leftarm" -> GenericClothes.LAYER_LEFT_ARM;
|
|
case "rightarm" -> GenericClothes.LAYER_RIGHT_ARM;
|
|
case "leftleg" -> GenericClothes.LAYER_LEFT_LEG;
|
|
case "rightleg" -> GenericClothes.LAYER_RIGHT_LEG;
|
|
default -> null;
|
|
};
|
|
}
|
|
}
|