From 2dd884829fa8294eb3f169bed737f782ff88b7c9 Mon Sep 17 00:00:00 2001 From: glisco Date: Sat, 5 Aug 2023 02:43:21 +0200 Subject: [PATCH 01/19] [ui] add combined panel + inset surface --- owo-ui.xsd | 8 +++++++ .../io/wispforest/owo/ui/core/Surface.java | 14 +++++++++++++ .../assets/uwu/owo_ui/smol_components.xml | 21 ++----------------- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/owo-ui.xsd b/owo-ui.xsd index 4fa96efa..703475b8 100644 --- a/owo-ui.xsd +++ b/owo-ui.xsd @@ -258,6 +258,14 @@ + + + + A panel inset bordered by a standard light panel + of the specified width on each border + + + diff --git a/src/main/java/io/wispforest/owo/ui/core/Surface.java b/src/main/java/io/wispforest/owo/ui/core/Surface.java index dfb5b50e..905b2048 100644 --- a/src/main/java/io/wispforest/owo/ui/core/Surface.java +++ b/src/main/java/io/wispforest/owo/ui/core/Surface.java @@ -90,6 +90,19 @@ static Surface tiled(Identifier texture, int textureWidth, int textureHeight) { }; } + static Surface panelWithInset(int insetWidth) { + return Surface.PANEL.and((context, component) -> { + NinePatchTexture.draw( + OwoUIDrawContext.PANEL_INSET_NINE_PATCH_TEXTURE, + context, + component.x() + insetWidth, + component.y() + insetWidth, + component.width() - insetWidth * 2, + component.height() - insetWidth * 2 + ); + }); + } + void draw(OwoUIDrawContext context, ParentComponent component); default Surface and(Surface surface) { @@ -123,6 +136,7 @@ static Surface parse(Element surfaceElement) { UIParsing.parseFloat(child.getAttributeNode("size")) )); } + case "panel-with-inset" -> surface.and(panelWithInset(UIParsing.parseUnsignedInt(child))); case "options-background" -> surface.and(OPTIONS_BACKGROUND); case "vanilla-translucent" -> surface.and(VANILLA_TRANSLUCENT); case "panel-inset" -> surface.and(PANEL_INSET); diff --git a/src/testmod/resources/assets/uwu/owo_ui/smol_components.xml b/src/testmod/resources/assets/uwu/owo_ui/smol_components.xml index 8804c6de..e51f503d 100644 --- a/src/testmod/resources/assets/uwu/owo_ui/smol_components.xml +++ b/src/testmod/resources/assets/uwu/owo_ui/smol_components.xml @@ -320,24 +320,7 @@ From 3b8f5f213be910478bfc77b0dd8815a2c4f67d0c Mon Sep 17 00:00:00 2001 From: glisco Date: Sat, 5 Aug 2023 02:44:46 +0200 Subject: [PATCH 02/19] [ui] use upper-bounded generic on collections passed into component methods --- .../io/wispforest/owo/ui/container/CollapsibleContainer.java | 4 ++-- src/main/java/io/wispforest/owo/ui/container/FlowLayout.java | 4 ++-- src/main/java/io/wispforest/owo/ui/container/StackLayout.java | 4 ++-- src/main/java/io/wispforest/owo/ui/core/Positioning.java | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/io/wispforest/owo/ui/container/CollapsibleContainer.java b/src/main/java/io/wispforest/owo/ui/container/CollapsibleContainer.java index a648de29..537ea618 100644 --- a/src/main/java/io/wispforest/owo/ui/container/CollapsibleContainer.java +++ b/src/main/java/io/wispforest/owo/ui/container/CollapsibleContainer.java @@ -136,7 +136,7 @@ public FlowLayout child(Component child) { } @Override - public FlowLayout children(Collection children) { + public FlowLayout children(Collection children) { this.collapsibleChildren.addAll(children); if (this.expanded) this.contentLayout.children(children); return this; @@ -150,7 +150,7 @@ public FlowLayout child(int index, Component child) { } @Override - public FlowLayout children(int index, Collection children) { + public FlowLayout children(int index, Collection children) { this.collapsibleChildren.addAll(index, children); if (this.expanded) this.contentLayout.children(index, children); return this; diff --git a/src/main/java/io/wispforest/owo/ui/container/FlowLayout.java b/src/main/java/io/wispforest/owo/ui/container/FlowLayout.java index a08f3a1b..b2a827b9 100644 --- a/src/main/java/io/wispforest/owo/ui/container/FlowLayout.java +++ b/src/main/java/io/wispforest/owo/ui/container/FlowLayout.java @@ -61,7 +61,7 @@ public FlowLayout child(Component child) { * * @param children The children to add to this layout */ - public FlowLayout children(Collection children) { + public FlowLayout children(Collection children) { this.children.addAll(children); this.updateLayout(); return this; @@ -87,7 +87,7 @@ public FlowLayout child(int index, Component child) { * @param index The index at which to begin inserting children * @param children The children to add to this layout */ - public FlowLayout children(int index, Collection children) { + public FlowLayout children(int index, Collection children) { this.children.addAll(index, children); this.updateLayout(); return this; diff --git a/src/main/java/io/wispforest/owo/ui/container/StackLayout.java b/src/main/java/io/wispforest/owo/ui/container/StackLayout.java index dfbe03f0..717c8bea 100644 --- a/src/main/java/io/wispforest/owo/ui/container/StackLayout.java +++ b/src/main/java/io/wispforest/owo/ui/container/StackLayout.java @@ -91,7 +91,7 @@ public StackLayout child(Component child) { * * @param children The children to add to this layout */ - public StackLayout children(Collection children) { + public StackLayout children(Collection children) { this.children.addAll(children); this.updateLayout(); return this; @@ -117,7 +117,7 @@ public StackLayout child(int index, Component child) { * @param index The index at which to begin inserting children * @param children The children to add to this layout */ - public StackLayout children(int index, Collection children) { + public StackLayout children(int index, Collection children) { this.children.addAll(index, children); this.updateLayout(); return this; diff --git a/src/main/java/io/wispforest/owo/ui/core/Positioning.java b/src/main/java/io/wispforest/owo/ui/core/Positioning.java index a03933b9..6c3c49ba 100644 --- a/src/main/java/io/wispforest/owo/ui/core/Positioning.java +++ b/src/main/java/io/wispforest/owo/ui/core/Positioning.java @@ -41,8 +41,8 @@ public Positioning interpolate(Positioning next, float delta) { } return new Positioning( - (int) MathHelper.lerp(delta, this.x, next.x), - (int) MathHelper.lerp(delta, this.y, next.y), + MathHelper.lerp(delta, this.x, next.x), + MathHelper.lerp(delta, this.y, next.y), this.type ); } From ec9910600e81857782dc56b89f16269c9d32fcd3 Mon Sep 17 00:00:00 2001 From: glisco Date: Sat, 5 Aug 2023 02:57:56 +0200 Subject: [PATCH 03/19] [ui] stop inflating explicitly positioned children twice as a side effect of BaseParentComponent#mountChild and remove then-redundant 'space' parameter --- .../owo/ui/base/BaseParentComponent.java | 57 ++++++++++--------- .../owo/ui/container/FlowLayout.java | 6 +- .../owo/ui/container/GridLayout.java | 4 +- .../owo/ui/container/StackLayout.java | 8 +-- .../wispforest/owo/ui/hud/HudContainer.java | 5 +- .../owo/ui/util/MountingHelper.java | 18 +++--- 6 files changed, 48 insertions(+), 50 deletions(-) diff --git a/src/main/java/io/wispforest/owo/ui/base/BaseParentComponent.java b/src/main/java/io/wispforest/owo/ui/base/BaseParentComponent.java index 476bc4ba..63e9149e 100644 --- a/src/main/java/io/wispforest/owo/ui/base/BaseParentComponent.java +++ b/src/main/java/io/wispforest/owo/ui/base/BaseParentComponent.java @@ -295,16 +295,28 @@ protected Size childMountingOffset() { return Size.of(padding.left(), padding.top()); } + /** + * @deprecated Use {@link #mountChild(Component, Consumer)} instead. This new + * overload no longer inflates the child prior to mounting, as that is + * rarely ever necessary and was simply causing unnecessary calculations + */ + @Deprecated(forRemoval = true) + protected void mountChild(@Nullable Component child, Size space, Consumer layoutFunc) { + if (child == null) return; + + child.inflate(space); + this.mountChild(child, layoutFunc); + } + /** * Mount a child using the given mounting function if its positioning * is equal to {@link Positioning#layout()}, or according to its * intrinsic positioning otherwise * * @param child The child to mount - * @param space The available space for the to expand into * @param layoutFunc The mounting function for components which follow the layout */ - protected void mountChild(@Nullable Component child, Size space, Consumer layoutFunc) { + protected void mountChild(@Nullable Component child, Consumer layoutFunc) { if (child == null) return; final var positioning = child.positioning().get(); @@ -313,30 +325,21 @@ protected void mountChild(@Nullable Component child, Size space, Consumer layoutFunc.accept(child); - case ABSOLUTE -> { - child.inflate(space); - child.mount( - this, - this.x + positioning.x + componentMargins.left() + padding.left(), - this.y + positioning.y + componentMargins.top() + padding.top() - ); - } - case RELATIVE -> { - child.inflate(space); - child.mount( - this, - this.x + padding.left() + componentMargins.left() + Math.round((positioning.x / 100f) * (this.width() - child.fullSize().width() - padding.horizontal())), - this.y + padding.top() + componentMargins.top() + Math.round((positioning.y / 100f) * (this.height() - child.fullSize().height() - padding.vertical())) - ); - } - case ACROSS -> { - child.inflate(space); - child.mount( - this, - this.x + padding.left() + componentMargins.left() + Math.round((positioning.x / 100f) * (this.width() - padding.horizontal())), - this.y + padding.top() + componentMargins.top() + Math.round((positioning.y / 100f) * (this.height() - padding.vertical())) - ); - } + case ABSOLUTE -> child.mount( + this, + this.x + positioning.x + componentMargins.left() + padding.left(), + this.y + positioning.y + componentMargins.top() + padding.top() + ); + case RELATIVE -> child.mount( + this, + this.x + padding.left() + componentMargins.left() + Math.round((positioning.x / 100f) * (this.width() - child.fullSize().width() - padding.horizontal())), + this.y + padding.top() + componentMargins.top() + Math.round((positioning.y / 100f) * (this.height() - child.fullSize().height() - padding.vertical())) + ); + case ACROSS -> child.mount( + this, + this.x + padding.left() + componentMargins.left() + Math.round((positioning.x / 100f) * (this.width() - padding.horizontal())), + this.y + padding.top() + componentMargins.top() + Math.round((positioning.y / 100f) * (this.height() - padding.vertical())) + ); } } @@ -347,7 +350,7 @@ protected void mountChild(@Nullable Component child, Size space, Consumer children) { + protected void drawChildren(OwoUIDrawContext context, int mouseX, int mouseY, float partialTicks, float delta, List children) { if (!this.allowOverflow) { var padding = this.padding.get(); ScissorStack.push(this.x + padding.left(), this.y + padding.top(), this.width - padding.horizontal(), this.height - padding.vertical(), context.getMatrices()); diff --git a/src/main/java/io/wispforest/owo/ui/container/FlowLayout.java b/src/main/java/io/wispforest/owo/ui/container/FlowLayout.java index b2a827b9..6f075e3a 100644 --- a/src/main/java/io/wispforest/owo/ui/container/FlowLayout.java +++ b/src/main/java/io/wispforest/owo/ui/container/FlowLayout.java @@ -184,7 +184,7 @@ public interface Algorithm { container.children.forEach(child -> child.inflate(childSpace)); - var mountState = MountingHelper.mountEarly(container::mountChild, container.children, childSpace, child -> { + var mountState = MountingHelper.mountEarly(container::mountChild, container.children, child -> { layout.add(child); child.mount(container, @@ -232,7 +232,7 @@ public interface Algorithm { container.children.forEach(child -> child.inflate(childSpace)); - var mountState = MountingHelper.mountEarly(container::mountChild, container.children, childSpace, child -> { + var mountState = MountingHelper.mountEarly(container::mountChild, container.children, child -> { layout.add(child); child.mount(container, @@ -287,7 +287,7 @@ public interface Algorithm { container.children.forEach(child -> child.inflate(childSpace)); - var mountState = MountingHelper.mountEarly(container::mountChild, container.children, childSpace, child -> { + var mountState = MountingHelper.mountEarly(container::mountChild, container.children, child -> { layout.add(child); int x = container.x + padding.left() + child.margins().get().left() + rowWidth.intValue(); diff --git a/src/main/java/io/wispforest/owo/ui/container/GridLayout.java b/src/main/java/io/wispforest/owo/ui/container/GridLayout.java index 4bdbb1e4..6c9ff769 100644 --- a/src/main/java/io/wispforest/owo/ui/container/GridLayout.java +++ b/src/main/java/io/wispforest/owo/ui/container/GridLayout.java @@ -70,7 +70,7 @@ public void layout(Size space) { int columnSize = columnSizes[column]; int rowSize = rowSizes[row]; - this.mountChild(this.getChild(row, column), childSpace, child -> { + this.mountChild(this.getChild(row, column), child -> { child.mount( this, layoutX.intValue() + child.margins().get().left() + this.horizontalAlignment().align(child.fullSize().width(), columnSize), @@ -99,7 +99,7 @@ public void draw(OwoUIDrawContext context, int mouseX, int mouseY, float partial } protected void determineSizes(int[] sizes, boolean rows) { - if ((rows ? this.verticalSizing : this.horizontalSizing).get().method != Sizing.Method.CONTENT) { + if (!(rows ? this.verticalSizing : this.horizontalSizing).get().isContent()) { Arrays.fill(sizes, (rows ? this.height - this.padding().get().vertical() : this.width - this.padding().get().horizontal()) / (rows ? this.rows : this.columns)); } else { for (int row = 0; row < this.rows; row++) { diff --git a/src/main/java/io/wispforest/owo/ui/container/StackLayout.java b/src/main/java/io/wispforest/owo/ui/container/StackLayout.java index 717c8bea..6f37a39f 100644 --- a/src/main/java/io/wispforest/owo/ui/container/StackLayout.java +++ b/src/main/java/io/wispforest/owo/ui/container/StackLayout.java @@ -44,9 +44,9 @@ public void layout(Size space) { var layoutHeight = new MutableInt(); var layout = new ArrayList(); - var helper = MountingHelper.mountEarly(this::mountChild, this.childrenView, childSpace, child -> { - child.mount(this, this.x + child.margins().get().left(), this.y + child.margins().get().top()); + var helper = MountingHelper.mountEarly(this::mountChild, this.childrenView, child -> { layout.add(child); + child.mount(this, this.x + this.padding.get().left() + child.margins().get().left(), this.y + this.padding.get().top() + child.margins().get().top()); var fullChildSize = child.fullSize(); layoutWidth.setValue(Math.max(layoutWidth.getValue(), fullChildSize.width())); @@ -60,8 +60,8 @@ public void layout(Size space) { var verticalAlignment = this.verticalAlignment(); for (var child : layout) { - child.updateX(child.x() + horizontalAlignment.align(child.fullSize().width(), this.width)); - child.updateY(child.y() + verticalAlignment.align(child.fullSize().height(), this.height)); + child.updateX(child.x() + horizontalAlignment.align(child.fullSize().width(), this.width - this.padding.get().horizontal())); + child.updateY(child.y() + verticalAlignment.align(child.fullSize().height(), this.height - this.padding.get().vertical())); } helper.mountLate(); diff --git a/src/main/java/io/wispforest/owo/ui/hud/HudContainer.java b/src/main/java/io/wispforest/owo/ui/hud/HudContainer.java index e75d242c..b14d6a4c 100644 --- a/src/main/java/io/wispforest/owo/ui/hud/HudContainer.java +++ b/src/main/java/io/wispforest/owo/ui/hud/HudContainer.java @@ -3,7 +3,6 @@ import io.wispforest.owo.ui.container.FlowLayout; import io.wispforest.owo.ui.core.Component; import io.wispforest.owo.ui.core.Positioning; -import io.wispforest.owo.ui.core.Size; import io.wispforest.owo.ui.core.Sizing; import org.jetbrains.annotations.Nullable; @@ -20,13 +19,13 @@ protected HudContainer(Sizing horizontalSizing, Sizing verticalSizing) { } @Override - protected void mountChild(@Nullable Component child, Size space, Consumer layoutFunc) { + protected void mountChild(@Nullable Component child, Consumer layoutFunc) { if (child == null) return; if (child.positioning().get().type == Positioning.Type.LAYOUT) { throw new IllegalStateException("owo-ui HUD components must be explicitly positioned"); } else { - super.mountChild(child, space, layoutFunc); + super.mountChild(child, layoutFunc); } } } diff --git a/src/main/java/io/wispforest/owo/ui/util/MountingHelper.java b/src/main/java/io/wispforest/owo/ui/util/MountingHelper.java index d564aeed..8309cfde 100644 --- a/src/main/java/io/wispforest/owo/ui/util/MountingHelper.java +++ b/src/main/java/io/wispforest/owo/ui/util/MountingHelper.java @@ -1,8 +1,6 @@ package io.wispforest.owo.ui.util; import io.wispforest.owo.ui.core.Component; -import io.wispforest.owo.ui.core.Positioning; -import io.wispforest.owo.ui.core.Size; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -13,37 +11,35 @@ public class MountingHelper { protected final ComponentSink sink; protected final List lateChildren; - protected final Size childSpace; - protected MountingHelper(ComponentSink sink, List children, Size childSpace) { + protected MountingHelper(ComponentSink sink, List children) { this.sink = sink; this.lateChildren = children; - this.childSpace = childSpace; } - public static MountingHelper mountEarly(ComponentSink sink, List children, Size childSpace, Consumer layoutFunc) { + public static MountingHelper mountEarly(ComponentSink sink, List children, Consumer layoutFunc) { var lateChildren = new ArrayList(); for (var child : children) { if (!child.positioning().get().isRelative()) { - sink.accept(child, childSpace, layoutFunc); + sink.accept(child, layoutFunc); } else { lateChildren.add(child); } } - return new MountingHelper(sink, lateChildren, childSpace); + return new MountingHelper(sink, lateChildren); } public void mountLate() { - for (var child : lateChildren) { - this.sink.accept(child, this.childSpace, component -> {throw new IllegalStateException("A layout-positioned child was mounted late");}); + for (var child : this.lateChildren) { + this.sink.accept(child, component -> {throw new IllegalStateException("A layout-positioned child was mounted late");}); } this.lateChildren.clear(); } public interface ComponentSink { - void accept(@Nullable Component child, Size space, Consumer layoutFunc); + void accept(@Nullable Component child, Consumer layoutFunc); } } From 0ef3e5ab6190650b1b085c87a8687866aa591b04 Mon Sep 17 00:00:00 2001 From: glisco Date: Sat, 5 Aug 2023 02:58:25 +0200 Subject: [PATCH 04/19] [ui] allow interpolating between sizing instances which use different methods --- .../owo/ui/base/BaseParentComponent.java | 4 +- .../io/wispforest/owo/ui/core/Sizing.java | 83 +++++++++++++++++-- .../uwu/client/SelectUwuScreenScreen.java | 1 + .../uwu/client/SizingTestScreen.java | 30 +++++++ 4 files changed, 111 insertions(+), 7 deletions(-) create mode 100644 src/testmod/java/io/wispforest/uwu/client/SizingTestScreen.java diff --git a/src/main/java/io/wispforest/owo/ui/base/BaseParentComponent.java b/src/main/java/io/wispforest/owo/ui/base/BaseParentComponent.java index 63e9149e..8d986625 100644 --- a/src/main/java/io/wispforest/owo/ui/base/BaseParentComponent.java +++ b/src/main/java/io/wispforest/owo/ui/base/BaseParentComponent.java @@ -388,8 +388,8 @@ protected Size calculateChildSpace(Size thisSpace) { final var padding = this.padding.get(); return Size.of( - this.horizontalSizing.get().isContent() ? thisSpace.width() - padding.horizontal() : this.width - padding.horizontal(), - this.verticalSizing.get().isContent() ? thisSpace.height() - padding.vertical() : this.height - padding.vertical() + MathHelper.lerp(this.horizontalSizing.get().contentFactor(), this.width - padding.horizontal(), thisSpace.width() - padding.horizontal()), + MathHelper.lerp(this.verticalSizing.get().contentFactor(), this.height - padding.vertical(), thisSpace.height() - padding.vertical()) ); } diff --git a/src/main/java/io/wispforest/owo/ui/core/Sizing.java b/src/main/java/io/wispforest/owo/ui/core/Sizing.java index 3179ce13..cc76439f 100644 --- a/src/main/java/io/wispforest/owo/ui/core/Sizing.java +++ b/src/main/java/io/wispforest/owo/ui/core/Sizing.java @@ -1,6 +1,5 @@ package io.wispforest.owo.ui.core; -import io.wispforest.owo.Owo; import io.wispforest.owo.ui.parsing.UIModelParsingException; import net.minecraft.util.math.MathHelper; import org.w3c.dom.Element; @@ -66,18 +65,33 @@ public static Sizing fill(int percent) { return new Sizing(percent, Method.FILL); } + /** + * @return {@code true} if this sizing instance + * uses the {@linkplain Method#CONTENT CONTENT} method + */ public boolean isContent() { return this.method == Method.CONTENT; } + /** + * The content factor of a sizing instance describes where + * on the spectrum from content to fixed sizing it sits. Specifically, this is + * used to lerp the reference frame used for calculating {@code fill(...)} sizing + * on children between the available space in this component (content factor 0) + * and this component's own available space (content factor 1), both of which can be + * independently determined prior to layout calculations + */ + public float contentFactor() { + return this.isContent() ? 1f : 0f; + } + @Override public Sizing interpolate(Sizing next, float delta) { if (next.method != this.method) { - Owo.LOGGER.warn("Cannot interpolate between sizing with method " + this.method + " and " + next.method); - return this; + return new MergedSizing(this, next, delta); + } else { + return new Sizing(MathHelper.lerp(delta, this.value, next.value), this.method); } - - return new Sizing((int) MathHelper.lerp(delta, this.value, next.value), this.method); } public enum Method { @@ -121,4 +135,63 @@ public int hashCode() { return Objects.hash(method, value); } + private static class MergedSizing extends Sizing { + + private final Sizing first, second; + private final float delta; + + private MergedSizing(Sizing first, Sizing second, float delta) { + super(first.value, first.method); + this.first = first; + this.second = second; + this.delta = delta; + } + + @Override + public int inflate(int space, Function contentSizeFunction) { + return MathHelper.lerp( + this.delta, + this.first.inflate(space, contentSizeFunction), + this.second.inflate(space, contentSizeFunction) + ); + } + + @Override + public Sizing interpolate(Sizing next, float delta) { + return this.first.interpolate(next, delta); + } + + @Override + public boolean isContent() { + return this.first.isContent() || this.second.isContent(); + } + + @Override + public float contentFactor() { + if (this.first.isContent() && this.second.isContent()) return super.contentFactor(); + + if (this.first.isContent()) { + return 1f - delta; + } else if (this.second.isContent()) { + return delta; + } else { + return 0f; + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + MergedSizing that = (MergedSizing) o; + return Float.compare(delta, that.delta) == 0 && Objects.equals(first, that.first) && Objects.equals(second, that.second); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), first, second, delta); + } + } + } diff --git a/src/testmod/java/io/wispforest/uwu/client/SelectUwuScreenScreen.java b/src/testmod/java/io/wispforest/uwu/client/SelectUwuScreenScreen.java index 01f69f93..b602f2e2 100644 --- a/src/testmod/java/io/wispforest/uwu/client/SelectUwuScreenScreen.java +++ b/src/testmod/java/io/wispforest/uwu/client/SelectUwuScreenScreen.java @@ -48,6 +48,7 @@ protected void build(FlowLayout rootComponent) { protected void build(FlowLayout rootComponent) {} }))); panel.child(Components.button(Text.literal("smolnite"), button -> this.client.setScreen(new SmolComponentTestScreen()))); + panel.child(Components.button(Text.literal("sizenite"), button -> this.client.setScreen(new SizingTestScreen()))); this.uiAdapter.rootComponent.child(panel); } diff --git a/src/testmod/java/io/wispforest/uwu/client/SizingTestScreen.java b/src/testmod/java/io/wispforest/uwu/client/SizingTestScreen.java new file mode 100644 index 00000000..9c1dc09a --- /dev/null +++ b/src/testmod/java/io/wispforest/uwu/client/SizingTestScreen.java @@ -0,0 +1,30 @@ +package io.wispforest.uwu.client; + +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.StackLayout; +import io.wispforest.owo.ui.core.*; +import net.minecraft.text.Text; +import org.jetbrains.annotations.NotNull; + +public class SizingTestScreen extends BaseOwoScreen { + @Override + protected @NotNull OwoUIAdapter createAdapter() { + return OwoUIAdapter.create(this, Containers::horizontalFlow); + } + + @Override + protected void build(FlowLayout rootComponent) { + rootComponent.horizontalAlignment(HorizontalAlignment.CENTER).verticalAlignment(VerticalAlignment.CENTER); + rootComponent.child(Containers.stack(Sizing.content(), Sizing.content()).configure(container -> { + container.horizontalAlignment(HorizontalAlignment.CENTER).surface(Surface.panelWithInset(6)).padding(Insets.of(15)); + + var animation = container.horizontalSizing().animate(500, Easing.CUBIC, Sizing.fill(75)); + container.child(Components.button(Text.literal("initialize sizenite"), button -> { + animation.reverse(); + }).horizontalSizing(Sizing.fill(50))); + })); + } +} From 4f50d45c6accde7b746ead5e34754aa7344ff565 Mon Sep 17 00:00:00 2001 From: glisco Date: Sat, 5 Aug 2023 15:28:42 +0200 Subject: [PATCH 05/19] [ui] begin implementing workaround for screens being disposed during cross-screen navigation --- .../owo/mixin/ui/MinecraftClientMixin.java | 43 +++++++++++++++++++ .../owo/ui/base/BaseOwoHandledScreen.java | 12 +++++- .../wispforest/owo/ui/base/BaseOwoScreen.java | 12 +++++- .../owo/ui/util/DisposableScreen.java | 19 ++++++++ 4 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 src/main/java/io/wispforest/owo/ui/util/DisposableScreen.java diff --git a/src/main/java/io/wispforest/owo/mixin/ui/MinecraftClientMixin.java b/src/main/java/io/wispforest/owo/mixin/ui/MinecraftClientMixin.java index 5606bf72..56a65757 100644 --- a/src/main/java/io/wispforest/owo/mixin/ui/MinecraftClientMixin.java +++ b/src/main/java/io/wispforest/owo/mixin/ui/MinecraftClientMixin.java @@ -1,25 +1,68 @@ package io.wispforest.owo.mixin.ui; import io.wispforest.owo.ui.event.WindowResizeCallback; +import io.wispforest.owo.ui.util.DisposableScreen; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.util.Window; +import net.minecraft.util.crash.CrashException; +import net.minecraft.util.crash.CrashReport; +import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.HashSet; +import java.util.Set; + @Mixin(MinecraftClient.class) public class MinecraftClientMixin { + @Unique + private final Set screensToDispose = new HashSet<>(); + @Shadow @Final private Window window; + @Shadow + @Nullable + public Screen currentScreen; + @Inject(method = "onResolutionChanged", at = @At("TAIL")) private void captureResize(CallbackInfo ci) { WindowResizeCallback.EVENT.invoker().onResized((MinecraftClient) (Object) this, this.window); } + @Inject(method = "setScreen", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/Screen;removed()V")) + private void captureSetScreen(Screen screen, CallbackInfo ci) { + if (screen != null && this.currentScreen instanceof DisposableScreen disposable) { + this.screensToDispose.add(disposable); + } else if (screen == null) { + if (this.currentScreen instanceof DisposableScreen disposable) { + this.screensToDispose.add(disposable); + } + + for (var disposable : this.screensToDispose) { + try { + disposable.dispose(); + } catch (Throwable error) { + var report = new CrashReport("Failed to dispose screen", error); + report.addElement("Screen being disposed: ") + .add("Screen class", disposable.getClass()) + .add("Screen being closed", this.currentScreen) + .add("Total screens to dispose", this.screensToDispose.size()); + + throw new CrashException(report); + } + } + + this.screensToDispose.clear(); + } + } + } diff --git a/src/main/java/io/wispforest/owo/ui/base/BaseOwoHandledScreen.java b/src/main/java/io/wispforest/owo/ui/base/BaseOwoHandledScreen.java index 3af7bd80..06772177 100644 --- a/src/main/java/io/wispforest/owo/ui/base/BaseOwoHandledScreen.java +++ b/src/main/java/io/wispforest/owo/ui/base/BaseOwoHandledScreen.java @@ -4,6 +4,7 @@ import io.wispforest.owo.mixin.ui.SlotAccessor; import io.wispforest.owo.ui.core.*; import io.wispforest.owo.ui.inject.GreedyInputComponent; +import io.wispforest.owo.ui.util.DisposableScreen; import io.wispforest.owo.ui.util.UIErrorToast; import io.wispforest.owo.util.pond.OwoSlotExtension; import net.minecraft.client.gui.DrawContext; @@ -21,7 +22,7 @@ import java.util.function.BiFunction; -public abstract class BaseOwoHandledScreen extends HandledScreen { +public abstract class BaseOwoHandledScreen extends HandledScreen implements DisposableScreen { /** * The UI adapter of this screen. This handles @@ -210,8 +211,15 @@ public Element getFocused() { @Override public void removed() { - if (this.uiAdapter != null) this.uiAdapter.dispose(); super.removed(); + if (this.uiAdapter != null) { + this.uiAdapter.cursorAdapter.applyStyle(CursorStyle.NONE); + } + } + + @Override + public void dispose() { + if (this.uiAdapter != null) this.uiAdapter.dispose(); } @Override diff --git a/src/main/java/io/wispforest/owo/ui/base/BaseOwoScreen.java b/src/main/java/io/wispforest/owo/ui/base/BaseOwoScreen.java index 1482d986..f690305f 100644 --- a/src/main/java/io/wispforest/owo/ui/base/BaseOwoScreen.java +++ b/src/main/java/io/wispforest/owo/ui/base/BaseOwoScreen.java @@ -2,14 +2,15 @@ import io.wispforest.owo.Owo; import io.wispforest.owo.ui.core.Component; +import io.wispforest.owo.ui.core.CursorStyle; import io.wispforest.owo.ui.core.OwoUIAdapter; import io.wispforest.owo.ui.core.ParentComponent; import io.wispforest.owo.ui.inject.GreedyInputComponent; +import io.wispforest.owo.ui.util.DisposableScreen; import io.wispforest.owo.ui.util.UIErrorToast; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.Element; import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,7 +32,7 @@ * * @param The type of root component this screen uses */ -public abstract class BaseOwoScreen extends Screen { +public abstract class BaseOwoScreen extends Screen implements DisposableScreen { /** * The UI adapter of this screen. This handles @@ -140,6 +141,13 @@ public Element getFocused() { @Override public void removed() { + if (this.uiAdapter != null) { + this.uiAdapter.cursorAdapter.applyStyle(CursorStyle.NONE); + } + } + + @Override + public void dispose() { if (this.uiAdapter != null) this.uiAdapter.dispose(); } } diff --git a/src/main/java/io/wispforest/owo/ui/util/DisposableScreen.java b/src/main/java/io/wispforest/owo/ui/util/DisposableScreen.java new file mode 100644 index 00000000..320c65f1 --- /dev/null +++ b/src/main/java/io/wispforest/owo/ui/util/DisposableScreen.java @@ -0,0 +1,19 @@ +package io.wispforest.owo.ui.util; + +import net.minecraft.client.gui.screen.Screen; + +/** + * Screens that wish to be notified when the players navigates back to + * the game instead of to another screen may implement this interface + * for a more reliable alternative to {@link Screen#removed()} + */ +public interface DisposableScreen { + + /** + * Invoked when a best-effort algorithm has determined + * that the player is navigating to return to the game instead of opening + * another screen - ensured to be called too often than too rarely + */ + void dispose(); + +} From 9a74a0d1ced4f41c9ef86015e6da51936148ced2 Mon Sep 17 00:00:00 2001 From: glisco Date: Sat, 5 Aug 2023 15:29:26 +0200 Subject: [PATCH 06/19] [ui] remove overzealous @Nullable annotation on ParentComponent#childById --- src/main/java/io/wispforest/owo/ui/core/ParentComponent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/wispforest/owo/ui/core/ParentComponent.java b/src/main/java/io/wispforest/owo/ui/core/ParentComponent.java index 1699ebba..d977813e 100644 --- a/src/main/java/io/wispforest/owo/ui/core/ParentComponent.java +++ b/src/main/java/io/wispforest/owo/ui/core/ParentComponent.java @@ -206,7 +206,7 @@ default void parseProperties(UIModel model, Element element, Map @Nullable T childById(@NotNull Class expectedClass, @NotNull String id) { + default T childById(@NotNull Class expectedClass, @NotNull String id) { var iter = this.children().listIterator(this.children().size()); while (iter.hasPrevious()) { From fce249c339509891d52f862d2cb5a73474ac07c0 Mon Sep 17 00:00:00 2001 From: glisco Date: Sun, 6 Aug 2023 00:56:50 +0200 Subject: [PATCH 07/19] [ui] add UIParsing.registerFactory overload which takes an identifier --- .../wispforest/owo/ui/parsing/UIParsing.java | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/main/java/io/wispforest/owo/ui/parsing/UIParsing.java b/src/main/java/io/wispforest/owo/ui/parsing/UIParsing.java index 06b6d507..0bf61261 100644 --- a/src/main/java/io/wispforest/owo/ui/parsing/UIParsing.java +++ b/src/main/java/io/wispforest/owo/ui/parsing/UIParsing.java @@ -8,6 +8,7 @@ import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.InvalidIdentifierException; +import org.jetbrains.annotations.ApiStatus; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -24,14 +25,11 @@ public class UIParsing { private static final Map> COMPONENT_FACTORIES = new HashMap<>(); /** - * Register a factory used to create components from XML elements. - * Most factories will only consider the tag name of the element, - * but more context can be extracted from the passed element - * - * @param componentTagName The tag name of elements for which the - * passed factory should be invoked - * @param factory The factory to register + * @deprecated In order to more properly separate factories added by different + * mods, use {@link #registerFactory(Identifier, Function)}, which takes an + * identifier instead */ + @ApiStatus.Internal public static void registerFactory(String componentTagName, Function factory) { if (COMPONENT_FACTORIES.containsKey(componentTagName)) { throw new IllegalStateException("A component factory with name " + componentTagName + " is already registered"); @@ -40,6 +38,20 @@ public static void registerFactory(String componentTagName, Function factory) { + registerFactory(componentId.getNamespace() + "." + componentId.getPath(), factory); + } + /** * Get the appropriate component factory for the given * XML element. An exception is thrown if none is registered From d397b9825c6b74315d3f5bb4a5617de36f7ea9ff Mon Sep 17 00:00:00 2001 From: chyzman <32403637+chyzman@users.noreply.github.com> Date: Wed, 9 Aug 2023 14:30:25 -0400 Subject: [PATCH 08/19] Made Sizing.fill better Sizing.fill() = Sizing.fill(100) --- src/main/java/io/wispforest/owo/ui/core/Sizing.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/io/wispforest/owo/ui/core/Sizing.java b/src/main/java/io/wispforest/owo/ui/core/Sizing.java index 3179ce13..e6eb3c24 100644 --- a/src/main/java/io/wispforest/owo/ui/core/Sizing.java +++ b/src/main/java/io/wispforest/owo/ui/core/Sizing.java @@ -56,6 +56,13 @@ public static Sizing content() { public static Sizing content(int padding) { return new Sizing(padding, Method.CONTENT); } + + /** + * Dynamically size the component to fill the available space + */ + public static Sizing fill() { + return fill(100); + } /** * Dynamically size the component based on the available space From 19dac0963e14108e18a80af8b4a045822f5559e2 Mon Sep 17 00:00:00 2001 From: glisco Date: Tue, 15 Aug 2023 00:33:37 +0200 Subject: [PATCH 09/19] only display multi-select hint when multiple tabs can actually be selected and don't display it on non-tab buttons --- .../io/wispforest/owo/itemgroup/OwoItemGroup.java | 4 ++++ .../owo/itemgroup/gui/ItemGroupButtonWidget.java | 4 ++++ .../itemgroup/CreativeInventoryScreenMixin.java | 14 ++++++++------ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/main/java/io/wispforest/owo/itemgroup/OwoItemGroup.java b/src/main/java/io/wispforest/owo/itemgroup/OwoItemGroup.java index 1194e9cc..97906cdc 100644 --- a/src/main/java/io/wispforest/owo/itemgroup/OwoItemGroup.java +++ b/src/main/java/io/wispforest/owo/itemgroup/OwoItemGroup.java @@ -326,6 +326,10 @@ public boolean shouldDisplaySingleTab() { return this.displaySingleTab; } + public boolean canSelectMultipleTabs() { + return this.allowMultiSelect; + } + public List getButtons() { return buttons; } diff --git a/src/main/java/io/wispforest/owo/itemgroup/gui/ItemGroupButtonWidget.java b/src/main/java/io/wispforest/owo/itemgroup/gui/ItemGroupButtonWidget.java index f685b901..23f3709f 100644 --- a/src/main/java/io/wispforest/owo/itemgroup/gui/ItemGroupButtonWidget.java +++ b/src/main/java/io/wispforest/owo/itemgroup/gui/ItemGroupButtonWidget.java @@ -32,6 +32,10 @@ public void renderButton(DrawContext context, int mouseX, int mouseY, float delt RenderSystem.disableBlend(); } + public boolean isTab() { + return this.definition instanceof ItemGroupTab; + } + public boolean trulyHovered() { return this.hovered; } diff --git a/src/main/java/io/wispforest/owo/mixin/itemgroup/CreativeInventoryScreenMixin.java b/src/main/java/io/wispforest/owo/mixin/itemgroup/CreativeInventoryScreenMixin.java index 940289d7..475eae5f 100644 --- a/src/main/java/io/wispforest/owo/mixin/itemgroup/CreativeInventoryScreenMixin.java +++ b/src/main/java/io/wispforest/owo/mixin/itemgroup/CreativeInventoryScreenMixin.java @@ -180,7 +180,14 @@ private void render(DrawContext context, int mouseX, int mouseY, float delta, Ca for (var button : this.owo$buttons) { if (button.trulyHovered()) { - context.drawTooltip(this.textRenderer, List.of(button.getMessage(), Text.translatable("text.owo.itemGroup.select_hint")), mouseX, mouseY); + context.drawTooltip( + this.textRenderer, + button.isTab() && ((OwoItemGroup)selectedTab).canSelectMultipleTabs() + ? List.of(button.getMessage(), Text.translatable("text.owo.itemGroup.select_hint")) + : List.of(button.getMessage()), + mouseX, + mouseY + ); anyButtonHovered = true; } } @@ -188,11 +195,6 @@ private void render(DrawContext context, int mouseX, int mouseY, float delta, Ca this.owo$cursorAdapter.applyStyle(anyButtonHovered ? CursorStyle.HAND : CursorStyle.NONE); } - @Inject(method = "init", at = @At("HEAD")) - private void createCursorAdapter(CallbackInfo ci) { -// this.owo$cursorAdapter = CursorAdapter.ofClientWindow(); - } - @Inject(method = "removed", at = @At("HEAD")) private void disposeCursorAdapter(CallbackInfo ci) { this.owo$cursorAdapter.dispose(); From 78ec9381012e7f4b87de6adde46c6f1672977482 Mon Sep 17 00:00:00 2001 From: glisco Date: Sun, 20 Aug 2023 14:56:53 +0200 Subject: [PATCH 10/19] [ui] properly separate base point and visual position of components to fix draggable container behaving incorrectly during sequential layout updates (fixes #154) --- gradle.properties | 2 +- .../owo/itemgroup/OwoItemGroup.java | 4 +- .../owo/ui/base/BaseParentComponent.java | 4 +- .../owo/ui/container/DraggableContainer.java | 10 +++++ .../owo/ui/container/FlowLayout.java | 18 ++++----- .../owo/ui/container/StackLayout.java | 4 +- .../io/wispforest/owo/ui/core/Component.java | 40 +++++++++++++++++++ 7 files changed, 66 insertions(+), 16 deletions(-) diff --git a/gradle.properties b/gradle.properties index 7a50663d..dac2667b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,7 +7,7 @@ minecraft_version=1.20.1 yarn_mappings=1.20.1+build.2 loader_version=0.14.21 # Mod Properties -mod_version=0.11.2-pre.9 +mod_version=0.11.2-pre.11 maven_group=io.wispforest archives_base_name=owo-lib # Dependencies diff --git a/src/main/java/io/wispforest/owo/itemgroup/OwoItemGroup.java b/src/main/java/io/wispforest/owo/itemgroup/OwoItemGroup.java index 97906cdc..af2c463a 100644 --- a/src/main/java/io/wispforest/owo/itemgroup/OwoItemGroup.java +++ b/src/main/java/io/wispforest/owo/itemgroup/OwoItemGroup.java @@ -32,7 +32,7 @@ * {@link OwoItemSettings#tab(int)}. Furthermore, tags can be used for easily populating * tabs from data *

- * This concept originated in Biome Makeover, where it was written by Lemonszz + * The roots of this implementation originated in Biome Makeover, where it was written by Lemonszz */ public abstract class OwoItemGroup extends ItemGroup { @@ -98,7 +98,7 @@ public void initialize() { if (this.initialized) return; if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) this.initializer.accept(this); - if (tabs.size() == 0) this.tabs.add(PLACEHOLDER_TAB); + if (this.tabs.isEmpty()) this.tabs.add(PLACEHOLDER_TAB); if (this.allowMultiSelect) { for (int tabIdx = 0; tabIdx < this.tabs.size(); tabIdx++) { diff --git a/src/main/java/io/wispforest/owo/ui/base/BaseParentComponent.java b/src/main/java/io/wispforest/owo/ui/base/BaseParentComponent.java index 8d986625..a3133939 100644 --- a/src/main/java/io/wispforest/owo/ui/base/BaseParentComponent.java +++ b/src/main/java/io/wispforest/owo/ui/base/BaseParentComponent.java @@ -271,7 +271,7 @@ public void updateX(int x) { super.updateX(x); for (var child : this.children()) { - child.updateX(child.x() + offset); + child.updateX(child.baseX() + offset); } } @@ -281,7 +281,7 @@ public void updateY(int y) { super.updateY(y); for (var child : this.children()) { - child.updateY(child.y() + offset); + child.updateY(child.baseY() + offset); } } diff --git a/src/main/java/io/wispforest/owo/ui/container/DraggableContainer.java b/src/main/java/io/wispforest/owo/ui/container/DraggableContainer.java index d5798392..51bf725c 100644 --- a/src/main/java/io/wispforest/owo/ui/container/DraggableContainer.java +++ b/src/main/java/io/wispforest/owo/ui/container/DraggableContainer.java @@ -72,6 +72,16 @@ public void updateY(int y) { super.updateY((int) (y + Math.round(this.yOffset))); } + @Override + public int baseX() { + return this.baseX; + } + + @Override + public int baseY() { + return this.baseY; + } + @Override public ParentComponent padding(Insets padding) { return super.padding(Insets.of(padding.top() + this.foreheadSize, padding.bottom(), padding.left(), padding.right())); diff --git a/src/main/java/io/wispforest/owo/ui/container/FlowLayout.java b/src/main/java/io/wispforest/owo/ui/container/FlowLayout.java index 6f075e3a..42d21ff4 100644 --- a/src/main/java/io/wispforest/owo/ui/container/FlowLayout.java +++ b/src/main/java/io/wispforest/owo/ui/container/FlowLayout.java @@ -205,16 +205,16 @@ public interface Algorithm { if (container.verticalAlignment() != VerticalAlignment.TOP) { for (var component : layout) { - component.updateY(component.y() + container.verticalAlignment().align(component.fullSize().height(), container.height - padding.vertical())); + component.updateY(component.baseY() + container.verticalAlignment().align(component.fullSize().height(), container.height - padding.vertical())); } } if (container.horizontalAlignment() != HorizontalAlignment.LEFT) { for (var component : layout) { if (container.horizontalAlignment() == HorizontalAlignment.CENTER) { - component.updateX(component.x() + (container.width - padding.horizontal() - layoutWidth.intValue()) / 2); + component.updateX(component.baseX() + (container.width - padding.horizontal() - layoutWidth.intValue()) / 2); } else { - component.updateX(component.x() + (container.width - padding.horizontal() - layoutWidth.intValue())); + component.updateX(component.baseX() + (container.width - padding.horizontal() - layoutWidth.intValue())); } } } @@ -253,16 +253,16 @@ public interface Algorithm { if (container.horizontalAlignment() != HorizontalAlignment.LEFT) { for (var component : layout) { - component.updateX(component.x() + container.horizontalAlignment().align(component.fullSize().width(), container.width - padding.horizontal())); + component.updateX(component.baseX() + container.horizontalAlignment().align(component.fullSize().width(), container.width - padding.horizontal())); } } if (container.verticalAlignment() != VerticalAlignment.TOP) { for (var component : layout) { if (container.verticalAlignment() == VerticalAlignment.CENTER) { - component.updateY(component.y() + (container.height - padding.vertical() - layoutHeight.intValue()) / 2); + component.updateY(component.baseY() + (container.height - padding.vertical() - layoutHeight.intValue()) / 2); } else { - component.updateY(component.y() + (container.height - padding.vertical() - layoutHeight.intValue())); + component.updateY(component.baseY() + (container.height - padding.vertical() - layoutHeight.intValue())); } } } @@ -320,16 +320,16 @@ public interface Algorithm { if (container.verticalAlignment() != VerticalAlignment.TOP) { for (var component : layout) { - component.updateY(component.y() + container.verticalAlignment().align(layoutHeight.intValue(), container.height - padding.vertical())); + component.updateY(component.baseY() + container.verticalAlignment().align(layoutHeight.intValue(), container.height - padding.vertical())); } } if (container.horizontalAlignment() != HorizontalAlignment.LEFT) { for (var component : layout) { if (container.horizontalAlignment() == HorizontalAlignment.CENTER) { - component.updateX(component.x() + (container.width - padding.horizontal() - layoutWidth.intValue()) / 2); + component.updateX(component.baseX() + (container.width - padding.horizontal() - layoutWidth.intValue()) / 2); } else { - component.updateX(component.x() + (container.width - padding.horizontal() - layoutWidth.intValue())); + component.updateX(component.baseX() + (container.width - padding.horizontal() - layoutWidth.intValue())); } } } diff --git a/src/main/java/io/wispforest/owo/ui/container/StackLayout.java b/src/main/java/io/wispforest/owo/ui/container/StackLayout.java index 6f37a39f..5b1ba040 100644 --- a/src/main/java/io/wispforest/owo/ui/container/StackLayout.java +++ b/src/main/java/io/wispforest/owo/ui/container/StackLayout.java @@ -60,8 +60,8 @@ public void layout(Size space) { var verticalAlignment = this.verticalAlignment(); for (var child : layout) { - child.updateX(child.x() + horizontalAlignment.align(child.fullSize().width(), this.width - this.padding.get().horizontal())); - child.updateY(child.y() + verticalAlignment.align(child.fullSize().height(), this.height - this.padding.get().vertical())); + child.updateX(child.baseX() + horizontalAlignment.align(child.fullSize().width(), this.width - this.padding.get().horizontal())); + child.updateY(child.baseY() + verticalAlignment.align(child.fullSize().height(), this.height - this.padding.get().vertical())); } helper.mountLate(); diff --git a/src/main/java/io/wispforest/owo/ui/core/Component.java b/src/main/java/io/wispforest/owo/ui/core/Component.java index de557a58..b4ec59ae 100644 --- a/src/main/java/io/wispforest/owo/ui/core/Component.java +++ b/src/main/java/io/wispforest/owo/ui/core/Component.java @@ -534,11 +534,31 @@ default void parseProperties(UIModel model, Element element, Map + * As a general rule of thumb, this property should be used + * whenever the component's position is queried during rendering, + * input processing and s on. If however, the position is required + * in the context of a layout operation, {@link #baseX()} is almost + * always the correct choice instead */ @Override @Contract(pure = true) int x(); + /** + * @return The current x-coordinate of this component's + * base point - the point on which it bases + * layout calculations. + *

+ * For the majority of components this will be identical + * to {@link #x()} as they don't have special logic. A notable + * exception is the {@link io.wispforest.owo.ui.container.DraggableContainer} + * which internally applies a separate offset from dragging + */ + default int baseX() { + return this.x(); + } + /** * Set the x-coordinate of the top-left corner of the * bounding box of this component. @@ -558,11 +578,31 @@ default void parseProperties(UIModel model, Element element, Map + * As a general rule of thumb, this property should be used + * whenever the component's position is queried during rendering, + * input processing and s on. If however, the position is required + * in the context of a layout operation, {@link #baseY()} is almost + * always the correct choice instead */ @Override @Contract(pure = true) int y(); + /** + * @return The current y-coordinate of this component's + * base point - the point on which it bases + * layout calculations. + *

+ * For the majority of components this will be identical + * to {@link #y()} as they don't have special logic. A notable + * exception is the {@link io.wispforest.owo.ui.container.DraggableContainer} + * which internally applies a separate offset from dragging + */ + default int baseY() { + return this.y(); + } + /** * Set the y-coordinate of the top-left corner of the * bounding box of this component. From 11ba4c8c3abd608ed8bae21bf72c6c3e2801df50 Mon Sep 17 00:00:00 2001 From: glisco Date: Sun, 20 Aug 2023 14:57:04 +0200 Subject: [PATCH 11/19] slot generator documentation --- .../owo/client/screens/SlotGenerator.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/main/java/io/wispforest/owo/client/screens/SlotGenerator.java b/src/main/java/io/wispforest/owo/client/screens/SlotGenerator.java index 8683b04e..2aaecb35 100644 --- a/src/main/java/io/wispforest/owo/client/screens/SlotGenerator.java +++ b/src/main/java/io/wispforest/owo/client/screens/SlotGenerator.java @@ -6,6 +6,10 @@ import java.util.function.Consumer; +/** + * Stateful slot generation utility for easily + * arranging the slot grid used in a {@link net.minecraft.screen.ScreenHandler} + */ public final class SlotGenerator { private int anchorX, anchorY; @@ -21,16 +25,38 @@ private SlotGenerator(Consumer slotConsumer, int anchorX, int anchorY) { this.slotConsumer = slotConsumer; } + /** + * Begin generating slots into {@code slotConsumer}, starting at + * ({@code anchorX}, {@code anchorY}). Usually, the {@code slotConsumer} + * will be the {@code addSlot} method of the screen handler for which + * slots are being generated + *

+ *

+     * {@code
+     * SlotGenerator.begin(this::addSlot, 50, 10)
+     *     .grid(someInventory, 0, 3, 3) // add a 3x3 grid of slots 0-8 of 'someInventory'
+     *     .moveTo(10, 100)
+     *     .playerInventory(playerInventory); // add the player inventory and hotbar slots
+     * }
+     * 
+ */ public static SlotGenerator begin(Consumer slotConsumer, int anchorX, int anchorY) { return new SlotGenerator(slotConsumer, anchorX, anchorY); } + /** + * Move the top-left anchor point of generated grids to ({@code anchorX}, {@code anchorY}) + */ public SlotGenerator moveTo(int anchorX, int anchorY) { this.anchorX = anchorX; this.anchorY = anchorY; return this; } + /** + * Shorthand for calling both {@link #horizontalSpacing} and + * {@link #verticalSpacing} with {@code spacing} + */ public SlotGenerator spacing(int spacing) { this.horizontalSpacing = spacing; this.verticalSpacing = spacing; @@ -52,11 +78,19 @@ public SlotGenerator slotConsumer(Consumer slotConsumer) { return this; } + /** + * Reset the slot factory of this generator + * to the default {@link Slot#Slot(Inventory, int, int, int)} constructor + */ public SlotGenerator defaultSlotFactory() { this.slotFactory = Slot::new; return this; } + /** + * Set the slot factory of this generator, used for instantiating + * each generated slot, to {@code slotFactory} + */ public SlotGenerator slotFactory(SlotFactory slotFactory) { this.slotFactory = slotFactory; return this; From 1d2711ca5b81eddc6532f82e935965de1b29fb62 Mon Sep 17 00:00:00 2001 From: glisco Date: Sun, 20 Aug 2023 14:57:39 +0200 Subject: [PATCH 12/19] more wisdom --- src/main/java/io/wispforest/owo/util/Wisdom.java | 3 ++- .../io/wispforest/owo/util/pond/MatrixStackTransformer.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/wispforest/owo/util/Wisdom.java b/src/main/java/io/wispforest/owo/util/Wisdom.java index c9b97c4f..a16125b2 100644 --- a/src/main/java/io/wispforest/owo/util/Wisdom.java +++ b/src/main/java/io/wispforest/owo/util/Wisdom.java @@ -49,7 +49,8 @@ private Wisdom() {} "chyz: now i just need to painstakingly move jerry (the little tiny lil fella tiny guy man button) to correct spot when recipe book is opened", "chyz: bro, can you stop breathing", "Noaaan: It's surprising how much knowledge is lost by the simple fact that people don't know it", - "Blodhgarm: Did you know it took four switcheroos to implement the Matrices in the correct folder" + "Blodhgarm: Did you know it took four switcheroos to implement MatrixStackTransformer in the correct package?", + "chyz: who would've thought that if you don't summon satan things go better. you can put that in wisdom if you like" ); public static void spread() { diff --git a/src/main/java/io/wispforest/owo/util/pond/MatrixStackTransformer.java b/src/main/java/io/wispforest/owo/util/pond/MatrixStackTransformer.java index 39be5e11..f4449b7e 100644 --- a/src/main/java/io/wispforest/owo/util/pond/MatrixStackTransformer.java +++ b/src/main/java/io/wispforest/owo/util/pond/MatrixStackTransformer.java @@ -6,7 +6,7 @@ import org.joml.Quaternionf; /** - * Helper Interface implemented on top of the {@link DrawContext} to allow for easier matrix stack transformations + * Helper interface implemented on top of the {@link DrawContext} to allow for easier matrix stack transformations */ public interface MatrixStackTransformer { From f705f91a33f9a31f38f27c0fd9032977f97f15ca Mon Sep 17 00:00:00 2001 From: glisco Date: Sun, 20 Aug 2023 23:51:14 +0200 Subject: [PATCH 13/19] enable automatic item use stat tracking via OwoItemSettings#trackUsageStat --- .../owo/itemgroup/OwoItemSettings.java | 18 ++++++++++++ .../ServerPlayerInteractionManagerMixin.java | 28 +++++++++++++++++++ .../owo/mixin/itemgroup/ItemMixin.java | 9 ++++++ .../owo/util/pond/OwoItemExtensions.java | 5 ++++ src/main/resources/owo.mixins.json | 3 +- .../uwu/items/UwuTestStickItem.java | 1 + 6 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 src/main/java/io/wispforest/owo/mixin/ServerPlayerInteractionManagerMixin.java diff --git a/src/main/java/io/wispforest/owo/itemgroup/OwoItemSettings.java b/src/main/java/io/wispforest/owo/itemgroup/OwoItemSettings.java index 95b4c95a..6b7e49f1 100644 --- a/src/main/java/io/wispforest/owo/itemgroup/OwoItemSettings.java +++ b/src/main/java/io/wispforest/owo/itemgroup/OwoItemSettings.java @@ -3,10 +3,13 @@ import net.fabricmc.fabric.api.item.v1.CustomDamageHandler; import net.fabricmc.fabric.api.item.v1.EquipmentSlotProvider; import net.fabricmc.fabric.api.item.v1.FabricItemSettings; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.FoodComponent; import net.minecraft.item.Item; import net.minecraft.item.ItemGroup; +import net.minecraft.util.Hand; import net.minecraft.util.Rarity; +import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; import java.util.function.BiConsumer; @@ -17,6 +20,7 @@ public class OwoItemSettings extends FabricItemSettings { private OwoItemGroup group = null; private int tab = 0; private BiConsumer stackGenerator = OwoItemGroup.DEFAULT_STACK_GENERATOR; + private boolean trackUsageStat = false; public OwoItemSettings group(ItemGroupReference ref) { this.group = ref.group(); @@ -58,6 +62,20 @@ public BiConsumer stackGenerator() { return this.stackGenerator; } + /** + * Automatically increment {@link net.minecraft.stat.Stats#USED} + * for this item every time {@link Item#use(World, PlayerEntity, Hand)} + * returns an accepted result + */ + public OwoItemSettings trackUsageStat() { + this.trackUsageStat = true; + return this; + } + + public boolean shouldTrackUsageStat() { + return this.trackUsageStat; + } + @Override public OwoItemSettings equipmentSlot(EquipmentSlotProvider equipmentSlotProvider) { return (OwoItemSettings) super.equipmentSlot(equipmentSlotProvider); diff --git a/src/main/java/io/wispforest/owo/mixin/ServerPlayerInteractionManagerMixin.java b/src/main/java/io/wispforest/owo/mixin/ServerPlayerInteractionManagerMixin.java new file mode 100644 index 00000000..35cc06f8 --- /dev/null +++ b/src/main/java/io/wispforest/owo/mixin/ServerPlayerInteractionManagerMixin.java @@ -0,0 +1,28 @@ +package io.wispforest.owo.mixin; + +import io.wispforest.owo.util.pond.OwoItemExtensions; +import net.minecraft.item.ItemStack; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.network.ServerPlayerInteractionManager; +import net.minecraft.stat.Stats; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(ServerPlayerInteractionManager.class) +public class ServerPlayerInteractionManagerMixin { + + @Inject(method = "interactItem", at = @At("RETURN")) + private void incrementUseState(ServerPlayerEntity player, World world, ItemStack stack, Hand hand, CallbackInfoReturnable cir) { + if (!((OwoItemExtensions) stack.getItem()).owo$shouldTrackUsageStat() || !cir.getReturnValue().shouldIncrementStat()) { + return; + } + + player.incrementStat(Stats.USED.getOrCreateStat(stack.getItem())); + } + +} diff --git a/src/main/java/io/wispforest/owo/mixin/itemgroup/ItemMixin.java b/src/main/java/io/wispforest/owo/mixin/itemgroup/ItemMixin.java index 59f000f5..e22072b2 100644 --- a/src/main/java/io/wispforest/owo/mixin/itemgroup/ItemMixin.java +++ b/src/main/java/io/wispforest/owo/mixin/itemgroup/ItemMixin.java @@ -26,12 +26,16 @@ public class ItemMixin implements OwoItemExtensions { @Unique private BiConsumer owo$stackGenerator; + @Unique + private boolean owo$trackUsageStat = false; + @Inject(method = "", at = @At("TAIL")) private void grabTab(Item.Settings settings, CallbackInfo ci) { if (settings instanceof OwoItemSettings owoSettings) { this.owo$tab = owoSettings.tab(); this.owo$stackGenerator = owoSettings.stackGenerator(); this.owo$group = owoSettings.group(); + this.owo$trackUsageStat = owoSettings.shouldTrackUsageStat(); } } @@ -54,4 +58,9 @@ private void grabTab(Item.Settings settings, CallbackInfo ci) { public @Nullable ItemGroup owo$group() { return this.owo$group; } + + @Override + public boolean owo$shouldTrackUsageStat() { + return this.owo$trackUsageStat; + } } diff --git a/src/main/java/io/wispforest/owo/util/pond/OwoItemExtensions.java b/src/main/java/io/wispforest/owo/util/pond/OwoItemExtensions.java index d7ec9a76..b511d3df 100644 --- a/src/main/java/io/wispforest/owo/util/pond/OwoItemExtensions.java +++ b/src/main/java/io/wispforest/owo/util/pond/OwoItemExtensions.java @@ -34,4 +34,9 @@ public interface OwoItemExtensions { */ @Nullable ItemGroup owo$group(); + /** + * @return {@code true} if this item should automatically + * have its usage stat incremented + */ + boolean owo$shouldTrackUsageStat(); } diff --git a/src/main/resources/owo.mixins.json b/src/main/resources/owo.mixins.json index 95bf6fdf..6d39c4ad 100644 --- a/src/main/resources/owo.mixins.json +++ b/src/main/resources/owo.mixins.json @@ -12,6 +12,7 @@ "ScreenHandlerMixin", "ServerLoginNetworkHandlerAccessor", "ServerPlayerEntityMixin", + "ServerPlayerInteractionManagerMixin", "ServerPlayNetworkHandlerAccessor", "SimpleRegistryMixin", "TagGroupLoaderMixin", @@ -36,8 +37,8 @@ ], "client": [ "ClientLoginNetworkHandlerAccessor", - "MinecraftClientMixin", "DrawContextMixin", + "MinecraftClientMixin", "itemgroup.AbstractInventoryScreenMixin", "itemgroup.CreativeInventoryScreenAccessor", "itemgroup.CreativeInventoryScreenMixin", diff --git a/src/testmod/java/io/wispforest/uwu/items/UwuTestStickItem.java b/src/testmod/java/io/wispforest/uwu/items/UwuTestStickItem.java index 8c596a28..fdbd39cc 100644 --- a/src/testmod/java/io/wispforest/uwu/items/UwuTestStickItem.java +++ b/src/testmod/java/io/wispforest/uwu/items/UwuTestStickItem.java @@ -30,6 +30,7 @@ public class UwuTestStickItem extends Item { public UwuTestStickItem() { super(new OwoItemSettings().group(Uwu.SIX_TAB_GROUP).tab(3).maxCount(1) + .trackUsageStat() .stackGenerator(OwoItemGroup.DEFAULT_STACK_GENERATOR.andThen((item, stacks) -> { final var stack = new ItemStack(item); stack.setCustomName(Text.literal("the stick of the test").styled(style -> style.withItalic(false))); From 3fd62aa4af9c5fed5b4faeba1c82818dcdb4f298 Mon Sep 17 00:00:00 2001 From: Basique Date: Sat, 9 Sep 2023 17:20:56 +0300 Subject: [PATCH 14/19] fix stuff ig --- build.gradle | 6 +-- gradle.properties | 22 +++++----- .../owo/compat/rei/ReiUIAdapter.java | 4 +- .../owo/compat/rei/ReiWidgetComponent.java | 2 +- .../owo/config/ConfigSynchronizer.java | 6 +-- .../ui/component/ListOptionContainer.java | 2 +- .../owo/itemgroup/json/WrapperGroup.java | 7 +-- ...> ServerCommonNetworkHandlerAccessor.java} | 5 ++- .../CreativeInventoryScreenMixin.java | 13 +++--- .../offline/AdvancementProgressAccessor.java | 8 ++-- .../PlayerAdvancementTrackerMixin.java | 4 +- .../mixin/offline/ProgressMapAccessor.java | 14 ++++++ .../recipe_remainders/RecipeManagerMixin.java | 10 +++-- .../mixin/recipe_remainders/RecipeMixin.java | 30 +++++++------ .../stapi/SystemDelegatedLanguageFixin.java | 6 +-- .../wispforest/owo/network/OwoNetChannel.java | 4 +- .../owo/offline/OfflineAdvancementLookup.java | 43 +++++++++++-------- .../owo/offline/OfflineAdvancementState.java | 11 ++--- .../owo/ui/component/EntityComponent.java | 35 +++++---------- .../owo/ui/component/TextBoxComponent.java | 2 +- .../ui/component/VanillaWidgetComponent.java | 22 +--------- .../wispforest/owo/ui/core/OwoUIAdapter.java | 4 +- .../owo/ui/hud/HudInspectorScreen.java | 1 - .../io/wispforest/owo/ui/layers/Layers.java | 2 +- .../wispforest/owo/ui/util/FocusHandler.java | 4 +- src/main/resources/owo.mixins.json | 3 +- .../io/wispforest/uwu/client/UwuClient.java | 2 + 27 files changed, 131 insertions(+), 141 deletions(-) rename src/main/java/io/wispforest/owo/mixin/{ServerPlayNetworkHandlerAccessor.java => ServerCommonNetworkHandlerAccessor.java} (66%) create mode 100644 src/main/java/io/wispforest/owo/mixin/offline/ProgressMapAccessor.java diff --git a/build.gradle b/build.gradle index f17e7fbd..d83aaed1 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ plugins { id 'fabric-loom' version '1.2-SNAPSHOT' id 'maven-publish' - id 'io.github.juuxel.loom-quiltflower' version '1.10.0' + id 'io.github.juuxel.loom-vineflower' version '1.11.0' } allprojects { @@ -128,14 +128,14 @@ dependencies { modCompileOnly("me.shedaniel:RoughlyEnoughItems-api-fabric:${project.rei_version}") modCompileOnly("dev.emi:emi-fabric:${project.emi_version}") - modLocalRuntime("dev.emi:emi-fabric:${project.emi_version}") +// modLocalRuntime("dev.emi:emi-fabric:${project.emi_version}") modCompileOnly("com.terraformersmc:modmenu:${project.modmenu_version}") modLocalRuntime("com.terraformersmc:modmenu:${project.modmenu_version}") api(include("blue.endless:jankson:${project.jankson_version}")) - modCompileOnly "fr.catcore:server-translations-api:${project.stapi_version}" + modCompileOnly "xyz.nucleoid:server-translations-api:${project.stapi_version}" testmodImplementation sourceSets.main.output testmodAnnotationProcessor sourceSets.main.output diff --git a/gradle.properties b/gradle.properties index dac2667b..ad11b8d5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,28 +2,28 @@ org.gradle.jvmargs=-Xmx2G # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_base_version=1.20 -minecraft_version=1.20.1 -yarn_mappings=1.20.1+build.2 -loader_version=0.14.21 +minecraft_base_version=1.20.2 +minecraft_version=1.20.2-pre2 +yarn_mappings=1.20.2-pre2+build.3 +loader_version=0.14.22 # Mod Properties mod_version=0.11.2-pre.11 maven_group=io.wispforest archives_base_name=owo-lib # Dependencies -fabric_version=0.85.0+1.20.1 +fabric_version=0.88.3+1.20.2 # https://maven.shedaniel.me/me/shedaniel/RoughlyEnoughItems-fabric/ -rei_version=12.0.625 +rei_version=13.0.654 -# https://maven.terraformersmc.com/releases/dev/emi/emi/ -emi_version=1.0.3+1.20 +# https://maven.terraformersmc.com/releases/dev/emi/emi-fabric/ +emi_version=1.0.19+1.20.1 # https://search.maven.org/artifact/blue.endless/jankson jankson_version=1.2.2 # https://maven.terraformersmc.com/releases/com/terraformersmc/modmenu -modmenu_version=7.0.1 +modmenu_version=8.0.0-beta.2 -# https://maven.nucleoid.xyz/fr/catcore/server-translations-api/ -stapi_version=1.4.19+1.19.3 +# https://maven.nucleoid.xyz/xyz/nucleoid/server-translations-api/ +stapi_version=2.0.0+1.20 diff --git a/src/main/java/io/wispforest/owo/compat/rei/ReiUIAdapter.java b/src/main/java/io/wispforest/owo/compat/rei/ReiUIAdapter.java index 6bae0608..d5a99d47 100644 --- a/src/main/java/io/wispforest/owo/compat/rei/ReiUIAdapter.java +++ b/src/main/java/io/wispforest/owo/compat/rei/ReiUIAdapter.java @@ -63,8 +63,8 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { } @Override - public boolean mouseScrolled(double mouseX, double mouseY, double amount) { - return this.adapter.mouseScrolled(mouseX - this.adapter.x(), mouseY - this.adapter.y(), amount); + public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { + return this.adapter.mouseScrolled(mouseX - this.adapter.x(), mouseY - this.adapter.y(), horizontalAmount, verticalAmount); } @Override diff --git a/src/main/java/io/wispforest/owo/compat/rei/ReiWidgetComponent.java b/src/main/java/io/wispforest/owo/compat/rei/ReiWidgetComponent.java index b19f3826..476780a5 100644 --- a/src/main/java/io/wispforest/owo/compat/rei/ReiWidgetComponent.java +++ b/src/main/java/io/wispforest/owo/compat/rei/ReiWidgetComponent.java @@ -86,7 +86,7 @@ public boolean onMouseUp(double mouseX, double mouseY, int button) { @Override public boolean onMouseScroll(double mouseX, double mouseY, double amount) { - return this.widget.mouseScrolled(this.x + mouseX, this.y + mouseY, amount) + return this.widget.mouseScrolled(this.x + mouseX, this.y + mouseY, 0, amount) | super.onMouseScroll(mouseX, mouseY, amount); } diff --git a/src/main/java/io/wispforest/owo/config/ConfigSynchronizer.java b/src/main/java/io/wispforest/owo/config/ConfigSynchronizer.java index e6645f62..e1f28347 100644 --- a/src/main/java/io/wispforest/owo/config/ConfigSynchronizer.java +++ b/src/main/java/io/wispforest/owo/config/ConfigSynchronizer.java @@ -2,7 +2,7 @@ import com.google.common.collect.HashMultimap; import io.wispforest.owo.Owo; -import io.wispforest.owo.mixin.ServerPlayNetworkHandlerAccessor; +import io.wispforest.owo.mixin.ServerCommonNetworkHandlerAccessor; import io.wispforest.owo.ops.TextOps; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -56,7 +56,7 @@ static void register(ConfigWrapper config) { * or {@code null} if no config with the given name was synced */ public static @Nullable Map getClientOptions(ServerPlayerEntity player, String configName) { - var storage = CLIENT_OPTION_STORAGE.get(((ServerPlayNetworkHandlerAccessor) player.networkHandler).owo$getConnection()); + var storage = CLIENT_OPTION_STORAGE.get(((ServerCommonNetworkHandlerAccessor) player.networkHandler).owo$getConnection()); if (storage == null) return null; return storage.get(configName); @@ -188,7 +188,7 @@ private static void applyClient(MinecraftClient client, ClientPlayNetworkHandler private static void applyServer(MinecraftServer server, ServerPlayerEntity player, ServerPlayNetworkHandler handler, PacketByteBuf buf, PacketSender sender) { Owo.LOGGER.info("Receiving client config"); - var connection = ((ServerPlayNetworkHandlerAccessor) player.networkHandler).owo$getConnection(); + var connection = ((ServerCommonNetworkHandlerAccessor) player.networkHandler).owo$getConnection(); read(buf, (option, optionBuf) -> { var config = CLIENT_OPTION_STORAGE.computeIfAbsent(connection, $ -> new HashMap<>()).computeIfAbsent(option.configName(), s -> new HashMap<>()); diff --git a/src/main/java/io/wispforest/owo/config/ui/component/ListOptionContainer.java b/src/main/java/io/wispforest/owo/config/ui/component/ListOptionContainer.java index d454967f..91fed89e 100644 --- a/src/main/java/io/wispforest/owo/config/ui/component/ListOptionContainer.java +++ b/src/main/java/io/wispforest/owo/config/ui/component/ListOptionContainer.java @@ -124,7 +124,7 @@ protected void refreshOptions() { final var box = new ConfigTextBox(); box.setText(this.backingList.get(i).toString()); - box.setCursorToStart(); + box.setCursorToStart(false); box.setDrawsBackground(false); box.margins(Insets.vertical(2)); box.horizontalSizing(Sizing.fill(95)); diff --git a/src/main/java/io/wispforest/owo/itemgroup/json/WrapperGroup.java b/src/main/java/io/wispforest/owo/itemgroup/json/WrapperGroup.java index f8dac27c..ebc48c45 100644 --- a/src/main/java/io/wispforest/owo/itemgroup/json/WrapperGroup.java +++ b/src/main/java/io/wispforest/owo/itemgroup/json/WrapperGroup.java @@ -8,10 +8,7 @@ import io.wispforest.owo.mixin.itemgroup.ItemGroupAccessor; import io.wispforest.owo.mixin.ui.SimpleRegistryAccessor; import net.minecraft.item.ItemGroup; -import net.minecraft.registry.MutableRegistry; -import net.minecraft.registry.Registries; -import net.minecraft.registry.RegistryKey; -import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.*; import net.minecraft.util.Identifier; import org.jetbrains.annotations.ApiStatus; @@ -36,7 +33,7 @@ public WrapperGroup(ItemGroup parent, Identifier parentId, List ta ((SimpleRegistryAccessor) Registries.ITEM_GROUP).owo$getValueToEntry().remove(parent); ((SimpleRegistryAccessor) Registries.ITEM_GROUP).owo$getEntryToLifecycle().remove(parent); - ((MutableRegistry) Registries.ITEM_GROUP).set(parentRawId, RegistryKey.of(RegistryKeys.ITEM_GROUP, parentId), this, Lifecycle.stable()); + ((SimpleRegistry) Registries.ITEM_GROUP).set(parentRawId, RegistryKey.of(RegistryKeys.ITEM_GROUP, parentId), this, Lifecycle.stable()); ((ItemGroupAccessor) this).owo$setDisplayName(parent.getDisplayName()); ((ItemGroupAccessor) this).owo$setColumn(parent.getColumn()); diff --git a/src/main/java/io/wispforest/owo/mixin/ServerPlayNetworkHandlerAccessor.java b/src/main/java/io/wispforest/owo/mixin/ServerCommonNetworkHandlerAccessor.java similarity index 66% rename from src/main/java/io/wispforest/owo/mixin/ServerPlayNetworkHandlerAccessor.java rename to src/main/java/io/wispforest/owo/mixin/ServerCommonNetworkHandlerAccessor.java index aa2dd185..c49f5fcf 100644 --- a/src/main/java/io/wispforest/owo/mixin/ServerPlayNetworkHandlerAccessor.java +++ b/src/main/java/io/wispforest/owo/mixin/ServerCommonNetworkHandlerAccessor.java @@ -1,12 +1,13 @@ package io.wispforest.owo.mixin; import net.minecraft.network.ClientConnection; +import net.minecraft.server.network.ServerCommonNetworkHandler; import net.minecraft.server.network.ServerPlayNetworkHandler; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(ServerPlayNetworkHandler.class) -public interface ServerPlayNetworkHandlerAccessor { +@Mixin(ServerCommonNetworkHandler.class) +public interface ServerCommonNetworkHandlerAccessor { @Accessor("connection") ClientConnection owo$getConnection(); diff --git a/src/main/java/io/wispforest/owo/mixin/itemgroup/CreativeInventoryScreenMixin.java b/src/main/java/io/wispforest/owo/mixin/itemgroup/CreativeInventoryScreenMixin.java index 475eae5f..f0b1aec5 100644 --- a/src/main/java/io/wispforest/owo/mixin/itemgroup/CreativeInventoryScreenMixin.java +++ b/src/main/java/io/wispforest/owo/mixin/itemgroup/CreativeInventoryScreenMixin.java @@ -71,38 +71,37 @@ private Identifier injectCustomGroupTexture(Identifier original) { // Scrollbar slider // ---------------- - @ModifyArgs(method = "drawBackground", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawTexture(Lnet/minecraft/util/Identifier;IIIIII)V", ordinal = 1)) + @ModifyArgs(method = "drawBackground", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawGuiTexture(Lnet/minecraft/util/Identifier;IIII)V")) private void injectCustomScrollbarTexture(Args args) { if (!(selectedTab instanceof OwoItemGroup owoGroup) || owoGroup.getCustomTexture() == null) return; + // TODO: make work. args.set(0, owoGroup.getCustomTexture()); - args.set(3, args.get(3) - 232); - args.set(4, 136); } // ------------- // Group headers // ------------- - @ModifyArg(method = "renderTabIcon", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawTexture(Lnet/minecraft/util/Identifier;IIIIII)V")) + @ModifyArg(method = "renderTabIcon", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawGuiTexture(Lnet/minecraft/util/Identifier;IIII)V")) private Identifier injectCustomTabTexture(Identifier texture) { if (!(selectedTab instanceof OwoItemGroup owoGroup) || owoGroup.getCustomTexture() == null) return texture; return owoGroup.getCustomTexture(); } - @ModifyArg(method = "renderTabIcon", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawTexture(Lnet/minecraft/util/Identifier;IIIIII)V"), index = 3) + @ModifyArg(method = "renderTabIcon", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawGuiTexture(Lnet/minecraft/util/Identifier;IIII)V"), index = 3) private int injectCustomTabTextureLocation(int original) { if (!(selectedTab instanceof OwoItemGroup owoGroup) || owoGroup.getCustomTexture() == null) return original; return owoGroup.getColumn() == 0 ? 195 : 221; } @Inject(method = "renderTabIcon", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemGroup;getIcon()Lnet/minecraft/item/ItemStack;"), locals = LocalCapture.CAPTURE_FAILHARD) - private void renderOwoIcon(DrawContext context, ItemGroup group, CallbackInfo ci, boolean bl, boolean bl2, int i, int j, int k, int l, int m) { + private void renderOwoIcon(DrawContext context, ItemGroup group, CallbackInfo ci, boolean bl, boolean bl2, int i, int j, int k) { if (!(group instanceof OwoItemGroup owoGroup)) return; RenderSystem.enableBlend(); RenderSystem.defaultBlendFunc(); - owoGroup.icon().render(context, l, m, 0, 0, 0); + owoGroup.icon().render(context, j, k, 0, 0, 0); RenderSystem.disableBlend(); } diff --git a/src/main/java/io/wispforest/owo/mixin/offline/AdvancementProgressAccessor.java b/src/main/java/io/wispforest/owo/mixin/offline/AdvancementProgressAccessor.java index 0e895b46..ff7d9401 100644 --- a/src/main/java/io/wispforest/owo/mixin/offline/AdvancementProgressAccessor.java +++ b/src/main/java/io/wispforest/owo/mixin/offline/AdvancementProgressAccessor.java @@ -1,6 +1,7 @@ package io.wispforest.owo.mixin.offline; import net.minecraft.advancement.AdvancementProgress; +import net.minecraft.advancement.AdvancementRequirements; import net.minecraft.advancement.criterion.CriterionProgress; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @@ -10,11 +11,8 @@ @Mixin(AdvancementProgress.class) public interface AdvancementProgressAccessor { @Accessor - Map getCriteriaProgresses(); + AdvancementRequirements getRequirements(); @Accessor - String[][] getRequirements(); - - @Accessor - void setRequirements(String[][] requirements); + void setRequirements(AdvancementRequirements requirements); } \ No newline at end of file diff --git a/src/main/java/io/wispforest/owo/mixin/offline/PlayerAdvancementTrackerMixin.java b/src/main/java/io/wispforest/owo/mixin/offline/PlayerAdvancementTrackerMixin.java index 38892587..badf7cf1 100644 --- a/src/main/java/io/wispforest/owo/mixin/offline/PlayerAdvancementTrackerMixin.java +++ b/src/main/java/io/wispforest/owo/mixin/offline/PlayerAdvancementTrackerMixin.java @@ -18,9 +18,9 @@ public class PlayerAdvancementTrackerMixin { private ServerPlayerEntity owner; @SuppressWarnings("unchecked") - @ModifyArg(method = "save", at = @At(value = "INVOKE", target = "Lcom/google/gson/Gson;toJsonTree(Ljava/lang/Object;)Lcom/google/gson/JsonElement;", remap = false)) + @ModifyArg(method = "save", at = @At(value = "INVOKE", target = "Lcom/mojang/serialization/Codec;encodeStart(Lcom/mojang/serialization/DynamicOps;Ljava/lang/Object;)Lcom/mojang/serialization/DataResult;", remap = false), index = 1) private Object onAdvancementsSaved(Object map) { - DataSavedEvents.ADVANCEMENTS.invoker().onSaved(owner.getUuid(), (Map) map); + DataSavedEvents.ADVANCEMENTS.invoker().onSaved(owner.getUuid(), ((ProgressMapAccessor) map).getMap()); return map; } } diff --git a/src/main/java/io/wispforest/owo/mixin/offline/ProgressMapAccessor.java b/src/main/java/io/wispforest/owo/mixin/offline/ProgressMapAccessor.java new file mode 100644 index 00000000..41d92fee --- /dev/null +++ b/src/main/java/io/wispforest/owo/mixin/offline/ProgressMapAccessor.java @@ -0,0 +1,14 @@ +package io.wispforest.owo.mixin.offline; + +import net.minecraft.advancement.AdvancementProgress; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.Map; + +@Mixin(targets = "net/minecraft/advancement/PlayerAdvancementTracker$ProgressMap") +public interface ProgressMapAccessor { + @Accessor + Map getMap(); +} diff --git a/src/main/java/io/wispforest/owo/mixin/recipe_remainders/RecipeManagerMixin.java b/src/main/java/io/wispforest/owo/mixin/recipe_remainders/RecipeManagerMixin.java index b017622d..273aa3cc 100644 --- a/src/main/java/io/wispforest/owo/mixin/recipe_remainders/RecipeManagerMixin.java +++ b/src/main/java/io/wispforest/owo/mixin/recipe_remainders/RecipeManagerMixin.java @@ -1,15 +1,19 @@ package io.wispforest.owo.mixin.recipe_remainders; import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; import com.google.gson.JsonPrimitive; +import com.mojang.serialization.JsonOps; import io.wispforest.owo.util.RecipeRemainderStorage; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.recipe.Recipe; +import net.minecraft.recipe.RecipeCodecs; import net.minecraft.recipe.RecipeManager; import net.minecraft.recipe.ShapedRecipe; import net.minecraft.util.Identifier; import net.minecraft.util.JsonHelper; +import net.minecraft.util.Util; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -29,11 +33,11 @@ private static void deserializeRecipeSpecificRemainders(Identifier id, JsonObjec var item = JsonHelper.asItem(new JsonPrimitive(remainderEntry.getKey()), remainderEntry.getKey()); if (remainderEntry.getValue().isJsonObject()) { - var remainderStack = ShapedRecipe.outputFromJson(remainderEntry.getValue().getAsJsonObject()); - remainders.put(item, remainderStack); + var remainderStack = Util.getResult(RecipeCodecs.CRAFTING_RESULT.parse(JsonOps.INSTANCE, remainderEntry.getValue().getAsJsonObject()), JsonParseException::new); + remainders.put(item.value(), remainderStack); } else { var remainderItem = JsonHelper.asItem(remainderEntry.getValue(), "item"); - remainders.put(item, new ItemStack(remainderItem)); + remainders.put(item.value(), new ItemStack(remainderItem)); } } diff --git a/src/main/java/io/wispforest/owo/mixin/recipe_remainders/RecipeMixin.java b/src/main/java/io/wispforest/owo/mixin/recipe_remainders/RecipeMixin.java index 39f8da50..8d289468 100644 --- a/src/main/java/io/wispforest/owo/mixin/recipe_remainders/RecipeMixin.java +++ b/src/main/java/io/wispforest/owo/mixin/recipe_remainders/RecipeMixin.java @@ -16,19 +16,21 @@ @Mixin(Recipe.class) public interface RecipeMixin { - @Shadow - Identifier getId(); + // TODO: make work - @Inject(method = "getRemainder", at = @At("RETURN"), locals = LocalCapture.CAPTURE_FAILHARD) - private void addRecipeSpecificRemainders(C inventory, CallbackInfoReturnable> cir, DefaultedList remainders) { - if (!RecipeRemainderStorage.has(this.getId())) return; - - var owoRemainders = RecipeRemainderStorage.get(this.getId()); - for (int i = 0; i < remainders.size(); ++i) { - var item = inventory.getStack(i).getItem(); - if (!owoRemainders.containsKey(item)) continue; - - remainders.set(i, owoRemainders.get(item).copy()); - } - } +// @Shadow +// Identifier getId(); +// +// @Inject(method = "getRemainder", at = @At("RETURN"), locals = LocalCapture.CAPTURE_FAILHARD) +// private void addRecipeSpecificRemainders(C inventory, CallbackInfoReturnable> cir, DefaultedList remainders) { +// if (!RecipeRemainderStorage.has(this.getId())) return; +// +// var owoRemainders = RecipeRemainderStorage.get(this.getId()); +// for (int i = 0; i < remainders.size(); ++i) { +// var item = inventory.getStack(i).getItem(); +// if (!owoRemainders.containsKey(item)) continue; +// +// remainders.set(i, owoRemainders.get(item).copy()); +// } +// } } \ No newline at end of file diff --git a/src/main/java/io/wispforest/owo/mixin/text/stapi/SystemDelegatedLanguageFixin.java b/src/main/java/io/wispforest/owo/mixin/text/stapi/SystemDelegatedLanguageFixin.java index 43588252..68e505f6 100644 --- a/src/main/java/io/wispforest/owo/mixin/text/stapi/SystemDelegatedLanguageFixin.java +++ b/src/main/java/io/wispforest/owo/mixin/text/stapi/SystemDelegatedLanguageFixin.java @@ -1,13 +1,13 @@ package io.wispforest.owo.mixin.text.stapi; -import fr.catcore.server.translations.api.resource.language.ServerLanguage; -import fr.catcore.server.translations.api.resource.language.SystemDelegatedLanguage; import io.wispforest.owo.text.TextLanguage; import net.minecraft.text.Text; import net.minecraft.util.Language; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Pseudo; import org.spongepowered.asm.mixin.Shadow; +import xyz.nucleoid.server.translations.api.language.ServerLanguage; +import xyz.nucleoid.server.translations.impl.language.SystemDelegatedLanguage; @Pseudo @Mixin(SystemDelegatedLanguage.class) @@ -19,7 +19,7 @@ public abstract class SystemDelegatedLanguageFixin implements TextLanguage { @Override public Text getText(String key) { - if (!(vanilla instanceof TextLanguage lang) || this.getSystemLanguage().local().contains(key)) + if (!(vanilla instanceof TextLanguage lang) || this.getSystemLanguage().serverTranslations().contains(key)) return null; return lang.getText(key); diff --git a/src/main/java/io/wispforest/owo/network/OwoNetChannel.java b/src/main/java/io/wispforest/owo/network/OwoNetChannel.java index b2a31fe8..9a72e51c 100644 --- a/src/main/java/io/wispforest/owo/network/OwoNetChannel.java +++ b/src/main/java/io/wispforest/owo/network/OwoNetChannel.java @@ -1,6 +1,6 @@ package io.wispforest.owo.network; -import io.wispforest.owo.mixin.ServerPlayNetworkHandlerAccessor; +import io.wispforest.owo.mixin.ServerCommonNetworkHandlerAccessor; import io.wispforest.owo.network.serialization.PacketBufSerializer; import io.wispforest.owo.network.serialization.RecordSerializer; import io.wispforest.owo.util.OwoFreezer; @@ -221,7 +221,7 @@ public boolean canSendToPlayer(ServerPlayNetworkHandler networkHandler) { if (required) return true; return OwoHandshake.isValid() ? - getChannelSet(((ServerPlayNetworkHandlerAccessor) networkHandler).owo$getConnection()).contains(this.packetId) + getChannelSet(((ServerCommonNetworkHandlerAccessor) networkHandler).owo$getConnection()).contains(this.packetId) : ServerPlayNetworking.canSend(networkHandler, this.packetId); } diff --git a/src/main/java/io/wispforest/owo/offline/OfflineAdvancementLookup.java b/src/main/java/io/wispforest/owo/offline/OfflineAdvancementLookup.java index fa7616ae..e0b75a39 100644 --- a/src/main/java/io/wispforest/owo/offline/OfflineAdvancementLookup.java +++ b/src/main/java/io/wispforest/owo/offline/OfflineAdvancementLookup.java @@ -4,19 +4,25 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; import com.google.gson.internal.Streams; import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonReader; +import com.mojang.serialization.Codec; import com.mojang.serialization.Dynamic; import com.mojang.serialization.JsonOps; import io.wispforest.owo.Owo; import io.wispforest.owo.mixin.offline.AdvancementProgressAccessor; +import net.minecraft.GameVersion; import net.minecraft.SharedConstants; import net.minecraft.advancement.Advancement; +import net.minecraft.advancement.AdvancementEntry; import net.minecraft.advancement.AdvancementProgress; +import net.minecraft.advancement.PlayerAdvancementTracker; import net.minecraft.datafixer.DataFixTypes; import net.minecraft.datafixer.Schemas; import net.minecraft.util.Identifier; +import net.minecraft.util.Util; import net.minecraft.util.WorldSavePath; import org.jetbrains.annotations.Nullable; @@ -35,11 +41,15 @@ * @author BasiqueEvangelist */ public final class OfflineAdvancementLookup { + private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); private OfflineAdvancementLookup() {} - private static final Gson GSON = (new GsonBuilder()).registerTypeAdapter(AdvancementProgress.class, new AdvancementProgress.Serializer()).registerTypeAdapter(Identifier.class, new Identifier.Serializer()).setPrettyPrinting().create(); - private static final TypeToken> JSON_TYPE = new TypeToken<>() {}; + public static final Codec> CODEC = DataFixTypes.ADVANCEMENTS.createDataFixingCodec( + Codec.unboundedMap(Identifier.CODEC, AdvancementProgress.CODEC), + Schemas.getFixer(), + 1343 + ); /** * Saves the given advancement state @@ -54,12 +64,10 @@ public static void put(UUID player, Map map) { try { Path advancementsPath = Owo.currentServer().getSavePath(WorldSavePath.ADVANCEMENTS); Path advancementPath = advancementsPath.resolve(player.toString() + ".json"); - JsonElement savedElement = GSON.toJsonTree(map); - savedElement.getAsJsonObject().addProperty("DataVersion", SharedConstants.getGameVersion().getSaveVersion().getId()); + JsonElement saved = Util.getResult(CODEC.encodeStart(JsonOps.INSTANCE, map), IllegalStateException::new); - try (OutputStream os = Files.newOutputStream(advancementPath); - OutputStreamWriter osWriter = new OutputStreamWriter(os, Charsets.UTF_8.newEncoder())) { - GSON.toJson(savedElement, osWriter); + try (BufferedWriter bw = Files.newBufferedWriter(advancementPath)) { + GSON.toJson(saved, bw); } } catch (IOException e) { @@ -88,27 +96,24 @@ public static void put(UUID player, Map map) { if (!Files.exists(advancementFile)) return null; - Dynamic dynamic; + Map parsedMap; + try (InputStream s = Files.newInputStream(advancementFile); InputStreamReader streamReader = new InputStreamReader(s); JsonReader reader = new JsonReader(streamReader)) { reader.setLenient(false); - dynamic = new Dynamic<>(JsonOps.INSTANCE, Streams.parse(reader)); - } - if (dynamic.get("DataVersion").asNumber().result().isEmpty()) { - dynamic = dynamic.set("DataVersion", dynamic.createInt(1343)); + JsonElement jsonElement = Streams.parse(reader); + parsedMap = Util.getResult(CODEC.parse(JsonOps.INSTANCE, jsonElement), JsonParseException::new); } - dynamic = DataFixTypes.ADVANCEMENTS.update(Schemas.getFixer(), dynamic, dynamic.get("DataVersion").asInt(0)); - dynamic = dynamic.remove("DataVersion"); - - Map parsedMap = GSON.getAdapter(JSON_TYPE).fromJsonTree(dynamic.getValue()); for (Map.Entry entry : parsedMap.entrySet()) { - if (((AdvancementProgressAccessor) entry.getValue()).getRequirements().length == 0) { - Advancement adv = Owo.currentServer().getAdvancementLoader().get(entry.getKey()); + var requirements = ((AdvancementProgressAccessor) entry.getValue()).getRequirements(); + + if (requirements.getLength() == 0) { + AdvancementEntry adv = Owo.currentServer().getAdvancementLoader().get(entry.getKey()); if (adv != null) { - ((AdvancementProgressAccessor) entry.getValue()).setRequirements(adv.getRequirements()); + ((AdvancementProgressAccessor) entry.getValue()).setRequirements(adv.value().requirements()); } } } diff --git a/src/main/java/io/wispforest/owo/offline/OfflineAdvancementState.java b/src/main/java/io/wispforest/owo/offline/OfflineAdvancementState.java index 1673c949..9a3614ec 100644 --- a/src/main/java/io/wispforest/owo/offline/OfflineAdvancementState.java +++ b/src/main/java/io/wispforest/owo/offline/OfflineAdvancementState.java @@ -1,6 +1,7 @@ package io.wispforest.owo.offline; import net.minecraft.advancement.Advancement; +import net.minecraft.advancement.AdvancementEntry; import net.minecraft.advancement.AdvancementProgress; import net.minecraft.util.Identifier; @@ -35,10 +36,10 @@ public Map advancementData() { * @param advancement The target advancement * @return The progress of the targeted advancement */ - public AdvancementProgress getOrAddProgress(Advancement advancement) { - return advancementData.computeIfAbsent(advancement.getId(), id -> { + public AdvancementProgress getOrAddProgress(AdvancementEntry advancement) { + return advancementData.computeIfAbsent(advancement.id(), id -> { AdvancementProgress progress = new AdvancementProgress(); - progress.init(advancement.getCriteria(), advancement.getRequirements()); + progress.init(advancement.value().requirements()); return progress; }); } @@ -49,7 +50,7 @@ public AdvancementProgress getOrAddProgress(Advancement advancement) { * * @param advancement The advancement to grant */ - public void grant(Advancement advancement) { + public void grant(AdvancementEntry advancement) { AdvancementProgress progress = getOrAddProgress(advancement); for (String criterion : progress.getUnobtainedCriteria()) { progress.obtain(criterion); @@ -62,7 +63,7 @@ public void grant(Advancement advancement) { * * @param advancement The advancement to revoke */ - public void revoke(Advancement advancement) { + public void revoke(AdvancementEntry advancement) { AdvancementProgress progress = getOrAddProgress(advancement); for (String criterion : progress.getObtainedCriteria()) { progress.reset(criterion); diff --git a/src/main/java/io/wispforest/owo/ui/component/EntityComponent.java b/src/main/java/io/wispforest/owo/ui/component/EntityComponent.java index bf7f8415..eeb1defd 100644 --- a/src/main/java/io/wispforest/owo/ui/component/EntityComponent.java +++ b/src/main/java/io/wispforest/owo/ui/component/EntityComponent.java @@ -20,6 +20,8 @@ import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.entity.EntityRenderDispatcher; import net.minecraft.client.render.entity.PlayerModelPart; +import net.minecraft.client.util.DefaultSkinHelper; +import net.minecraft.client.util.SkinTextures; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; @@ -242,40 +244,28 @@ public static EntityComponent parse(Element element) { public static class RenderablePlayerEntity extends ClientPlayerEntity { - protected Identifier skinTextureId = null; - protected String model = null; + protected SkinTextures skinTextures; protected RenderablePlayerEntity(GameProfile profile) { super(MinecraftClient.getInstance(), MinecraftClient.getInstance().world, new ClientPlayNetworkHandler(MinecraftClient.getInstance(), - null, new ClientConnection(NetworkSide.CLIENTBOUND), - null, - profile, - MinecraftClient.getInstance().getTelemetryManager().createWorldSession(false, Duration.ZERO, "tetris") + null ), null, null, false, false ); - this.client.getSkinProvider().loadSkin(this.getGameProfile(), (type, identifier, texture) -> { - if (type != MinecraftProfileTexture.Type.SKIN) return; + this.skinTextures = DefaultSkinHelper.getTexture(profile); - this.skinTextureId = identifier; - this.model = texture.getMetadata("model"); - if (this.model == null) this.model = "default"; - - }, true); - } - - @Override - public boolean hasSkinTexture() { - return skinTextureId != null; + this.client.getSkinProvider().fetchSkinTextures(this.getGameProfile()).thenAccept(textures -> { + this.skinTextures = textures; + }); } @Override - public Identifier getSkinTexture() { - return this.skinTextureId != null ? this.skinTextureId : super.getSkinTexture(); + public SkinTextures method_52814() { + return skinTextures; } @Override @@ -283,11 +273,6 @@ public boolean isPartVisible(PlayerModelPart modelPart) { return true; } - @Override - public String getModel() { - return this.model != null ? this.model : super.getModel(); - } - @Nullable @Override protected PlayerListEntry getPlayerListEntry() { diff --git a/src/main/java/io/wispforest/owo/ui/component/TextBoxComponent.java b/src/main/java/io/wispforest/owo/ui/component/TextBoxComponent.java index e3cf85d7..b5018c78 100644 --- a/src/main/java/io/wispforest/owo/ui/component/TextBoxComponent.java +++ b/src/main/java/io/wispforest/owo/ui/component/TextBoxComponent.java @@ -74,7 +74,7 @@ public EventSource onChanged() { public TextBoxComponent text(String text) { this.setText(text); - this.setCursorToStart(); + this.setCursorToStart(false); return this; } diff --git a/src/main/java/io/wispforest/owo/ui/component/VanillaWidgetComponent.java b/src/main/java/io/wispforest/owo/ui/component/VanillaWidgetComponent.java index 6ff8852d..856cbfae 100644 --- a/src/main/java/io/wispforest/owo/ui/component/VanillaWidgetComponent.java +++ b/src/main/java/io/wispforest/owo/ui/component/VanillaWidgetComponent.java @@ -16,7 +16,6 @@ public class VanillaWidgetComponent extends BaseComponent { private final ClickableWidget widget; private float time = 0f; - private @Nullable Runnable tickCallback = null; protected VanillaWidgetComponent(ClickableWidget widget) { this.widget = widget; @@ -24,25 +23,8 @@ protected VanillaWidgetComponent(ClickableWidget widget) { this.horizontalSizing.set(Sizing.fixed(this.widget.getWidth())); this.verticalSizing.set(Sizing.fixed(this.widget.getHeight())); - if (widget instanceof TextFieldWidget textField) { + if (widget instanceof TextFieldWidget) { this.margins(Insets.none()); - this.tickCallback = textField::tick; - } - - if (widget instanceof EditBoxWidget editBox) { - this.tickCallback = editBox::tick; - } - } - - @Override - public void update(float delta, int mouseX, int mouseY) { - super.update(delta, mouseX, mouseY); - if (this.tickCallback == null) return; - - this.time += delta; - while (this.time >= 1f) { - this.time -= 1f; - this.tickCallback.run(); } } @@ -161,7 +143,7 @@ public boolean onMouseUp(double mouseX, double mouseY, int button) { @Override public boolean onMouseScroll(double mouseX, double mouseY, double amount) { - return this.widget.mouseScrolled(this.x + mouseX, this.y + mouseY, amount) + return this.widget.mouseScrolled(this.x + mouseX, this.y + mouseY, 0, amount) | super.onMouseScroll(mouseX, mouseY, amount); } diff --git a/src/main/java/io/wispforest/owo/ui/core/OwoUIAdapter.java b/src/main/java/io/wispforest/owo/ui/core/OwoUIAdapter.java index c82d34ad..cdb15418 100644 --- a/src/main/java/io/wispforest/owo/ui/core/OwoUIAdapter.java +++ b/src/main/java/io/wispforest/owo/ui/core/OwoUIAdapter.java @@ -224,8 +224,8 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) { } @Override - public boolean mouseScrolled(double mouseX, double mouseY, double amount) { - return this.rootComponent.onMouseScroll(mouseX, mouseY, amount); + public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { + return this.rootComponent.onMouseScroll(mouseX, mouseY, verticalAmount); } @Override diff --git a/src/main/java/io/wispforest/owo/ui/hud/HudInspectorScreen.java b/src/main/java/io/wispforest/owo/ui/hud/HudInspectorScreen.java index 1ade071c..8d4015ea 100644 --- a/src/main/java/io/wispforest/owo/ui/hud/HudInspectorScreen.java +++ b/src/main/java/io/wispforest/owo/ui/hud/HudInspectorScreen.java @@ -17,7 +17,6 @@ public HudInspectorScreen() { @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { - this.renderBackground(context); super.render(context, mouseX, mouseY, delta); if (Hud.adapter == null) return; diff --git a/src/main/java/io/wispforest/owo/ui/layers/Layers.java b/src/main/java/io/wispforest/owo/ui/layers/Layers.java index 559483ab..c4b42f8f 100644 --- a/src/main/java/io/wispforest/owo/ui/layers/Layers.java +++ b/src/main/java/io/wispforest/owo/ui/layers/Layers.java @@ -118,7 +118,7 @@ public static Layer add(BiFu ScreenMouseEvents.allowMouseScroll(screeen).register((screen, mouseX, mouseY, horizontalAmount, verticalAmount) -> { boolean handled; for (var instance : getInstances(screen)) { - handled = instance.adapter.mouseScrolled(mouseX, mouseY, verticalAmount); + handled = instance.adapter.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); if (handled) return false; } diff --git a/src/main/java/io/wispforest/owo/ui/util/FocusHandler.java b/src/main/java/io/wispforest/owo/ui/util/FocusHandler.java index f3bfb119..1c02ac57 100644 --- a/src/main/java/io/wispforest/owo/ui/util/FocusHandler.java +++ b/src/main/java/io/wispforest/owo/ui/util/FocusHandler.java @@ -34,7 +34,7 @@ public Component.FocusSource lastFocusSource() { public void cycle(boolean forwards) { var allChildren = new ArrayList(); - this.root.collectChildren(allChildren); + this.root.collectDescendants(allChildren); allChildren.removeIf(component -> !component.canFocus(Component.FocusSource.KEYBOARD_CYCLE)); if (allChildren.isEmpty()) return; @@ -53,7 +53,7 @@ public void moveFocus(int keyCode) { if (this.focused == null) return; var allChildren = new ArrayList(); - this.root.collectChildren(allChildren); + this.root.collectDescendants(allChildren); allChildren.removeIf(component -> !component.canFocus(Component.FocusSource.KEYBOARD_CYCLE)); if (allChildren.isEmpty()) return; diff --git a/src/main/resources/owo.mixins.json b/src/main/resources/owo.mixins.json index 6d39c4ad..2ae25408 100644 --- a/src/main/resources/owo.mixins.json +++ b/src/main/resources/owo.mixins.json @@ -13,13 +13,14 @@ "ServerLoginNetworkHandlerAccessor", "ServerPlayerEntityMixin", "ServerPlayerInteractionManagerMixin", - "ServerPlayNetworkHandlerAccessor", + "ServerCommonNetworkHandlerAccessor", "SimpleRegistryMixin", "TagGroupLoaderMixin", "itemgroup.ItemGroupAccessor", "itemgroup.ItemMixin", "offline.AdvancementProgressAccessor", "offline.PlayerAdvancementTrackerMixin", + "offline.ProgressMapAccessor", "offline.WorldSaveHandlerMixin", "recipe_remainders.CraftingResultSlotMixin", "recipe_remainders.RecipeManagerMixin", diff --git a/src/testmod/java/io/wispforest/uwu/client/UwuClient.java b/src/testmod/java/io/wispforest/uwu/client/UwuClient.java index 8e252697..646c91b2 100644 --- a/src/testmod/java/io/wispforest/uwu/client/UwuClient.java +++ b/src/testmod/java/io/wispforest/uwu/client/UwuClient.java @@ -113,6 +113,8 @@ public void onInitializeClient() { }); Layers.add(Containers::verticalFlow, instance -> { + if (MinecraftClient.getInstance().world == null) return; + instance.adapter.rootComponent.child( Containers.horizontalFlow(Sizing.content(), Sizing.content()) .child(Components.entity(Sizing.fixed(20), EntityType.ALLAY, null).>configure(component -> { From 11da2e235ac700f43b6413e405b109705ca0187f Mon Sep 17 00:00:00 2001 From: glisco Date: Tue, 12 Sep 2023 12:34:57 +0200 Subject: [PATCH 15/19] fix server translations api compat --- build.gradle | 2 +- gradle.properties | 4 ++-- .../mixin/text/stapi/SystemDelegatedLanguageFixin.java | 9 ++++++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index f17e7fbd..b36b7bcf 100644 --- a/build.gradle +++ b/build.gradle @@ -135,7 +135,7 @@ dependencies { api(include("blue.endless:jankson:${project.jankson_version}")) - modCompileOnly "fr.catcore:server-translations-api:${project.stapi_version}" + modCompileOnly "xyz.nucleoid:server-translations-api:${project.stapi_version}" testmodImplementation sourceSets.main.output testmodAnnotationProcessor sourceSets.main.output diff --git a/gradle.properties b/gradle.properties index dac2667b..4ee2cb08 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,7 +7,7 @@ minecraft_version=1.20.1 yarn_mappings=1.20.1+build.2 loader_version=0.14.21 # Mod Properties -mod_version=0.11.2-pre.11 +mod_version=0.11.2-pre.14 maven_group=io.wispforest archives_base_name=owo-lib # Dependencies @@ -26,4 +26,4 @@ jankson_version=1.2.2 modmenu_version=7.0.1 # https://maven.nucleoid.xyz/fr/catcore/server-translations-api/ -stapi_version=1.4.19+1.19.3 +stapi_version=2.0.0+1.20 diff --git a/src/main/java/io/wispforest/owo/mixin/text/stapi/SystemDelegatedLanguageFixin.java b/src/main/java/io/wispforest/owo/mixin/text/stapi/SystemDelegatedLanguageFixin.java index 43588252..25b4ba58 100644 --- a/src/main/java/io/wispforest/owo/mixin/text/stapi/SystemDelegatedLanguageFixin.java +++ b/src/main/java/io/wispforest/owo/mixin/text/stapi/SystemDelegatedLanguageFixin.java @@ -1,17 +1,19 @@ package io.wispforest.owo.mixin.text.stapi; -import fr.catcore.server.translations.api.resource.language.ServerLanguage; -import fr.catcore.server.translations.api.resource.language.SystemDelegatedLanguage; import io.wispforest.owo.text.TextLanguage; import net.minecraft.text.Text; import net.minecraft.util.Language; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Pseudo; import org.spongepowered.asm.mixin.Shadow; +import xyz.nucleoid.server.translations.api.language.ServerLanguage; +import xyz.nucleoid.server.translations.impl.language.SystemDelegatedLanguage; @Pseudo @Mixin(SystemDelegatedLanguage.class) public abstract class SystemDelegatedLanguageFixin implements TextLanguage { + @Final @Shadow private Language vanilla; @Shadow @@ -19,8 +21,9 @@ public abstract class SystemDelegatedLanguageFixin implements TextLanguage { @Override public Text getText(String key) { - if (!(vanilla instanceof TextLanguage lang) || this.getSystemLanguage().local().contains(key)) + if (!(vanilla instanceof TextLanguage lang) || this.getSystemLanguage().serverTranslations().contains(key)) { return null; + } return lang.getText(key); } From deff18cca246e5477549dc080b2dceb5600a44f8 Mon Sep 17 00:00:00 2001 From: glisco Date: Tue, 12 Sep 2023 12:35:11 +0200 Subject: [PATCH 16/19] fix groups without primary tab being empty by default --- src/main/java/io/wispforest/owo/itemgroup/OwoItemGroup.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/io/wispforest/owo/itemgroup/OwoItemGroup.java b/src/main/java/io/wispforest/owo/itemgroup/OwoItemGroup.java index af2c463a..3787a7f3 100644 --- a/src/main/java/io/wispforest/owo/itemgroup/OwoItemGroup.java +++ b/src/main/java/io/wispforest/owo/itemgroup/OwoItemGroup.java @@ -105,6 +105,8 @@ public void initialize() { if (!this.tabs.get(tabIdx).primary()) continue; this.activeTabs.add(tabIdx); } + + if (this.activeTabs.isEmpty()) this.activeTabs.add(0); } else { this.activeTabs.add(0); } From bd1b648b2a909e87147439216f09d26c7ab058d8 Mon Sep 17 00:00:00 2001 From: Basique Date: Fri, 29 Sep 2023 13:05:19 +0300 Subject: [PATCH 17/19] handshake update (i think) --- .../ClientCommonNetworkHandlerAccessor.java | 12 +++ .../ServerLoginNetworkHandlerAccessor.java | 14 --- .../wispforest/owo/network/OwoHandshake.java | 92 ++++++++++--------- .../wispforest/owo/network/OwoNetChannel.java | 4 +- src/main/resources/owo.mixins.json | 2 +- 5 files changed, 62 insertions(+), 62 deletions(-) create mode 100644 src/main/java/io/wispforest/owo/mixin/ClientCommonNetworkHandlerAccessor.java delete mode 100644 src/main/java/io/wispforest/owo/mixin/ServerLoginNetworkHandlerAccessor.java diff --git a/src/main/java/io/wispforest/owo/mixin/ClientCommonNetworkHandlerAccessor.java b/src/main/java/io/wispforest/owo/mixin/ClientCommonNetworkHandlerAccessor.java new file mode 100644 index 00000000..c054de04 --- /dev/null +++ b/src/main/java/io/wispforest/owo/mixin/ClientCommonNetworkHandlerAccessor.java @@ -0,0 +1,12 @@ +package io.wispforest.owo.mixin; + +import net.minecraft.client.network.ClientCommonNetworkHandler; +import net.minecraft.network.ClientConnection; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(ClientCommonNetworkHandler.class) +public interface ClientCommonNetworkHandlerAccessor { + @Accessor + ClientConnection getConnection(); +} diff --git a/src/main/java/io/wispforest/owo/mixin/ServerLoginNetworkHandlerAccessor.java b/src/main/java/io/wispforest/owo/mixin/ServerLoginNetworkHandlerAccessor.java deleted file mode 100644 index 476a393e..00000000 --- a/src/main/java/io/wispforest/owo/mixin/ServerLoginNetworkHandlerAccessor.java +++ /dev/null @@ -1,14 +0,0 @@ -package io.wispforest.owo.mixin; - -import net.minecraft.network.ClientConnection; -import net.minecraft.server.network.ServerLoginNetworkHandler; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(ServerLoginNetworkHandler.class) -public interface ServerLoginNetworkHandlerAccessor { - - @Accessor("connection") - ClientConnection owo$getConnection(); - -} diff --git a/src/main/java/io/wispforest/owo/network/OwoHandshake.java b/src/main/java/io/wispforest/owo/network/OwoHandshake.java index e83fd9ff..79583d56 100644 --- a/src/main/java/io/wispforest/owo/network/OwoHandshake.java +++ b/src/main/java/io/wispforest/owo/network/OwoHandshake.java @@ -1,10 +1,8 @@ package io.wispforest.owo.network; -import io.netty.util.concurrent.Future; -import io.netty.util.concurrent.GenericFutureListener; import io.wispforest.owo.Owo; -import io.wispforest.owo.mixin.ClientLoginNetworkHandlerAccessor; -import io.wispforest.owo.mixin.ServerLoginNetworkHandlerAccessor; +import io.wispforest.owo.mixin.ClientCommonNetworkHandlerAccessor; +import io.wispforest.owo.mixin.ServerCommonNetworkHandlerAccessor; import io.wispforest.owo.network.serialization.PacketBufSerializer; import io.wispforest.owo.ops.TextOps; import io.wispforest.owo.particles.systems.ParticleSystemController; @@ -12,19 +10,14 @@ import io.wispforest.owo.util.ServicesFrozenException; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.client.networking.v1.ClientLoginConnectionEvents; -import net.fabricmc.fabric.api.client.networking.v1.ClientLoginNetworking; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.client.networking.v1.*; import net.fabricmc.fabric.api.networking.v1.*; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientLoginNetworkHandler; -import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.network.ClientConfigurationNetworkHandler; import net.minecraft.network.PacketByteBuf; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerLoginNetworkHandler; +import net.minecraft.server.network.ServerConfigurationNetworkHandler; import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.util.Identifier; @@ -36,9 +29,9 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.CompletableFuture; -import java.util.function.Consumer; import java.util.function.ToIntFunction; +@SuppressWarnings("UnstableApiUsage") @ApiStatus.Internal public final class OwoHandshake { @@ -60,7 +53,10 @@ private OwoHandshake() {} // Registration // ------------ - public static void enable() {} + public static void enable() { + if (OwoFreezer.isFrozen()) + throw new ServicesFrozenException("The oωo handshake may only be enabled during mod initialization"); + } public static void requireHandshake() { if (OwoFreezer.isFrozen()) @@ -70,25 +66,23 @@ public static void requireHandshake() { } static { - ServerLoginConnectionEvents.QUERY_START.register(OwoHandshake::queryStart); - ServerLoginNetworking.registerGlobalReceiver(OwoHandshake.CHANNEL_ID, OwoHandshake::syncServer); - - if (!ENABLED) { - ServerPlayNetworking.registerGlobalReceiver(OwoHandshake.OFF_CHANNEL_ID, (server, player, handler, buf, responseSender) -> {}); - } else { - ServerLifecycleEvents.SERVER_STARTED.register(server -> QUERY_RECEIVED = true); - } + ServerConfigurationConnectionEvents.CONFIGURE.register(OwoHandshake::configureStart); + ServerConfigurationNetworking.registerGlobalReceiver(OwoHandshake.CHANNEL_ID, OwoHandshake::syncServer); if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) { - ClientLoginNetworking.registerGlobalReceiver(OwoHandshake.CHANNEL_ID, OwoHandshake::syncClient); - ClientPlayConnectionEvents.JOIN.register(OwoHandshake::handleJoinClient); + if (!ENABLED) { + ClientConfigurationNetworking.registerGlobalReceiver(OwoHandshake.OFF_CHANNEL_ID, (client, handler, buf, responseSender) -> {}); + } + + ClientConfigurationNetworking.registerGlobalReceiver(OwoHandshake.CHANNEL_ID, OwoHandshake::syncClient); + ClientConfigurationConnectionEvents.READY.register(OwoHandshake::handleReadyClient); ClientPlayConnectionEvents.DISCONNECT.register((handler, client) -> QUERY_RECEIVED = false); - ClientLoginConnectionEvents.DISCONNECT.register((handler, client) -> QUERY_RECEIVED = false); + ClientConfigurationConnectionEvents.DISCONNECT.register((handler, client) -> QUERY_RECEIVED = false); } } - public static boolean isValid() { + public static boolean isValidClient() { return ENABLED && QUERY_RECEIVED; } @@ -96,23 +90,36 @@ public static boolean isValid() { // Packets // ------- - private static void queryStart(ServerLoginNetworkHandler serverLoginNetworkHandler, MinecraftServer server, PacketSender sender, ServerLoginNetworking.LoginSynchronizer loginSynchronizer) { + private static void configureStart(ServerConfigurationNetworkHandler handler, MinecraftServer server) { if (!ENABLED) return; + if (ServerConfigurationNetworking.canSend(handler, OFF_CHANNEL_ID)) { + Owo.LOGGER.info("[Handshake] Handshake disabled by client, skipping"); + return; + } + + if (!ServerConfigurationNetworking.canSend(handler, CHANNEL_ID)) { + if (!HANDSHAKE_REQUIRED) return; + + handler.disconnect(TextOps.concat(PREFIX, Text.of("incompatible client"))); + Owo.LOGGER.info("[Handshake] Handshake failed, client doesn't understand channel packet"); + return; + } + var request = PacketByteBufs.create(); writeHashes(request, OwoNetChannel.OPTIONAL_CHANNELS, OwoHandshake::hashChannel); - sender.sendPacket(OwoHandshake.CHANNEL_ID, request); - Owo.LOGGER.info("[Handshake] Sending channel query"); + ServerConfigurationNetworking.send(handler, OwoHandshake.CHANNEL_ID, request); + Owo.LOGGER.info("[Handshake] Sending channel packet"); } @Environment(EnvType.CLIENT) - private static CompletableFuture syncClient(MinecraftClient client, ClientLoginNetworkHandler clientLoginNetworkHandler, PacketByteBuf buf, Consumer>> genericFutureListenerConsumer) { + private static void syncClient(MinecraftClient client, ClientConfigurationNetworkHandler handler, PacketByteBuf buf, PacketSender sender) { Owo.LOGGER.info("[Handshake] Sending client channels"); QUERY_RECEIVED = true; if (buf.readableBytes() > 0) { final var serverOptionalChannels = RESPONSE_SERIALIZER.deserializer().apply(buf); - ((OwoClientConnectionExtension) ((ClientLoginNetworkHandlerAccessor) clientLoginNetworkHandler).owo$getConnection()).owo$setChannelSet(filterOptionalServices(serverOptionalChannels, OwoNetChannel.REGISTERED_CHANNELS, OwoHandshake::hashChannel)); + ((OwoClientConnectionExtension) ((ClientCommonNetworkHandlerAccessor) handler).getConnection()).owo$setChannelSet(filterOptionalServices(serverOptionalChannels, OwoNetChannel.REGISTERED_CHANNELS, OwoHandshake::hashChannel)); } var response = PacketByteBufs.create(); @@ -120,18 +127,10 @@ private static CompletableFuture syncClient(MinecraftClient clien writeHashes(response, ParticleSystemController.REGISTERED_CONTROLLERS, OwoHandshake::hashController); writeHashes(response, OwoNetChannel.OPTIONAL_CHANNELS, OwoHandshake::hashChannel); - return CompletableFuture.completedFuture(response); + sender.sendPacket(CHANNEL_ID, response); } - private static void syncServer(MinecraftServer server, ServerLoginNetworkHandler handler, boolean responded, PacketByteBuf buf, ServerLoginNetworking.LoginSynchronizer loginSynchronizer, PacketSender packetSender) { - if (!responded) { - if (!HANDSHAKE_REQUIRED) return; - - handler.disconnect(TextOps.concat(PREFIX, Text.of("incompatible client"))); - Owo.LOGGER.info("[Handshake] Handshake failed, client did not respond to channel query"); - return; - } - + private static void syncServer(MinecraftServer server, ServerConfigurationNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { Owo.LOGGER.info("[Handshake] Receiving client channels"); final var clientChannels = RESPONSE_SERIALIZER.deserializer().apply(buf); @@ -148,17 +147,20 @@ private static void syncServer(MinecraftServer server, ServerLoginNetworkHandler if (buf.readableBytes() > 0) { final var clientOptionalChannels = RESPONSE_SERIALIZER.deserializer().apply(buf); - ((OwoClientConnectionExtension) ((ServerLoginNetworkHandlerAccessor) handler).owo$getConnection()).owo$setChannelSet(filterOptionalServices(clientOptionalChannels, OwoNetChannel.OPTIONAL_CHANNELS, OwoHandshake::hashChannel)); + ((OwoClientConnectionExtension) ((ServerCommonNetworkHandlerAccessor) handler).owo$getConnection()).owo$setChannelSet(filterOptionalServices(clientOptionalChannels, OwoNetChannel.OPTIONAL_CHANNELS, OwoHandshake::hashChannel)); } Owo.LOGGER.info("[Handshake] Handshake completed successfully"); } @Environment(EnvType.CLIENT) - private static void handleJoinClient(ClientPlayNetworkHandler handler, PacketSender packetSender, MinecraftClient client) { - if (QUERY_RECEIVED || ClientPlayNetworking.canSend(OFF_CHANNEL_ID) || !HANDSHAKE_REQUIRED || !ENABLED) return; + private static void handleReadyClient(ClientConfigurationNetworkHandler handler, MinecraftClient client) { + if (ClientConfigurationNetworking.canSend(CHANNEL_ID) || !HANDSHAKE_REQUIRED || !ENABLED) return; + client.execute(() -> { - handler.getConnection().disconnect(TextOps.concat(PREFIX, Text.of("incompatible server"))); + ((ClientCommonNetworkHandlerAccessor) handler) + .getConnection() + .disconnect(TextOps.concat(PREFIX, Text.of("incompatible server"))); }); } diff --git a/src/main/java/io/wispforest/owo/network/OwoNetChannel.java b/src/main/java/io/wispforest/owo/network/OwoNetChannel.java index 9a72e51c..ff2355b7 100644 --- a/src/main/java/io/wispforest/owo/network/OwoNetChannel.java +++ b/src/main/java/io/wispforest/owo/network/OwoNetChannel.java @@ -220,7 +220,7 @@ public boolean canSendToPlayer(ServerPlayerEntity player) { public boolean canSendToPlayer(ServerPlayNetworkHandler networkHandler) { if (required) return true; - return OwoHandshake.isValid() ? + return OwoHandshake.isValidClient() ? getChannelSet(((ServerCommonNetworkHandlerAccessor) networkHandler).owo$getConnection()).contains(this.packetId) : ServerPlayNetworking.canSend(networkHandler, this.packetId); } @@ -229,7 +229,7 @@ public boolean canSendToPlayer(ServerPlayNetworkHandler networkHandler) { public boolean canSendToServer() { if (required) return true; - return OwoHandshake.isValid() ? + return OwoHandshake.isValidClient() ? getChannelSet(MinecraftClient.getInstance().getNetworkHandler().getConnection()).contains(packetId) : ClientPlayNetworking.canSend(this.packetId); } diff --git a/src/main/resources/owo.mixins.json b/src/main/resources/owo.mixins.json index 2ae25408..401d5901 100644 --- a/src/main/resources/owo.mixins.json +++ b/src/main/resources/owo.mixins.json @@ -4,13 +4,13 @@ "package": "io.wispforest.owo.mixin", "compatibilityLevel": "JAVA_16", "mixins": [ + "ClientCommonNetworkHandlerAccessor", "ClientConnectionMixin", "Copenhagen", "ItemStackMixin", "NbtCompoundMixin", "ScreenHandlerInvoker", "ScreenHandlerMixin", - "ServerLoginNetworkHandlerAccessor", "ServerPlayerEntityMixin", "ServerPlayerInteractionManagerMixin", "ServerCommonNetworkHandlerAccessor", From 60d6391499270f435ae2314f0592ccc66c410342 Mon Sep 17 00:00:00 2001 From: glisco Date: Mon, 2 Oct 2023 17:26:12 +0200 Subject: [PATCH 18/19] final fixes for 1.20.2 - fix owo screen background rendering - migrate owo item group textures to individual atlas sprites - fix per-recipe remainders - fix EntityComponent.createRenderablePlayer - bump version --- gradle.properties | 12 ++-- .../owo/itemgroup/OwoItemGroup.java | 46 +++++++++--- .../owo/itemgroup/json/WrapperGroup.java | 7 +- .../CreativeInventoryScreenMixin.java | 67 +++++++++++------- .../recipe_remainders/RecipeManagerMixin.java | 25 +++++-- .../mixin/recipe_remainders/RecipeMixin.java | 36 ---------- .../owo/ui/base/BaseOwoHandledScreen.java | 3 + .../wispforest/owo/ui/base/BaseOwoScreen.java | 3 + .../owo/ui/component/EntityComponent.java | 18 ++--- src/main/resources/owo.mixins.json | 1 - src/testmod/java/io/wispforest/uwu/Uwu.java | 10 ++- .../assets/uwu/textures/gui/group.png | Bin 1825 -> 1167 bytes 12 files changed, 135 insertions(+), 93 deletions(-) delete mode 100644 src/main/java/io/wispforest/owo/mixin/recipe_remainders/RecipeMixin.java diff --git a/gradle.properties b/gradle.properties index ad11b8d5..04fe17a9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,18 +3,18 @@ org.gradle.jvmargs=-Xmx2G # Fabric Properties # check these on https://fabricmc.net/develop minecraft_base_version=1.20.2 -minecraft_version=1.20.2-pre2 -yarn_mappings=1.20.2-pre2+build.3 +minecraft_version=1.20.2 +yarn_mappings=1.20.2+build.1 loader_version=0.14.22 # Mod Properties -mod_version=0.11.2-pre.11 +mod_version=0.11.3 maven_group=io.wispforest archives_base_name=owo-lib # Dependencies -fabric_version=0.88.3+1.20.2 +fabric_version=0.89.2+1.20.2 # https://maven.shedaniel.me/me/shedaniel/RoughlyEnoughItems-fabric/ -rei_version=13.0.654 +rei_version=13.0.661 # https://maven.terraformersmc.com/releases/dev/emi/emi-fabric/ emi_version=1.0.19+1.20.1 @@ -23,7 +23,7 @@ emi_version=1.0.19+1.20.1 jankson_version=1.2.2 # https://maven.terraformersmc.com/releases/com/terraformersmc/modmenu -modmenu_version=8.0.0-beta.2 +modmenu_version=8.0.0 # https://maven.nucleoid.xyz/xyz/nucleoid/server-translations-api/ stapi_version=2.0.0+1.20 diff --git a/src/main/java/io/wispforest/owo/itemgroup/OwoItemGroup.java b/src/main/java/io/wispforest/owo/itemgroup/OwoItemGroup.java index af2c463a..c346bf8c 100644 --- a/src/main/java/io/wispforest/owo/itemgroup/OwoItemGroup.java +++ b/src/main/java/io/wispforest/owo/itemgroup/OwoItemGroup.java @@ -52,20 +52,25 @@ public abstract class OwoItemGroup extends ItemGroup { private final IntSet activeTabsView = IntSets.unmodifiable(this.activeTabs); private boolean initialized = false; + private final @Nullable Identifier backgroundTexture; + private final @Nullable ScrollerTextures scrollerTextures; + private final @Nullable TabTextures tabTextures; + private final int tabStackHeight; private final int buttonStackHeight; - private final Identifier customTexture; private final boolean useDynamicTitle; private final boolean displaySingleTab; private final boolean allowMultiSelect; - protected OwoItemGroup(Identifier id, Consumer initializer, Supplier iconSupplier, int tabStackHeight, int buttonStackHeight, @Nullable Identifier customTexture, boolean useDynamicTitle, boolean displaySingleTab, boolean allowMultiSelect) { + protected OwoItemGroup(Identifier id, Consumer initializer, Supplier iconSupplier, int tabStackHeight, int buttonStackHeight, @Nullable Identifier backgroundTexture, @Nullable ScrollerTextures scrollerTextures, @Nullable TabTextures tabTextures, boolean useDynamicTitle, boolean displaySingleTab, boolean allowMultiSelect) { super(null, -1, Type.CATEGORY, Text.translatable("itemGroup.%s.%s".formatted(id.getNamespace(), id.getPath())), () -> ItemStack.EMPTY, (displayContext, entries) -> {}); this.initializer = initializer; this.iconSupplier = iconSupplier; this.tabStackHeight = tabStackHeight; this.buttonStackHeight = buttonStackHeight; - this.customTexture = customTexture; + this.backgroundTexture = backgroundTexture; + this.scrollerTextures = scrollerTextures; + this.tabTextures = tabTextures; this.useDynamicTitle = useDynamicTitle; this.displaySingleTab = displaySingleTab; this.allowMultiSelect = allowMultiSelect; @@ -306,8 +311,16 @@ public boolean isTabSelected(int tab) { return this.activeTabs.contains(tab); } - public Identifier getCustomTexture() { - return customTexture; + public @Nullable Identifier getBackgroundTexture() { + return this.backgroundTexture; + } + + public @Nullable ScrollerTextures getScrollerTextures() { + return this.scrollerTextures; + } + + public @Nullable TabTextures getTabTextures() { + return this.tabTextures; } public int getTabStackHeight() { @@ -361,7 +374,9 @@ public static class Builder { private Consumer initializer = owoItemGroup -> {}; private int tabStackHeight = 4; private int buttonStackHeight = 4; - private @Nullable Identifier customTexture = null; + private @Nullable Identifier backgroundTexture = null; + private @Nullable ScrollerTextures scrollerTextures = null; + private @Nullable TabTextures tabTextures = null; private boolean useDynamicTitle = true; private boolean displaySingleTab = false; private boolean allowMultiSelect = true; @@ -386,8 +401,18 @@ public Builder buttonStackHeight(int buttonStackHeight) { return this; } - public Builder customTexture(@Nullable Identifier customTexture) { - this.customTexture = customTexture; + public Builder backgroundTexture(@Nullable Identifier backgroundTexture) { + this.backgroundTexture = backgroundTexture; + return this; + } + + public Builder scrollerTextures(ScrollerTextures scrollerTextures) { + this.scrollerTextures = scrollerTextures; + return this; + } + + public Builder tabTextures(TabTextures tabTextures) { + this.tabTextures = tabTextures; return this; } @@ -407,7 +432,7 @@ public Builder withoutMultipleSelection() { } public OwoItemGroup build() { - final var group = new OwoItemGroup(id, initializer, iconSupplier, tabStackHeight, buttonStackHeight, customTexture, useDynamicTitle, displaySingleTab, allowMultiSelect) {}; + final var group = new OwoItemGroup(id, initializer, iconSupplier, tabStackHeight, buttonStackHeight, backgroundTexture, scrollerTextures, tabTextures, useDynamicTitle, displaySingleTab, allowMultiSelect) {}; Registry.register(Registries.ITEM_GROUP, this.id, group); return group; } @@ -426,6 +451,9 @@ public void add(ItemStack stack, StackVisibility visibility) { } } + public record ScrollerTextures(Identifier enabled, Identifier disabled) {} + public record TabTextures(Identifier topSelected, Identifier topSelectedFirstColumn, Identifier topUnselected, Identifier bottomSelected, Identifier bottomSelectedFirstColumn, Identifier bottomUnselected) {} + // Utility /** diff --git a/src/main/java/io/wispforest/owo/itemgroup/json/WrapperGroup.java b/src/main/java/io/wispforest/owo/itemgroup/json/WrapperGroup.java index ebc48c45..182c4a56 100644 --- a/src/main/java/io/wispforest/owo/itemgroup/json/WrapperGroup.java +++ b/src/main/java/io/wispforest/owo/itemgroup/json/WrapperGroup.java @@ -8,7 +8,10 @@ import io.wispforest.owo.mixin.itemgroup.ItemGroupAccessor; import io.wispforest.owo.mixin.ui.SimpleRegistryAccessor; import net.minecraft.item.ItemGroup; -import net.minecraft.registry.*; +import net.minecraft.registry.Registries; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.SimpleRegistry; import net.minecraft.util.Identifier; import org.jetbrains.annotations.ApiStatus; @@ -27,7 +30,7 @@ public class WrapperGroup extends OwoItemGroup { @SuppressWarnings("unchecked") public WrapperGroup(ItemGroup parent, Identifier parentId, List tabs, List buttons) { - super(parentId, owoItemGroup -> {}, () -> Icon.of(parent.getIcon()), 4, 4, null, true, false, false); + super(parentId, owoItemGroup -> {}, () -> Icon.of(parent.getIcon()), 4, 4, null, null, null, true, false, false); int parentRawId = Registries.ITEM_GROUP.getRawId(parent); diff --git a/src/main/java/io/wispforest/owo/mixin/itemgroup/CreativeInventoryScreenMixin.java b/src/main/java/io/wispforest/owo/mixin/itemgroup/CreativeInventoryScreenMixin.java index f0b1aec5..fffabb8e 100644 --- a/src/main/java/io/wispforest/owo/mixin/itemgroup/CreativeInventoryScreenMixin.java +++ b/src/main/java/io/wispforest/owo/mixin/itemgroup/CreativeInventoryScreenMixin.java @@ -16,6 +16,7 @@ import net.minecraft.resource.featuretoggle.FeatureSet; import net.minecraft.text.Text; import net.minecraft.util.Identifier; +import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -43,18 +44,24 @@ public abstract class CreativeInventoryScreenMixin extends AbstractInventoryScre @Shadow protected abstract boolean shouldShowOperatorTab(PlayerEntity player); + @Shadow + protected abstract boolean hasScrollbar(); + + @Unique + private @Nullable OwoItemGroup contextGroup = null; + @Unique - private final List owo$buttons = new ArrayList<>(); + private final List owoButtons = new ArrayList<>(); @Unique - private FeatureSet owo$enabledFeatures = null; + private FeatureSet enabledFeatures = null; @Unique - private final CursorAdapter owo$cursorAdapter = CursorAdapter.ofClientWindow(); + private final CursorAdapter cursorAdapter = CursorAdapter.ofClientWindow(); @Inject(method = "", at = @At("TAIL")) private void captureFeatures(PlayerEntity player, FeatureSet enabledFeatures, boolean operatorTabEnabled, CallbackInfo ci) { - this.owo$enabledFeatures = enabledFeatures; + this.enabledFeatures = enabledFeatures; } // ---------- @@ -63,8 +70,8 @@ private void captureFeatures(PlayerEntity player, FeatureSet enabledFeatures, bo @ModifyArg(method = "drawBackground", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawTexture(Lnet/minecraft/util/Identifier;IIIIII)V", ordinal = 0)) private Identifier injectCustomGroupTexture(Identifier original) { - if (!(selectedTab instanceof OwoItemGroup owoGroup) || owoGroup.getCustomTexture() == null) return original; - return owoGroup.getCustomTexture(); + if (!(selectedTab instanceof OwoItemGroup owoGroup) || owoGroup.getBackgroundTexture() == null) return original; + return owoGroup.getBackgroundTexture(); } // ---------------- @@ -73,26 +80,32 @@ private Identifier injectCustomGroupTexture(Identifier original) { @ModifyArgs(method = "drawBackground", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawGuiTexture(Lnet/minecraft/util/Identifier;IIII)V")) private void injectCustomScrollbarTexture(Args args) { - if (!(selectedTab instanceof OwoItemGroup owoGroup) || owoGroup.getCustomTexture() == null) return; + if (!(selectedTab instanceof OwoItemGroup owoGroup) || owoGroup.getScrollerTextures() == null) return; - // TODO: make work. - args.set(0, owoGroup.getCustomTexture()); + args.set(0, this.hasScrollbar() ? owoGroup.getScrollerTextures().enabled() : owoGroup.getScrollerTextures().disabled()); } // ------------- // Group headers // ------------- + @Inject(method = "renderTabIcon", at = @At("HEAD")) + private void captureContextGroup(DrawContext context, ItemGroup group, CallbackInfo ci) { + if (group instanceof OwoItemGroup owoGroup) { + this.contextGroup = owoGroup; + } else { + this.contextGroup = null; + } + } + @ModifyArg(method = "renderTabIcon", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawGuiTexture(Lnet/minecraft/util/Identifier;IIII)V")) private Identifier injectCustomTabTexture(Identifier texture) { - if (!(selectedTab instanceof OwoItemGroup owoGroup) || owoGroup.getCustomTexture() == null) return texture; - return owoGroup.getCustomTexture(); - } + if (this.contextGroup == null || this.contextGroup.getTabTextures() == null) return texture; - @ModifyArg(method = "renderTabIcon", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawGuiTexture(Lnet/minecraft/util/Identifier;IIII)V"), index = 3) - private int injectCustomTabTextureLocation(int original) { - if (!(selectedTab instanceof OwoItemGroup owoGroup) || owoGroup.getCustomTexture() == null) return original; - return owoGroup.getColumn() == 0 ? 195 : 221; + var textures = this.contextGroup.getTabTextures(); + return this.contextGroup.getRow() == ItemGroup.Row.TOP + ? selectedTab == this.contextGroup ? this.contextGroup.getColumn() == 0 ? textures.topSelectedFirstColumn() : textures.topSelected() : textures.topUnselected() + : selectedTab == this.contextGroup ? this.contextGroup.getColumn() == 0 ? textures.bottomSelectedFirstColumn() : textures.bottomSelected() : textures.bottomUnselected(); } @Inject(method = "renderTabIcon", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemGroup;getIcon()Lnet/minecraft/item/ItemStack;"), locals = LocalCapture.CAPTURE_FAILHARD) @@ -111,7 +124,9 @@ private void renderOwoIcon(DrawContext context, ItemGroup group, CallbackInfo ci @ModifyArg(method = "drawForeground", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawText(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/text/Text;IIIZ)I")) private Text injectTabNameAsTitle(Text original) { - if (!(selectedTab instanceof OwoItemGroup owoGroup) || !owoGroup.hasDynamicTitle() || owoGroup.selectedTabs().size() != 1) return original; + if (!(selectedTab instanceof OwoItemGroup owoGroup) || !owoGroup.hasDynamicTitle() || owoGroup.selectedTabs().size() != 1) { + return original; + } var singleActiveTab = owoGroup.getTab(owoGroup.selectedTabs().iterator().nextInt()); if (singleActiveTab.primary()) { @@ -131,8 +146,8 @@ private Text injectTabNameAsTitle(Text original) { @Inject(at = @At("HEAD"), method = "setSelectedTab(Lnet/minecraft/item/ItemGroup;)V") private void setSelectedTab(ItemGroup group, CallbackInfo ci) { - this.owo$buttons.forEach(this::remove); - this.owo$buttons.clear(); + this.owoButtons.forEach(this::remove); + this.owoButtons.clear(); if (group instanceof OwoItemGroup owoGroup) { int tabRootY = this.y; @@ -150,7 +165,7 @@ private void setSelectedTab(ItemGroup group, CallbackInfo ci) { var tabButton = new ItemGroupButtonWidget(xOffset, yOffset, 32, tab, owo$createSelectAction(owoGroup, tabIdx)); if (owoGroup.isTabSelected(tabIdx)) tabButton.isSelected = true; - this.owo$buttons.add(tabButton); + this.owoButtons.add(tabButton); this.addDrawableChild(tabButton); } } @@ -167,7 +182,7 @@ private void setSelectedTab(ItemGroup group, CallbackInfo ci) { var tabButton = new ItemGroupButtonWidget(xOffset, yOffset, 0, buttonDefinition, __ -> buttonDefinition.action().run()); - this.owo$buttons.add(tabButton); + this.owoButtons.add(tabButton); this.addDrawableChild(tabButton); } } @@ -177,11 +192,11 @@ private void setSelectedTab(ItemGroup group, CallbackInfo ci) { private void render(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { boolean anyButtonHovered = false; - for (var button : this.owo$buttons) { + for (var button : this.owoButtons) { if (button.trulyHovered()) { context.drawTooltip( this.textRenderer, - button.isTab() && ((OwoItemGroup)selectedTab).canSelectMultipleTabs() + button.isTab() && ((OwoItemGroup) selectedTab).canSelectMultipleTabs() ? List.of(button.getMessage(), Text.translatable("text.owo.itemGroup.select_hint")) : List.of(button.getMessage()), mouseX, @@ -191,12 +206,12 @@ private void render(DrawContext context, int mouseX, int mouseY, float delta, Ca } } - this.owo$cursorAdapter.applyStyle(anyButtonHovered ? CursorStyle.HAND : CursorStyle.NONE); + this.cursorAdapter.applyStyle(anyButtonHovered ? CursorStyle.HAND : CursorStyle.NONE); } @Inject(method = "removed", at = @At("HEAD")) private void disposeCursorAdapter(CallbackInfo ci) { - this.owo$cursorAdapter.dispose(); + this.cursorAdapter.dispose(); } @Override @@ -212,7 +227,7 @@ private void disposeCursorAdapter(CallbackInfo ci) { @Unique private Consumer owo$createSelectAction(OwoItemGroup group, int tabIdx) { return button -> { - var context = new ItemGroup.DisplayContext(this.owo$enabledFeatures, this.shouldShowOperatorTab(this.handler.player()), this.handler.player().getWorld().getRegistryManager()); + var context = new ItemGroup.DisplayContext(this.enabledFeatures, this.shouldShowOperatorTab(this.handler.player()), this.handler.player().getWorld().getRegistryManager()); if (Screen.hasShiftDown()) { group.toggleTab(tabIdx, context); } else { diff --git a/src/main/java/io/wispforest/owo/mixin/recipe_remainders/RecipeManagerMixin.java b/src/main/java/io/wispforest/owo/mixin/recipe_remainders/RecipeManagerMixin.java index 273aa3cc..7a696841 100644 --- a/src/main/java/io/wispforest/owo/mixin/recipe_remainders/RecipeManagerMixin.java +++ b/src/main/java/io/wispforest/owo/mixin/recipe_remainders/RecipeManagerMixin.java @@ -5,21 +5,23 @@ import com.google.gson.JsonPrimitive; import com.mojang.serialization.JsonOps; import io.wispforest.owo.util.RecipeRemainderStorage; +import net.minecraft.inventory.Inventory; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.recipe.Recipe; -import net.minecraft.recipe.RecipeCodecs; -import net.minecraft.recipe.RecipeManager; -import net.minecraft.recipe.ShapedRecipe; +import net.minecraft.recipe.*; import net.minecraft.util.Identifier; import net.minecraft.util.JsonHelper; import net.minecraft.util.Util; +import net.minecraft.util.collection.DefaultedList; +import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import java.util.HashMap; +import java.util.Optional; @Mixin(RecipeManager.class) public abstract class RecipeManagerMixin { @@ -44,4 +46,19 @@ private static void deserializeRecipeSpecificRemainders(Identifier id, JsonObjec if (remainders.isEmpty()) return; RecipeRemainderStorage.store(id, remainders); } + + @Inject(method = "getRemainingStacks", at = @At(value = "RETURN", ordinal = 0), locals = LocalCapture.CAPTURE_FAILHARD) + private > void addRecipeSpecificRemainders(RecipeType type, I inventory, World world, CallbackInfoReturnable> cir, Optional> optional) { + if (optional.isEmpty() || !RecipeRemainderStorage.has(optional.get().id())) return; + + var remainders = cir.getReturnValue(); + var owoRemainders = RecipeRemainderStorage.get(optional.get().id()); + + for (int i = 0; i < remainders.size(); ++i) { + var item = inventory.getStack(i).getItem(); + if (!owoRemainders.containsKey(item)) continue; + + remainders.set(i, owoRemainders.get(item).copy()); + } + } } diff --git a/src/main/java/io/wispforest/owo/mixin/recipe_remainders/RecipeMixin.java b/src/main/java/io/wispforest/owo/mixin/recipe_remainders/RecipeMixin.java deleted file mode 100644 index 8d289468..00000000 --- a/src/main/java/io/wispforest/owo/mixin/recipe_remainders/RecipeMixin.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.wispforest.owo.mixin.recipe_remainders; - -import io.wispforest.owo.util.RecipeRemainderStorage; -import net.minecraft.inventory.Inventory; -import net.minecraft.item.ItemStack; -import net.minecraft.recipe.Recipe; -import net.minecraft.util.Identifier; -import net.minecraft.util.collection.DefaultedList; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -@Mixin(Recipe.class) -public interface RecipeMixin { - - // TODO: make work - -// @Shadow -// Identifier getId(); -// -// @Inject(method = "getRemainder", at = @At("RETURN"), locals = LocalCapture.CAPTURE_FAILHARD) -// private void addRecipeSpecificRemainders(C inventory, CallbackInfoReturnable> cir, DefaultedList remainders) { -// if (!RecipeRemainderStorage.has(this.getId())) return; -// -// var owoRemainders = RecipeRemainderStorage.get(this.getId()); -// for (int i = 0; i < remainders.size(); ++i) { -// var item = inventory.getStack(i).getItem(); -// if (!owoRemainders.containsKey(item)) continue; -// -// remainders.set(i, owoRemainders.get(item).copy()); -// } -// } -} \ No newline at end of file diff --git a/src/main/java/io/wispforest/owo/ui/base/BaseOwoHandledScreen.java b/src/main/java/io/wispforest/owo/ui/base/BaseOwoHandledScreen.java index 06772177..4edf3959 100644 --- a/src/main/java/io/wispforest/owo/ui/base/BaseOwoHandledScreen.java +++ b/src/main/java/io/wispforest/owo/ui/base/BaseOwoHandledScreen.java @@ -154,6 +154,9 @@ protected SlotComponent slotAsComponent(int index) { return this.uiAdapter.rootComponent.childById(expectedClass, id); } + @Override + public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) {} + @Override public void render(DrawContext vanillaContext, int mouseX, int mouseY, float delta) { var context = OwoUIDrawContext.of(vanillaContext); diff --git a/src/main/java/io/wispforest/owo/ui/base/BaseOwoScreen.java b/src/main/java/io/wispforest/owo/ui/base/BaseOwoScreen.java index f690305f..8b339970 100644 --- a/src/main/java/io/wispforest/owo/ui/base/BaseOwoScreen.java +++ b/src/main/java/io/wispforest/owo/ui/base/BaseOwoScreen.java @@ -107,6 +107,9 @@ protected void init() { return this.uiAdapter.rootComponent.childById(expectedClass, id); } + @Override + public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) {} + @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { if (!this.invalid) { diff --git a/src/main/java/io/wispforest/owo/ui/component/EntityComponent.java b/src/main/java/io/wispforest/owo/ui/component/EntityComponent.java index eeb1defd..57c48a1c 100644 --- a/src/main/java/io/wispforest/owo/ui/component/EntityComponent.java +++ b/src/main/java/io/wispforest/owo/ui/component/EntityComponent.java @@ -1,7 +1,6 @@ package io.wispforest.owo.ui.component; import com.mojang.authlib.GameProfile; -import com.mojang.authlib.minecraft.MinecraftProfileTexture; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.brigadier.exceptions.CommandSyntaxException; import io.wispforest.owo.ui.base.BaseComponent; @@ -12,14 +11,14 @@ import io.wispforest.owo.ui.parsing.UIParsing; import io.wispforest.owo.util.pond.OwoEntityRenderDispatcherExtension; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.network.PlayerListEntry; +import net.minecraft.client.network.*; import net.minecraft.client.render.DiffuseLighting; import net.minecraft.client.render.LightmapTextureManager; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.entity.EntityRenderDispatcher; import net.minecraft.client.render.entity.PlayerModelPart; +import net.minecraft.client.session.telemetry.TelemetrySender; +import net.minecraft.client.session.telemetry.WorldSession; import net.minecraft.client.util.DefaultSkinHelper; import net.minecraft.client.util.SkinTextures; import net.minecraft.client.util.math.MatrixStack; @@ -31,7 +30,6 @@ import net.minecraft.network.ClientConnection; import net.minecraft.network.NetworkSide; import net.minecraft.registry.Registries; -import net.minecraft.util.Identifier; import net.minecraft.util.math.RotationAxis; import org.jetbrains.annotations.Nullable; import org.joml.Vector3f; @@ -251,8 +249,12 @@ protected RenderablePlayerEntity(GameProfile profile) { MinecraftClient.getInstance().world, new ClientPlayNetworkHandler(MinecraftClient.getInstance(), new ClientConnection(NetworkSide.CLIENTBOUND), - null - ), + new ClientConnectionState( + profile, new WorldSession(TelemetrySender.NOOP, false, Duration.ZERO, ""), + MinecraftClient.getInstance().world.getRegistryManager().toImmutable(), + MinecraftClient.getInstance().world.getEnabledFeatures(), + "Wisp Forest Enterprises", null, null + )), null, null, false, false ); @@ -264,7 +266,7 @@ protected RenderablePlayerEntity(GameProfile profile) { } @Override - public SkinTextures method_52814() { + public SkinTextures getSkinTextures() { return skinTextures; } diff --git a/src/main/resources/owo.mixins.json b/src/main/resources/owo.mixins.json index 401d5901..12d63b92 100644 --- a/src/main/resources/owo.mixins.json +++ b/src/main/resources/owo.mixins.json @@ -24,7 +24,6 @@ "offline.WorldSaveHandlerMixin", "recipe_remainders.CraftingResultSlotMixin", "recipe_remainders.RecipeManagerMixin", - "recipe_remainders.RecipeMixin", "text.LanguageMixin", "text.TextSerializerMixin", "text.TranslatableTextContentMixin", diff --git a/src/testmod/java/io/wispforest/uwu/Uwu.java b/src/testmod/java/io/wispforest/uwu/Uwu.java index 42b1aae3..b0e6d3f1 100644 --- a/src/testmod/java/io/wispforest/uwu/Uwu.java +++ b/src/testmod/java/io/wispforest/uwu/Uwu.java @@ -89,7 +89,15 @@ public class Uwu implements ModInitializer { public static final OwoItemGroup SIX_TAB_GROUP = OwoItemGroup.builder(new Identifier("uwu", "six_tab_group"), () -> Icon.of(Items.POWDER_SNOW_BUCKET)) .tabStackHeight(3) - .customTexture(GROUP_TEXTURE) + .backgroundTexture(GROUP_TEXTURE) + .scrollerTextures(new OwoItemGroup.ScrollerTextures(new Identifier("uwu", "scroller"), new Identifier("uwu", "scroller_disabled"))) + .tabTextures(new OwoItemGroup.TabTextures( + new Identifier("uwu", "top_selected"), + new Identifier("uwu", "top_selected_first_column"), + new Identifier("uwu", "top_unselected"), + new Identifier("uwu", "bottom_selected"), + new Identifier("uwu", "bottom_selected_first_column"), + new Identifier("uwu", "bottom_unselected"))) .initializer(group -> { group.addTab(Icon.of(Items.DIAMOND), "tab_1", null, true); group.addTab(Icon.of(Items.EMERALD), "tab_2", null, false); diff --git a/src/testmod/resources/assets/uwu/textures/gui/group.png b/src/testmod/resources/assets/uwu/textures/gui/group.png index e71054f889183c07243c5ddfdc5d618b67a7e0db..d079b245bed65ab0a7aa0e73e89c7643124419fc 100644 GIT binary patch literal 1167 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|G!U;i$lZxy-8q?;3=Axuo-U3d z6?5L+wat?bmteh+&yvoo$CJXE7vz<*ry=BEP7A~K2}&LedWTsfB_o+5cNNanW81+d zK3PdYr+CT)wXZI{?<}X*o$&Tz(3fNXR2m-7%UZcB+rBaT*8dNO4J!UlUjBO5ss}EoSk*U-MsbRa~^c+PCvbBRn*$B&_?yf*}vykd~}{R`>{D=oE9s? zK@kR)U)znSyx?)U1GePRxwSLNT|e`{~`Uf+8vYV{q7}Wo5ohD=HTbyx-lcCAh zlkv}&U)?g6;pY?20Qs5>9N$z}KNNm%h6~BwWxfG)CD7jgd(YO#F4=kiPSKN?NzT%- zp}dC;LarYEZ@a@)!ScM~^M$Spj!Upa>P-&~-5Rxa)xTO>myH}M=|YzLx=e+Z*BKOM zFf}A_F*HT8Ofv43nNiX@7GYQ-9# z_$alT=`fv~>C)%A0Ktf11{(`B2&na(NfFp*P-CI`l-t$jKrAt|?6HJI5zwH{lVD$i z9MmauYXjJ^VvPt!0WUa6P~8XOVR!`SxFb&tp0R*qU^9n`x>~y-#4qPmiZTu>O_<~P zB!VRi!7zn*8`XUfV^KW#mz;1s0ABEcc*Q@qUQ-1zt&dr>%LcV16wM_Nzk4|&$KDy}I>#Z`D>CbmK+-=*A zoIvoVU})Ozd&l^tHop7lqetwMl%E@JJ>{D$IwK>ju`vP|xta_~Z~OnBj0+9DUV3-K z&740@3TOVYT)2DpZtU0216!BGF|3jLf8lWGJl2@-C*AVE{5=5Rf$9(T+uM1URD~WW P0$K0r>gTe~DWM4f^%a+b literal 1825 zcmcgtcTkf_6yJc9pYez)2q zAlW9AtK+E*ljIdTJWzFZJ-FYhp#HVk{zp8SZa06Dx-+b}AlEFj$M~V?x`c)Y$z>Lu zb~NaX5_R6x_D||;Xy(Drw{y3{MwHoiVVqs$a2Q!-m`7bQ1NS1W68 zZ;u;bS9^~&1P?k)pEok!9ogja?2@p5@63!R2D8BB#UZAf%R6Rtpyg9qZ}#eO%u33x zuB@!+O|YFA&wHO#c2mfa7su%I3!e72wzk)NeShGEM@-SZeKXszV@5r&r0!#uZ2@-E z24Y};Avo#wU*_JZP(Nq>OQ7^~w8i>(wQiN{9w~#?Ug~KCK`C<{&uwn;i;az~3J-KF z?IYFI)!m5rf*>#Ab5f+a`Pqf*7tnwG7`~>|iX_lc2Gc$pX<_w!%$`+Va(=$bXi(D4VDeN*jfM%;is10RzoafTHMOj^7O9V*IXr&fLVBR9*@W4LU?yq%D0dwb zj?T!+GR9yUMib-W=63o$X#Ulv5{ri)ftzC02vZh2E?ePJuG^f*r8sTj+67EIpzXty zT=+IpD8dJ9zT?h^cm?@f!Odxk>Nh4DpndgxwE{vjRSL*xZ~pj_F&@@G7`&$ysVgm; z!8j%_ib$7GF`>Hq)uV#;C*qZpGO+Z@6L59$KCtho5Rf?wnVnH|f0a$awjw!3czffs zv}lXcv#|o;5CVzB)du{57F}RjeB?FWR6xXk@*f%>cRfgpJoGYw)#RE$B9RKFoSdAD zT0T$ZsHuI(PH<%FpM#L|;g-NQ^Tq=@TL;nc9`aNL-p*j8I=8ei-*NdS@gzY%**1tQDk0S_nNJu8WVxEMwf~{Tu^7x_=71CX|`0Bum)NkdX3=Har zUGgWH*2gxra>x+1eigc0g3{Bo3z_Y_dcvrkiK6tn93eB7xfb5z$S|wtRn)p&Agy%C z>|=7k6hUrFW?jOi7)WtHNx;5~=gg-Mxg4>ZJ01LTczC#tDJ}*o#}*d+r(RT4R20ai z2QyJEIA9kAdFL8p;`p3x30cJO2J~tUc9Qw=`+MD%ZJS;uC3nv~p|SR*SQBaYl`AMU z!-Ncz=`IN$*gyAI*5(DE!m>R7sE_%Y!+D{ANTd$XXrTnDipyb&HGRwzo=^?t>!H!9 zD%0JFcjH_RlY;x2b^ILrCh+&(XGzh(TY2hjP`A0U+>iSZa9{?wSV5UjGo9`H%_(0o zlm>MdeUNqzYB=S@q1{jYO4|gwn2Qq(2E$X!Bq8HxuLFVRtdt@Z=1^^r{e3hkDOdc0 zc8GMnDQzvIMi>w^KvJ5(Ne6PhP_@)?w|KUh082gq#1E&$1f(tsxU_tBen||y^Nekk zwFZY9aT*%1SqrpmcKG^|$Ha?qjlQQpxfra8b;gJ~T;tc3Cn@hT*f$s&mnyw$~> z=ViNY(gdC{M!c}TjQSh;k<4+AS9QUTj|FR#t{QNJ1Ud)eSe9^Skws)AWUu83MqX_E z1*-CTwFc-%&P_%wR?N*eBfl^M!RQF4rCthT!Jy(RyHNtWJt|!67hNkU z%Cryx#24a#cm?V Date: Mon, 2 Oct 2023 17:33:56 +0200 Subject: [PATCH 19/19] add missing testmod textures --- .../uwu/textures/gui/sprites/bottom_selected.png | Bin 0 -> 164 bytes .../gui/sprites/bottom_selected_first_column.png | Bin 0 -> 139 bytes .../textures/gui/sprites/bottom_unselected.png | Bin 0 -> 146 bytes .../assets/uwu/textures/gui/sprites/scroller.png | Bin 0 -> 188 bytes .../textures/gui/sprites/scroller_disabled.png | Bin 0 -> 187 bytes .../uwu/textures/gui/sprites/top_selected.png | Bin 0 -> 176 bytes .../gui/sprites/top_selected_first_column.png | Bin 0 -> 154 bytes .../uwu/textures/gui/sprites/top_unselected.png | Bin 0 -> 138 bytes 8 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/testmod/resources/assets/uwu/textures/gui/sprites/bottom_selected.png create mode 100644 src/testmod/resources/assets/uwu/textures/gui/sprites/bottom_selected_first_column.png create mode 100644 src/testmod/resources/assets/uwu/textures/gui/sprites/bottom_unselected.png create mode 100644 src/testmod/resources/assets/uwu/textures/gui/sprites/scroller.png create mode 100644 src/testmod/resources/assets/uwu/textures/gui/sprites/scroller_disabled.png create mode 100644 src/testmod/resources/assets/uwu/textures/gui/sprites/top_selected.png create mode 100644 src/testmod/resources/assets/uwu/textures/gui/sprites/top_selected_first_column.png create mode 100644 src/testmod/resources/assets/uwu/textures/gui/sprites/top_unselected.png diff --git a/src/testmod/resources/assets/uwu/textures/gui/sprites/bottom_selected.png b/src/testmod/resources/assets/uwu/textures/gui/sprites/bottom_selected.png new file mode 100644 index 0000000000000000000000000000000000000000..cc1c4bd5ac79cf813b10f281908cbf740abf0827 GIT binary patch literal 164 zcmeAS@N?(olHy`uVBq!ia0vp^Qb4T0!3-p=OJ|q^DaPU;cPEB*=VV?2Is5@WA+A9B z|NsBTjvWgP4F$5fE@u4#QmiFGe!(D#|1uZUKqeV^x;TbtOniGuk%_^8=g@(Y5C6^A ze?IDOGHG)`l85QrNdc}!O8UBg{eH}?Si$L@IlGDbNEW-*y5BDYfVvqxUHx3vIVCg! E0Pv|c`~Uy| literal 0 HcmV?d00001 diff --git a/src/testmod/resources/assets/uwu/textures/gui/sprites/bottom_selected_first_column.png b/src/testmod/resources/assets/uwu/textures/gui/sprites/bottom_selected_first_column.png new file mode 100644 index 0000000000000000000000000000000000000000..e8b54db1bf8cd250a3aafc91d54a8dd089a4f583 GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^Qb4T0!VDz;wU(LzDgFST5LY1m|NsAE$Bu=Dh634K z7qfl=DaMi@zhDN3XE)M-94${5$B>G+EBwlGLcC~*5A fBOwtH^Pqu|LEyD*T+D?IkhKh+u6{1-oD!Myzoc9Slej6)CaJFfZ4oSjEDWj3Ouo#t(d-4ffWgz%&t;ucLK6UWJVrnO literal 0 HcmV?d00001 diff --git a/src/testmod/resources/assets/uwu/textures/gui/sprites/scroller_disabled.png b/src/testmod/resources/assets/uwu/textures/gui/sprites/scroller_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..ae24e31bb471bd456db126c6344e3e7dd6628e07 GIT binary patch literal 187 zcmeAS@N?(olHy`uVBq!ia0vp^JV4CP!2~4Zn|I0qDaPU;cPEB*=VV?2Ii;R1jv*Qo zlmGlbGMkZa$#w@x|Jnz4re}*t{I~!3F7n-h25FDEF(;T3=USC=t>!W|HfCdE6HDRK zbGWhOvwmcx#FFg>244cQgudQM(fBvJ_2Ei>=4R&DJ0<^AwMA>cfBG?X`s{fJf3`i^ le|~?8smOocjT}lG46}tyGQ^&KGypn)!PC{xWt~$(695F>M4kWu literal 0 HcmV?d00001 diff --git a/src/testmod/resources/assets/uwu/textures/gui/sprites/top_selected.png b/src/testmod/resources/assets/uwu/textures/gui/sprites/top_selected.png new file mode 100644 index 0000000000000000000000000000000000000000..ce80bddd54a167819da0ee96dfb5a79b7d03a155 GIT binary patch literal 176 zcmeAS@N?(olHy`uVBq!ia0vp^Qb4T0!3HFGR%fsRDaPU;cPEB*=VV?2Ia!`Ajv*eM zZ?7409WdZ%eR%(ld{O@sxn~h&nz<(~xwapwp1k10!pX;GE7+Hb2~K=J<7V;}EtUg! zAMTqn_d=95@2kDc2G5tg?e%%$^IJ|(#bbhkV-pLf&=>XUq?kk|J44$rjF6*2UngH6zKUn|( literal 0 HcmV?d00001 diff --git a/src/testmod/resources/assets/uwu/textures/gui/sprites/top_selected_first_column.png b/src/testmod/resources/assets/uwu/textures/gui/sprites/top_selected_first_column.png new file mode 100644 index 0000000000000000000000000000000000000000..f2bfc8d25f058c430597c214b35a11968ca321f1 GIT binary patch literal 154 zcmeAS@N?(olHy`uVBq!ia0vp^Qb4T0!VDz;wU(LzDTx4|5LY10@SpAf|Nq_H-TxUF zjvYG|8X5`|GdfWMQp#8ot41KsENVT)z4*}Q$iB}`syW4 literal 0 HcmV?d00001