Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support custom output paths, better item selection, "Headless" Rendering #101

Open
wants to merge 1 commit into
base: 1.20
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
import com.glisco.isometricrenders.screen.RenderScreen;
import com.glisco.isometricrenders.screen.ScreenScheduler;
import com.glisco.isometricrenders.util.AreaSelectionHelper;
import com.glisco.isometricrenders.util.InstantRenderer;
import com.glisco.isometricrenders.util.OutputPathBuilder;
import com.glisco.isometricrenders.util.Translate;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.BoolArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
Expand All @@ -22,6 +25,7 @@
import net.minecraft.command.CommandSource;
import net.minecraft.command.argument.*;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.decoration.ItemFrameEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
Expand Down Expand Up @@ -78,8 +82,22 @@ public static void register(CommandDispatcher<FabricClientCommandSource> dispatc
.executes(IsorenderCommand::renderPlayerWithNbt))))
.then(literal("item")
.executes(IsorenderCommand::renderHeldItem)
.then(literal("selection")
.then(argument("folder", StringArgumentType.string())
.then(argument("name", StringArgumentType.string())
.executes(IsorenderCommand::renderItemWithNbtAndOutput))
)
.then(argument("folder", StringArgumentType.string())
.then(argument("name", StringArgumentType.string())
.then(argument("silent", BoolArgumentType.bool())
.executes(IsorenderCommand::renderItemWithNbtAndOutput))
)))
.then(argument("item", ItemStackArgumentType.itemStack(access))
.executes(IsorenderCommand::renderItemWithArgument)))
.executes(IsorenderCommand::renderItemWithArgument)
.then(argument("folder", StringArgumentType.string())
.then(argument("name", StringArgumentType.string())
.executes(IsorenderCommand::renderItemWithArgumentAndOutput))
)))
.then(literal("tooltip")
.executes(IsorenderCommand::renderHeldItemTooltip)
.then(argument("item", ItemStackArgumentType.itemStack(access))
Expand Down Expand Up @@ -219,6 +237,56 @@ private static int renderItemWithArgument(CommandContext<FabricClientCommandSour
return 0;
}

private static ItemStack getItemToRender() {
MinecraftClient client = MinecraftClient.getInstance();
ItemStack item = client.player.getMainHandStack();

if (item.isEmpty()) {
// Attempt to get item from targeted ItemFrame
ItemFrameEntity itemFrame = client.targetedEntity instanceof ItemFrameEntity ?
(ItemFrameEntity) client.targetedEntity : null;
if (itemFrame != null) {
item = itemFrame.getHeldItemStack();
}
}

return item.isEmpty() ? null : item;
}

private static void render(ItemRenderable renderable, CommandContext<FabricClientCommandSource> context) {
boolean renderSilent;
try {
renderSilent = BoolArgumentType.getBool(context, "silent");
} catch (Exception e) {
renderSilent = false;
}
if (renderSilent) {
InstantRenderer.render(renderable);
} else {
ScreenScheduler.schedule(new RenderScreen(renderable));
}
}

private static int renderItemWithNbtAndOutput(CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException {
ItemStack item = getItemToRender();
ItemRenderable renderable = new ItemRenderable(item);
OutputPathBuilder builder = new OutputPathBuilder(renderable, context);
String result = builder.appendToRenderable();
if (result != null) {
return 1;
}
render(renderable, context);
return 0;
}

private static int renderItemWithArgumentAndOutput(CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException {
ItemRenderable renderable = new ItemRenderable(ItemStackArgumentType.getItemStackArgument(context, "item").createStack(1, false));
OutputPathBuilder builder = new OutputPathBuilder(renderable, context);
builder.appendToRenderable();
render(renderable, context);
return 0;
}

private static int renderHeldItem(CommandContext<FabricClientCommandSource> context) {
ScreenScheduler.schedule(new RenderScreen(
new ItemRenderable(MinecraftClient.getInstance().player.getMainHandStack())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,14 @@ public class ItemRenderable extends DefaultRenderable<DefaultPropertyBundle> {
}

private final ItemStack stack;
private ExportPathSpec exportPath;

public ItemRenderable(ItemStack stack) {
this.stack = stack;
this.exportPath = ExportPathSpec.ofIdentified(
Registries.ITEM.getId(this.stack.getItem()),
"item"
);
}

@Override
Expand Down Expand Up @@ -58,9 +63,14 @@ public DefaultPropertyBundle properties() {

@Override
public ExportPathSpec exportPath() {
return ExportPathSpec.ofIdentified(
Registries.ITEM.getId(this.stack.getItem()),
"item"
);
return this.exportPath;
}

public ItemStack stack(){
return this.stack;
}

public void exportPath(String rootOffset, String path){
this.exportPath = ExportPathSpec.forced(rootOffset, path);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.glisco.isometricrenders.util;

import com.glisco.isometricrenders.render.Renderable;
import com.glisco.isometricrenders.render.RenderableDispatcher;

import static com.glisco.isometricrenders.property.GlobalProperties.exportResolution;

public class InstantRenderer {
public static void render(Renderable<?> renderable){
ImageIO.save(
RenderableDispatcher.drawIntoImage(renderable, 0, exportResolution),
renderable.exportPath()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package com.glisco.isometricrenders.util;

import com.glisco.isometricrenders.render.ItemRenderable;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import org.jetbrains.annotations.Nullable;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class OutputPathBuilder {
private final ItemRenderable renderable;
private final String rawFolder;
private final String rawName;

public OutputPathBuilder(ItemRenderable renderable, CommandContext<FabricClientCommandSource> context){
this.renderable = renderable;
this.rawFolder = StringArgumentType.getString(context, "folder").replaceAll("\\.", "/");
this.rawName = StringArgumentType.getString(context, "name");
}

public ItemRenderable renderable(){
return renderable;
}

@Nullable
public String appendToRenderable(){
String nbtData = renderable.stack().getNbt() != null ? renderable.stack().getNbt().asString() : "{}";

Pattern pattern = Pattern.compile("\\{NBT:([a-zA-Z0-9.\\[\\]]+)\\}");

try{
String name = replaceNBTPlaceholders(rawName, nbtData, pattern);
renderable.exportPath(rawFolder, name);
return null;
}catch (IllegalArgumentException iae){
return iae.getMessage();
}
}

private static String replaceNBTPlaceholders(String s, String nbtData, Pattern pattern) {
Matcher matcher = pattern.matcher(s);

while (matcher.find()) {
String fullPath = matcher.group(0);
String path = matcher.group(1);
String value = getValueFromNBTByPath(nbtData, path);
s = s.replace(fullPath, value);
}

return s;
}

private static String getValueFromNBTByPath(String nbtJson, String path) {
JsonElement je = JsonParser.parseString(nbtJson);

for (String part : path.split("\\.")) {

if (part.matches(".+\\[\\d+\\]")) {

int leftBracketIndex = part.indexOf("[");
int rightBracketIndex = part.indexOf("]");

if (je.isJsonObject() && je.getAsJsonObject().has(part.substring(0, leftBracketIndex))) {
je = je.getAsJsonObject().get(part.substring(0, leftBracketIndex)); // get the array
} else {
throw new IllegalArgumentException("No such field exists in the nbt data: " + part);
}

int index;
try {
index = Integer.parseInt(part.substring(leftBracketIndex + 1, rightBracketIndex)); // get index
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid index value for nbt part: " + part);
}

if (je.isJsonArray() && je.getAsJsonArray().size() > index) {
je = je.getAsJsonArray().get(index); // get value at index
} else {
throw new IllegalArgumentException("Array index out of bound for nbt part: " + part);
}

} else {
if (je.isJsonObject() && je.getAsJsonObject().has(part)) {
je = je.getAsJsonObject().get(part);
} else {
throw new IllegalArgumentException("No such field exists in the nbt data: " + part);
}
}
}

return je.getAsString();
}
}