Skip to content

Commit

Permalink
Added helper methods to get item/fluid/blockstate web icons, fixed it…
Browse files Browse the repository at this point in the history
…em/fluid components
  • Loading branch information
LatvianModder committed Aug 18, 2024
1 parent c2a14e3 commit 6d6a63a
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@

import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -102,6 +99,11 @@ static DataComponentType<?> wrapType(Object object) {

static DataComponentMap readMap(DynamicOps<Tag> registryOps, StringReader reader) throws CommandSyntaxException {
reader.skipWhitespace();

if (!reader.canRead()) {
return DataComponentMap.EMPTY;
}

DataComponentMap.Builder builder = null;

if (reader.canRead() && reader.peek() == '[') {
Expand Down Expand Up @@ -156,6 +158,11 @@ static DataComponentMap readMap(DynamicOps<Tag> registryOps, StringReader reader

static DataComponentPatch readPatch(DynamicOps<Tag> registryOps, StringReader reader) throws CommandSyntaxException {
reader.skipWhitespace();

if (!reader.canRead()) {
return DataComponentPatch.EMPTY;
}

DataComponentPatch.Builder builder = null;

if (reader.canRead() && reader.peek() == '[') {
Expand Down Expand Up @@ -263,6 +270,14 @@ static DataComponentMap mapOf(DynamicOps<Tag> ops, Object o) {
}
}

static DataComponentMap mapOrEmptyOf(DynamicOps<Tag> ops, Object o) {
try {
return readMap(ops, new StringReader(o.toString()));
} catch (CommandSyntaxException ex) {
return DataComponentMap.EMPTY;
}
}

static DataComponentPatch patchOf(DynamicOps<Tag> ops, Object o) {
try {
return readPatch(ops, new StringReader(o.toString()));
Expand All @@ -271,6 +286,14 @@ static DataComponentPatch patchOf(DynamicOps<Tag> ops, Object o) {
}
}

static DataComponentPatch patchOrEmptyOf(DynamicOps<Tag> ops, Object o) {
try {
return readPatch(ops, new StringReader(o.toString()));
} catch (CommandSyntaxException ex) {
return DataComponentPatch.EMPTY;
}
}

static StringBuilder mapToString(StringBuilder builder, DynamicOps<Tag> ops, DataComponentMap map) {
builder.append('[');

Expand Down Expand Up @@ -323,20 +346,23 @@ static StringBuilder patchToString(StringBuilder builder, DynamicOps<Tag> ops, D
return builder;
}

static String urlEncodePatch(DynamicOps<Tag> ops, DataComponentPatch patch) {
var sb = patchToString(new StringBuilder(), ops, patch);
return URLEncoder.encode(sb.substring(1, sb.length() - 1), StandardCharsets.UTF_8);
}

static DataComponentPatch urlDecodePatch(DynamicOps<Tag> ops, String s) {
if (s.isEmpty()) {
static DataComponentPatch visualPatch(DataComponentPatch patch) {
if (patch.isEmpty()) {
return DataComponentPatch.EMPTY;
}

try {
return readPatch(ops, new StringReader("[" + URLDecoder.decode(s, StandardCharsets.UTF_8) + "]"));
} catch (Exception ex) {
return DataComponentPatch.EMPTY;
var builder = DataComponentPatch.builder();

for (var entry : patch.entrySet()) {
if (VISUAL_DIFFERENCE.get().contains(entry.getKey())) {
if (entry.getValue().isPresent()) {
builder.set(entry.getKey(), Cast.to(entry.getValue().get()));
} else {
builder.remove(entry.getKey());
}
}
}

return builder.build();
}
}
4 changes: 0 additions & 4 deletions src/main/java/dev/latvian/mods/kubejs/core/BlockKJS.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,4 @@ public interface BlockKJS extends BlockBuilderProvider, RegistryObjectKJS<Block>
default Object replaceThisWith(Context cx, Object with) {
return with instanceof Block block ? block : with instanceof BlockState state ? state.getBlock() : cx.jsToJava(with, BlockWrapper.TYPE_INFO);
}

default String getWebIconURL(int size) {
return this instanceof Block block ? block.defaultBlockState().getWebIconURL(size) : "";
}
}
8 changes: 4 additions & 4 deletions src/main/java/dev/latvian/mods/kubejs/core/BlockStateKJS.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;

import java.util.Map;

@RemapPrefixForJS("kjs$")
public interface BlockStateKJS extends RegistryObjectKJS<Block>, Replaceable {
@Override
Expand Down Expand Up @@ -73,10 +75,8 @@ default Object replaceThisWith(Context cx, Object with) {
return with instanceof BlockState state ? state : with instanceof Block block ? block.defaultBlockState() : cx.jsToJava(with, BlockWrapper.STATE_TYPE_INFO);
}

default String getWebIconURL(int size) {
default String kjs$getWebIconURL(int size) {
var url = "/img/" + size + "/block/" + ID.url(kjs$getIdLocation());


return KubeJSLocalWebServer.getURL(url);
return KubeJSLocalWebServer.getURL(url, Map.of());
}
}
12 changes: 5 additions & 7 deletions src/main/java/dev/latvian/mods/kubejs/core/FluidStackKJS.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import net.neoforged.neoforge.fluids.FluidStack;
import net.neoforged.neoforge.fluids.crafting.FluidIngredient;

import java.util.Map;

public interface FluidStackKJS extends
Replaceable,
SpecialEquality,
Expand Down Expand Up @@ -143,13 +145,9 @@ default boolean matches(Context cx, FluidIngredient ingredient, boolean exact) {
return ingredient.test(kjs$self());
}

default String getWebIconURL(DynamicOps<Tag> ops, int size) {
default String kjs$getWebIconURL(DynamicOps<Tag> ops, int size) {
var url = "/img/" + size + "/fluid/" + ID.url(kjs$getIdLocation());

if (!kjs$self().isComponentsPatchEmpty()) {
url += "?components=" + DataComponentWrapper.urlEncodePatch(ops, kjs$self().getComponentsPatch());
}

return KubeJSLocalWebServer.getURL(url);
var c = DataComponentWrapper.patchToString(new StringBuilder(), ops, DataComponentWrapper.visualPatch(kjs$self().getComponentsPatch())).toString();
return KubeJSLocalWebServer.getURL(url, c.equals("[]") ? Map.of() : Map.of("components", c.substring(1, c.length() - 1)));
}
}
10 changes: 3 additions & 7 deletions src/main/java/dev/latvian/mods/kubejs/core/ItemStackKJS.java
Original file line number Diff line number Diff line change
Expand Up @@ -279,13 +279,9 @@ default boolean matches(Context cx, ItemLike itemLike, boolean exact) {
return kjs$self().getItem() == itemLike.asItem();
}

default String getWebIconURL(DynamicOps<Tag> ops, int size) {
default String kjs$getWebIconURL(DynamicOps<Tag> ops, int size) {
var url = "/img/" + size + "/item/" + ID.url(kjs$getIdLocation());

if (!kjs$self().isComponentsPatchEmpty()) {
url += "?components=" + DataComponentWrapper.urlEncodePatch(ops, kjs$self().getComponentsPatch());
}

return KubeJSLocalWebServer.getURL(url);
var c = DataComponentWrapper.patchToString(new StringBuilder(), ops, DataComponentWrapper.visualPatch(kjs$self().getComponentsPatch())).toString();
return KubeJSLocalWebServer.getURL(url, c.equals("[]") ? Map.of() : Map.of("components", c.substring(1, c.length() - 1)));
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
package dev.latvian.mods.kubejs.util;

import dev.latvian.mods.kubejs.component.DataComponentWrapper;
import dev.latvian.mods.kubejs.core.RegistryObjectKJS;
import io.netty.buffer.Unpooled;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.material.Fluid;
import net.neoforged.neoforge.fluids.FluidStack;

import java.util.UUID;

public record CachedComponentObject<T extends RegistryObjectKJS<T>>(UUID cacheKey, T value, DataComponentPatch components) {
public static <T extends RegistryObjectKJS<T>> CachedComponentObject<T> of(T value, DataComponentPatch components) {
public record CachedComponentObject<T extends RegistryObjectKJS<T>, S>(UUID cacheKey, T value, S stack, DataComponentPatch components) {
public static <T extends RegistryObjectKJS<T>, S> CachedComponentObject<T, S> of(T value, S stack, DataComponentPatch components) {
var buf = new FriendlyByteBuf(Unpooled.buffer());
buf.writeUtf(value.kjs$getId());
buf.writeVarInt(components.size());
Expand All @@ -25,11 +30,19 @@ public static <T extends RegistryObjectKJS<T>> CachedComponentObject<T> of(T val
}
}

return new CachedComponentObject<>(UUID.nameUUIDFromBytes(buf.array()), value, components);
return new CachedComponentObject<>(UUID.nameUUIDFromBytes(buf.array()), value, stack, components);
}

public static CachedComponentObject<Item, ItemStack> ofItemStack(ItemStack stack, boolean visual) {
return of(stack.getItem(), stack, visual ? DataComponentWrapper.visualPatch(stack.getComponentsPatch()) : stack.getComponentsPatch());
}

public static CachedComponentObject<Fluid, FluidStack> ofFluidStack(FluidStack stack, boolean visual) {
return of(stack.getFluid(), stack, visual ? DataComponentWrapper.visualPatch(stack.getComponentsPatch()) : stack.getComponentsPatch());
}

@Override
public boolean equals(Object o) {
return this == o || o instanceof CachedComponentObject<?> c && value == c.value && components.equals(c.components);
return this == o || o instanceof CachedComponentObject<?, ?> c && value == c.value && components.equals(c.components);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@ public ResourceLocation id() {
}

public DataComponentPatch components(DynamicOps<Tag> ops) throws CommandSyntaxException {
return DataComponentWrapper.urlDecodePatch(ops, query().getOrDefault("components", ""));
return DataComponentWrapper.patchOrEmptyOf(ops, "[" + query().getOrDefault("components", "") + "]");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
import net.neoforged.fml.ModList;
import org.jetbrains.annotations.Nullable;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Map;

public record KubeJSLocalWebServer(HTTPServer<KJSHTTPRequest> server, String url) implements ServerRegistry<KJSHTTPRequest> {
private static KubeJSLocalWebServer instance;
Expand All @@ -26,8 +29,20 @@ public static KubeJSLocalWebServer instance() {
return instance;
}

public static String getURL(String path) {
return instance == null ? "" : instance.url + path;
public static String getURL(String path, Map<String, String> query) {
if (instance == null) {
return "";
}

var url = new StringBuilder(instance.url + path);
boolean first = true;

for (var entry : query.entrySet()) {
url.append(first ? '?' : '&').append(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8)).append('=').append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8));
first = false;
}

return url.toString();
}

@HideFromJS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public static HTTPResponse item(KJSHTTPRequest req) throws Exception {
return HTTPStatus.NOT_FOUND;
}

return renderCanvas(req, 16, "item", CachedComponentObject.of(stack.getItem(), stack.getComponentsPatch()).cacheKey(), render -> {
return renderCanvas(req, 16, "item", CachedComponentObject.ofItemStack(stack, true).cacheKey(), render -> {
render.graphics.renderFakeItem(stack, 0, 0, 0);
render.graphics.renderItemDecorations(render.mc.font, stack, 0, 0);
});
Expand Down Expand Up @@ -225,7 +225,7 @@ public static HTTPResponse fluid(KJSHTTPRequest req) throws Exception {
int g = (tint >> 8) & 0xFF;
int b = tint & 0xFF;

return renderCanvas(req, 16, "fluid", CachedComponentObject.of(stack.getFluid(), stack.getComponentsPatch()).cacheKey(), render -> {
return renderCanvas(req, 16, "fluid", CachedComponentObject.ofFluidStack(stack, true).cacheKey(), render -> {
var s = render.mc.getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(still);
RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_BLOCKS);
RenderSystem.setShader(GameRenderer::getPositionTexColorShader);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,35 @@
import dev.latvian.apps.tinyserver.http.response.HTTPResponse;
import dev.latvian.apps.tinyserver.http.response.HTTPStatus;
import dev.latvian.mods.kubejs.KubeJS;
import dev.latvian.mods.kubejs.bindings.UUIDWrapper;
import dev.latvian.mods.kubejs.script.ScriptType;
import dev.latvian.mods.kubejs.util.CachedComponentObject;
import dev.latvian.mods.kubejs.util.Cast;
import dev.latvian.mods.kubejs.util.Lazy;
import dev.latvian.mods.kubejs.web.JsonContent;
import dev.latvian.mods.kubejs.web.KJSHTTPRequest;
import dev.latvian.mods.kubejs.web.KubeJSLocalWebServer;
import dev.latvian.mods.kubejs.web.local.KubeJSWeb;
import net.minecraft.client.Minecraft;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.NbtOps;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.CreativeModeTabs;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;

public class KubeJSClientWeb {
public static final Lazy<Map<UUID, CachedComponentObject<Item>>> CACHED_ITEM_SEARCH = Lazy.of(() -> {
var map = new HashMap<UUID, CachedComponentObject<Item>>();
public static final Lazy<Map<UUID, CachedComponentObject<Item, ItemStack>>> CACHED_ITEM_SEARCH = Lazy.of(() -> {
var map = new LinkedHashMap<UUID, CachedComponentObject<Item, ItemStack>>();

for (var stack : BuiltInRegistries.CREATIVE_MODE_TAB.get(CreativeModeTabs.SEARCH).getSearchTabDisplayItems()) {

var patch = stack.getComponentsPatch();

if (!patch.isEmpty()) {
map.put(UUID.randomUUID(), new CachedComponentObject<>(UUID.randomUUID(), stack.getItem(), patch));
}
map.put(UUID.randomUUID(), new CachedComponentObject<>(UUID.randomUUID(), stack.getItem(), stack, patch));
}

return map;
Expand Down Expand Up @@ -66,15 +67,20 @@ public static void register(ServerRegistry<KJSHTTPRequest> registry) {
}

private static HTTPResponse getItemsResponse(KJSHTTPRequest req) {
return HTTPResponse.ok().content(JsonContent.array(json -> {
var ops = Minecraft.getInstance().level == null ? req.registries().json() : Minecraft.getInstance().level.registryAccess().createSerializationContext(JsonOps.INSTANCE);
return HTTPResponse.ok().content(JsonContent.object(json -> {
var jsonOps = Minecraft.getInstance().level == null ? req.registries().json() : Minecraft.getInstance().level.registryAccess().createSerializationContext(JsonOps.INSTANCE);
var nbtOps = Minecraft.getInstance().level == null ? req.registries().nbt() : Minecraft.getInstance().level.registryAccess().createSerializationContext(NbtOps.INSTANCE);
var results = new JsonArray();
var iconPathRoot = KubeJSLocalWebServer.instance().url() + "/img/64/item/";

for (var stack : BuiltInRegistries.CREATIVE_MODE_TAB.get(CreativeModeTabs.SEARCH).getSearchTabDisplayItems()) {
for (var item : CACHED_ITEM_SEARCH.get().values()) {
var o = new JsonObject();
o.addProperty("id", stack.kjs$getId());
o.addProperty("name", stack.getHoverName().getString());
o.addProperty("cache_key", UUIDWrapper.toString(item.cacheKey()));
o.addProperty("id", item.value().kjs$getId());
o.addProperty("name", item.stack().getHoverName().getString());
o.addProperty("icon_path", item.stack().kjs$getWebIconURL(nbtOps, 64).substring(iconPathRoot.length()));

var patch = stack.getComponentsPatch();
var patch = item.components();

if (!patch.isEmpty()) {
var p = new JsonObject();
Expand All @@ -86,18 +92,21 @@ private static HTTPResponse getItemsResponse(KJSHTTPRequest req) {
if (entry.getValue().isEmpty()) {
p.add(key, JsonNull.INSTANCE);
} else if (entry.getKey().codec() != null) {
p.add(key, entry.getKey().codec().encodeStart(ops, Cast.to(entry.getValue().get())).getOrThrow());
p.add(key, entry.getKey().codec().encodeStart(jsonOps, Cast.to(entry.getValue().get())).getOrThrow());
}
}

o.add("patch", p);
o.add("components", p);
} catch (Exception ex) {
ex.printStackTrace();
}
}

json.add(o);
results.add(o);
}

json.addProperty("icon_path_root", iconPathRoot);
json.add("results", results);
}));
}

Expand Down

0 comments on commit 6d6a63a

Please sign in to comment.