Skip to content

Commit

Permalink
more command helpers and dump tags command
Browse files Browse the repository at this point in the history
  • Loading branch information
UpcraftLP committed Apr 7, 2024
1 parent 197ebdc commit cdf8a69
Show file tree
Hide file tree
Showing 14 changed files with 259 additions and 29 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package dev.upcraft.sparkweave.api.command;

import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
import dev.upcraft.sparkweave.api.platform.Services;
import dev.upcraft.sparkweave.api.platform.services.SparkweaveHelperService;
import net.minecraft.commands.synchronization.ArgumentTypeInfo;
import net.minecraft.network.chat.Component;

public class CommandHelper {

private static final SparkweaveHelperService HELPER = Services.getService(SparkweaveHelperService.class);

public static final DynamicCommandExceptionType IO_EXCEPTION = new DynamicCommandExceptionType(ex -> Component.translatable("commands.sparkweave.error.io_exception", ex instanceof Throwable t ? t.getMessage() : ex));

public static <A extends ArgumentType<?>, T extends ArgumentTypeInfo.Template<A>> ArgumentTypeInfo<A, T> createArgumentInfo(Class<A> clazz, ArgumentTypeInfo<A, T> info) {
return HELPER.create(clazz, info);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dev.upcraft.sparkweave.api.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;
Expand All @@ -8,25 +9,25 @@
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.commands.arguments.ResourceLocationArgument;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;

import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Stream;

public class RegistryArgumentHelper {
public class RegistryArgumentType implements ArgumentType<ResourceLocation> {

private static final DynamicCommandExceptionType REGISTRY_NOT_FOUND = new DynamicCommandExceptionType(x -> Component.translatable("argument.sparkweave.registries.not_found", x));
private static final DynamicCommandExceptionType REGISTRY_NOT_FOUND = new DynamicCommandExceptionType(x -> Component.translatable("argument.sparkweave.registry.not_found", x));
private static final List<String> EXAMPLES = Stream.of(Registries.ITEM, Registries.BLOCK, Registries.BIOME, Registries.BANNER_PATTERN, Registries.CONFIGURED_FEATURE).map(ResourceKey::location).map(ResourceLocation::toString).toList();

public static CompletableFuture<Suggestions> suggestRegistries(CommandContext<CommandSourceStack> ctx, SuggestionsBuilder builder) {
return SharedSuggestionProvider.suggestResource(ctx.getSource().registryAccess().listRegistries().map(ResourceKey::location), builder);
}

public static ArgumentType<ResourceLocation> registryArgument() {
return ResourceLocationArgument.id();
public static RegistryArgumentType registry() {
return new RegistryArgumentType();
}

public static <T> Registry<T> getRegistry(CommandContext<CommandSourceStack> ctx, String name) throws CommandSyntaxException {
Expand All @@ -35,4 +36,22 @@ public static <T> Registry<T> getRegistry(CommandContext<CommandSourceStack> ctx
return optional.orElseThrow(() -> REGISTRY_NOT_FOUND.create(location));
}

@Override
public ResourceLocation parse(StringReader reader) throws CommandSyntaxException {
return ResourceLocation.read(reader);
}

@Override
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
if (context.getSource() instanceof SharedSuggestionProvider provider) {
return SharedSuggestionProvider.suggestResource(provider.registryAccess().listRegistries().map(ResourceKey::location), builder);
}

return builder.buildFuture();
}

@Override
public Collection<String> getExamples() {
return EXAMPLES;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package dev.upcraft.sparkweave.api.platform.services;

import com.mojang.brigadier.arguments.ArgumentType;
import net.minecraft.commands.synchronization.ArgumentTypeInfo;
import net.minecraft.world.item.CreativeModeTab;

public interface SparkweaveHelperService {
Expand All @@ -8,4 +10,9 @@ public interface SparkweaveHelperService {
* @see dev.upcraft.sparkweave.api.item.CreativeTabHelper
*/
CreativeModeTab.Builder newCreativeTabBuilder();

/**
* @see dev.upcraft.sparkweave.api.command.CommandHelper#createArgumentInfo(Class, ArgumentTypeInfo)
*/
<A extends ArgumentType<?>, T extends ArgumentTypeInfo.Template<A>> ArgumentTypeInfo<A, T> create(Class<A> clazz, ArgumentTypeInfo<A, T> info);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
import dev.upcraft.sparkweave.api.command.argument.RegistryArgumentHelper;
import dev.upcraft.sparkweave.SparkweaveMod;
import dev.upcraft.sparkweave.api.command.CommandHelper;
import dev.upcraft.sparkweave.api.command.argument.RegistryArgumentType;
import dev.upcraft.sparkweave.api.platform.Services;
import dev.upcraft.sparkweave.api.serialization.CSVWriter;
import dev.upcraft.sparkweave.logging.SparkweaveLogging;
import net.minecraft.ChatFormatting;
import net.minecraft.commands.CommandBuildContext;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.core.Registry;
Expand All @@ -24,25 +24,24 @@

public class DumpRegistryCommand {

private static final DynamicCommandExceptionType IO_EXCEPTION = new DynamicCommandExceptionType(ex -> Component.translatable("commands.sparkweave.debug.dump_registries.io_exception", ex));

public static void register(LiteralArgumentBuilder<CommandSourceStack> $, CommandBuildContext buildContext) {
public static void register(LiteralArgumentBuilder<CommandSourceStack> $) {
$.then(Commands.literal("dump_registries")
.requires(src -> src.hasPermission(Commands.LEVEL_OWNERS))
.executes(DumpRegistryCommand::dumpAllRegistries)
.then(Commands.argument("registry", RegistryArgumentHelper.registryArgument())
.suggests(RegistryArgumentHelper::suggestRegistries)
.executes(ctx -> dumpRegistry(ctx, RegistryArgumentHelper.getRegistry(ctx, "registry")))
.then(Commands.argument("registry", RegistryArgumentType.registry())
.executes(ctx -> dumpRegistry(ctx, RegistryArgumentType.getRegistry(ctx, "registry")))
)
.then(Commands.literal("all")
.executes(DumpRegistryCommand::dumpAllRegistries))
.executes(DumpRegistryCommand::dumpAllRegistries)
)
);
}

private static int dumpAllRegistries(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
var player = ctx.getSource().getPlayerOrException();
var registryAccess = ctx.getSource().getServer().registries().compositeAccess();
var registries = registryAccess.listRegistries().toList();
var dir = Services.PLATFORM.getGameDir().resolve("sparkweave").resolve("registry_export");
var dir = Services.PLATFORM.getGameDir().resolve(SparkweaveMod.MODID).resolve("registry_export");

for (ResourceKey<? extends Registry<?>> registryKey : registries) {
var registry = registryAccess.registry(registryKey).orElseThrow();
Expand Down Expand Up @@ -76,7 +75,7 @@ private static void saveRegistryToFile(Registry<?> registry, Path outputDir) thr
}
} catch (IOException e) {
SparkweaveLogging.getLogger().error("Failed to write registry dump for {}", registry.key().location(), e);
throw IO_EXCEPTION.create(e.getMessage());
throw CommandHelper.IO_EXCEPTION.create(e.getMessage());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package dev.upcraft.sparkweave.command;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import dev.upcraft.sparkweave.SparkweaveMod;
import dev.upcraft.sparkweave.api.command.CommandHelper;
import dev.upcraft.sparkweave.api.command.argument.RegistryArgumentType;
import dev.upcraft.sparkweave.api.platform.Services;
import net.minecraft.ChatFormatting;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.core.Registry;
import net.minecraft.network.chat.ClickEvent;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.HoverEvent;
import net.minecraft.resources.ResourceKey;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public class DumpTagsCommand {

private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();

public static void register(LiteralArgumentBuilder<CommandSourceStack> $) {
$.then(Commands.literal("dump_tags")
.requires(src -> src.hasPermission(Commands.LEVEL_OWNERS))
.executes(DumpTagsCommand::dumpAllTags)
.then(Commands.argument("type", RegistryArgumentType.registry())
.executes(ctx -> dumpTags(ctx, RegistryArgumentType.getRegistry(ctx, "type")))
)
.then(Commands.literal("all")
.executes(DumpTagsCommand::dumpAllTags)
)
);
}

private static int dumpAllTags(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
var player = ctx.getSource().getPlayerOrException();
var registryAccess = ctx.getSource().getServer().registries().compositeAccess();
var registries = registryAccess.listRegistries().toList();
var dir = Services.PLATFORM.getGameDir().resolve(SparkweaveMod.MODID).resolve("tag_export");

for (ResourceKey<? extends Registry<?>> registryKey : registries) {
var registry = registryAccess.registry(registryKey).orElseThrow();
saveTags(registry, dir);
}

if (ctx.getSource().getServer().isSingleplayerOwner(player.getGameProfile())) {
var path = Component.literal(dir.toString()).withStyle(style -> style
.applyFormats(ChatFormatting.BLUE, ChatFormatting.UNDERLINE)
.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("chat.sparkweave.open_folder")))
.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_FILE, dir.toString()))
);

//TODO directly send to client to bypass message click event filtering
ctx.getSource().sendSuccess(() -> Component.translatable("commands.sparkweave.debug.dump_tags.multi_success_path", registries.size(), path), true);
} else {
ctx.getSource().sendSuccess(() -> Component.translatable("commands.sparkweave.debug.dump_tags.multi_success", registries.size()), true);
}

return registries.size();
}

private static void saveTags(Registry<?> registry, Path dir) throws CommandSyntaxException {
Path rootDir = dir.resolve(registry.key().location().getNamespace()).resolve(registry.key().location().getPath());

var tags = registry.getTags().toList();
for (var tagPair : tags) {
var name = tagPair.getFirst().location();
var outputFile = rootDir.resolve(name.getNamespace()).resolve(name.getPath() + ".json");

var json = new JsonObject();
var array = new JsonArray();
tagPair.getSecond().stream()
.map(holder -> holder.unwrap().map(k -> k.location().toString(), Object::toString))
.forEach(array::add);
json.add("values", array);

try {
Files.createDirectories(outputFile.getParent());
try (var writer = Files.newBufferedWriter(outputFile)) {
GSON.toJson(json, writer);
}
} catch (IOException e) {
throw CommandHelper.IO_EXCEPTION.create(e);
}
}
}

private static int dumpTags(CommandContext<CommandSourceStack> ctx, Registry<?> registry) throws CommandSyntaxException {
var player = ctx.getSource().getPlayerOrException();

var dir = Services.PLATFORM.getGameDir().resolve("sparkweave").resolve("tag_export");
saveTags(registry, dir);

if (ctx.getSource().getServer().isSingleplayerOwner(player.getGameProfile())) {
var resolvedDir = dir.resolve(registry.key().location().getNamespace()).resolve(registry.key().location().getPath()).toString();
var path = Component.literal(resolvedDir).withStyle(style -> style
.applyFormats(ChatFormatting.BLUE, ChatFormatting.UNDERLINE)
.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("chat.sparkweave.open_folder")))
.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_FILE, resolvedDir))
);

//TODO directly send to client to bypass message click event filtering
ctx.getSource().sendSuccess(() -> Component.translatable("commands.sparkweave.debug.dump_tags.success_path", registry.key().location(), path), true);
} else {
ctx.getSource().sendSuccess(() -> Component.translatable("commands.sparkweave.debug.dump_tags.success", registry.key().location()), true);
}
return 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ public class SparkweaveCommandRoot {

public static void register(CommandDispatcher<CommandSourceStack> dispatcher, CommandBuildContext buildContext, Commands.CommandSelection environment) {
var root = Commands.literal(SparkweaveMod.MODID);
var debug = Commands.literal("debug");
var debug = Commands.literal("debug").requires(src -> src.hasPermission(Commands.LEVEL_ADMINS));

DumpRegistryCommand.register(debug, buildContext);
DumpRegistryCommand.register(debug);
DumpTagsCommand.register(debug);

root.then(debug);
dispatcher.register(root);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package dev.upcraft.sparkweave.registry;

import dev.upcraft.sparkweave.SparkweaveMod;
import dev.upcraft.sparkweave.api.command.CommandHelper;
import dev.upcraft.sparkweave.api.command.argument.RegistryArgumentType;
import dev.upcraft.sparkweave.api.registry.RegistryHandler;
import dev.upcraft.sparkweave.api.registry.RegistrySupplier;
import net.minecraft.commands.synchronization.ArgumentTypeInfo;
import net.minecraft.commands.synchronization.SingletonArgumentInfo;
import net.minecraft.core.registries.Registries;

public class SparkweaveCommandArgumentTypes {

public static final RegistryHandler<ArgumentTypeInfo<?, ?>> ARGUMENT_TYPES = RegistryHandler.create(Registries.COMMAND_ARGUMENT_TYPE, SparkweaveMod.MODID);

public static final RegistrySupplier<ArgumentTypeInfo<RegistryArgumentType, ?>> REGISTRY = ARGUMENT_TYPES.register("registry", () -> CommandHelper.createArgumentInfo(RegistryArgumentType.class, SingletonArgumentInfo.contextFree(RegistryArgumentType::registry)));
}
8 changes: 6 additions & 2 deletions Common/src/main/resources/assets/sparkweave/lang/en_us.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
{
"argument.sparkweave.registries.not_found": "Registry not found: %s",
"argument.sparkweave.registry.not_found": "Registry not found: %s",
"chat.sparkweave.open_folder": "Click to view in File Explorer",
"commands.sparkweave.debug.dump_registries.io_exception": "An IO error occurred while dumping registries: %s",
"commands.sparkweave.error.io_exception": "An IO error occurred while performing the command: %s",
"commands.sparkweave.debug.dump_tags.success": "Successfully exported tags for registry %s",
"commands.sparkweave.debug.dump_tags.success_path": "Successfully exported tags for registry %s to %s",
"commands.sparkweave.debug.dump_tags.multi_success": "Successfully exported tags for %s registries",
"commands.sparkweave.debug.dump_tags.multi_success_path": "Successfully exported tags for %s registries to %s",
"commands.sparkweave.debug.dump_registries.success": "Successfully exported registry %s",
"commands.sparkweave.debug.dump_registries.success_path": "Successfully exported registry %s to %s",
"commands.sparkweave.debug.dump_registries.multi_success": "Successfully exported %s registries",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
import dev.upcraft.sparkweave.api.entrypoint.ClientEntryPoint;
import dev.upcraft.sparkweave.api.entrypoint.DedicatedServerEntryPoint;
import dev.upcraft.sparkweave.api.entrypoint.MainEntryPoint;
import dev.upcraft.sparkweave.api.platform.services.RegistryService;
import dev.upcraft.sparkweave.api.registry.block.BlockItemProvider;
import dev.upcraft.sparkweave.entrypoint.EntrypointHelper;
import dev.upcraft.sparkweave.logging.SparkweaveLogging;
import dev.upcraft.sparkweave.registry.SparkweaveCommandArgumentTypes;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.neoforged.bus.api.IEventBus;
Expand All @@ -23,21 +25,26 @@ public class Main {
public Main(IEventBus bus) {
bus.register(this);

var helper = RegistryService.get();
SparkweaveCommandArgumentTypes.ARGUMENT_TYPES.accept(helper);

EntrypointHelper.fireEntrypoints(MainEntryPoint.class, MainEntryPoint::onInitialize);

switch (FMLEnvironment.dist) {
case CLIENT -> EntrypointHelper.fireEntrypoints(ClientEntryPoint.class, ClientEntryPoint::onInitializeClient);
case DEDICATED_SERVER -> EntrypointHelper.fireEntrypoints(DedicatedServerEntryPoint.class, DedicatedServerEntryPoint::onInitializeServer);
case CLIENT ->
EntrypointHelper.fireEntrypoints(ClientEntryPoint.class, ClientEntryPoint::onInitializeClient);
case DEDICATED_SERVER ->
EntrypointHelper.fireEntrypoints(DedicatedServerEntryPoint.class, DedicatedServerEntryPoint::onInitializeServer);
}

SparkweaveLogging.getLogger().debug("System initialized!");
}

@SubscribeEvent
public void processBlockItems(RegisterEvent event) {
if(event.getRegistryKey() == Registries.ITEM) {
if (event.getRegistryKey() == Registries.ITEM) {
BuiltInRegistries.BLOCK.entrySet().forEach(entry -> {
if(entry.getValue() instanceof BlockItemProvider provider) {
if (entry.getValue() instanceof BlockItemProvider provider) {
event.register(Registries.ITEM, entry.getKey().location(), provider::createItem);
}
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package dev.upcraft.sparkweave.neoforge.service;

import com.mojang.brigadier.arguments.ArgumentType;
import dev.upcraft.sparkweave.api.annotation.CalledByReflection;
import dev.upcraft.sparkweave.api.platform.services.SparkweaveHelperService;
import net.minecraft.commands.synchronization.ArgumentTypeInfo;
import net.minecraft.commands.synchronization.ArgumentTypeInfos;
import net.minecraft.world.item.CreativeModeTab;

public class NeoHelperService implements SparkweaveHelperService {
Expand All @@ -15,4 +18,9 @@ public NeoHelperService() {
public CreativeModeTab.Builder newCreativeTabBuilder() {
return CreativeModeTab.builder();
}

@Override
public <A extends ArgumentType<?>, T extends ArgumentTypeInfo.Template<A>> ArgumentTypeInfo<A, T> create(Class<A> clazz, ArgumentTypeInfo<A, T> info) {
return ArgumentTypeInfos.registerByClass(clazz, info);
}
}
Loading

0 comments on commit cdf8a69

Please sign in to comment.