Skip to content
This repository has been archived by the owner on Dec 15, 2024. It is now read-only.

Commit

Permalink
use a more nbt-oriented component data screen design
Browse files Browse the repository at this point in the history
  • Loading branch information
BasiqueEvangelist committed Jul 26, 2024
1 parent ce2c6ea commit dbfce8d
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.wispforest.gadget.client.gui;

import io.wispforest.owo.ui.component.Components;
import io.wispforest.owo.ui.component.LabelComponent;
import io.wispforest.owo.ui.container.Containers;
import io.wispforest.owo.ui.container.FlowLayout;
import io.wispforest.owo.ui.core.*;
Expand Down Expand Up @@ -43,10 +44,12 @@ public void button(Text icon, @Nullable Text tooltip, OnPressHandler handler) {
}

public static class Button extends FlowLayout {
private final LabelComponent iconLabel;

public Button(Text icon, Text tooltip) {
super(Sizing.fixed(16), Sizing.fixed(16), Algorithm.VERTICAL);

child(Components.label(icon)
child((iconLabel = Components.label(icon))
.verticalTextAlignment(VerticalAlignment.CENTER)
.horizontalTextAlignment(HorizontalAlignment.CENTER)
.positioning(Positioning.absolute(5, 4))
Expand All @@ -63,6 +66,12 @@ public Button(Text icon, Text tooltip) {
mouseLeave().subscribe(
() -> surface(Surface.BLANK));
}

public Button icon(Text icon) {
iconLabel.text(icon);

return this;
}
}

public interface OnPressHandler {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,85 @@
package io.wispforest.gadget.client.nbt;

import com.mojang.serialization.DataResult;
import io.wispforest.gadget.client.ServerData;
import io.wispforest.gadget.client.gui.SidebarBuilder;
import io.wispforest.gadget.network.GadgetNetworking;
import io.wispforest.gadget.network.packet.c2s.ReplaceStackC2SPacket;
import io.wispforest.owo.ui.base.BaseOwoScreen;
import io.wispforest.owo.ui.component.Components;
import io.wispforest.owo.ui.container.Containers;
import io.wispforest.owo.ui.container.FlowLayout;
import io.wispforest.owo.ui.container.ScrollContainer;
import io.wispforest.owo.ui.core.*;
import io.wispforest.owo.ui.util.UISounds;
import io.wispforest.owo.util.Observable;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.item.ItemStack;
import net.minecraft.client.gui.tooltip.TooltipComponent;
import net.minecraft.component.ComponentChanges;
import net.minecraft.component.ComponentMapImpl;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
import net.minecraft.nbt.NbtOps;
import net.minecraft.registry.Registries;
import net.minecraft.screen.slot.Slot;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import org.apache.commons.lang3.mutable.MutableInt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.glfw.GLFW;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

public class StackComponentDataScreen extends BaseOwoScreen<FlowLayout> {
private final ItemStack stack;
private final NbtDataIsland island;
private final HandledScreen<?> parent;
private final Observable<@Nullable String> currentEncodingError = Observable.of(null);

public StackComponentDataScreen(HandledScreen<?> parent, Slot slot) {
this.stack = slot.getStack();
var stack = slot.getStack();
Consumer<NbtCompound> reloader = null;

var registries = MinecraftClient.getInstance().world.getRegistryManager();

if (ServerData.canReplaceStacks()) {
reloader = newNbt -> {
DataResult<ComponentChanges> result = ComponentChanges.CODEC.parse(
registries.getOps(NbtOps.INSTANCE),
newNbt
);

result
.ifError(error -> {
currentEncodingError.set(error.message());
})
.ifSuccess(newChanges -> {
currentEncodingError.set(null);

((ComponentMapImpl) stack.getComponents()).setChanges(newChanges);
stack.getItem().postProcessComponents(stack);

if (parent instanceof CreativeInventoryScreen) {
// Let it handle it.
return;
}

GadgetNetworking.CHANNEL.clientHandle().send(new ReplaceStackC2SPacket(slot.id, stack));
});
};
}

NbtCompound tag = (NbtCompound) ComponentChanges.CODEC.encodeStart(
registries.getOps(NbtOps.INSTANCE),
stack.getComponentChanges()
)
.getOrThrow();

if (tag == null) tag = new NbtCompound();

this.parent = parent;
this.island = new NbtDataIsland(tag, reloader);
}

@Override
Expand All @@ -49,33 +105,67 @@ protected void build(FlowLayout rootComponent) {
main
.padding(Insets.of(15));

for (var component : stack.getComponents()) {
FlowLayout full = Containers.verticalFlow(Sizing.content(), Sizing.content());
FlowLayout row = Containers.horizontalFlow(Sizing.content(), Sizing.content());
main.child(island);

FlowLayout sidebar = Containers.verticalFlow(Sizing.content(), Sizing.content());

if (island.reloader != null) {
var addButton = Containers.verticalFlow(Sizing.fixed(16), Sizing.fixed(16))
.child(Components.label(Text.literal("+"))
.verticalTextAlignment(VerticalAlignment.CENTER)
.horizontalTextAlignment(HorizontalAlignment.CENTER)
.positioning(Positioning.absolute(5, 4))
.cursorStyle(CursorStyle.HAND)
);

addButton
.cursorStyle(CursorStyle.HAND);

addButton.mouseEnter().subscribe(
() -> addButton.surface(Surface.flat(0x80ffffff)));

full.child(row);
main.child(full);
addButton.mouseLeave().subscribe(
() -> addButton.surface(Surface.BLANK));

row.child(Components.label(Text.literal(Registries.DATA_COMPONENT_TYPE.getId(component.type()).toString())
.append(Text.literal(" = ")
.formatted(Formatting.GRAY))));
addButton.mouseDown().subscribe((mouseX, mouseY, button) -> {
if (button != GLFW.GLFW_MOUSE_BUTTON_LEFT) return false;

NbtElement tag = component.encode(client.world.getRegistryManager().getOps(NbtOps.INSTANCE)).getOrThrow();
UISounds.playInteractionSound();

NbtCompound compound;
if (tag instanceof NbtCompound c) {
compound = c;
island.typeSelector(
(int) (addButton.x() + mouseX),
(int) (addButton.y() + mouseY),
type -> island.child(new KeyAdderWidget(island, NbtPath.EMPTY, type, unused -> true)));

return true;
});

sidebar.child(addButton);
}

var infoButton = new SidebarBuilder.Button(Text.translatable("text.gadget.encode_status.success"), Text.translatable("text.gadget.encode_status.success.tooltip"));

currentEncodingError.observe(error -> {
if (error == null) {
infoButton.icon(Text.translatable("text.gadget.encode_status.success"));
infoButton.tooltip(Text.translatable("text.gadget.encode_status.success.tooltip"));
} else {
compound = new NbtCompound();
compound.put("<value>", tag);
infoButton.icon(Text.translatable("text.gadget.encode_status.failure"));
infoButton.tooltip(Text.translatable("text.gadget.encode_status.failure.tooltip", error));
}
});

full.child(new NbtDataIsland(compound, null));
}
sidebar.child(infoButton);

sidebar
.positioning(Positioning.absolute(0, 0))
.padding(Insets.of(5));

rootComponent.child(sidebar);
}

@Override
public void close() {
client.setScreen(parent);
}
}
}
17 changes: 17 additions & 0 deletions src/main/resources/assets/gadget/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,23 @@
"font": "gadget:monocraft"
},
"text.gadget.export_button.tooltip": "Export",
"text.gadget.encode_status.success": {
"text": "",
"color": "green"
},
"text.gadget.encode_status.success.tooltip": {
"text": "Component NBT is fully valid",
"color": "green"
},
"text.gadget.encode_status.failure": {
"text": "",
"color": "dark_red"
},
"text.gadget.encode_status.failure.tooltip": [
"",
{"text": "Component NBT is invalid and has not been applied.\n\n", "color": "dark_red"},
{"index": 0}
],
"text.gadget.back": "",
"text.gadget.back.tooltip": "Back",
"text.gadget.open": {
Expand Down

0 comments on commit dbfce8d

Please sign in to comment.