diff --git a/src/main/java/com/cleanroommc/modularui/ClientEventHandler.java b/src/main/java/com/cleanroommc/modularui/ClientEventHandler.java deleted file mode 100644 index 9f7212682..000000000 --- a/src/main/java/com/cleanroommc/modularui/ClientEventHandler.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.cleanroommc.modularui; - -import com.cleanroommc.modularui.api.IMuiScreen; -import com.cleanroommc.modularui.drawable.Stencil; - -import net.minecraftforge.client.event.GuiScreenEvent; -import net.minecraftforge.fml.common.eventhandler.EventPriority; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.gameevent.TickEvent; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import org.lwjgl.opengl.GL11; - -import java.io.IOException; - -@SideOnly(Side.CLIENT) -public class ClientEventHandler { - - private static long ticks = 0L; - - public static long getTicks() { - return ticks; - } - - @SubscribeEvent - public static void onClientTick(TickEvent.ClientTickEvent event) { - if (event.phase == TickEvent.Phase.START) { - ticks++; - } - } - - @SubscribeEvent - public static void preDraw(TickEvent.RenderTickEvent event) { - if (event.phase == TickEvent.Phase.START) { - GL11.glEnable(GL11.GL_STENCIL_TEST); - } - Stencil.reset(); - } - - @SubscribeEvent(priority = EventPriority.HIGHEST) - public static void onGuiInput(GuiScreenEvent.MouseInputEvent.Pre event) { - if (hasDraggable(event)) { - // cancel interactions with other mods - try { - event.getGui().handleMouseInput(); - } catch (IOException e) { - throw new RuntimeException(e); - } - event.setCanceled(true); - } - } - - @SubscribeEvent(priority = EventPriority.HIGHEST) - public static void onGuiInput(GuiScreenEvent.KeyboardInputEvent.Pre event) { - if (hasDraggable(event)) { - // cancel interactions with other mods - try { - event.getGui().handleKeyboardInput(); - } catch (IOException e) { - throw new RuntimeException(e); - } - event.setCanceled(true); - } - } - - private static boolean hasDraggable(GuiScreenEvent event) { - return event.getGui() instanceof IMuiScreen screenWrapper && screenWrapper.getScreen().getContext().hasDraggable(); - } -} diff --git a/src/main/java/com/cleanroommc/modularui/ClientProxy.java b/src/main/java/com/cleanroommc/modularui/ClientProxy.java index 5c8eb5914..a39f078b8 100644 --- a/src/main/java/com/cleanroommc/modularui/ClientProxy.java +++ b/src/main/java/com/cleanroommc/modularui/ClientProxy.java @@ -32,7 +32,6 @@ public class ClientProxy extends CommonProxy { void preInit(FMLPreInitializationEvent event) { super.preInit(event); - MinecraftForge.EVENT_BUS.register(ClientEventHandler.class); MinecraftForge.EVENT_BUS.register(ClientScreenHandler.class); MinecraftForge.EVENT_BUS.register(OverlayManager.class); MinecraftForge.EVENT_BUS.register(KeyBindHandler.class); diff --git a/src/main/java/com/cleanroommc/modularui/api/IPanelHandler.java b/src/main/java/com/cleanroommc/modularui/api/IPanelHandler.java index 197a81a82..abd4dc9ff 100644 --- a/src/main/java/com/cleanroommc/modularui/api/IPanelHandler.java +++ b/src/main/java/com/cleanroommc/modularui/api/IPanelHandler.java @@ -2,6 +2,7 @@ import com.cleanroommc.modularui.screen.ModularPanel; import com.cleanroommc.modularui.screen.SecondaryPanel; +import com.cleanroommc.modularui.value.sync.ItemSlotSH; import com.cleanroommc.modularui.value.sync.PanelSyncHandler; import com.cleanroommc.modularui.value.sync.PanelSyncManager; @@ -34,6 +35,8 @@ static IPanelHandler simple(ModularPanel parent, SecondaryPanel.IPanelBuilder pr return new SecondaryPanel(parent, provider, subPanel); } + boolean isPanelOpen(); + /** * Opens the panel. If there is no cached panel, one will be created. * Can be called on both sides if this handler is synced. @@ -60,9 +63,9 @@ static IPanelHandler simple(ModularPanel parent, SecondaryPanel.IPanelBuilder pr /** * Deletes the current cached panel. Should not be used frequently. - * This only works on non synced panels. Otherwise, it crashes. + * This only works on panels which don't have {@link ItemSlotSH} sync handlers. * - * @throws UnsupportedOperationException if this handler is synced + * @throws UnsupportedOperationException if this handler has ItemSlot sync handlers */ void deleteCachedPanel(); diff --git a/src/main/java/com/cleanroommc/modularui/api/IPanelSyncManager.java b/src/main/java/com/cleanroommc/modularui/api/IPanelSyncManager.java deleted file mode 100644 index d87691d34..000000000 --- a/src/main/java/com/cleanroommc/modularui/api/IPanelSyncManager.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.cleanroommc.modularui.api; - -import com.cleanroommc.modularui.value.sync.SyncHandler; - -import net.minecraft.entity.player.EntityPlayer; - -import org.jetbrains.annotations.ApiStatus; - -public interface IPanelSyncManager { - - @ApiStatus.Internal - void detectAndSendChanges(boolean init); - - void onClose(); - - void onOpen(); - - EntityPlayer getPlayer(); - - IPanelSyncManager syncValue(String key, int id, SyncHandler syncHandler); - -} diff --git a/src/main/java/com/cleanroommc/modularui/api/drawable/IKey.java b/src/main/java/com/cleanroommc/modularui/api/drawable/IKey.java index 206a3beb1..728e69e08 100644 --- a/src/main/java/com/cleanroommc/modularui/api/drawable/IKey.java +++ b/src/main/java/com/cleanroommc/modularui/api/drawable/IKey.java @@ -130,7 +130,7 @@ static IKey comp(@NotNull IKey... keys) { * @param getter string supplier * @return dynamic text key */ - static IKey dynamic(@NotNull Supplier getter) { + static IKey dynamic(@NotNull Supplier<@NotNull String> getter) { return new DynamicKey(getter); } @@ -181,7 +181,7 @@ default StyledText alignment(Alignment alignment) { return withStyle().alignment(alignment); } - default StyledText color(int color) { + default StyledText color(@Nullable Integer color) { return withStyle().color(color); } @@ -189,7 +189,7 @@ default StyledText scale(float scale) { return withStyle().scale(scale); } - default StyledText shadow(boolean shadow) { + default StyledText shadow(@Nullable Boolean shadow) { return withStyle().shadow(shadow); } diff --git a/src/main/java/com/cleanroommc/modularui/drawable/text/AnimatedText.java b/src/main/java/com/cleanroommc/modularui/drawable/text/AnimatedText.java index 96d19ec34..ac72617d8 100644 --- a/src/main/java/com/cleanroommc/modularui/drawable/text/AnimatedText.java +++ b/src/main/java/com/cleanroommc/modularui/drawable/text/AnimatedText.java @@ -10,6 +10,8 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import org.jetbrains.annotations.Nullable; + public class AnimatedText extends StyledText { private String fullString; @@ -111,7 +113,7 @@ public AnimatedText alignment(Alignment alignment) { } @Override - public AnimatedText color(int color) { + public AnimatedText color(@Nullable Integer color) { return (AnimatedText) super.color(color); } @@ -121,7 +123,7 @@ public AnimatedText scale(float scale) { } @Override - public AnimatedText shadow(boolean shadow) { + public AnimatedText shadow(@Nullable Boolean shadow) { return (AnimatedText) super.shadow(shadow); } diff --git a/src/main/java/com/cleanroommc/modularui/drawable/text/CompoundKey.java b/src/main/java/com/cleanroommc/modularui/drawable/text/CompoundKey.java index 6b8fae1ea..56b6f20dd 100644 --- a/src/main/java/com/cleanroommc/modularui/drawable/text/CompoundKey.java +++ b/src/main/java/com/cleanroommc/modularui/drawable/text/CompoundKey.java @@ -1,7 +1,7 @@ package com.cleanroommc.modularui.drawable.text; -import com.cleanroommc.modularui.ClientEventHandler; import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.screen.ClientScreenHandler; public class CompoundKey extends BaseKey { @@ -17,8 +17,8 @@ public CompoundKey(IKey... keys) { @Override public String get() { - if (ClientEventHandler.getTicks() != this.time) { - this.time = ClientEventHandler.getTicks(); + if (ClientScreenHandler.getTicks() != this.time) { + this.time = ClientScreenHandler.getTicks(); StringBuilder builder = new StringBuilder(); for (IKey key : this.keys) { builder.append(key.get()); diff --git a/src/main/java/com/cleanroommc/modularui/drawable/text/DynamicKey.java b/src/main/java/com/cleanroommc/modularui/drawable/text/DynamicKey.java index 844073303..0694e550e 100644 --- a/src/main/java/com/cleanroommc/modularui/drawable/text/DynamicKey.java +++ b/src/main/java/com/cleanroommc/modularui/drawable/text/DynamicKey.java @@ -1,5 +1,6 @@ package com.cleanroommc.modularui.drawable.text; +import java.util.Objects; import java.util.function.Supplier; public class DynamicKey extends BaseKey { @@ -7,6 +8,7 @@ public class DynamicKey extends BaseKey { private final Supplier supplier; public DynamicKey(Supplier supplier) { + Objects.requireNonNull(supplier.get(), "IKey returns a null string!"); this.supplier = supplier; } diff --git a/src/main/java/com/cleanroommc/modularui/drawable/text/LangKey.java b/src/main/java/com/cleanroommc/modularui/drawable/text/LangKey.java index c8ab8f159..c0cdb0c7f 100644 --- a/src/main/java/com/cleanroommc/modularui/drawable/text/LangKey.java +++ b/src/main/java/com/cleanroommc/modularui/drawable/text/LangKey.java @@ -1,6 +1,6 @@ package com.cleanroommc.modularui.drawable.text; -import com.cleanroommc.modularui.ClientEventHandler; +import com.cleanroommc.modularui.screen.ClientScreenHandler; import net.minecraft.client.resources.I18n; @@ -48,10 +48,10 @@ public Supplier getArgsSupplier() { @Override public String get() { - if (this.time == ClientEventHandler.getTicks()) { + if (this.time == ClientScreenHandler.getTicks()) { return this.string; } - this.time = ClientEventHandler.getTicks(); + this.time = ClientScreenHandler.getTicks(); this.string = I18n.format(Objects.requireNonNull(this.keySupplier.get()), this.argsSupplier.get()).replaceAll("\\\\n", "\n"); return string; } diff --git a/src/main/java/com/cleanroommc/modularui/drawable/text/StyledText.java b/src/main/java/com/cleanroommc/modularui/drawable/text/StyledText.java index 457a5c8e7..46336330b 100644 --- a/src/main/java/com/cleanroommc/modularui/drawable/text/StyledText.java +++ b/src/main/java/com/cleanroommc/modularui/drawable/text/StyledText.java @@ -10,6 +10,8 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import org.jetbrains.annotations.Nullable; + public class StyledText extends BaseKey { private final IKey key; @@ -72,7 +74,7 @@ public StyledText alignment(Alignment alignment) { } @Override - public StyledText color(int color) { + public StyledText color(@Nullable Integer color) { this.color = color; return this; } @@ -84,7 +86,7 @@ public StyledText scale(float scale) { } @Override - public StyledText shadow(boolean shadow) { + public StyledText shadow(@Nullable Boolean shadow) { this.shadow = shadow; return this; } diff --git a/src/main/java/com/cleanroommc/modularui/screen/ClientScreenHandler.java b/src/main/java/com/cleanroommc/modularui/screen/ClientScreenHandler.java index 506929b87..c15150e6b 100644 --- a/src/main/java/com/cleanroommc/modularui/screen/ClientScreenHandler.java +++ b/src/main/java/com/cleanroommc/modularui/screen/ClientScreenHandler.java @@ -51,6 +51,7 @@ import org.jetbrains.annotations.Nullable; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; import java.awt.*; import java.io.IOException; @@ -65,6 +66,7 @@ public class ClientScreenHandler { private static ModularScreen currentScreen = null; private static Character lastChar = null; private static final FpsCounter fpsCounter = new FpsCounter(); + private static long ticks = 0L; @SubscribeEvent public static void onGuiOpen(GuiOpenEvent event) { @@ -148,9 +150,22 @@ public static void onTick(TickEvent.ClientTickEvent event) { if (checkGui()) { currentScreen.onUpdate(); } + ticks++; } } + @SubscribeEvent + public static void preDraw(TickEvent.RenderTickEvent event) { + if (event.phase == TickEvent.Phase.START) { + GL11.glEnable(GL11.GL_STENCIL_TEST); + } + Stencil.reset(); + } + + public static long getTicks() { + return ticks; + } + public static void onFrameUpdate() { OverlayStack.foreach(ModularScreen::onFrameUpdate, true); if (currentScreen != null) currentScreen.onFrameUpdate(); diff --git a/src/main/java/com/cleanroommc/modularui/screen/ModularPanel.java b/src/main/java/com/cleanroommc/modularui/screen/ModularPanel.java index 011fae61a..66bb5b66e 100644 --- a/src/main/java/com/cleanroommc/modularui/screen/ModularPanel.java +++ b/src/main/java/com/cleanroommc/modularui/screen/ModularPanel.java @@ -624,9 +624,13 @@ public final boolean isMainPanel() { } @ApiStatus.Internal - public void setSyncHandler(@Nullable PanelSyncHandler syncHandler) { + @Override + public void setSyncHandler(@Nullable SyncHandler syncHandler) { + if (!isValidSyncHandler(syncHandler)) + throw new IllegalStateException("Panel SyncHandler's must implement IPanelHandler!"); + super.setSyncHandler(syncHandler); - setPanelHandler(syncHandler); + setPanelHandler((IPanelHandler) syncHandler); } @NotNull diff --git a/src/main/java/com/cleanroommc/modularui/screen/SecondaryPanel.java b/src/main/java/com/cleanroommc/modularui/screen/SecondaryPanel.java index 5ec853202..d62d8a85f 100644 --- a/src/main/java/com/cleanroommc/modularui/screen/SecondaryPanel.java +++ b/src/main/java/com/cleanroommc/modularui/screen/SecondaryPanel.java @@ -63,6 +63,11 @@ public boolean isSubPanel() { return subPanel; } + @Override + public boolean isPanelOpen() { + return this.open; + } + @Override public void openPanel() { if (this.open) return; diff --git a/src/main/java/com/cleanroommc/modularui/test/TestTile.java b/src/main/java/com/cleanroommc/modularui/test/TestTile.java index bdb37d874..874369014 100644 --- a/src/main/java/com/cleanroommc/modularui/test/TestTile.java +++ b/src/main/java/com/cleanroommc/modularui/test/TestTile.java @@ -19,7 +19,6 @@ import com.cleanroommc.modularui.value.IntValue; import com.cleanroommc.modularui.value.StringValue; import com.cleanroommc.modularui.value.sync.IntSyncValue; -import com.cleanroommc.modularui.value.sync.PanelSyncHandler; import com.cleanroommc.modularui.value.sync.PanelSyncManager; import com.cleanroommc.modularui.value.sync.SyncHandlers; import com.cleanroommc.modularui.widget.ParentWidget; @@ -41,6 +40,7 @@ import org.jetbrains.annotations.NotNull; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; @@ -128,6 +128,11 @@ public ModularPanel buildUI(PosGuiData guiData, PanelSyncManager guiSyncManager) .child(new ButtonWidget<>() .size(60, 18) .overlay(IKey.dynamic(() -> "Button " + this.val))) + .child(new Rectangle() + .setColor(Color.RED.main) + .asWidget() + .size(32, 2) + .setEnabledIf(widget -> this.val > 10)) .child(new FluidSlot() .margin(2) .syncHandler(SyncHandlers.fluidSlot(this.fluidTank))) @@ -163,7 +168,8 @@ public ModularPanel buildUI(PosGuiData guiData, PanelSyncManager guiSyncManager) .size(60, 20) .value(SyncHandlers.doubleNumber(() -> this.doubleValue, val -> this.doubleValue = val)) .setNumbersDouble(Function.identity())) - .child(IKey.str("Test string").asWidget().padding(2).debugName("test string"))) + .child(IKey.str("Test string").asWidget().padding(2).debugName("test string")) + .child(IKey.EMPTY.asWidget().debugName("Empty Ikey"))) .child(new Column() .debugName("button and slots test 2") .coverChildren() @@ -327,14 +333,17 @@ public ModularPanel buildUI(PosGuiData guiData, PanelSyncManager guiSyncManager) return panel; } - public ModularPanel openSecondWindow(PanelSyncManager syncManager, PanelSyncHandler syncHandler) { + public ModularPanel openSecondWindow(PanelSyncManager syncManager, IPanelHandler syncHandler) { ModularPanel panel = new Dialog<>("second_window", null) .setDisablePanelsBelow(false) .setCloseOnOutOfBoundsClick(false) .size(100, 100); SlotGroup slotGroup = new SlotGroup("small_inv", 2); syncManager.registerSlotGroup(slotGroup); - IPanelHandler panelSyncHandler = syncManager.panel("other_panel_2", this::openThirdWindow, true); + AtomicInteger number = new AtomicInteger(0); + syncManager.syncValue("int_value", new IntSyncValue(number::get, number::set)); + IPanelHandler panelSyncHandler = syncManager.panel("other_panel_2", (syncManager1, syncHandler1) -> + openThirdWindow(syncManager1, syncHandler1, number), true); panel.child(ButtonWidget.panelCloseButton()) .child(new ButtonWidget<>() .size(10).top(14).right(4) @@ -351,19 +360,31 @@ public ModularPanel openSecondWindow(PanelSyncManager syncManager, PanelSyncHand .row("II") .key('I', i -> new ItemSlot().slot(new ModularSlot(smallInv, i).slotGroup(slotGroup))) .build() - .center()); + .center()) + .child(new ButtonWidget<>() + .bottom(5) + .right(5) + .tooltip(richTooltip -> richTooltip.textColor(Color.RED.main).add("WARNING! Very Dangerous")) + .onMousePressed(mouseButton -> { + if (!panelSyncHandler.isPanelOpen()) { + panelSyncHandler.deleteCachedPanel(); + number.incrementAndGet(); + } + return true; + })); return panel; } - public ModularPanel openThirdWindow(PanelSyncManager syncManager, PanelSyncHandler syncHandler) { + public ModularPanel openThirdWindow(PanelSyncManager syncManager, IPanelHandler syncHandler, AtomicInteger integer) { ModularPanel panel = new Dialog<>("third_window", null) .setDisablePanelsBelow(false) .setCloseOnOutOfBoundsClick(false) + .setDraggable(true) .size(50, 50); panel.child(ButtonWidget.panelCloseButton()) - .child(IKey.str("3rd Panel") + .child(IKey.str("3rd Panel: " + integer.get()) .asWidget() - .pos(5, 5)); + .pos(5, 17)); return panel; } diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/ItemSlotSH.java b/src/main/java/com/cleanroommc/modularui/value/sync/ItemSlotSH.java index c40e57c27..8ba24c62c 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/ItemSlotSH.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/ItemSlotSH.java @@ -22,6 +22,7 @@ public class ItemSlotSH extends SyncHandler { private final ModularSlot slot; private ItemStack lastStoredItem; private ItemStack lastStoredPhantomItem = ItemStack.EMPTY; + private boolean registered = false; @ApiStatus.Internal public ItemSlotSH(ModularSlot slot) { @@ -31,7 +32,10 @@ public ItemSlotSH(ModularSlot slot) { @Override public void init(String key, PanelSyncManager syncHandler) { super.init(key, syncHandler); - syncHandler.getContainer().registerSlot(syncHandler.getPanelName(), this.slot); + if (!registered) { + getSyncManager().getContainer().registerSlot(getSyncManager().getPanelName(), this.slot); + this.registered = true; + } this.lastStoredItem = getSlot().getStack().copy(); if (isPhantom() && !getSlot().getStack().isEmpty()) { this.lastStoredPhantomItem = getSlot().getStack().copy(); diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/ModularSyncManager.java b/src/main/java/com/cleanroommc/modularui/value/sync/ModularSyncManager.java index 107e78e47..d8bd02558 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/ModularSyncManager.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/ModularSyncManager.java @@ -1,7 +1,6 @@ package com.cleanroommc.modularui.value.sync; import com.cleanroommc.modularui.ModularUI; -import com.cleanroommc.modularui.api.IPanelSyncManager; import com.cleanroommc.modularui.screen.ModularContainer; import com.cleanroommc.modularui.widgets.slot.SlotGroup; import com.cleanroommc.bogosorter.api.ISortingContextBuilder; @@ -58,11 +57,11 @@ public void detectAndSendChanges(boolean init) { } public void onClose() { - this.panelSyncManagerMap.values().forEach(IPanelSyncManager::onClose); + this.panelSyncManagerMap.values().forEach(PanelSyncManager::onClose); } public void onOpen() { - this.panelSyncManagerMap.values().forEach(IPanelSyncManager::onOpen); + this.panelSyncManagerMap.values().forEach(PanelSyncManager::onOpen); } public PanelSyncManager getPanelSyncManager(String panelName) { diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/PanelSyncHandler.java b/src/main/java/com/cleanroommc/modularui/value/sync/PanelSyncHandler.java index f07d48979..c12d44171 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/PanelSyncHandler.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/PanelSyncHandler.java @@ -1,6 +1,7 @@ package com.cleanroommc.modularui.value.sync; import com.cleanroommc.modularui.api.IPanelHandler; +import com.cleanroommc.modularui.api.widget.ISynced; import com.cleanroommc.modularui.screen.ModularPanel; import com.cleanroommc.modularui.screen.ModularScreen; import com.cleanroommc.modularui.widget.WidgetTree; @@ -18,7 +19,7 @@ * Register it in any {@link PanelSyncManager} (preferably the main one). * Then you can call {@link #openPanel()} and {@link #closePanel()} from any side. */ -public class PanelSyncHandler extends SyncHandler implements IPanelHandler { +public final class PanelSyncHandler extends SyncHandler implements IPanelHandler { private final IPanelBuilder panelBuilder; private final boolean subPanel; @@ -47,6 +48,7 @@ public void openPanel() { } private void openPanel(boolean syncToServer) { + if (isPanelOpen()) return; boolean client = getSyncManager().isClient(); if (syncToServer && client) { syncToServer(0); @@ -59,7 +61,7 @@ private void openPanel(boolean syncToServer) { this.openedPanel = Objects.requireNonNull(createUI(this.syncManager)); this.panelName = this.openedPanel.getName(); this.openedPanel.setSyncHandler(this); - WidgetTree.collectSyncValues(getSyncManager(), this.openedPanel); + WidgetTree.collectSyncValues(this.syncManager, this.openedPanel, false); if (!client) { this.openedPanel = null; } @@ -107,9 +109,29 @@ public void closePanelInternal() { @Override public void deleteCachedPanel() { + if (openedPanel == null || isPanelOpen()) return; + boolean canDispose = WidgetTree.foreachChild(openedPanel, iWidget -> { + if (!iWidget.isValid()) return false; + if (iWidget instanceof ISyncedsynced && synced.isSynced()) { + return !(synced.getSyncHandler() instanceof ItemSlotSH); + } + return true; + }, false); + // This is because we can't guarantee that the sync handlers of the new panel are the same. // Dynamic sync handler changing is very error-prone. - throw new UnsupportedOperationException("Can't delete cached panel in synced panel handlers!"); + if (!canDispose) + throw new UnsupportedOperationException("Can't delete cached panel if it's still open or has ItemSlot Sync Handlers!"); + + disposePanel(); + + sync(3); + } + + private void disposePanel() { + this.panelName = null; + this.syncManager = null; + this.openedPanel = null; } @Override @@ -117,6 +139,7 @@ public boolean isSubPanel() { return subPanel; } + @Override public boolean isPanelOpen() { return this.open; } @@ -127,6 +150,8 @@ public void readOnClient(int i, PacketBuffer packetBuffer) throws IOException { openPanel(false); } else if (i == 2) { closePanel(); + } else if (i == 3) { + disposePanel(); } } @@ -137,6 +162,8 @@ public void readOnServer(int i, PacketBuffer packetBuffer) throws IOException { syncToClient(1); } else if (i == 2) { closePanelInternal(); + } else if (i == 3) { + disposePanel(); } } @@ -153,6 +180,6 @@ public interface IPanelBuilder { * @return the created panel */ @NotNull - ModularPanel buildUI(@NotNull PanelSyncManager syncManager, @NotNull PanelSyncHandler syncHandler); + ModularPanel buildUI(@NotNull PanelSyncManager syncManager, @NotNull IPanelHandler syncHandler); } } diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/PanelSyncManager.java b/src/main/java/com/cleanroommc/modularui/value/sync/PanelSyncManager.java index a144e73db..6a1316c2d 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/PanelSyncManager.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/PanelSyncManager.java @@ -1,7 +1,7 @@ package com.cleanroommc.modularui.value.sync; +import com.cleanroommc.modularui.ModularUI; import com.cleanroommc.modularui.api.IPanelHandler; -import com.cleanroommc.modularui.api.IPanelSyncManager; import com.cleanroommc.modularui.screen.ContainerCustomizer; import com.cleanroommc.modularui.screen.ModularContainer; import com.cleanroommc.modularui.widgets.slot.ModularSlot; @@ -22,7 +22,7 @@ import java.util.*; import java.util.function.Consumer; -public class PanelSyncManager implements IPanelSyncManager { +public class PanelSyncManager { private final Map syncHandlers = new Object2ObjectLinkedOpenHashMap<>(); private final Map slotGroups = new Object2ObjectOpenHashMap<>(); @@ -79,8 +79,8 @@ public void onOpen() { public void onClose() { this.closeListener.forEach(listener -> listener.accept(getPlayer())); for (String name : this.subPanels.keySet()) { - SyncHandler sh = this.modularSyncManager.getMainPSM().syncHandlers.remove(name); - this.modularSyncManager.getMainPSM().reverseSyncHandlers.remove(sh); + SyncHandler sh = this.getModularSyncManager().getMainPSM().syncHandlers.remove(name); + this.getModularSyncManager().getMainPSM().reverseSyncHandlers.remove(sh); } } @@ -98,6 +98,10 @@ public void detectAndSendChanges(boolean init) { } public void receiveWidgetUpdate(String mapKey, int id, PacketBuffer buf) throws IOException { + if (!this.syncHandlers.containsKey(mapKey)) { + ModularUI.LOGGER.warn("SyncHandler \"{}\" does not exist for panel \"{}\"! ID was {}.", mapKey, panelName, id); + return; + } SyncHandler syncHandler = this.syncHandlers.get(mapKey); if (isClient()) { syncHandler.readOnClient(id, buf); @@ -194,9 +198,6 @@ public IPanelHandler panel(String key, PanelSyncHandler.IPanelBuilder panelBuild if (sh != null) return (IPanelHandler) sh; PanelSyncHandler syncHandler = new PanelSyncHandler(panelBuilder, subPanel); this.subPanels.put(key, syncHandler); - if (isInitialised()) { - this.modularSyncManager.getMainPSM().registerPanelSyncHandler(key, syncHandler); - } return syncHandler; } diff --git a/src/main/java/com/cleanroommc/modularui/widget/WidgetTree.java b/src/main/java/com/cleanroommc/modularui/widget/WidgetTree.java index 012c46452..1ba6c55ef 100644 --- a/src/main/java/com/cleanroommc/modularui/widget/WidgetTree.java +++ b/src/main/java/com/cleanroommc/modularui/widget/WidgetTree.java @@ -346,6 +346,11 @@ public static T findParent(IWidget parent, Class type) { @ApiStatus.Internal public static void collectSyncValues(PanelSyncManager syncManager, ModularPanel panel) { + collectSyncValues(syncManager, panel, true); + } + + @ApiStatus.Internal + public static void collectSyncValues(PanelSyncManager syncManager, ModularPanel panel, boolean includePanel) { AtomicInteger id = new AtomicInteger(0); String syncKey = ModularSyncManager.AUTO_SYNC_PREFIX + panel.getName(); foreachChildBFS(panel, widget -> { @@ -355,7 +360,7 @@ public static void collectSyncValues(PanelSyncManager syncManager, ModularPanel } } return true; - }, true); + }, includePanel); } public static boolean hasSyncedValues(ModularPanel panel) { diff --git a/src/main/java/com/cleanroommc/modularui/widgets/ScrollingTextWidget.java b/src/main/java/com/cleanroommc/modularui/widgets/ScrollingTextWidget.java index 7a8d7a496..aeb49f85c 100644 --- a/src/main/java/com/cleanroommc/modularui/widgets/ScrollingTextWidget.java +++ b/src/main/java/com/cleanroommc/modularui/widgets/ScrollingTextWidget.java @@ -6,6 +6,8 @@ import com.cleanroommc.modularui.theme.WidgetTheme; import com.cleanroommc.modularui.utils.Alignment; +import org.jetbrains.annotations.Nullable; + public class ScrollingTextWidget extends TextWidget { private static final int pauseTime = 60; @@ -86,7 +88,7 @@ public ScrollingTextWidget alignment(Alignment alignment) { } @Override - public ScrollingTextWidget color(int color) { + public ScrollingTextWidget color(@Nullable Integer color) { return (ScrollingTextWidget) super.color(color); } @@ -96,7 +98,7 @@ public ScrollingTextWidget scale(float scale) { } @Override - public ScrollingTextWidget shadow(boolean shadow) { + public ScrollingTextWidget shadow(@Nullable Boolean shadow) { return (ScrollingTextWidget) super.shadow(shadow); } diff --git a/src/main/java/com/cleanroommc/modularui/widgets/TextWidget.java b/src/main/java/com/cleanroommc/modularui/widgets/TextWidget.java index 9f3bf82e2..34c3f4339 100644 --- a/src/main/java/com/cleanroommc/modularui/widgets/TextWidget.java +++ b/src/main/java/com/cleanroommc/modularui/widgets/TextWidget.java @@ -10,6 +10,8 @@ import net.minecraft.util.text.TextFormatting; +import org.jetbrains.annotations.Nullable; + public class TextWidget extends Widget { private final IKey key; @@ -57,7 +59,7 @@ public int getDefaultHeight() { } TextRenderer renderer = simulate(maxWidth); Box padding = getArea().getPadding(); - return (int) (renderer.getLastHeight() + padding.vertical() + 0.5f); + return Math.max(1, (int) (renderer.getLastHeight() + padding.vertical() + 0.5f)); } @Override @@ -68,7 +70,7 @@ public int getDefaultWidth() { } TextRenderer renderer = simulate(maxWidth); Box padding = getArea().getPadding(); - return (int) (renderer.getLastWidth() + padding.horizontal() + 0.5f); + return Math.max(1, (int) (renderer.getLastWidth() + padding.horizontal() + 0.5f)); } public IKey getKey() { @@ -96,7 +98,7 @@ public TextWidget alignment(Alignment alignment) { return this; } - public TextWidget color(int color) { + public TextWidget color(@Nullable Integer color) { this.color = color; return this; } @@ -106,7 +108,7 @@ public TextWidget scale(float scale) { return this; } - public TextWidget shadow(boolean shadow) { + public TextWidget shadow(@Nullable Boolean shadow) { this.shadow = shadow; return this; }