Skip to content

Commit

Permalink
Implement modifier priority command
Browse files Browse the repository at this point in the history
Ths commit introduces a subcommand "/tconstruct report" for "/tconstruct report modifier_priority", it also moves modifier_usage to be a subcommand of the same (which will make it nicer to tab complete "/tconstruct modifiers"
Useful for determining the order things with the same hook will run. Unfortuantely will have limited benefits until 1.19 when modifier hooks are mandatory (as the report won't show overrides of non-modiifer hooks)
  • Loading branch information
KnightMiner committed Mar 10, 2024
1 parent 50def7e commit 563cb6b
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
Expand All @@ -14,6 +15,8 @@ private ModifierHooks() {}

/** Map of ID to hook */
private static final Map<ResourceLocation,ModifierHook<?>> HOOKS = new ConcurrentHashMap<>();
/** Unmodifiable view of the hook map */
private static final Collection<ResourceLocation> HOOK_IDS = Collections.unmodifiableCollection(HOOKS.keySet());


/* Registry */
Expand Down Expand Up @@ -67,4 +70,9 @@ public static <T> ModifierHook<T> register(ResourceLocation name, Class<T> filte
public static <T> ModifierHook<T> register(ResourceLocation name, Class<T> filter, T defaultInstance) {
return register(name, filter, defaultInstance, null);
}

/** Gets an unmodifiable view of the list of all registered hooks */
public static Collection<ResourceLocation> listAllIDs() {
return HOOK_IDS;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
import slimeknights.tconstruct.TConstruct;
import slimeknights.tconstruct.shared.command.argument.MaterialArgument;
import slimeknights.tconstruct.shared.command.argument.ModifierArgument;
import slimeknights.tconstruct.shared.command.argument.ModifierHookArgument;
import slimeknights.tconstruct.shared.command.argument.SlotTypeArgument;
import slimeknights.tconstruct.shared.command.argument.ToolStatArgument;
import slimeknights.tconstruct.shared.command.subcommand.GeneratePartTexturesCommand;
import slimeknights.tconstruct.shared.command.subcommand.ModifierPriorityCommand;
import slimeknights.tconstruct.shared.command.subcommand.ModifierUsageCommand;
import slimeknights.tconstruct.shared.command.subcommand.ModifiersCommand;
import slimeknights.tconstruct.shared.command.subcommand.SlotsCommand;
Expand All @@ -28,6 +30,7 @@ public static void init() {
ArgumentTypes.register(TConstruct.resourceString("tool_stat"), ToolStatArgument.class, new EmptyArgumentSerializer<>(ToolStatArgument::stat));
ArgumentTypes.register(TConstruct.resourceString("modifier"), ModifierArgument.class, new EmptyArgumentSerializer<>(ModifierArgument::modifier));
ArgumentTypes.register(TConstruct.resourceString("material"), MaterialArgument.class, new EmptyArgumentSerializer<>(MaterialArgument::material));
ArgumentTypes.register(TConstruct.resourceString("modifier_hook"), ModifierHookArgument.class, new EmptyArgumentSerializer<>(ModifierHookArgument::modifierHook));

// add command listener
MinecraftForge.EVENT_BUS.addListener(TConstructCommand::registerCommand);
Expand All @@ -48,7 +51,10 @@ private static void registerCommand(RegisterCommandsEvent event) {
register(builder, "modifiers", ModifiersCommand::register);
register(builder, "tool_stats", StatsCommand::register);
register(builder, "slots", SlotsCommand::register);
register(builder, "modifier_usage", ModifierUsageCommand::register);
register(builder, "report", b -> {
register(b, "modifier_usage", ModifierUsageCommand::register);
register(b, "modifier_priority", ModifierPriorityCommand::register);
});
register(builder, "generate_part_textures", GeneratePartTexturesCommand::register);

// register final command
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package slimeknights.tconstruct.shared.command.argument;

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.DynamicCommandExceptionType;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import lombok.NoArgsConstructor;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.resources.ResourceLocation;
import slimeknights.tconstruct.TConstruct;
import slimeknights.tconstruct.library.modifiers.ModifierHook;
import slimeknights.tconstruct.library.modifiers.ModifierHooks;

import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.CompletableFuture;

/** Argument type for a modifier */
@NoArgsConstructor(staticName = "modifierHook")
public class ModifierHookArgument implements ArgumentType<ModifierHook<?>> {
private static final Collection<String> EXAMPLES = Arrays.asList("tconstruct:tool_stats", "tconstruct:tooltip");
private static final DynamicCommandExceptionType HOOK_NOT_FOUND = new DynamicCommandExceptionType(name -> TConstruct.makeTranslation("command", "modifier_hook.not_found", name));

@Override
public ModifierHook<?> parse(StringReader reader) throws CommandSyntaxException {
ResourceLocation loc = ResourceLocation.read(reader);
ModifierHook<?> hook = ModifierHooks.getHook(loc);
if (hook == null) {
throw HOOK_NOT_FOUND.create(loc);
}
return hook;
}

/** Gets a modifier from the command context */
public static ModifierHook<?> getModifier(CommandContext<CommandSourceStack> context, String name) {
return context.getArgument(name, ModifierHook.class);
}

@Override
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
return SharedSuggestionProvider.suggestResource(ModifierHooks.listAllIDs(), builder);
}

@Override
public Collection<String> getExamples() {
return EXAMPLES;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package slimeknights.tconstruct.shared.command.subcommand;

import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.common.util.TablePrinter;
import slimeknights.mantle.command.MantleCommand;
import slimeknights.tconstruct.TConstruct;
import slimeknights.tconstruct.library.modifiers.Modifier;
import slimeknights.tconstruct.library.modifiers.ModifierHook;
import slimeknights.tconstruct.library.modifiers.ModifierManager;
import slimeknights.tconstruct.shared.command.argument.ModifierHookArgument;

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/** Command to list priorities for all modifiers */
public class ModifierPriorityCommand {
private static final Component SUCCESS = new TranslatableComponent("command.tconstruct.modifier_priority");

/**
* Registers this sub command with the root command
* @param subCommand Command builder
*/
public static void register(LiteralArgumentBuilder<CommandSourceStack> subCommand) {
subCommand.requires(sender -> sender.hasPermission(MantleCommand.PERMISSION_EDIT_SPAWN))
// no argument: list all priorities
.executes(context -> run(context, false))
// argument: list only priorities of modifiers using that hook
.then(Commands.argument("modifier_hook", ModifierHookArgument.modifierHook())
.executes(context -> run(context, true)));
}

/**
* Runs the command
* @param context Command context
* @param filtered If true, filter the modifiers based on the hook argument
* @return Number of modifiers that are in the output table
*/
private static int run(CommandContext<CommandSourceStack> context, boolean filtered) {
// common table properties
TablePrinter<Modifier> table = new TablePrinter<>();
table.header("ID", m -> m.getId().toString());
table.header("Priority", m -> Integer.toString(m.getPriority()));
Stream<Modifier> modifiers = ModifierManager.INSTANCE.getAllValues();
StringBuilder builder = new StringBuilder();
builder.append("Modifier Priorities");

// if filtered, show fewer modifiers and add to the log name
if (filtered) {
ModifierHook<?> filter = ModifierHookArgument.getModifier(context, "modifier_hook");
modifiers = modifiers.filter(m -> m.getHooks().hasHook(filter));
builder.append(" for ").append(filter.getName());
} else {
// if not filtered, include a row listing all used hooks
table.header("Hooks", m -> m.getHooks().getAllModules().keySet().stream().map(ModifierHook::getName).sorted().map(ResourceLocation::toString).collect(Collectors.joining(", ")));
}
builder.append(":").append(System.lineSeparator());
List<Modifier> list = modifiers.sorted(Comparator.comparingInt(Modifier::getPriority).reversed().thenComparing(Modifier::getId)).toList();
table.add(list);

table.build(builder);
TConstruct.LOG.info(builder.toString());
context.getSource().sendSuccess(SUCCESS, true);
return list.size();
}
}
2 changes: 2 additions & 0 deletions src/main/resources/assets/tconstruct/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -2787,7 +2787,9 @@
"command.tconstruct.stat_type.wrong_type": "Invalid stat type %s, must inherit from %s",
"command.tconstruct.material.not_found": "Unknown material %s",
"command.tconstruct.modifier.not_found": "Unknown modifier %s",
"command.tconstruct.modifier_hook.not_found": "Unknown modifier hook %s",
"command.tconstruct.modifier_usage": "Successfully printed modifier usage to the game log",
"command.tconstruct.modifier_priority": "Successfully printed modifier priorities to the game log",

"command.tconstruct.modifiers.success.add.single": "Applied modifier %s to %s's item",
"command.tconstruct.modifiers.success.add.multiple": "Applied modifier %s to %s entities",
Expand Down

0 comments on commit 563cb6b

Please sign in to comment.