Skip to content

Commit

Permalink
Add possibility of dumping all resources to the file system
Browse files Browse the repository at this point in the history
Signed-off-by: TheSilkMiner <thesilkminer@outlook.com>
  • Loading branch information
TheSilkMiner committed Jul 21, 2022
1 parent ecc9510 commit 4450d8c
Showing 1 changed file with 51 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@
import com.blamejared.contenttweaker.core.ContentTweakerCore;
import com.blamejared.contenttweaker.core.api.ContentTweakerConstants;
import com.blamejared.contenttweaker.core.api.resource.ResourceFragment;
import com.blamejared.contenttweaker.core.service.ServiceManager;
import com.blamejared.crafttweaker.api.CraftTweakerAPI;
import com.blamejared.crafttweaker.api.command.CommandUtilities;
import com.blamejared.crafttweaker.api.plugin.ICommandRegistrationHandler;
import com.google.common.base.Suppliers;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import net.minecraft.ChatFormatting;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.server.packs.PackType;

Expand All @@ -18,6 +23,7 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.DosFileAttributes;
import java.util.ArrayList;
Expand All @@ -26,18 +32,20 @@
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Supplier;

public final class RuntimeResourceDumpingCommand {
private record VisitResult(Path path, String name) {}

private static final class ResourceVisitor extends SimpleFileVisitor<Path> {
private final Path root;
private final ResourceFragment.Key key;
private final Consumer<Path> pathConsumer;

ResourceVisitor(final Path root, final ResourceFragment.Key key, final Consumer<String> stringConsumer) {
ResourceVisitor(final Path root, final ResourceFragment.Key key, final Consumer<VisitResult> resultConsumer) {
this.root = root;
this.key = key;
this.pathConsumer = path -> this.pathToName(path, stringConsumer);
this.pathConsumer = path -> this.pathToName(path, resultConsumer);
}

@Override
Expand All @@ -57,30 +65,49 @@ public FileVisitResult visitFile(final Path file, final BasicFileAttributes attr
return FileVisitResult.CONTINUE;
}

private void pathToName(final Path path, final Consumer<String> stringConsumer) {
private void pathToName(final Path path, final Consumer<VisitResult> resultConsumer) {
final Path absolute = path.toAbsolutePath().normalize();
final Path targetPath = this.root.relativize(path.toAbsolutePath().normalize()).normalize();
stringConsumer.accept("%s/%s/%s".formatted(this.key.type().getDirectory(), this.key.id(), targetPath));
resultConsumer.accept(new VisitResult(absolute, "%s/%s/%s".formatted(this.key.type().getDirectory(), this.key.id(), targetPath)));
}
}

// TODO("Find a suitable directory")
private static final Supplier<Path> DUMP_ROOT = Suppliers.memoize(() -> ServiceManager.platform().gameDirectory().resolve("./ct_dumps/contenttweaker_resources"));

private RuntimeResourceDumpingCommand() {}

public static void register(final ICommandRegistrationHandler handler) {
handler.registerDump(
"contenttweaker_resources",
new TranslatableComponent(ContentTweakerConstants.ln("command.dump_resources.desc")),
it -> it.requires(p -> p.hasPermission(2)).executes(RuntimeResourceDumpingCommand::execute)
RuntimeResourceDumpingCommand::buildCommand
);
}

private static int execute(final CommandContext<CommandSourceStack> context) {
private static void buildCommand(final LiteralArgumentBuilder<CommandSourceStack> builder) {
builder.requires(p -> p.hasPermission(2))
.then(Commands.literal("log").executes(RuntimeResourceDumpingCommand::executeLog))
.then(Commands.literal("file").executes(RuntimeResourceDumpingCommand::executeFile))
.executes(RuntimeResourceDumpingCommand::executeLog);
}

private static int executeLog(final CommandContext<CommandSourceStack> context) {
return execute(context, CraftTweakerAPI.LOGGER::info);
}

private static int executeFile(final CommandContext<CommandSourceStack> context) {
return execute(context, RuntimeResourceDumpingCommand::write);
}

private static int execute(final CommandContext<CommandSourceStack> context, final Consumer<VisitResult> executor) {
Arrays.stream(PackType.values())
.map(ContentTweakerCore.core().resourceManager()::fragments)
.map(Map::values)
.flatMap(Collection::stream)
.map(RuntimeResourceDumpingCommand::dumpFragment)
.map(RuntimeResourceDumpingCommand::gatherFragment)
.flatMap(Collection::stream)
.forEach(CraftTweakerAPI.LOGGER::info);
.forEach(executor);

CommandUtilities.send(
CommandUtilities.openingLogFile(
Expand All @@ -92,23 +119,34 @@ private static int execute(final CommandContext<CommandSourceStack> context) {
context.getSource()
);

return 1;
return Command.SINGLE_SUCCESS;
}

private static List<String> dumpFragment(final RuntimeFragment fragment) {
private static List<VisitResult> gatherFragment(final RuntimeFragment fragment) {
final ResourceFragment.Key key = fragment.key();
final List<String> outer = new ArrayList<>();
final List<VisitResult> outer = new ArrayList<>();
fragment.fs()
.getRootDirectories()
.forEach(root -> dumpRoot(root, outer, key));
.forEach(root -> gatherFromRoot(root, outer, key));
return outer;
}

private static void dumpRoot(final Path root, final List<String> outer, final ResourceFragment.Key key) {
private static void gatherFromRoot(final Path root, final List<VisitResult> outer, final ResourceFragment.Key key) {
try {
Files.walkFileTree(root, new ResourceVisitor(root, key, outer::add));
} catch (final IOException e) {
throw new UncheckedIOException(e);
}
}

private static void write(final VisitResult result) {
try {
final Path dumpPath = DUMP_ROOT.get().resolve(result.name());
final Path parent = dumpPath.getParent();
Files.createDirectories(parent);
Files.copy(result.path(), dumpPath, StandardCopyOption.REPLACE_EXISTING);
} catch (final IOException e) {
CraftTweakerAPI.LOGGER.error(() -> "Unable to correctly dump resource %s due to an error".formatted(result.name()), e);
}
}
}

0 comments on commit 4450d8c

Please sign in to comment.