package shcm.shsupercm.fabric.citresewn; import com.mojang.brigadier.LiteralMessage; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.text.Text; import shcm.shsupercm.fabric.citresewn.cit.*; import shcm.shsupercm.fabric.citresewn.config.CITResewnConfig; import shcm.shsupercm.fabric.citresewn.pack.format.PropertyKey; import shcm.shsupercm.fabric.citresewn.pack.format.PropertyValue; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument; import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; import static net.minecraft.text.Text.of; /** * Logic for the /citresewn client command. Only enabled when Fabric API is present.<br> * Structure: * <pre> * /citresewn - General info command * /citresewn config - Opens the config gui(only when Cloth Config is present) * /citresewn analyze pack <pack> - Displays data for the given loaded cit pack. * </pre> */ public class CITResewnCommand { /** * @see shcm.shsupercm.fabric.citresewn.mixin.ChatScreenMixin */ public static boolean openConfig = false; /** * Registers all of CIT Resewn's commands. */ public static void register() { ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> { dispatcher.register( ClientCommandManager.literal("citresewn").executes(context -> { context.getSource().sendFeedback(of("CIT Resewn v" + FabricLoader.getInstance().getModContainer("citresewn").orElseThrow().getMetadata().getVersion() + ":")); context.getSource().sendFeedback(of(" Registered: " + CITRegistry.TYPES.values().stream().distinct().count() + " types and " + CITRegistry.CONDITIONS.values().stream().distinct().count() + " conditions")); final boolean active = CITResewnConfig.INSTANCE.enabled && ActiveCITs.isActive(); context.getSource().sendFeedback(of(" Active: " + (active ? "yes" : ("no, " + (CITResewnConfig.INSTANCE.enabled ? "no cit packs loaded" : "disabled in config"))))); if (active) { context.getSource().sendFeedback(of(" Loaded: " + ActiveCITs.getActive().cits.values().stream().mapToLong(Collection::size).sum() + " CITs from " + ActiveCITs.getActive().cits.values().stream().flatMap(Collection::stream).map(cit -> cit.packName).distinct().count() + " resourcepacks")); } context.getSource().sendFeedback(of("")); return 1; }) .then(literal("config") .executes(context -> { //citresewn config openConfig = true; return 1; })) .then(literal("analyze") .then(literal("pack") .then(argument("pack", new LoadedCITPackArgument()) .executes(context -> { //citresewn analyze <pack> final String pack = context.getArgument("pack", String.class); if (ActiveCITs.isActive()) { context.getSource().sendFeedback(of("Analyzed CIT data of \"" + pack + "\u00a7r\":")); List<Text> builder = new ArrayList<>(); for (Map.Entry<PropertyKey, Set<PropertyValue>> entry : ActiveCITs.getActive().globalProperties.properties.entrySet()) for (PropertyValue value : entry.getValue()) if (value.packName().equals(pack)) builder.add(of(" " + entry.getKey().toString() + (value.keyMetadata() == null ? "" : "." + value.keyMetadata()) + " = " + value.value())); if (!builder.isEmpty()) { context.getSource().sendFeedback(of(" Global Properties:")); for (Text text : builder) context.getSource().sendFeedback(text); builder.clear(); } for (Map.Entry<Class<? extends CITType>, List<CIT<?>>> entry : ActiveCITs.getActive().cits.entrySet()) if (!entry.getValue().isEmpty()) { long count = entry.getValue().stream().filter(cit -> cit.packName.equals(pack)).count(); if (count > 0) builder.add(of(" " + CITRegistry.idOfType(entry.getKey()).toString() + " = " + count)); } if (!builder.isEmpty()) { context.getSource().sendFeedback(of(" Types:")); for (Text text : builder) context.getSource().sendFeedback(text); builder.clear(); } List<CITCondition> conditions = ActiveCITs.getActive().cits.values().stream() .flatMap(Collection::stream) .filter(cit -> cit.packName.equals(pack)) .flatMap(cit -> Arrays.stream(cit.conditions)) .toList(); if (!conditions.isEmpty()) context.getSource().sendFeedback(of(" Utilizing " + conditions.size() + " conditions(" + conditions.stream().map(Object::getClass).distinct().count() + " unique condition types)")); } else context.getSource().sendFeedback(of("Not active")); return 1; }) ) ) ) ); }); } /** * Greedy string argument that is limited to cit pack names loaded in {@link shcm.shsupercm.fabric.citresewn.cit.ActiveCITs}. */ private static class LoadedCITPackArgument implements ArgumentType<String> { @Override public String parse(StringReader reader) throws CommandSyntaxException { StringBuilder builder = new StringBuilder(); while (reader.canRead()) builder.append(reader.read()); String pack = builder.toString().trim(); if (!getPacks().contains(pack)) { LiteralMessage message = new LiteralMessage("Could not find CIT pack"); throw new CommandSyntaxException(new SimpleCommandExceptionType(message), message); } return pack; } @Override public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) { return CompletableFuture.supplyAsync(() -> { for (String pack : getPacks()) { builder.suggest(pack); } return builder.build(); }); } private static Set<String> getPacks() { if (ActiveCITs.isActive()) return ActiveCITs.getActive().cits.values().stream() .flatMap(Collection::stream) .map(cit -> cit.packName) .collect(Collectors.toSet()); else return Collections.emptySet(); } } }