Skip to content

Commit

Permalink
Added WIP local web server
Browse files Browse the repository at this point in the history
  • Loading branch information
LatvianModder committed Aug 7, 2024
1 parent 909a2ed commit 6446199
Show file tree
Hide file tree
Showing 23 changed files with 772 additions and 3 deletions.
11 changes: 11 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,17 @@ dependencies {
compileOnly("mezz.jei:jei-1.21-neoforge:$jei_version")
compileOnly("me.shedaniel:RoughlyEnoughItems-neoforge:$rei_version")
compileOnly("dev.emi:emi-neoforge:$emi_version:api")

/*
jarJar(implementation 'org.java-websocket:Java-WebSocket') {
version {
strictly '[1.5,)'
prefer "$java_websocket_version"
}
}
additionalRuntimeClasspath("org.java-websocket:Java-WebSocket:$java_websocket_version")
*/
}

processResources {
Expand Down
5 changes: 3 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ modrinth_id=umyGl7zF
minecraft_version=1.21
mod_version=2100.7.0

neoforge_version=21.0.148
parchment_version=2024.07.07
neoforge_version=21.0.163
parchment_version=2024.07.28
rhino_version=2100.2.5-build.46
java_websocket_version=1.5.7

architectury_version=13.0.6
rei_version=16.0.744
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/dev/latvian/mods/kubejs/bindings/BlockWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import dev.latvian.mods.kubejs.block.predicate.BlockIDPredicate;
import dev.latvian.mods.kubejs.block.predicate.BlockPredicate;
import dev.latvian.mods.kubejs.typings.Info;
import dev.latvian.mods.kubejs.util.Cast;
import dev.latvian.mods.kubejs.util.RegistryAccessContainer;
import dev.latvian.mods.kubejs.util.Tags;
import dev.latvian.mods.rhino.Context;
Expand All @@ -19,6 +20,7 @@
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockSetType;
import net.minecraft.world.level.block.state.properties.Property;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
Expand Down Expand Up @@ -162,4 +164,22 @@ public static BlockState wrapBlockState(RegistryAccessContainer registries, Obje
default -> parseBlockState(registries, o.toString());
};
}

public static BlockState withProperties(BlockState state, Map<?, ?> properties) {
var pmap = new HashMap<String, Property<?>>();

for (var property : state.getProperties()) {
pmap.put(property.getName(), property);
}

for (var entry : properties.entrySet()) {
var property = pmap.get(String.valueOf(entry.getKey()));

if (property != null) {
state = state.setValue(property, Cast.to(property.getValue(String.valueOf(entry.getValue())).orElseThrow()));
}
}

return state;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import dev.latvian.mods.kubejs.script.BindingRegistry;
import dev.latvian.mods.kubejs.script.PlatformWrapper;
import dev.latvian.mods.kubejs.util.ScheduledEvents;
import dev.latvian.mods.kubejs.web.WebServerRegistry;
import net.minecraft.client.Minecraft;
import net.neoforged.fml.ModList;

Expand All @@ -30,6 +31,16 @@ public void registerBindings(BindingRegistry bindings) {
}
}

@Override
public void registerLocalWebServer(WebServerRegistry registry) {
registry.get("img/{size}/item/{namespace}/<path>", ImageGenerator::item);
registry.get("img/{size}/block/{namespace}/<path>", ImageGenerator::block);
registry.get("img/{size}/fluid/{namespace}/<path>", ImageGenerator::fluid);
registry.get("img/{size}/item-tag/{namespace}/<path>", ImageGenerator::itemTag);
registry.get("img/{size}/block-tag/{namespace}/<path>", ImageGenerator::blockTag);
registry.get("img/{size}/fluid-tag/{namespace}/<path>", ImageGenerator::fluidTag);
}

@Override
public void generateLang(LangKubeEvent event) {
event.add(KubeJS.MOD_ID, "key.categories.kubejs", "KubeJS");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public static void reload() {
// private static final ColourScheme.Colour DEFAULT_FOREGROUND_COLOR = new ColourScheme.Colour(236, 239, 244); // #ECEFF4

public String windowTitle;
public int localServerHttpPort;
// public int localServerWsPort;
public boolean showTagNames;
public boolean showComponents;
public boolean disableRecipeBook;
Expand All @@ -44,6 +46,8 @@ private ClientProperties() {
@Override
protected void load() {
windowTitle = get("window_title", "");
localServerHttpPort = get("local_server_http_port", 61423);
// localServerWsPort = get("local_server_ws_port", 61433);
showTagNames = get("show_tag_names", true);
showComponents = get("show_components", true);
disableRecipeBook = get("disable_recipe_book", false);
Expand Down
218 changes: 218 additions & 0 deletions src/main/java/dev/latvian/mods/kubejs/client/ImageGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
package dev.latvian.mods.kubejs.client;

import com.mojang.blaze3d.pipeline.TextureTarget;
import com.mojang.blaze3d.platform.NativeImage;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.BufferUploader;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.Tesselator;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.blaze3d.vertex.VertexSorting;
import com.mojang.brigadier.StringReader;
import dev.latvian.mods.kubejs.bindings.BlockWrapper;
import dev.latvian.mods.kubejs.bindings.DataComponentWrapper;
import dev.latvian.mods.kubejs.util.RegistryAccessContainer;
import dev.latvian.mods.kubejs.web.http.HTTPContext;
import dev.latvian.mods.kubejs.web.http.HTTPResponse;
import dev.latvian.mods.kubejs.web.http.SimpleHTTPResponse;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.tags.BlockTags;
import net.minecraft.tags.FluidTags;
import net.minecraft.tags.ItemTags;
import net.minecraft.world.item.Items;
import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions;
import net.neoforged.neoforge.fluids.FluidStack;
import net.neoforged.neoforge.fluids.FluidType;
import org.joml.Matrix4f;

import java.util.function.Consumer;

public class ImageGenerator {
private record RenderImage(Minecraft mc, GuiGraphics graphics, int size) {
}

public static final Int2ObjectMap<TextureTarget> FB_CACHE = new Int2ObjectArrayMap<>();

private static HTTPResponse renderCanvas(HTTPContext ctx, int canvasSize, Consumer<RenderImage> render) {
int size = Integer.parseInt(ctx.variables().get("size"));

if (size < 1 || size > 1024) {
return SimpleHTTPResponse.text(400, "Invalid size, must be [1, 1024]");
}

var bytes = ctx.supplyInRenderThread(() -> {
var target = FB_CACHE.get(size);

if (target == null) {
target = new TextureTarget(size, size, true, Minecraft.ON_OSX);
FB_CACHE.put(size, target);
}

var mc = Minecraft.getInstance();

/*
mc.renderBuffers().bufferSource().endBatch();
target.clear(Minecraft.ON_OSX);
target.bindWrite(true);
RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, canvasSize, canvasSize, 0, 1000F, 3000F), VertexSorting.ORTHOGRAPHIC_Z);
var view = RenderSystem.getModelViewStack();
view.pushMatrix();
view.translate(0F, 0F, 0F);
RenderSystem.applyModelViewMatrix();
var graphics = new GuiGraphics(mc, mc.renderBuffers().bufferSource());
RenderSystem.disableCull();
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
render.accept(new RenderImage(mc, graphics, size));
graphics.flush();
try (var img = new NativeImage(size, size, false)) {
target.bindRead();
RenderSystem.bindTexture(target.getColorTextureId());
img.downloadTexture(0, false);
img.flipY();
return img.asByteArray();
} catch (Exception ex) {
ex.printStackTrace();
return new byte[0];
} finally {
target.unbindRead();
target.unbindWrite();
mc.getMainRenderTarget().bindWrite(true);
view.popMatrix();
RenderSystem.applyModelViewMatrix();
}
*/

var bufferSource = mc.renderBuffers().bufferSource();

target.clear(Minecraft.ON_OSX);
target.bindWrite(true);
RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, canvasSize, canvasSize, 0, -1000F, 1000F), VertexSorting.ORTHOGRAPHIC_Z);

var view = RenderSystem.getModelViewStack();
view.pushMatrix();
view.translation(0F, 0F, 0F);

RenderSystem.applyModelViewMatrix();

GuiGraphics graphics = new GuiGraphics(mc, bufferSource);
render.accept(new RenderImage(mc, graphics, size));
graphics.flush();

target.bindRead();
RenderSystem.bindTexture(target.getColorTextureId());

try (var image = new NativeImage(size, size, false)) {
image.downloadTexture(0, false);
image.flipY();
return image.asByteArray();
} catch (Exception ex) {
ex.printStackTrace();
return null;
} finally {
target.unbindRead();
target.unbindWrite();

view.popMatrix();
RenderSystem.applyModelViewMatrix();
}
});

return new SimpleHTTPResponse(200, bytes, "image/png");
}

public static HTTPResponse item(HTTPContext ctx) throws Exception {
var stack = BuiltInRegistries.ITEM.get(ctx.id()).getDefaultInstance();
stack.applyComponents(DataComponentWrapper.readPatch(RegistryAccessContainer.BUILTIN.nbt(), new StringReader(ctx.query().getOrDefault("components", ""))));

if (stack.isEmpty()) {
return HTTPResponse.NOT_FOUND;
}

return renderCanvas(ctx, 16, render -> {
render.graphics.renderFakeItem(stack, 0, 0, 0);
render.graphics.renderItemDecorations(render.mc.font, stack, 0, 0);
});
}

public static HTTPResponse block(HTTPContext ctx) throws Exception {
var state = BlockWrapper.withProperties(BuiltInRegistries.BLOCK.get(ctx.id()).defaultBlockState(), ctx.query());

if (state.isEmpty()) {
return HTTPResponse.NOT_FOUND;
}

return renderCanvas(ctx, 16, render -> {
render.graphics.fill(0, 0, 16, 16, 0xFFFF00FF);
});
}

public static HTTPResponse fluid(HTTPContext ctx) throws Exception {
var stack = new FluidStack(BuiltInRegistries.FLUID.get(ctx.id()), FluidType.BUCKET_VOLUME);
stack.applyComponents(DataComponentWrapper.readPatch(RegistryAccessContainer.BUILTIN.nbt(), new StringReader(ctx.query().getOrDefault("components", ""))));

if (stack.isEmpty()) {
return HTTPResponse.NOT_FOUND;
}

var fluidInfo = IClientFluidTypeExtensions.of(stack.getFluid());
var still = fluidInfo.getStillTexture(stack);
var tint = fluidInfo.getTintColor(stack);
int a = 255;
int r = (tint >> 16) & 0xFF;
int g = (tint >> 8) & 0xFF;
int b = tint & 0xFF;

return renderCanvas(ctx, 16, render -> {
var s = render.mc.getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(still);
RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_BLOCKS);
RenderSystem.setShader(GameRenderer::getPositionTexColorShader);
var builder = Tesselator.getInstance().begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
var m = render.graphics.pose().last().pose();
builder.addVertex(m, 0F, 0F, 0F).setUv(s.getU0(), s.getV1()).setColor(r, g, b, a);
builder.addVertex(m, 0F, 16F, 0F).setUv(s.getU0(), s.getV0()).setColor(r, g, b, a);
builder.addVertex(m, 16F, 16F, 0F).setUv(s.getU1(), s.getV0()).setColor(r, g, b, a);
builder.addVertex(m, 16F, 0F, 0F).setUv(s.getU1(), s.getV1()).setColor(r, g, b, a);
BufferUploader.drawWithShader(builder.buildOrThrow());
});
}

public static HTTPResponse itemTag(HTTPContext ctx) throws Exception {
var tagKey = ItemTags.create(ctx.id());

return renderCanvas(ctx, 16, render -> {
// render.graphics.fill(0, 0, 16, 16, 0xFFFF00FF);
render.graphics.renderFakeItem(Items.NAME_TAG.getDefaultInstance(), 0, 0, 0);
});
}

public static HTTPResponse blockTag(HTTPContext ctx) throws Exception {
var tagKey = BlockTags.create(ctx.id());

return renderCanvas(ctx, 16, render -> {
// render.graphics.fill(0, 0, 16, 16, 0xFFFF00FF);
render.graphics.renderFakeItem(Items.NAME_TAG.getDefaultInstance(), 0, 0, 0);
});
}

public static HTTPResponse fluidTag(HTTPContext ctx) throws Exception {
var tagKey = FluidTags.create(ctx.id());

return renderCanvas(ctx, 16, render -> {
// render.graphics.fill(0, 0, 16, 16, 0xFFFF00FF);
render.graphics.renderFakeItem(Items.NAME_TAG.getDefaultInstance(), 0, 0, 0);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,30 @@ public static void hudPostDraw(RenderGuiEvent.Post event) {
if (mc.screen == null) {
KubedexHighlight.INSTANCE.afterEverything(mc, event.getGuiGraphics(), event.getPartialTick().getGameTimeDeltaPartialTick(false));
}

/*
if (PlatformWrapper.isDevelopmentEnvironment()) {
var fb = ImageGenerator.FB_CACHE.get(128);
if (fb != null) {
var graphics = event.getGuiGraphics();
graphics.pose().pushPose();
graphics.pose().translate(event.getGuiGraphics().guiWidth() - 66F - 3F, 4F, 0F);
graphics.fill(0, 0, 66, 66, 0xFF000000);
graphics.fill(1, 1, 65, 65, 0xFF222222);
RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderTexture(0, fb.getColorTextureId());
var m = graphics.pose().last().pose();
var builder = Tesselator.getInstance().begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX);
builder.addVertex(m, 1F, 1F, 10F).setUv(0F, 1F);
builder.addVertex(m, 1F, 65F, 10F).setUv(0F, 0F);
builder.addVertex(m, 65F, 65F, 10F).setUv(1F, 0F);
builder.addVertex(m, 65F, 1F, 10F).setUv(1F, 1F);
BufferUploader.drawWithShader(builder.buildOrThrow());
graphics.pose().popPose();
}
}
*/
}

@SubscribeEvent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@
import dev.latvian.mods.kubejs.item.ModifyItemTooltipsKubeEvent;
import dev.latvian.mods.kubejs.kubedex.KubedexHighlight;
import dev.latvian.mods.kubejs.registry.RegistryObjectStorage;
import dev.latvian.mods.kubejs.script.PlatformWrapper;
import dev.latvian.mods.kubejs.script.ScriptType;
import dev.latvian.mods.kubejs.text.tooltip.ItemTooltipData;
import dev.latvian.mods.kubejs.util.ID;
import dev.latvian.mods.kubejs.web.KubeJSLocalWebServer;
import net.minecraft.client.KeyMapping;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ItemBlockRenderTypes;
Expand Down Expand Up @@ -99,6 +101,10 @@ private static void setupClient0() {
var list = new ArrayList<ItemTooltipData>();
ItemEvents.MODIFY_TOOLTIPS.post(ScriptType.CLIENT, new ModifyItemTooltipsKubeEvent(list::add));
KubeJSClient.clientItemTooltips = List.copyOf(list);

if (!PlatformWrapper.isGeneratingData()) {
KubeJSLocalWebServer.start();
}
}

@SubscribeEvent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ public interface MinecraftClientKJS extends MinecraftEnvironmentKJS {
kjs$self().updateTitle();
}

default String kjs$getTitle() {
throw new NoMixinException();
}

default String kjs$getCurrentWorldName() {
var server = kjs$self().getCurrentServer();
return server == null ? "Singleplayer" : server.name;
Expand Down
Loading

0 comments on commit 6446199

Please sign in to comment.