Skip to content

Commit 2ab2d02

Browse files
committed
syncable item display widget
1 parent 3c3dc47 commit 2ab2d02

File tree

8 files changed

+219
-40
lines changed

8 files changed

+219
-40
lines changed

src/main/java/com/cleanroommc/modularui/drawable/GuiDraw.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,18 @@
33
import com.cleanroommc.modularui.drawable.text.TextRenderer;
44
import com.cleanroommc.modularui.screen.RichTooltip;
55
import com.cleanroommc.modularui.screen.RichTooltipEvent;
6+
import com.cleanroommc.modularui.utils.Alignment;
67
import com.cleanroommc.modularui.utils.Color;
8+
import com.cleanroommc.modularui.utils.NumberFormat;
79
import com.cleanroommc.modularui.utils.Platform;
10+
import com.cleanroommc.modularui.widget.sizer.Area;
811

912
import net.minecraft.client.Minecraft;
1013
import net.minecraft.client.gui.FontRenderer;
1114
import net.minecraft.client.gui.Gui;
1215
import net.minecraft.client.renderer.BufferBuilder;
1316
import net.minecraft.client.renderer.GlStateManager;
1417
import net.minecraft.client.renderer.RenderItem;
15-
import net.minecraft.client.renderer.Tessellator;
1618
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
1719
import net.minecraft.client.renderer.texture.TextureMap;
1820
import net.minecraft.item.ItemStack;
@@ -30,6 +32,8 @@
3032

3133
public class GuiDraw {
3234

35+
private static final TextRenderer textRenderer = new TextRenderer();
36+
3337
public static final double PI2 = Math.PI * 2;
3438
public static final double PI_2 = Math.PI / 2;
3539

@@ -304,6 +308,37 @@ public static void drawFluidTexture(FluidStack content, float x0, float y0, floa
304308
GlStateManager.color(1f, 1f, 1f, 1f);
305309
}
306310

311+
public static void drawStandardSlotAmountText(int amount, String format, Area area) {
312+
drawAmountText(amount, format, 1, 1, area.width - 1, area.height - 1, Alignment.BottomRight);
313+
}
314+
315+
public static void drawAmountText(int amount, String format, int x, int y, int width, int height, Alignment alignment) {
316+
if (amount > 1 || format != null) {
317+
String amountText = NumberFormat.AMOUNT_TEXT.format(amount);
318+
if (format != null) {
319+
amountText = format + amountText;
320+
}
321+
float scale = 1f;
322+
if (amountText.length() == 3) {
323+
scale = 0.8f;
324+
} else if (amountText.length() == 4) {
325+
scale = 0.6f;
326+
} else if (amountText.length() > 4) {
327+
scale = 0.5f;
328+
}
329+
textRenderer.setShadow(true);
330+
textRenderer.setScale(scale);
331+
textRenderer.setColor(Color.WHITE.main);
332+
textRenderer.setAlignment(alignment, width, height);
333+
textRenderer.setPos(x, y);
334+
textRenderer.setHardWrapOnBorder(false);
335+
GlStateManager.disableLighting();
336+
GlStateManager.disableDepth();
337+
textRenderer.draw(amountText);
338+
textRenderer.setHardWrapOnBorder(true);
339+
}
340+
}
341+
307342
public static void drawSprite(TextureAtlasSprite sprite, float x0, float y0, float w, float h) {
308343
drawSprite(Minecraft.getMinecraft().getTextureMapBlocks(), sprite, x0, y0, w, h);
309344
}

src/main/java/com/cleanroommc/modularui/drawable/text/TextRenderer.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public class TextRenderer {
3333
protected float lastActualHeight = 0;
3434
protected float lastTrimmedHeight = 0;
3535
protected float lastX = 0, lastY = 0;
36+
protected boolean hardWrapOnBorder = true;
3637
protected boolean scrollOnOverflow = false;
3738

3839
public void setAlignment(Alignment alignment, float maxWidth) {
@@ -62,12 +63,16 @@ public void setColor(int color) {
6263
this.color = color;
6364
}
6465

66+
public void setHardWrapOnBorder(boolean hardWrapOnBorder) {
67+
this.hardWrapOnBorder = hardWrapOnBorder;
68+
}
69+
6570
public void setSimulate(boolean simulate) {
6671
this.simulate = simulate;
6772
}
6873

6974
public void draw(String text) {
70-
if (this.maxWidth <= 0 && !text.contains("\n'")) {
75+
if ((this.maxWidth <= 0 || !this.hardWrapOnBorder) && !text.contains("\n'")) {
7176
drawSimple(text);
7277
} else {
7378
draw(Collections.singletonList(text));
@@ -106,8 +111,12 @@ public void drawSimple(String text) {
106111
public List<Line> measureLines(List<String> lines) {
107112
List<Line> measuredLines = new ArrayList<>();
108113
for (String line : lines) {
109-
for (String subLine : wrapLine(line)) {
110-
measuredLines.add(line(subLine));
114+
if (this.hardWrapOnBorder) {
115+
for (String subLine : wrapLine(line)) {
116+
measuredLines.add(line(subLine));
117+
}
118+
} else {
119+
measuredLines.add(line(line));
111120
}
112121
}
113122
return measuredLines;

src/main/java/com/cleanroommc/modularui/test/TestTile.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.cleanroommc.modularui.value.BoolValue;
2020
import com.cleanroommc.modularui.value.IntValue;
2121
import com.cleanroommc.modularui.value.StringValue;
22+
import com.cleanroommc.modularui.value.sync.GenericSyncValue;
2223
import com.cleanroommc.modularui.value.sync.IntSyncValue;
2324
import com.cleanroommc.modularui.value.sync.PanelSyncManager;
2425
import com.cleanroommc.modularui.value.sync.SyncHandlers;
@@ -32,16 +33,20 @@
3233

3334
import net.minecraft.init.Blocks;
3435
import net.minecraft.init.Items;
36+
import net.minecraft.item.Item;
3537
import net.minecraft.item.ItemStack;
3638
import net.minecraft.nbt.NBTTagCompound;
3739
import net.minecraft.tileentity.TileEntity;
3840
import net.minecraft.util.ITickable;
3941
import net.minecraftforge.fluids.FluidTank;
42+
import net.minecraftforge.fml.common.registry.ForgeRegistries;
4043
import net.minecraftforge.items.IItemHandlerModifiable;
4144
import net.minecraftforge.items.ItemStackHandler;
4245

4346
import org.jetbrains.annotations.NotNull;
4447

48+
import java.util.Collection;
49+
import java.util.Random;
4550
import java.util.concurrent.atomic.AtomicInteger;
4651
import java.util.concurrent.atomic.AtomicReference;
4752
import java.util.function.Function;
@@ -57,6 +62,7 @@ public class TestTile extends TileEntity implements IGuiHolder<PosGuiData>, ITic
5762
private final int duration = 80;
5863
private int progress = 0;
5964
private int cycleState = 0;
65+
private ItemStack displayItem = new ItemStack(Items.DIAMOND);
6066
private final IItemHandlerModifiable inventory = new ItemStackHandler(2) {
6167
@Override
6268
public int getSlotLimit(int slot) {
@@ -85,6 +91,7 @@ public ModularPanel buildUI(PosGuiData guiData, PanelSyncManager guiSyncManager,
8591
guiSyncManager.syncValue("mixer_fluids", 1, SyncHandlers.fluidSlot(this.mixerFluids2));
8692
IntSyncValue cycleStateValue = new IntSyncValue(() -> this.cycleState, val -> this.cycleState = val);
8793
guiSyncManager.syncValue("cycle_state", cycleStateValue);
94+
guiSyncManager.syncValue("display_item", GenericSyncValue.forItem(() -> this.displayItem, null));
8895
guiSyncManager.bindPlayerInventory(guiData.getPlayer());
8996

9097
Rectangle colorPickerBackground = new Rectangle().setColor(Color.RED.main);
@@ -339,11 +346,12 @@ public ModularPanel buildUI(PosGuiData guiData, PanelSyncManager guiSyncManager,
339346
.debugName("page 4 crafting")
340347
.sizeRel(1f)
341348
.child(SlotGroupWidget.builder()
342-
.row("III ")
349+
.row("III D")
343350
.row("III O")
344351
.row("III ")
345352
.key('I', i -> new ItemSlot().slot(new ModularSlot(this.craftingInventory, i)))
346353
.key('O', new ItemSlot().slot(new ModularCraftingSlot(this.craftingInventory, 9)))
354+
.key('D', new ItemDisplayWidget().syncHandler("display_item").displayAmount(true))
347355
.build()
348356
.center())
349357
)))
@@ -369,7 +377,7 @@ public ModularPanel openSecondWindow(PanelSyncManager syncManager, IPanelHandler
369377
.setDraggable(true)
370378
.size(100, 100);
371379
SlotGroup slotGroup = new SlotGroup("small_inv", 2);
372-
IntSyncValue timeSync = new IntSyncValue(() -> (int)java.lang.System.currentTimeMillis(), val -> {java.lang.System.out.println(val);});
380+
IntSyncValue timeSync = new IntSyncValue(() -> (int)java.lang.System.currentTimeMillis());
373381
syncManager.syncValue(123456,timeSync);
374382
syncManager.registerSlotGroup(slotGroup);
375383
AtomicInteger number = new AtomicInteger(0);
@@ -442,8 +450,11 @@ public void update() {
442450
this.val++;
443451
}
444452
} else {
445-
if (this.time++ % 20 == 0 && ++this.val2 == 3) {
446-
this.val2 = 0;
453+
if (this.time++ % 20 == 0) {
454+
if (++this.val2 == 3) this.val2 = 0;
455+
Collection<Item> vals = ForgeRegistries.ITEMS.getValuesCollection();
456+
Item item = vals.stream().skip(new Random().nextInt(vals.size())).findFirst().orElse(Items.DIAMOND);
457+
this.displayItem = new ItemStack(item, 26735987);
447458
}
448459
}
449460
if (++this.progress == this.duration) {

src/main/java/com/cleanroommc/modularui/utils/NumberFormat.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ public ParamsBuilder copyToBuilder() {
8282
.considerMinusForLength(this.considerMinusForLength)
8383
.considerSuffixForLength(this.considerSuffixForLength);
8484
}
85+
86+
public String format(double number) {
87+
return NumberFormat.format(number, this);
88+
}
8589
}
8690

8791
public static class ParamsBuilder {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.cleanroommc.modularui.value;
2+
3+
import com.cleanroommc.modularui.api.value.IValue;
4+
5+
import java.util.function.Consumer;
6+
import java.util.function.Supplier;
7+
8+
public class ObjectValue<T> implements IValue<T> {
9+
10+
private T value;
11+
12+
public ObjectValue(T value) {
13+
this.value = value;
14+
}
15+
16+
@Override
17+
public T getValue() {
18+
return value;
19+
}
20+
21+
@Override
22+
public void setValue(T value) {
23+
this.value = value;
24+
}
25+
26+
public static class Dynamic<T> implements IValue<T> {
27+
28+
private final Supplier<T> getter;
29+
private final Consumer<T> setter;
30+
31+
public Dynamic(Supplier<T> getter, Consumer<T> setter) {
32+
this.getter = getter;
33+
this.setter = setter;
34+
}
35+
36+
@Override
37+
public T getValue() {
38+
return this.getter.get();
39+
}
40+
41+
@Override
42+
public void setValue(T value) {
43+
this.setter.accept(value);
44+
}
45+
}
46+
}

src/main/java/com/cleanroommc/modularui/value/sync/GenericSyncValue.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
package com.cleanroommc.modularui.value.sync;
22

33
import com.cleanroommc.modularui.utils.ICopy;
4+
import com.cleanroommc.modularui.utils.serialization.ByteBufAdapters;
45
import com.cleanroommc.modularui.utils.serialization.IByteBufAdapter;
56
import com.cleanroommc.modularui.utils.serialization.IByteBufDeserializer;
67
import com.cleanroommc.modularui.utils.serialization.IByteBufSerializer;
78
import com.cleanroommc.modularui.utils.serialization.IEquals;
89

10+
import net.minecraft.item.ItemStack;
911
import net.minecraft.network.PacketBuffer;
12+
import net.minecraftforge.fluids.FluidStack;
1013

1114
import org.jetbrains.annotations.NotNull;
1215
import org.jetbrains.annotations.Nullable;
@@ -18,6 +21,14 @@
1821

1922
public class GenericSyncValue<T> extends ValueSyncHandler<T> {
2023

24+
public static GenericSyncValue<ItemStack> forItem(@NotNull Supplier<ItemStack> getter, @Nullable Consumer<ItemStack> setter) {
25+
return new GenericSyncValue<>(getter, setter, ByteBufAdapters.ITEM_STACK);
26+
}
27+
28+
public static GenericSyncValue<FluidStack> forFluid(@NotNull Supplier<FluidStack> getter, @Nullable Consumer<FluidStack> setter) {
29+
return new GenericSyncValue<>(getter, setter, ByteBufAdapters.FLUID_STACK);
30+
}
31+
2132
private final Supplier<T> getter;
2233
private final Consumer<T> setter;
2334
private final IByteBufDeserializer<T> deserializer;
@@ -128,4 +139,29 @@ public void write(PacketBuffer buffer) throws IOException {
128139
public void read(PacketBuffer buffer) throws IOException {
129140
setValue(this.deserializer.deserialize(buffer), true, false);
130141
}
142+
143+
@SuppressWarnings("unchecked")
144+
public @Nullable Class<? extends T> getType() {
145+
if (this.cache != null) {
146+
return (Class<? extends T>) this.cache.getClass();
147+
}
148+
T t = this.getter.get();
149+
if (t != null) {
150+
return (Class<? extends T>) t.getClass();
151+
}
152+
return null;
153+
}
154+
155+
public boolean isOfType(Class<?> expectedType) {
156+
Class<? extends T> type = getType();
157+
if (type == null) {
158+
throw new IllegalStateException("Could not infer type of GenericSyncValue since value is null!");
159+
}
160+
return expectedType.isAssignableFrom(type);
161+
}
162+
163+
@SuppressWarnings("unchecked")
164+
public <V> GenericSyncValue<V> cast() {
165+
return (GenericSyncValue<V>) this;
166+
}
131167
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package com.cleanroommc.modularui.widgets;
2+
3+
import com.cleanroommc.modularui.api.ITheme;
4+
import com.cleanroommc.modularui.api.value.IValue;
5+
import com.cleanroommc.modularui.drawable.GuiDraw;
6+
import com.cleanroommc.modularui.screen.viewport.ModularGuiContext;
7+
import com.cleanroommc.modularui.theme.WidgetTheme;
8+
import com.cleanroommc.modularui.utils.Platform;
9+
import com.cleanroommc.modularui.value.ObjectValue;
10+
import com.cleanroommc.modularui.value.sync.GenericSyncValue;
11+
import com.cleanroommc.modularui.value.sync.SyncHandler;
12+
import com.cleanroommc.modularui.widget.Widget;
13+
14+
import net.minecraft.item.ItemStack;
15+
16+
/**
17+
* An item slot which only purpose is to display an item stack.
18+
* The displayed item stack can be supplied directly, by an {@link ObjectValue} dynamically or by a {@link GenericSyncValue} synced.
19+
* Players can not interact with this widget in any form.
20+
*/
21+
public class ItemDisplayWidget extends Widget<ItemDisplayWidget> {
22+
23+
private IValue<ItemStack> value;
24+
private boolean displayAmount = false;
25+
26+
public ItemDisplayWidget() {
27+
size(18);
28+
}
29+
30+
@Override
31+
public boolean isValidSyncHandler(SyncHandler syncHandler) {
32+
if (syncHandler instanceof GenericSyncValue<?> genericSyncValue && genericSyncValue.isOfType(ItemStack.class)) {
33+
this.value = genericSyncValue.cast();
34+
return true;
35+
}
36+
return false;
37+
}
38+
39+
@Override
40+
protected WidgetTheme getWidgetThemeInternal(ITheme theme) {
41+
return theme.getItemSlotTheme();
42+
}
43+
44+
@Override
45+
public void draw(ModularGuiContext context, WidgetTheme widgetTheme) {
46+
ItemStack item = value.getValue();
47+
if (!Platform.isStackEmpty(item)) {
48+
GuiDraw.drawItem(item, 1, 1, 16, 16, context.getCurrentDrawingZ());
49+
if (this.displayAmount) {
50+
GuiDraw.drawStandardSlotAmountText(item.getCount(), null, getArea());
51+
}
52+
}
53+
}
54+
55+
public ItemDisplayWidget item(IValue<ItemStack> itemSupplier) {
56+
this.value = itemSupplier;
57+
setValue(itemSupplier);
58+
return this;
59+
}
60+
61+
public ItemDisplayWidget item(ItemStack itemStack) {;
62+
return item(new ObjectValue<>(itemStack));
63+
}
64+
65+
public ItemDisplayWidget displayAmount(boolean displayAmount) {
66+
this.displayAmount = displayAmount;
67+
return this;
68+
}
69+
}

0 commit comments

Comments
 (0)