diff --git a/src/main/java/com/cleanroommc/modularui/api/value/ISyncOrValue.java b/src/main/java/com/cleanroommc/modularui/api/value/ISyncOrValue.java new file mode 100644 index 000000000..cc1d8f4ff --- /dev/null +++ b/src/main/java/com/cleanroommc/modularui/api/value/ISyncOrValue.java @@ -0,0 +1,120 @@ +package com.cleanroommc.modularui.api.value; + +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * An interface that is implemented on {@link IValue} and {@link com.cleanroommc.modularui.value.sync.SyncHandler SyncHandler} for easier + * validation and setters. + */ +@ApiStatus.NonExtendable +public interface ISyncOrValue { + + /** + * A sync handler or value representing null. + */ + ISyncOrValue EMPTY = new ISyncOrValue() { + @Override + public @Nullable T castNullable(Class type) { + return null; + } + + @Override + public boolean isTypeOrEmpty(Class type) { + return true; + } + }; + + /** + * Returns the given sync handler or value or {@link #EMPTY} if null. + * + * @param syncOrValue sync handler or value + * @return a non-null representation of the given sync handler or value + */ + @NotNull + static ISyncOrValue orEmpty(@Nullable ISyncOrValue syncOrValue) { + return syncOrValue != null ? syncOrValue : EMPTY; + } + + /** + * Returns if this sync handler or value is an instance of the given type or if this represents null. This is useful, when the value or + * sync handler can be null in the widget. + * + * @param type type to check for + * @return if this sync handler or value is an instance of the type or empty + */ + default boolean isTypeOrEmpty(Class type) { + return type.isAssignableFrom(getClass()); + } + + /** + * Casts this sync handler or value to the given type or null if this isn't a subtype of the given type. + * + * @param type type to cast this sync handle or value to + * @param type to cast to + * @return this cast sync handler or value + */ + @Nullable + @SuppressWarnings("unchecked") + default T castNullable(Class type) { + return type.isAssignableFrom(getClass()) ? (T) this : null; + } + + /** + * Casts this sync handler or value to a {@link IValue IValue<V>} if it is a value handler and the containing value is of type + * {@link V} else null. + * + * @param valueType expected type of the containing value + * @param expected type of the containing value + * @return a {@link IValue IValue<V>} if types match or null + */ + @Nullable + default IValue castValueNullable(Class valueType) { + return null; + } + + /** + * Casts this sync handler or value to the given type or throws an exception if this isn't a subtype of the given type. + * + * @param type type to cast this sync handle or value to + * @param type to cast to + * @return this cast sync handler or value + * @throws IllegalStateException if this is not a subtype of the given type + */ + default T castOrThrow(Class type) { + T t = castNullable(type); + if (t == null) { + if (!isSyncHandler() && !isValueHandler()) { + throw new IllegalStateException("Empty sync handler or value can't be used for anything."); + } + String self = isSyncHandler() ? "sync handler" : "value"; + throw new IllegalStateException("Can't cast " + self + " of type '" + getClass().getSimpleName() + "' to type '" + type.getSimpleName() + "'."); + } + return t; + } + + /** + * Returns if the containing value of this is of the given type. If this is not a value it will always return false. + * + * @param type expected value type + * @return if the containing value of this is of the given type + */ + default boolean isValueOfType(Class type) { + return false; + } + + /** + * @return if this is a sync handler (false if this represents null) + */ + default boolean isSyncHandler() { + return false; + } + + /** + * @return if this is a value handler (false if this represents null) + */ + default boolean isValueHandler() { + return false; + } +} diff --git a/src/main/java/com/cleanroommc/modularui/api/value/IValue.java b/src/main/java/com/cleanroommc/modularui/api/value/IValue.java index ff164c7f2..a1a8ff299 100644 --- a/src/main/java/com/cleanroommc/modularui/api/value/IValue.java +++ b/src/main/java/com/cleanroommc/modularui/api/value/IValue.java @@ -5,7 +5,7 @@ * * @param value type */ -public interface IValue { +public interface IValue extends ISyncOrValue { /** * Gets the current value. @@ -20,4 +20,21 @@ public interface IValue { * @param value new value */ void setValue(T value); + + Class getValueType(); + + default boolean isValueOfType(Class type) { + return type.isAssignableFrom(getValueType()); + } + + @SuppressWarnings("unchecked") + @Override + default IValue castValueNullable(Class valueType) { + return isValueOfType(valueType) ? (IValue) this : null; + } + + @Override + default boolean isValueHandler() { + return true; + } } diff --git a/src/main/java/com/cleanroommc/modularui/api/widget/ISynced.java b/src/main/java/com/cleanroommc/modularui/api/widget/ISynced.java index 2e2543595..206f12f0f 100644 --- a/src/main/java/com/cleanroommc/modularui/api/widget/ISynced.java +++ b/src/main/java/com/cleanroommc/modularui/api/widget/ISynced.java @@ -1,5 +1,6 @@ package com.cleanroommc.modularui.api.widget; +import com.cleanroommc.modularui.api.value.ISyncOrValue; import com.cleanroommc.modularui.value.sync.GenericSyncValue; import com.cleanroommc.modularui.value.sync.ModularSyncManager; import com.cleanroommc.modularui.value.sync.SyncHandler; @@ -29,21 +30,32 @@ default W getThis() { * Called when this widget gets initialised or when this widget is added to the gui * * @param syncManager sync manager - * @param late + * @param late if this is called at any point after the panel this widget belongs to opened */ void initialiseSyncHandler(ModularSyncManager syncManager, boolean late); /** - * Checks and return if the received sync handler is valid for this widget This is usually an instanceof check.
- * Synced widgets must override this! - * - * @param syncHandler received sync handler - * @return true if sync handler is valid + * @deprecated use {@link #isValidSyncOrValue(ISyncOrValue)} */ + @ApiStatus.ScheduledForRemoval(inVersion = "3.2.0") + @Deprecated default boolean isValidSyncHandler(SyncHandler syncHandler) { return false; } + /** + * Returns if the given value or sync handler is valid for this widget. This is usually a call to + * {@link ISyncOrValue#isTypeOrEmpty(Class)}. If the widget must specify a value (disallow null) instanceof check can be used. You can + * check for primitive types which don't have a dedicated {@link com.cleanroommc.modularui.api.value.IValue IValue} interface with + * {@link ISyncOrValue#isValueOfType(Class)}. + * + * @param syncOrValue a sync handler or a value, but never null + * @return if the value or sync handler is valid for this class + */ + default boolean isValidSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + return !(syncOrValue instanceof SyncHandler syncHandler) || isValidSyncHandler(syncHandler); + } + /** * Checks if the given sync handler is valid for this widget and throws an exception if not. * Override {@link #isValidSyncHandler(SyncHandler)} @@ -52,17 +64,21 @@ default boolean isValidSyncHandler(SyncHandler syncHandler) { * @throws IllegalStateException if the given sync handler is invalid for this widget. */ @ApiStatus.NonExtendable - default void checkValidSyncHandler(SyncHandler syncHandler) { - if (!isValidSyncHandler(syncHandler)) { + default void checkValidSyncOrValue(ISyncOrValue syncHandler) { + if (!isValidSyncOrValue(syncHandler)) { throw new IllegalStateException("SyncHandler of type '" + syncHandler.getClass().getSimpleName() + "' is not valid " + "for widget '" + this + "'."); } } + @ApiStatus.ScheduledForRemoval(inVersion = "3.2.0") + @Deprecated default T castIfTypeElseNull(SyncHandler syncHandler, Class clazz) { return castIfTypeElseNull(syncHandler, clazz, null); } + @ApiStatus.ScheduledForRemoval(inVersion = "3.2.0") + @Deprecated @SuppressWarnings("unchecked") default T castIfTypeElseNull(SyncHandler syncHandler, Class clazz, @Nullable Consumer setup) { if (syncHandler != null && clazz.isAssignableFrom(syncHandler.getClass())) { @@ -73,10 +89,14 @@ default T castIfTypeElseNull(SyncHandler syncHandler, Class clazz, @Nulla return null; } + @ApiStatus.ScheduledForRemoval(inVersion = "3.2.0") + @Deprecated default GenericSyncValue castIfTypeGenericElseNull(SyncHandler syncHandler, Class clazz) { return castIfTypeGenericElseNull(syncHandler, clazz, null); } + @ApiStatus.ScheduledForRemoval(inVersion = "3.2.0") + @Deprecated default GenericSyncValue castIfTypeGenericElseNull(SyncHandler syncHandler, Class clazz, @Nullable Consumer> setup) { if (syncHandler instanceof GenericSyncValue genericSyncValue && genericSyncValue.isOfType(clazz)) { diff --git a/src/main/java/com/cleanroommc/modularui/screen/ModularPanel.java b/src/main/java/com/cleanroommc/modularui/screen/ModularPanel.java index 6de1f1678..8a7d43799 100644 --- a/src/main/java/com/cleanroommc/modularui/screen/ModularPanel.java +++ b/src/main/java/com/cleanroommc/modularui/screen/ModularPanel.java @@ -8,6 +8,7 @@ import com.cleanroommc.modularui.api.UpOrDown; import com.cleanroommc.modularui.api.layout.IViewport; import com.cleanroommc.modularui.api.layout.IViewportStack; +import com.cleanroommc.modularui.api.value.ISyncOrValue; import com.cleanroommc.modularui.api.widget.IDragResizeable; import com.cleanroommc.modularui.api.widget.IFocusedWidget; import com.cleanroommc.modularui.api.widget.IWidget; @@ -25,7 +26,6 @@ import com.cleanroommc.modularui.utils.ObjectList; import com.cleanroommc.modularui.value.sync.PanelSyncHandler; import com.cleanroommc.modularui.value.sync.PanelSyncManager; -import com.cleanroommc.modularui.value.sync.SyncHandler; import com.cleanroommc.modularui.widget.ParentWidget; import com.cleanroommc.modularui.widget.WidgetTree; import com.cleanroommc.modularui.widget.sizer.Area; @@ -112,15 +112,19 @@ public void onInit() { } @Override - public boolean isValidSyncHandler(SyncHandler syncHandler) { - return syncHandler instanceof IPanelHandler; + public boolean isValidSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + return syncOrValue.isTypeOrEmpty(IPanelHandler.class); } - @ApiStatus.Internal @Override - public void setSyncHandler(@Nullable SyncHandler syncHandler) { - super.setSyncHandler(syncHandler); - setPanelHandler((IPanelHandler) syncHandler); + protected void setSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + super.setSyncOrValue(syncOrValue); + setPanelHandler(syncOrValue.castNullable(IPanelHandler.class)); + } + + @ApiStatus.Internal + public void setPanelSyncHandler(PanelSyncHandler syncHandler) { + setSyncOrValue(ISyncOrValue.orEmpty(syncHandler)); } /** @@ -612,7 +616,7 @@ public boolean onMouseDrag(int mouseButton, long timeSinceClick) { mouseButton == this.mouse.lastButton && this.mouse.lastPressed != null && this.mouse.lastPressed.getElement() instanceof Interactable interactable && - this.mouse.lastPressed.getElement().isValid()) { + this.mouse.lastPressed.getElement().isValid()) { this.mouse.lastPressed.applyMatrix(getContext()); interactable.onMouseDrag(mouseButton, timeSinceClick); this.mouse.lastPressed.unapplyMatrix(getContext()); diff --git a/src/main/java/com/cleanroommc/modularui/utils/serialization/ByteBufAdapters.java b/src/main/java/com/cleanroommc/modularui/utils/serialization/ByteBufAdapters.java index 3e1dced2e..f63ae2c39 100644 --- a/src/main/java/com/cleanroommc/modularui/utils/serialization/ByteBufAdapters.java +++ b/src/main/java/com/cleanroommc/modularui/utils/serialization/ByteBufAdapters.java @@ -14,6 +14,7 @@ import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; +import java.util.Objects; public class ByteBufAdapters { @@ -108,8 +109,7 @@ public boolean areEqual(@NotNull BigDecimal t1, @NotNull BigDecimal t2) { } }; - public static IByteBufAdapter makeAdapter(@NotNull IByteBufDeserializer deserializer, @NotNull IByteBufSerializer serializer, @Nullable IEquals comparator) { - final IEquals tester = comparator != null ? comparator : IEquals.defaultTester(); + public static IByteBufAdapter makeAdapter(@NotNull IByteBufDeserializer deserializer, @NotNull IByteBufSerializer serializer, @Nullable IEquals tester) { return new IByteBufAdapter<>() { @Override public T deserialize(PacketBuffer buffer) throws IOException { @@ -123,7 +123,7 @@ public void serialize(PacketBuffer buffer, T u) throws IOException { @Override public boolean areEqual(@NotNull T t1, @NotNull T t2) { - return tester.areEqual(t1, t2); + return tester != null ? tester.areEqual(t1, t2) : Objects.equals(t1, t2); } }; } diff --git a/src/main/java/com/cleanroommc/modularui/value/BoolValue.java b/src/main/java/com/cleanroommc/modularui/value/BoolValue.java index 9feb5c44e..75744b8ee 100644 --- a/src/main/java/com/cleanroommc/modularui/value/BoolValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/BoolValue.java @@ -54,6 +54,11 @@ public void setStringValue(String val) { setBoolValue(Boolean.parseBoolean(val)); } + @Override + public Class getValueType() { + return Boolean.class; + } + public static class Dynamic implements IBoolValue, IIntValue, IStringValue { private final BooleanSupplier getter; @@ -103,5 +108,10 @@ public int getIntValue() { public void setIntValue(int val) { setBoolValue(val == 1); } + + @Override + public Class getValueType() { + return Boolean.class; + } } } diff --git a/src/main/java/com/cleanroommc/modularui/value/ByteValue.java b/src/main/java/com/cleanroommc/modularui/value/ByteValue.java index c7a975642..28e217242 100644 --- a/src/main/java/com/cleanroommc/modularui/value/ByteValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/ByteValue.java @@ -30,6 +30,11 @@ public void setValue(Byte value) { setByteValue(value); } + @Override + public Class getValueType() { + return Byte.class; + } + public static class Dynamic extends ByteValue { private final Supplier getter; diff --git a/src/main/java/com/cleanroommc/modularui/value/ConstValue.java b/src/main/java/com/cleanroommc/modularui/value/ConstValue.java index 90bd99a73..a5bd4e94b 100644 --- a/src/main/java/com/cleanroommc/modularui/value/ConstValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/ConstValue.java @@ -26,4 +26,9 @@ public T getValue() { public void setValue(T value) { this.value = value; } + + @Override + public Class getValueType() { + return (Class) value.getClass(); + } } diff --git a/src/main/java/com/cleanroommc/modularui/value/DoubleValue.java b/src/main/java/com/cleanroommc/modularui/value/DoubleValue.java index 8a6ba1c69..9f28c0465 100644 --- a/src/main/java/com/cleanroommc/modularui/value/DoubleValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/DoubleValue.java @@ -65,6 +65,11 @@ public void setFloatValue(float val) { setDoubleValue(val); } + @Override + public Class getValueType() { + return Double.class; + } + public static class Dynamic implements IDoubleValue, IStringValue { private final DoubleSupplier getter; @@ -104,5 +109,10 @@ public Double getValue() { public void setValue(Double value) { setDoubleValue(value); } + + @Override + public Class getValueType() { + return Double.class; + } } } diff --git a/src/main/java/com/cleanroommc/modularui/value/DynamicValue.java b/src/main/java/com/cleanroommc/modularui/value/DynamicValue.java index aa7ae620f..416c312d8 100644 --- a/src/main/java/com/cleanroommc/modularui/value/DynamicValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/DynamicValue.java @@ -35,4 +35,9 @@ public void setValue(T value) { this.setter.accept(value); } } + + @Override + public Class getValueType() { + return (Class) this.getter.get().getClass(); + } } diff --git a/src/main/java/com/cleanroommc/modularui/value/EnumValue.java b/src/main/java/com/cleanroommc/modularui/value/EnumValue.java index a57a9ec78..d9117c05b 100644 --- a/src/main/java/com/cleanroommc/modularui/value/EnumValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/EnumValue.java @@ -45,6 +45,11 @@ public Class getEnumClass() { return this.enumClass; } + @Override + public Class getValueType() { + return this.enumClass; + } + public static class Dynamic> implements IEnumValue, IIntValue { protected final Class enumClass; @@ -81,5 +86,10 @@ public void setValue(T value) { public Class getEnumClass() { return this.enumClass; } + + @Override + public Class getValueType() { + return this.enumClass; + } } } diff --git a/src/main/java/com/cleanroommc/modularui/value/FloatValue.java b/src/main/java/com/cleanroommc/modularui/value/FloatValue.java index 85b4b9c5c..5b04ea311 100644 --- a/src/main/java/com/cleanroommc/modularui/value/FloatValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/FloatValue.java @@ -64,6 +64,11 @@ public void setStringValue(String val) { setFloatValue(Float.parseFloat(val)); } + @Override + public Class getValueType() { + return Float.class; + } + public static class Dynamic implements IFloatValue, IDoubleValue, IStringValue { private final FloatSupplier getter; @@ -113,5 +118,10 @@ public double getDoubleValue() { public void setDoubleValue(double val) { setFloatValue((float) val); } + + @Override + public Class getValueType() { + return Float.class; + } } } diff --git a/src/main/java/com/cleanroommc/modularui/value/IntValue.java b/src/main/java/com/cleanroommc/modularui/value/IntValue.java index 5f8faba69..a594ffa5d 100644 --- a/src/main/java/com/cleanroommc/modularui/value/IntValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/IntValue.java @@ -64,6 +64,11 @@ public void setStringValue(String val) { setIntValue(Integer.parseInt(val)); } + @Override + public Class getValueType() { + return Integer.class; + } + public static class Dynamic implements IIntValue, IStringValue { private final IntSupplier getter; @@ -103,5 +108,10 @@ public Integer getValue() { public void setValue(Integer value) { setIntValue(value); } + + @Override + public Class getValueType() { + return Integer.class; + } } } diff --git a/src/main/java/com/cleanroommc/modularui/value/LongValue.java b/src/main/java/com/cleanroommc/modularui/value/LongValue.java index dc7b161fd..0eececdce 100644 --- a/src/main/java/com/cleanroommc/modularui/value/LongValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/LongValue.java @@ -64,6 +64,11 @@ public void setIntValue(int val) { setLongValue(val); } + @Override + public Class getValueType() { + return Long.class; + } + public static class Dynamic implements ILongValue, IIntValue, IStringValue { private final LongSupplier getter; @@ -113,5 +118,10 @@ public int getIntValue() { public void setIntValue(int val) { setLongValue(val); } + + @Override + public Class getValueType() { + return Long.class; + } } } diff --git a/src/main/java/com/cleanroommc/modularui/value/ObjectValue.java b/src/main/java/com/cleanroommc/modularui/value/ObjectValue.java index d089c9313..a87840c26 100644 --- a/src/main/java/com/cleanroommc/modularui/value/ObjectValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/ObjectValue.java @@ -3,6 +3,7 @@ import com.cleanroommc.modularui.api.value.IValue; import com.google.common.util.concurrent.AtomicDouble; +import org.jetbrains.annotations.ApiStatus; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; @@ -18,9 +19,18 @@ public static Dynamic wrapAtomic(AtomicReference val) { return new Dynamic<>(val::get, val::set); } + private final Class type; private T value; + public ObjectValue(Class type, T value) { + this.type = type; + this.value = value; + } + + @ApiStatus.ScheduledForRemoval(inVersion = "3.2.0") + @Deprecated public ObjectValue(T value) { + this.type = value != null ? (Class) value.getClass() : null; this.value = value; } @@ -34,14 +44,30 @@ public void setValue(T value) { this.value = value; } + @Override + public Class getValueType() { + return this.type != null ? this.type : (Class) this.value.getClass(); + } + public static class Dynamic implements IValue { + private final Class type; private final Supplier getter; private final Consumer setter; + public Dynamic(Class type, Supplier getter, Consumer setter) { + this.type = type; + this.getter = getter; + this.setter = setter; + } + + @ApiStatus.ScheduledForRemoval(inVersion = "3.2.0") + @Deprecated public Dynamic(Supplier getter, Consumer setter) { this.getter = getter; this.setter = setter; + T value = getter.get(); + this.type = value != null ? (Class) value.getClass() : null; } @Override @@ -53,5 +79,10 @@ public T getValue() { public void setValue(T value) { this.setter.accept(value); } + + @Override + public Class getValueType() { + return this.type != null ? this.type : (Class) this.getter.get().getClass(); + } } } diff --git a/src/main/java/com/cleanroommc/modularui/value/StringValue.java b/src/main/java/com/cleanroommc/modularui/value/StringValue.java index 30808995b..67bd94052 100644 --- a/src/main/java/com/cleanroommc/modularui/value/StringValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/StringValue.java @@ -14,7 +14,7 @@ public static Dynamic wrap(IStringValue val) { } public StringValue(String value) { - super(value); + super(String.class, value); } @Override @@ -30,7 +30,7 @@ public void setStringValue(String val) { public static class Dynamic extends ObjectValue.Dynamic implements IStringValue { public Dynamic(Supplier getter, @Nullable Consumer setter) { - super(getter, setter); + super(String.class, getter, setter); } @Override diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/AbstractGenericSyncValue.java b/src/main/java/com/cleanroommc/modularui/value/sync/AbstractGenericSyncValue.java new file mode 100644 index 000000000..687aa028e --- /dev/null +++ b/src/main/java/com/cleanroommc/modularui/value/sync/AbstractGenericSyncValue.java @@ -0,0 +1,143 @@ +package com.cleanroommc.modularui.value.sync; + +import com.cleanroommc.modularui.network.NetworkUtils; + +import net.minecraft.network.PacketBuffer; + +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public abstract class AbstractGenericSyncValue extends ValueSyncHandler { + + private final Class type; + private final Supplier getter; + private final Consumer setter; + private T cache; + + protected AbstractGenericSyncValue(Class type, Supplier getter, Consumer setter) { + this.getter = Objects.requireNonNull(getter); + this.setter = setter; + this.cache = getter.get(); + if (type == null && this.cache != null) { + type = (Class) this.cache.getClass(); + } + this.type = type; + } + + @Contract("_, null, _, null, _ -> fail") + protected AbstractGenericSyncValue(Class type, @Nullable Supplier clientGetter, @Nullable Consumer clientSetter, + @Nullable Supplier serverGetter, @Nullable Consumer serverSetter) { + if (clientGetter == null && serverGetter == null) { + throw new NullPointerException("Client or server getter must not be null!"); + } + if (NetworkUtils.isClient()) { + this.getter = clientGetter != null ? clientGetter : serverGetter; + this.setter = clientSetter != null ? clientSetter : serverSetter; + } else { + this.getter = serverGetter != null ? serverGetter : clientGetter; + this.setter = serverSetter != null ? serverSetter : clientSetter; + } + this.cache = this.getter.get(); + if (type == null && this.cache != null) { + type = (Class) this.cache.getClass(); + } + this.type = type; + } + + protected abstract T createDeepCopyOf(T value); + + protected abstract boolean areEqual(T a, T b); + + protected abstract void serialize(PacketBuffer buffer, T value) throws IOException; + + protected abstract T deserialize(PacketBuffer buffer) throws IOException; + + @Override + public T getValue() { + return this.cache; + } + + @Override + public void setValue(T value, boolean setSource, boolean sync) { + this.cache = createDeepCopyOf(value); + if (setSource && this.setter != null) { + this.setter.accept(value); + } + onValueChanged(); + if (sync) sync(); + } + + @Override + public boolean updateCacheFromSource(boolean isFirstSync) { + if (this.getter == null) return false; + T t = this.getter.get(); + if (isFirstSync || !areEqual(this.cache, t)) { + setValue(t, false, false); + return true; + } + return false; + } + + @Override + public void notifyUpdate() { + if (this.getter == null) throw new NullPointerException("Can't notify sync handler with null getter."); + setValue(this.getter.get(), false, true); + } + + @Override + public void write(PacketBuffer buffer) throws IOException { + serialize(buffer, this.cache); + } + + @Override + public void read(PacketBuffer buffer) throws IOException { + setValue(deserialize(buffer), true, false); + } + + @SuppressWarnings("unchecked") + @Override + public Class getValueType() { + return (Class) getType(); + } + + @ApiStatus.ScheduledForRemoval(inVersion = "3.2.0") + @Deprecated + @SuppressWarnings("unchecked") + public @Nullable Class getType() { + if (this.type != null) return type; + if (this.cache != null) { + return (Class) this.cache.getClass(); + } + T t = this.getter.get(); + if (t != null) { + return (Class) t.getClass(); + } + return null; + } + + @ApiStatus.ScheduledForRemoval(inVersion = "3.2.0") + @Deprecated + public boolean isOfType(Class expectedType) { + return isValueOfType(expectedType); + } + + @Override + public boolean isValueOfType(Class expectedType) { + Class type = getValueType(); + if (type == null) { + throw new IllegalStateException("Could not infer type of GenericSyncValue since value is null!"); + } + return expectedType.isAssignableFrom(type); + } + + @SuppressWarnings("unchecked") + public AbstractGenericSyncValue cast() { + return (AbstractGenericSyncValue) this; + } +} diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/BigDecimalSyncValue.java b/src/main/java/com/cleanroommc/modularui/value/sync/BigDecimalSyncValue.java index ef4091c42..e3d2a2573 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/BigDecimalSyncValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/BigDecimalSyncValue.java @@ -14,7 +14,7 @@ public class BigDecimalSyncValue extends GenericSyncValue implements IStringValue { public BigDecimalSyncValue(@NotNull Supplier getter, @Nullable Consumer setter) { - super(getter, setter, ByteBufAdapters.BIG_DECIMAL, ICopy.immutable()); + super(BigDecimal.class, getter, setter, ByteBufAdapters.BIG_DECIMAL, ICopy.immutable()); } @Override diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/BigIntSyncValue.java b/src/main/java/com/cleanroommc/modularui/value/sync/BigIntSyncValue.java index fecb3fba9..7a1f9a48f 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/BigIntSyncValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/BigIntSyncValue.java @@ -14,7 +14,7 @@ public class BigIntSyncValue extends GenericSyncValue implements IStringValue { public BigIntSyncValue(@NotNull Supplier getter, @Nullable Consumer setter) { - super(getter, setter, ByteBufAdapters.BIG_INT, ICopy.immutable()); + super(BigInteger.class, getter, setter, ByteBufAdapters.BIG_INT, ICopy.immutable()); } @Override diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/BooleanSyncValue.java b/src/main/java/com/cleanroommc/modularui/value/sync/BooleanSyncValue.java index 4f5020f47..74f7c40f9 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/BooleanSyncValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/BooleanSyncValue.java @@ -110,4 +110,9 @@ public void setStringValue(String value, boolean setSource, boolean sync) { public String getStringValue() { return String.valueOf(this.cache); } + + @Override + public Class getValueType() { + return Boolean.class; + } } diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/ByteArraySyncValue.java b/src/main/java/com/cleanroommc/modularui/value/sync/ByteArraySyncValue.java index c56168887..7d900fe34 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/ByteArraySyncValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/ByteArraySyncValue.java @@ -11,6 +11,6 @@ public class ByteArraySyncValue extends GenericSyncValue { public ByteArraySyncValue(@NotNull Supplier getter, @Nullable Consumer setter) { - super(getter, setter, ByteBufAdapters.BYTE_ARR, byte[]::clone); + super(byte[].class, getter, setter, ByteBufAdapters.BYTE_ARR, byte[]::clone); } } diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/ByteSyncValue.java b/src/main/java/com/cleanroommc/modularui/value/sync/ByteSyncValue.java index c7385a0b0..c89352484 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/ByteSyncValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/ByteSyncValue.java @@ -97,4 +97,9 @@ public void setByteValue(byte value, boolean setSource, boolean sync) { public byte getByteValue() { return this.cache; } + + @Override + public Class getValueType() { + return Byte.class; + } } diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/DoubleSyncValue.java b/src/main/java/com/cleanroommc/modularui/value/sync/DoubleSyncValue.java index ca78ff139..d7465216d 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/DoubleSyncValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/DoubleSyncValue.java @@ -121,4 +121,9 @@ public float getFloatValue() { public void setFloatValue(float value, boolean setSource, boolean sync) { setDoubleValue(value, setSource, sync); } + + @Override + public Class getValueType() { + return Double.class; + } } diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/EnumSyncValue.java b/src/main/java/com/cleanroommc/modularui/value/sync/EnumSyncValue.java index 016bad601..e35fff830 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/EnumSyncValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/EnumSyncValue.java @@ -109,4 +109,9 @@ public void setIntValue(int value, boolean setSource, boolean sync) { public int getIntValue() { return this.cache.ordinal(); } + + @Override + public Class getValueType() { + return this.enumClass; + } } diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/FloatSyncValue.java b/src/main/java/com/cleanroommc/modularui/value/sync/FloatSyncValue.java index 9501bd029..00387b8c5 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/FloatSyncValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/FloatSyncValue.java @@ -121,4 +121,9 @@ public double getDoubleValue() { public void setDoubleValue(double value, boolean setSource, boolean sync) { setFloatValue((float) value, setSource, sync); } + + @Override + public Class getValueType() { + return Float.class; + } } diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java b/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java index ce84bc10e..f707d51e1 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java @@ -82,6 +82,11 @@ public boolean updateCacheFromSource(boolean isFirstSync) { return false; } + @Override + public Class getValueType() { + return FluidStack.class; + } + @Override public void notifyUpdate() { setValue(this.fluidTank.getFluid(), false, true); diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/GenericListSyncHandler.java b/src/main/java/com/cleanroommc/modularui/value/sync/GenericListSyncHandler.java index 4b20eaddf..09c2b3b92 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/GenericListSyncHandler.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/GenericListSyncHandler.java @@ -60,6 +60,11 @@ public void read(PacketBuffer buffer) throws IOException { onSetCache(getValue(), true, false); } + @Override + public Class> getValueType() { + return (Class>) (Object) List.class; + } + public static Builder builder() { return new Builder<>(); } diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/GenericMapSyncHandler.java b/src/main/java/com/cleanroommc/modularui/value/sync/GenericMapSyncHandler.java index 4eca9174d..92bb48983 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/GenericMapSyncHandler.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/GenericMapSyncHandler.java @@ -112,6 +112,11 @@ public Map getValue() { return Collections.unmodifiableMap(this.cache); } + @Override + public Class> getValueType() { + return (Class>) (Object) Map.class; + } + public static class Builder { private Supplier> getter; diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/GenericSetSyncHandler.java b/src/main/java/com/cleanroommc/modularui/value/sync/GenericSetSyncHandler.java index 9fcf0c80e..f0714cc8b 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/GenericSetSyncHandler.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/GenericSetSyncHandler.java @@ -54,6 +54,11 @@ public void read(PacketBuffer buffer) throws IOException { onSetCache(getValue(), true, false); } + @Override + public Class> getValueType() { + return (Class>) (Object) Set.class; + } + public static Builder builder() { return new Builder<>(); } diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/GenericSyncValue.java b/src/main/java/com/cleanroommc/modularui/value/sync/GenericSyncValue.java index dbf9711a6..23e6242b2 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/GenericSyncValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/GenericSyncValue.java @@ -11,6 +11,7 @@ import net.minecraft.network.PacketBuffer; import net.minecraftforge.fluids.FluidStack; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -19,7 +20,7 @@ import java.util.function.Consumer; import java.util.function.Supplier; -public class GenericSyncValue extends ValueSyncHandler { +public class GenericSyncValue extends AbstractGenericSyncValue { public static GenericSyncValue forItem(@NotNull Supplier getter, @Nullable Consumer setter) { return new GenericSyncValue<>(getter, setter, ByteBufAdapters.ITEM_STACK); @@ -29,20 +30,21 @@ public static GenericSyncValue forFluid(@NotNull Supplier(getter, setter, ByteBufAdapters.FLUID_STACK); } - private final Supplier getter; - private final Consumer setter; private final IByteBufDeserializer deserializer; private final IByteBufSerializer serializer; private final IEquals equals; private final ICopy copy; - private T cache; + @ApiStatus.ScheduledForRemoval(inVersion = "3.2.0") + @Deprecated public GenericSyncValue(@NotNull Supplier getter, @Nullable Consumer setter, @NotNull IByteBufAdapter adapter) { this(getter, setter, adapter, adapter, adapter, null); } + @ApiStatus.ScheduledForRemoval(inVersion = "3.2.0") + @Deprecated public GenericSyncValue(@NotNull Supplier getter, @Nullable Consumer setter, @NotNull IByteBufAdapter adapter, @@ -50,6 +52,8 @@ public GenericSyncValue(@NotNull Supplier getter, this(getter, setter, adapter, adapter, adapter, copy); } + @ApiStatus.ScheduledForRemoval(inVersion = "3.2.0") + @Deprecated public GenericSyncValue(@NotNull Supplier getter, @Nullable Consumer setter, @NotNull IByteBufDeserializer deserializer, @@ -57,6 +61,8 @@ public GenericSyncValue(@NotNull Supplier getter, this(getter, setter, deserializer, serializer, null, null); } + @ApiStatus.ScheduledForRemoval(inVersion = "3.2.0") + @Deprecated public GenericSyncValue(@NotNull Supplier getter, @Nullable Consumer setter, @NotNull IByteBufDeserializer deserializer, @@ -65,23 +71,31 @@ public GenericSyncValue(@NotNull Supplier getter, this(getter, setter, deserializer, serializer, null, copy); } + @ApiStatus.ScheduledForRemoval(inVersion = "3.2.0") + @Deprecated public GenericSyncValue(@NotNull Supplier getter, @NotNull IByteBufAdapter adapter) { this(getter, null, adapter, adapter, adapter, null); } + @ApiStatus.ScheduledForRemoval(inVersion = "3.2.0") + @Deprecated public GenericSyncValue(@NotNull Supplier getter, @NotNull IByteBufAdapter adapter, @Nullable ICopy copy) { this(getter, null, adapter, adapter, adapter, copy); } + @ApiStatus.ScheduledForRemoval(inVersion = "3.2.0") + @Deprecated public GenericSyncValue(@NotNull Supplier getter, @NotNull IByteBufDeserializer deserializer, @NotNull IByteBufSerializer serializer) { this(getter, null, deserializer, serializer, null, null); } + @ApiStatus.ScheduledForRemoval(inVersion = "3.2.0") + @Deprecated public GenericSyncValue(@NotNull Supplier getter, @NotNull IByteBufDeserializer deserializer, @NotNull IByteBufSerializer serializer, @@ -89,15 +103,40 @@ public GenericSyncValue(@NotNull Supplier getter, this(getter, null, deserializer, serializer, null, copy); } + @ApiStatus.ScheduledForRemoval(inVersion = "3.2.0") + @Deprecated public GenericSyncValue(@NotNull Supplier getter, @Nullable Consumer setter, @NotNull IByteBufDeserializer deserializer, @NotNull IByteBufSerializer serializer, @Nullable IEquals equals, @Nullable ICopy copy) { - this.getter = Objects.requireNonNull(getter); - this.cache = getter.get(); - this.setter = setter; + this(null, getter, setter, deserializer, serializer, equals, copy); + } + + public GenericSyncValue(@NotNull Class type, + @NotNull Supplier getter, + @Nullable Consumer setter, + @NotNull IByteBufAdapter adapter, + @Nullable ICopy copy) { + this(type, getter, setter, adapter, adapter, adapter, copy); + } + + public GenericSyncValue(@NotNull Class type, + @NotNull Supplier getter, + @Nullable Consumer setter, + @NotNull IByteBufAdapter adapter) { + this(type, getter, setter, adapter, adapter, adapter, null); + } + + public GenericSyncValue(@NotNull Class type, + @NotNull Supplier getter, + @Nullable Consumer setter, + @NotNull IByteBufDeserializer deserializer, + @NotNull IByteBufSerializer serializer, + @Nullable IEquals equals, + @Nullable ICopy copy) { + super(type, getter, setter); this.deserializer = Objects.requireNonNull(deserializer); this.serializer = Objects.requireNonNull(serializer); this.equals = equals == null ? Objects::equals : IEquals.wrapNullSafe(equals); @@ -105,69 +144,95 @@ public GenericSyncValue(@NotNull Supplier getter, } @Override - public T getValue() { - return this.cache; + protected T createDeepCopyOf(T value) { + return this.copy.createDeepCopy(value); } @Override - public void setValue(T value, boolean setSource, boolean sync) { - this.cache = this.copy.createDeepCopy(value); - if (setSource && this.setter != null) { - this.setter.accept(value); - } - onValueChanged(); - if (sync) sync(); + protected boolean areEqual(T a, T b) { + return this.equals.areEqual(a, b); } @Override - public boolean updateCacheFromSource(boolean isFirstSync) { - if (this.getter == null) return false; - T t = this.getter.get(); - if (isFirstSync || !this.equals.areEqual(this.cache, t)) { - setValue(t, false, false); - return true; - } - return false; + protected void serialize(PacketBuffer buffer, T value) throws IOException { + this.serializer.serialize(buffer, value); } @Override - public void notifyUpdate() { - if (this.getter == null) throw new NullPointerException("Can't notify sync handler with null getter."); - setValue(this.getter.get(), false, true); + protected T deserialize(PacketBuffer buffer) throws IOException { + return this.deserializer.deserialize(buffer); } @Override - public void write(PacketBuffer buffer) throws IOException { - this.serializer.serialize(buffer, this.cache); + @SuppressWarnings("unchecked") + public GenericSyncValue cast() { + return (GenericSyncValue) this; } - @Override - public void read(PacketBuffer buffer) throws IOException { - setValue(this.deserializer.deserialize(buffer), true, false); - } + public static class Builder { - @SuppressWarnings("unchecked") - public @Nullable Class getType() { - if (this.cache != null) { - return (Class) this.cache.getClass(); + private final Class type; + private Supplier getter; + private Consumer setter; + private IByteBufDeserializer deserializer; + private IByteBufSerializer serializer; + private IEquals equals; + private ICopy copy; + + public Builder(Class type) { + this.type = type; } - T t = this.getter.get(); - if (t != null) { - return (Class) t.getClass(); + + public Builder getter(Supplier getter) { + this.getter = getter; + return this; } - return null; - } - public boolean isOfType(Class expectedType) { - Class type = getType(); - if (type == null) { - throw new IllegalStateException("Could not infer type of GenericSyncValue since value is null!"); + public Builder setter(Consumer setter) { + this.setter = setter; + return this; } - return expectedType.isAssignableFrom(type); - } - @SuppressWarnings("unchecked") - public GenericSyncValue cast() { - return (GenericSyncValue) this; + public Builder deserializer(IByteBufDeserializer deserializer) { + this.deserializer = deserializer; + return this; + } + + public Builder serializer(IByteBufSerializer serializer) { + this.serializer = serializer; + return this; + } + + public Builder equals(IEquals equals) { + this.equals = equals; + return this; + } + + public Builder equalsDefault() { + return equals(IEquals.defaultTester()); + } + + public Builder equalsReference() { + return equals((a, b) -> a == b); + } + + public Builder copy(ICopy copy) { + this.copy = copy; + return this; + } + + public Builder copyImmutable() { + return copy(ICopy.immutable()); + } + + public Builder adapter(IByteBufAdapter adapter) { + return deserializer(adapter) + .serializer(adapter) + .equals(adapter); + } + + public GenericSyncValue build() { + return new GenericSyncValue<>(type, getter, setter, deserializer, serializer, equals, copy); + } } } diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/IntSyncValue.java b/src/main/java/com/cleanroommc/modularui/value/sync/IntSyncValue.java index 58172a75f..122d72992 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/IntSyncValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/IntSyncValue.java @@ -121,4 +121,9 @@ public void setStringValue(String value, boolean setSource, boolean sync) { public String getStringValue() { return String.valueOf(this.cache); } + + @Override + public Class getValueType() { + return Integer.class; + } } diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/LongArraySyncValue.java b/src/main/java/com/cleanroommc/modularui/value/sync/LongArraySyncValue.java index 0278432d6..f970d8a38 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/LongArraySyncValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/LongArraySyncValue.java @@ -11,6 +11,6 @@ public class LongArraySyncValue extends GenericSyncValue { public LongArraySyncValue(@NotNull Supplier getter, @Nullable Consumer setter) { - super(getter, setter, ByteBufAdapters.LONG_ARR, long[]::clone); + super(long[].class, getter, setter, ByteBufAdapters.LONG_ARR, long[]::clone); } } diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/LongSyncValue.java b/src/main/java/com/cleanroommc/modularui/value/sync/LongSyncValue.java index deaf591f6..6c2330711 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/LongSyncValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/LongSyncValue.java @@ -121,4 +121,9 @@ public int getIntValue() { public String getStringValue() { return String.valueOf(this.cache); } + + @Override + public Class getValueType() { + return Long.class; + } } 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 58802bd94..c7a13ae59 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/PanelSyncHandler.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/PanelSyncHandler.java @@ -65,7 +65,7 @@ private void openPanel(boolean syncToServer) { this.syncManager = new PanelSyncManager(client); this.openedPanel = Objects.requireNonNull(createUI(this.syncManager)); this.panelName = this.openedPanel.getName(); - this.openedPanel.setSyncHandler(this); + this.openedPanel.setPanelSyncHandler(this); WidgetTree.collectSyncValues(this.syncManager, this.openedPanel, false); if (!client) { this.openedPanel = null; diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/StringSyncValue.java b/src/main/java/com/cleanroommc/modularui/value/sync/StringSyncValue.java index 3da601895..4ad600bd6 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/StringSyncValue.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/StringSyncValue.java @@ -9,20 +9,15 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.IOException; import java.util.Objects; import java.util.function.Consumer; import java.util.function.Supplier; -public class StringSyncValue extends ValueSyncHandler implements IStringSyncValue { +public class StringSyncValue extends AbstractGenericSyncValue implements IStringSyncValue { - private final Supplier getter; - private final Consumer setter; - private String cache; - - public StringSyncValue(@NotNull Supplier getter, @Nullable Consumer setter) { - this.getter = Objects.requireNonNull(getter); - this.setter = setter; - this.cache = getter.get(); + public StringSyncValue(Supplier getter, Consumer setter) { + super(String.class, getter, setter); } public StringSyncValue(@NotNull Supplier getter) { @@ -31,72 +26,43 @@ public StringSyncValue(@NotNull Supplier getter) { @Contract("null, null -> fail") public StringSyncValue(@Nullable Supplier clientGetter, - @Nullable Supplier serverGetter) { + @Nullable Supplier serverGetter) { this(clientGetter, null, serverGetter, null); } @Contract("null, _, null, _ -> fail") public StringSyncValue(@Nullable Supplier clientGetter, @Nullable Consumer clientSetter, - @Nullable Supplier serverGetter, @Nullable Consumer serverSetter) { - if (clientGetter == null && serverGetter == null) { - throw new NullPointerException("Client or server getter must not be null!"); - } - if (NetworkUtils.isClient()) { - this.getter = clientGetter != null ? clientGetter : serverGetter; - this.setter = clientSetter != null ? clientSetter : serverSetter; - } else { - this.getter = serverGetter != null ? serverGetter : clientGetter; - this.setter = serverSetter != null ? serverSetter : clientSetter; - } - this.cache = this.getter.get(); - } - - @Override - public String getValue() { - return this.cache; + @Nullable Supplier serverGetter, @Nullable Consumer serverSetter) { + super(String.class, clientGetter, clientSetter, serverGetter, serverSetter); } @Override - public String getStringValue() { - return this.cache; + protected String createDeepCopyOf(String value) { + return value; } @Override - public void setValue(String value, boolean setSource, boolean sync) { - setStringValue(value, setSource, sync); + protected boolean areEqual(String a, String b) { + return Objects.equals(a, b); } @Override - public void setStringValue(String value, boolean setSource, boolean sync) { - this.cache = value; - if (setSource && this.setter != null) { - this.setter.accept(value); - } - onValueChanged(); - if (sync) sync(); + protected void serialize(PacketBuffer buffer, String value) throws IOException { + NetworkUtils.writeStringSafe(buffer, value, Short.MAX_VALUE - 74); } @Override - public boolean updateCacheFromSource(boolean isFirstSync) { - if (isFirstSync || !Objects.equals(this.getter.get(), this.cache)) { - setValue(this.getter.get(), false, false); - return true; - } - return false; + protected String deserialize(PacketBuffer buffer) throws IOException { + return NetworkUtils.readStringSafe(buffer); } @Override - public void notifyUpdate() { - setValue(this.getter.get(), false, true); - } - - @Override - public void write(PacketBuffer buffer) { - NetworkUtils.writeStringSafe(buffer, getValue(), Short.MAX_VALUE - 74); + public String getStringValue() { + return getValue(); } @Override - public void read(PacketBuffer buffer) { - setValue(NetworkUtils.readStringSafe(buffer), true, false); + public void setStringValue(String value, boolean setSource, boolean sync) { + setValue(value, setSource, sync); } } diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/SyncHandler.java b/src/main/java/com/cleanroommc/modularui/value/sync/SyncHandler.java index fb4945437..7e2cfdd7b 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/SyncHandler.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/SyncHandler.java @@ -1,6 +1,7 @@ package com.cleanroommc.modularui.value.sync; import com.cleanroommc.modularui.api.IPacketWriter; +import com.cleanroommc.modularui.api.value.ISyncOrValue; import com.cleanroommc.modularui.network.NetworkHandler; import com.cleanroommc.modularui.network.packets.PacketSyncHandler; @@ -22,7 +23,7 @@ * A sync handler must exist on client and server. * It must be configured exactly the same to avoid issues. */ -public abstract class SyncHandler { +public abstract class SyncHandler implements ISyncOrValue { private PanelSyncManager syncManager; private String key; @@ -151,8 +152,7 @@ public final void sync(int id) { * * @param init if this method is being called the first time. */ - public void detectAndSendChanges(boolean init) { - } + public void detectAndSendChanges(boolean init) {} /** * @return the key that belongs to this sync handler @@ -178,6 +178,11 @@ public PanelSyncManager getSyncManager() { return this.syncManager; } + @Override + public boolean isSyncHandler() { + return true; + } + public static void sendToClient(String panel, PacketBuffer buffer, SyncHandler syncHandler) { Objects.requireNonNull(buffer); Objects.requireNonNull(syncHandler); diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/SyncHandlers.java b/src/main/java/com/cleanroommc/modularui/value/sync/SyncHandlers.java index e1403b6da..2fc276f48 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/SyncHandlers.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/SyncHandlers.java @@ -18,8 +18,7 @@ public class SyncHandlers { - private SyncHandlers() { - } + private SyncHandlers() {} public static IntSyncValue intNumber(IntSupplier getter, IntConsumer setter) { return new IntSyncValue(getter, setter); @@ -52,4 +51,8 @@ public static FluidSlotSyncHandler fluidSlot(IFluidTank fluidTank) { public static > EnumSyncValue enumValue(Class clazz, Supplier getter, Consumer setter) { return new EnumSyncValue<>(clazz, getter, setter); } + + public static GenericSyncValue.Builder generic(Class type) { + return new GenericSyncValue.Builder<>(type); + } } diff --git a/src/main/java/com/cleanroommc/modularui/widget/Widget.java b/src/main/java/com/cleanroommc/modularui/widget/Widget.java index 94af093cd..a29f2c5e2 100644 --- a/src/main/java/com/cleanroommc/modularui/widget/Widget.java +++ b/src/main/java/com/cleanroommc/modularui/widget/Widget.java @@ -5,6 +5,7 @@ import com.cleanroommc.modularui.api.drawable.IDrawable; import com.cleanroommc.modularui.api.layout.IResizeable; import com.cleanroommc.modularui.api.layout.IViewportStack; +import com.cleanroommc.modularui.api.value.ISyncOrValue; import com.cleanroommc.modularui.api.value.IValue; import com.cleanroommc.modularui.api.widget.IDragResizeable; import com.cleanroommc.modularui.api.widget.IGuiAction; @@ -150,8 +151,7 @@ public void initialiseSyncHandler(ModularSyncManager syncManager, boolean late) if (handler == null && this.syncKey != null) { handler = syncManager.getSyncHandler(getPanel().getName(), this.syncKey); } - if (handler != null) checkValidSyncHandler(handler); - setSyncHandler(handler); + if (handler != null) setSyncOrValue(handler); if (this.syncHandler instanceof ValueSyncHandler valueSyncHandler && valueSyncHandler.getChangeListener() == null) { valueSyncHandler.setChangeListener(this::markTooltipDirty); } @@ -851,6 +851,8 @@ public W syncHandler(String name, int id) { * Used for widgets to set a value handler.
* Will also call {@link #setSyncHandler(SyncHandler)} if it is a SyncHandler */ + @ApiStatus.ScheduledForRemoval(inVersion = "3.2.0") + @Deprecated protected void setValue(IValue value) { this.value = value; if (value instanceof SyncHandler handler) { @@ -861,11 +863,21 @@ protected void setValue(IValue value) { /** * Used for widgets to set a sync handler. */ + @ApiStatus.ScheduledForRemoval(inVersion = "3.2.0") + @Deprecated protected void setSyncHandler(@Nullable SyncHandler syncHandler) { - if (syncHandler != null) checkValidSyncHandler(syncHandler); + if (syncHandler != null) checkValidSyncOrValue(syncHandler); this.syncHandler = syncHandler; } + @MustBeInvokedByOverriders + protected void setSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + if (!syncOrValue.isSyncHandler() && !syncOrValue.isValueHandler()) return; + checkValidSyncOrValue(syncOrValue); + if (syncOrValue instanceof SyncHandler syncHandler1) setSyncHandler(syncHandler1); + if (syncOrValue instanceof IValue value1) setValue(value1); + } + // ------------- // === Other === // ------------- diff --git a/src/main/java/com/cleanroommc/modularui/widgets/AbstractCycleButtonWidget.java b/src/main/java/com/cleanroommc/modularui/widgets/AbstractCycleButtonWidget.java index 2fea1a6ae..797be4e2c 100644 --- a/src/main/java/com/cleanroommc/modularui/widgets/AbstractCycleButtonWidget.java +++ b/src/main/java/com/cleanroommc/modularui/widgets/AbstractCycleButtonWidget.java @@ -7,14 +7,13 @@ import com.cleanroommc.modularui.api.value.IBoolValue; import com.cleanroommc.modularui.api.value.IEnumValue; import com.cleanroommc.modularui.api.value.IIntValue; -import com.cleanroommc.modularui.api.value.IValue; +import com.cleanroommc.modularui.api.value.ISyncOrValue; import com.cleanroommc.modularui.api.widget.Interactable; import com.cleanroommc.modularui.drawable.UITexture; import com.cleanroommc.modularui.screen.RichTooltip; import com.cleanroommc.modularui.theme.WidgetThemeEntry; import com.cleanroommc.modularui.utils.Alignment; import com.cleanroommc.modularui.value.IntValue; -import com.cleanroommc.modularui.value.sync.SyncHandler; import com.cleanroommc.modularui.widget.Widget; import org.jetbrains.annotations.NotNull; @@ -44,23 +43,18 @@ public void onInit() { } @Override - public boolean isValidSyncHandler(SyncHandler syncHandler) { - return syncHandler instanceof IIntValue; + public boolean isValidSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + return syncOrValue.isTypeOrEmpty(IIntValue.class); } @Override - protected void setSyncHandler(@Nullable SyncHandler syncHandler) { - super.setSyncHandler(syncHandler); - if (syncHandler != null) { - this.intValue = castIfTypeElseNull(syncHandler, IIntValue.class); - } - } - - @Override - protected void setValue(IValue value) { - super.setValue(value); - if (value instanceof IIntValue intValue1) { - this.intValue = intValue1; + protected void setSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + super.setSyncOrValue(syncOrValue); + this.intValue = syncOrValue.castNullable(IIntValue.class); + if (syncOrValue instanceof IEnumValue enumValue) { + stateCount(enumValue.getEnumClass().getEnumConstants().length); + } else if (syncOrValue instanceof IBoolValue) { + stateCount(2); } } @@ -183,13 +177,7 @@ public W disableHoverOverlay() { } protected W value(IIntValue value) { - this.intValue = value; - setValue(value); - if (value instanceof IEnumValue enumValue) { - stateCount(enumValue.getEnumClass().getEnumConstants().length); - } else if (value instanceof IBoolValue) { - stateCount(2); - } + setSyncOrValue(ISyncOrValue.orEmpty(value)); return getThis(); } diff --git a/src/main/java/com/cleanroommc/modularui/widgets/ButtonWidget.java b/src/main/java/com/cleanroommc/modularui/widgets/ButtonWidget.java index da734fd89..fdaa89833 100644 --- a/src/main/java/com/cleanroommc/modularui/widgets/ButtonWidget.java +++ b/src/main/java/com/cleanroommc/modularui/widgets/ButtonWidget.java @@ -3,16 +3,15 @@ import com.cleanroommc.modularui.api.ITheme; import com.cleanroommc.modularui.api.IThemeApi; import com.cleanroommc.modularui.api.UpOrDown; +import com.cleanroommc.modularui.api.value.ISyncOrValue; import com.cleanroommc.modularui.api.widget.IGuiAction; import com.cleanroommc.modularui.api.widget.Interactable; import com.cleanroommc.modularui.drawable.GuiTextures; import com.cleanroommc.modularui.theme.WidgetThemeEntry; import com.cleanroommc.modularui.value.sync.InteractionSyncHandler; -import com.cleanroommc.modularui.value.sync.SyncHandler; import com.cleanroommc.modularui.widget.SingleChildWidget; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; public class ButtonWidget> extends SingleChildWidget implements Interactable { @@ -43,13 +42,19 @@ public static ButtonWidget panelCloseButton() { private InteractionSyncHandler syncHandler; @Override - public boolean isValidSyncHandler(SyncHandler syncHandler) { - return syncHandler instanceof InteractionSyncHandler; + public WidgetThemeEntry getWidgetThemeInternal(ITheme theme) { + return theme.getButtonTheme(); } @Override - public WidgetThemeEntry getWidgetThemeInternal(ITheme theme) { - return theme.getButtonTheme(); + public boolean isValidSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + return syncOrValue.isTypeOrEmpty(InteractionSyncHandler.class); + } + + @Override + protected void setSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + super.setSyncOrValue(syncOrValue); + this.syncHandler = syncOrValue.castNullable(InteractionSyncHandler.class); } public void playClickSound() { @@ -166,16 +171,10 @@ public W onKeyTapped(IGuiAction.KeyPressed keyTapped) { } public W syncHandler(InteractionSyncHandler interactionSyncHandler) { - setSyncHandler(interactionSyncHandler); + setSyncOrValue(ISyncOrValue.orEmpty(interactionSyncHandler)); return getThis(); } - @Override - protected void setSyncHandler(@Nullable SyncHandler syncHandler) { - super.setSyncHandler(syncHandler); - this.syncHandler = castIfTypeElseNull(syncHandler, InteractionSyncHandler.class); - } - public W playClickSound(boolean play) { this.playClickSound = play; return getThis(); diff --git a/src/main/java/com/cleanroommc/modularui/widgets/CycleButtonWidget.java b/src/main/java/com/cleanroommc/modularui/widgets/CycleButtonWidget.java index 53c9e6046..e29c00b46 100644 --- a/src/main/java/com/cleanroommc/modularui/widgets/CycleButtonWidget.java +++ b/src/main/java/com/cleanroommc/modularui/widgets/CycleButtonWidget.java @@ -11,6 +11,7 @@ *

Note that you need to set the amount of states before setting any state backgrounds etc. The state count is automatically set, if the * passed {@link IIntValue} is a {@link com.cleanroommc.modularui.api.value.IEnumValue IEnumValue} or a * {@link com.cleanroommc.modularui.api.value.IBoolValue IBoolValue}.

+ * * @see ToggleButton */ public class CycleButtonWidget extends AbstractCycleButtonWidget { diff --git a/src/main/java/com/cleanroommc/modularui/widgets/DynamicSyncedWidget.java b/src/main/java/com/cleanroommc/modularui/widgets/DynamicSyncedWidget.java index c494fd373..8e57dba3f 100644 --- a/src/main/java/com/cleanroommc/modularui/widgets/DynamicSyncedWidget.java +++ b/src/main/java/com/cleanroommc/modularui/widgets/DynamicSyncedWidget.java @@ -1,12 +1,12 @@ package com.cleanroommc.modularui.widgets; +import com.cleanroommc.modularui.api.value.ISyncOrValue; import com.cleanroommc.modularui.api.widget.IWidget; import com.cleanroommc.modularui.value.sync.DynamicSyncHandler; import com.cleanroommc.modularui.value.sync.SyncHandler; import com.cleanroommc.modularui.widget.Widget; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.Collections; import java.util.List; @@ -26,14 +26,15 @@ public class DynamicSyncedWidget> extends Widge private IWidget child; @Override - public boolean isValidSyncHandler(SyncHandler syncHandler) { - return syncHandler instanceof DynamicSyncHandler; + public boolean isValidSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + return syncOrValue.isTypeOrEmpty(DynamicSyncHandler.class); } @Override - protected void setSyncHandler(@Nullable SyncHandler syncHandler) { - super.setSyncHandler(syncHandler); - this.syncHandler = castIfTypeElseNull(syncHandler, DynamicSyncHandler.class, t -> t.attachDynamicWidgetListener(this::updateChild)); + protected void setSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + super.setSyncOrValue(syncOrValue); + this.syncHandler = syncOrValue.castNullable(DynamicSyncHandler.class); + if (this.syncHandler != null) this.syncHandler.attachDynamicWidgetListener(this::updateChild); } @Override @@ -59,7 +60,7 @@ private void updateChild(IWidget widget) { } public W syncHandler(DynamicSyncHandler syncHandler) { - setSyncHandler(syncHandler); + setSyncOrValue(ISyncOrValue.orEmpty(syncHandler)); return getThis(); } diff --git a/src/main/java/com/cleanroommc/modularui/widgets/Expandable.java b/src/main/java/com/cleanroommc/modularui/widgets/Expandable.java index 339189877..c77de8fcd 100644 --- a/src/main/java/com/cleanroommc/modularui/widgets/Expandable.java +++ b/src/main/java/com/cleanroommc/modularui/widgets/Expandable.java @@ -4,12 +4,10 @@ import com.cleanroommc.modularui.animation.MutableObjectAnimator; import com.cleanroommc.modularui.api.drawable.IInterpolation; import com.cleanroommc.modularui.api.layout.IViewport; -import com.cleanroommc.modularui.api.layout.IViewportStack; import com.cleanroommc.modularui.api.widget.IWidget; import com.cleanroommc.modularui.api.widget.Interactable; import com.cleanroommc.modularui.drawable.Stencil; import com.cleanroommc.modularui.screen.viewport.ModularGuiContext; -import com.cleanroommc.modularui.utils.HoveredWidgetList; import com.cleanroommc.modularui.utils.Interpolation; import com.cleanroommc.modularui.widget.EmptyWidget; import com.cleanroommc.modularui.widget.Widget; diff --git a/src/main/java/com/cleanroommc/modularui/widgets/ItemDisplayWidget.java b/src/main/java/com/cleanroommc/modularui/widgets/ItemDisplayWidget.java index 0f99dfed9..714afb240 100644 --- a/src/main/java/com/cleanroommc/modularui/widgets/ItemDisplayWidget.java +++ b/src/main/java/com/cleanroommc/modularui/widgets/ItemDisplayWidget.java @@ -1,6 +1,7 @@ package com.cleanroommc.modularui.widgets; import com.cleanroommc.modularui.api.ITheme; +import com.cleanroommc.modularui.api.value.ISyncOrValue; import com.cleanroommc.modularui.api.value.IValue; import com.cleanroommc.modularui.drawable.GuiDraw; import com.cleanroommc.modularui.screen.viewport.ModularGuiContext; @@ -8,13 +9,11 @@ import com.cleanroommc.modularui.utils.Platform; import com.cleanroommc.modularui.value.ObjectValue; import com.cleanroommc.modularui.value.sync.GenericSyncValue; -import com.cleanroommc.modularui.value.sync.SyncHandler; import com.cleanroommc.modularui.widget.Widget; import net.minecraft.item.ItemStack; -import org.jetbrains.annotations.Nullable; -import scala.tools.nsc.doc.model.Class; +import org.jetbrains.annotations.NotNull; /** * An item slot which only purpose is to display an item stack. @@ -31,22 +30,14 @@ public ItemDisplayWidget() { } @Override - public boolean isValidSyncHandler(SyncHandler syncHandler) { - return syncHandler instanceof GenericSyncValue gsv && gsv.isOfType(ItemStack.class); + public boolean isValidSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + return syncOrValue.isValueOfType(ItemStack.class); } @Override - protected void setSyncHandler(@Nullable SyncHandler syncHandler) { - super.setSyncHandler(syncHandler); - if (syncHandler != null) { - this.value = castIfTypeGenericElseNull(syncHandler, ItemStack.class); - } - } - - @Override - protected void setValue(IValue value) { - super.setValue(value); - this.value = (IValue) value; + protected void setSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + super.setSyncOrValue(syncOrValue); + this.value = syncOrValue.castValueNullable(ItemStack.class); } @Override @@ -66,13 +57,12 @@ public void draw(ModularGuiContext context, WidgetThemeEntry widgetTheme) { } public ItemDisplayWidget item(IValue itemSupplier) { - this.value = itemSupplier; - setValue(itemSupplier); + setSyncOrValue(ISyncOrValue.orEmpty(itemSupplier)); return this; } public ItemDisplayWidget item(ItemStack itemStack) { - return item(new ObjectValue<>(itemStack)); + return item(new ObjectValue<>(ItemStack.class, itemStack)); } public ItemDisplayWidget displayAmount(boolean displayAmount) { diff --git a/src/main/java/com/cleanroommc/modularui/widgets/ProgressWidget.java b/src/main/java/com/cleanroommc/modularui/widgets/ProgressWidget.java index a3099fa8d..de79e2ad2 100644 --- a/src/main/java/com/cleanroommc/modularui/widgets/ProgressWidget.java +++ b/src/main/java/com/cleanroommc/modularui/widgets/ProgressWidget.java @@ -2,7 +2,7 @@ import com.cleanroommc.modularui.ModularUIConfig; import com.cleanroommc.modularui.api.value.IDoubleValue; -import com.cleanroommc.modularui.api.value.IValue; +import com.cleanroommc.modularui.api.value.ISyncOrValue; import com.cleanroommc.modularui.drawable.UITexture; import com.cleanroommc.modularui.screen.viewport.ModularGuiContext; import com.cleanroommc.modularui.theme.WidgetTheme; @@ -10,10 +10,9 @@ import com.cleanroommc.modularui.utils.Color; import com.cleanroommc.modularui.utils.MathUtils; import com.cleanroommc.modularui.value.DoubleValue; -import com.cleanroommc.modularui.value.sync.SyncHandler; import com.cleanroommc.modularui.widget.Widget; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; import java.util.function.DoubleSupplier; @@ -41,24 +40,14 @@ public void onInit() { } @Override - public boolean isValidSyncHandler(SyncHandler syncHandler) { - return syncHandler instanceof IDoubleValue; + public boolean isValidSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + return syncOrValue.isTypeOrEmpty(IDoubleValue.class); } @Override - protected void setSyncHandler(@Nullable SyncHandler syncHandler) { - super.setSyncHandler(syncHandler); - if (syncHandler != null) { - this.doubleValue = castIfTypeElseNull(syncHandler, IDoubleValue.class); - } - } - - @Override - protected void setValue(IValue value) { - super.setValue(value); - if (value instanceof IDoubleValue value1) { - this.doubleValue = value1; - } + protected void setSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + super.setSyncOrValue(syncOrValue); + this.doubleValue = syncOrValue.castNullable(IDoubleValue.class); } @Override @@ -170,8 +159,7 @@ private void drawCircular(float progress, WidgetTheme widgetTheme) { } public ProgressWidget value(IDoubleValue value) { - this.doubleValue = value; - setValue(value); + setSyncOrValue(ISyncOrValue.orEmpty(value)); return this; } diff --git a/src/main/java/com/cleanroommc/modularui/widgets/SliderWidget.java b/src/main/java/com/cleanroommc/modularui/widgets/SliderWidget.java index 53cadf3cf..cc501b0eb 100644 --- a/src/main/java/com/cleanroommc/modularui/widgets/SliderWidget.java +++ b/src/main/java/com/cleanroommc/modularui/widgets/SliderWidget.java @@ -3,7 +3,7 @@ import com.cleanroommc.modularui.api.GuiAxis; import com.cleanroommc.modularui.api.drawable.IDrawable; import com.cleanroommc.modularui.api.value.IDoubleValue; -import com.cleanroommc.modularui.api.value.IValue; +import com.cleanroommc.modularui.api.value.ISyncOrValue; import com.cleanroommc.modularui.api.widget.IGuiAction; import com.cleanroommc.modularui.api.widget.Interactable; import com.cleanroommc.modularui.drawable.GuiTextures; @@ -14,7 +14,6 @@ import com.cleanroommc.modularui.utils.Color; import com.cleanroommc.modularui.utils.MathUtils; import com.cleanroommc.modularui.value.DoubleValue; -import com.cleanroommc.modularui.value.sync.SyncHandler; import com.cleanroommc.modularui.widget.Widget; import com.cleanroommc.modularui.widget.sizer.Area; import com.cleanroommc.modularui.widget.sizer.Unit; @@ -22,7 +21,6 @@ import it.unimi.dsi.fastutil.doubles.DoubleArrayList; import it.unimi.dsi.fastutil.doubles.DoubleList; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; public class SliderWidget extends Widget implements Interactable { @@ -64,24 +62,14 @@ public void onInit() { } @Override - public boolean isValidSyncHandler(SyncHandler syncHandler) { - return syncHandler instanceof IDoubleValue; + public boolean isValidSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + return syncOrValue.isTypeOrEmpty(IDoubleValue.class); } @Override - protected void setSyncHandler(@Nullable SyncHandler syncHandler) { - super.setSyncHandler(syncHandler); - if (syncHandler != null) { - this.doubleValue = castIfTypeElseNull(syncHandler, IDoubleValue.class); - } - } - - @Override - protected void setValue(IValue value) { - super.setValue(value); - if (value instanceof IDoubleValue doubleValue1) { - this.doubleValue = doubleValue1; - } + protected void setSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + super.setSyncOrValue(syncOrValue); + this.doubleValue = syncOrValue.castNullable(IDoubleValue.class); } @Override @@ -211,8 +199,7 @@ public String toString() { } public SliderWidget value(IDoubleValue value) { - this.doubleValue = value; - setValue(value); + setSyncOrValue(ISyncOrValue.orEmpty(value)); return this; } diff --git a/src/main/java/com/cleanroommc/modularui/widgets/SortableListWidget.java b/src/main/java/com/cleanroommc/modularui/widgets/SortableListWidget.java index ff077cc77..532126f16 100644 --- a/src/main/java/com/cleanroommc/modularui/widgets/SortableListWidget.java +++ b/src/main/java/com/cleanroommc/modularui/widgets/SortableListWidget.java @@ -160,7 +160,7 @@ public static class Item extends DraggableWidget> implements IValueWi private Predicate dropPredicate; private SortableListWidget listWidget; private int index = -1; - private int movingFrom = -1; + private final int movingFrom = -1; public Item(T value) { this.value = value; diff --git a/src/main/java/com/cleanroommc/modularui/widgets/slot/FluidSlot.java b/src/main/java/com/cleanroommc/modularui/widgets/slot/FluidSlot.java index ed5499260..34cfcf720 100644 --- a/src/main/java/com/cleanroommc/modularui/widgets/slot/FluidSlot.java +++ b/src/main/java/com/cleanroommc/modularui/widgets/slot/FluidSlot.java @@ -6,6 +6,7 @@ import com.cleanroommc.modularui.api.UpOrDown; import com.cleanroommc.modularui.api.drawable.IDrawable; import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.api.value.ISyncOrValue; import com.cleanroommc.modularui.api.widget.Interactable; import com.cleanroommc.modularui.drawable.GuiDraw; import com.cleanroommc.modularui.drawable.text.TextRenderer; @@ -23,7 +24,6 @@ import com.cleanroommc.modularui.utils.Platform; import com.cleanroommc.modularui.utils.SIPrefix; import com.cleanroommc.modularui.value.sync.FluidSlotSyncHandler; -import com.cleanroommc.modularui.value.sync.SyncHandler; import com.cleanroommc.modularui.widget.Widget; import net.minecraft.client.renderer.GlStateManager; @@ -145,14 +145,14 @@ public void onInit() { } @Override - public boolean isValidSyncHandler(SyncHandler syncHandler) { - return syncHandler instanceof FluidSlotSyncHandler; + public boolean isValidSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + return syncOrValue.isTypeOrEmpty(FluidSlotSyncHandler.class); } @Override - protected void setSyncHandler(@Nullable SyncHandler syncHandler) { - super.setSyncHandler(syncHandler); - this.syncHandler = castIfTypeElseNull(syncHandler, FluidSlotSyncHandler.class); + protected void setSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + super.setSyncOrValue(syncOrValue); + this.syncHandler = syncOrValue.castNullable(FluidSlotSyncHandler.class); } @Override @@ -289,7 +289,7 @@ public FluidSlot syncHandler(IFluidTank fluidTank) { } public FluidSlot syncHandler(FluidSlotSyncHandler syncHandler) { - setSyncHandler(syncHandler); + setSyncOrValue(ISyncOrValue.orEmpty(syncHandler)); return this; } diff --git a/src/main/java/com/cleanroommc/modularui/widgets/slot/ItemSlot.java b/src/main/java/com/cleanroommc/modularui/widgets/slot/ItemSlot.java index f3fa47b9f..e9dedf0ea 100644 --- a/src/main/java/com/cleanroommc/modularui/widgets/slot/ItemSlot.java +++ b/src/main/java/com/cleanroommc/modularui/widgets/slot/ItemSlot.java @@ -3,6 +3,7 @@ import com.cleanroommc.modularui.ModularUI; import com.cleanroommc.modularui.api.ITheme; import com.cleanroommc.modularui.api.IThemeApi; +import com.cleanroommc.modularui.api.value.ISyncOrValue; import com.cleanroommc.modularui.api.widget.IVanillaSlot; import com.cleanroommc.modularui.api.widget.Interactable; import com.cleanroommc.modularui.core.mixins.early.minecraft.GuiAccessor; @@ -18,7 +19,6 @@ import com.cleanroommc.modularui.theme.WidgetThemeEntry; import com.cleanroommc.modularui.utils.Platform; import com.cleanroommc.modularui.value.sync.ItemSlotSH; -import com.cleanroommc.modularui.value.sync.SyncHandler; import com.cleanroommc.modularui.widget.Widget; import com.cleanroommc.neverenoughanimations.NEAConfig; @@ -67,14 +67,15 @@ public void onInit() { } @Override - public boolean isValidSyncHandler(SyncHandler syncHandler) { - return syncHandler instanceof ItemSlotSH; + public boolean isValidSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + // disallow null + return syncOrValue instanceof ItemSlotSH; } @Override - protected void setSyncHandler(@Nullable SyncHandler syncHandler) { - super.setSyncHandler(syncHandler); - this.syncHandler = castIfTypeElseNull(syncHandler, ItemSlotSH.class); + protected void setSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + super.setSyncOrValue(syncOrValue); + this.syncHandler = syncOrValue.castOrThrow(ItemSlotSH.class); } @Override @@ -212,7 +213,7 @@ public ItemSlot slot(IItemHandlerModifiable itemHandler, int index) { } public ItemSlot syncHandler(ItemSlotSH syncHandler) { - setSyncHandler(syncHandler); + setSyncOrValue(ISyncOrValue.orEmpty(syncHandler)); return this; } diff --git a/src/main/java/com/cleanroommc/modularui/widgets/slot/ModularSlot.java b/src/main/java/com/cleanroommc/modularui/widgets/slot/ModularSlot.java index e6985b24a..9d2ecc59f 100644 --- a/src/main/java/com/cleanroommc/modularui/widgets/slot/ModularSlot.java +++ b/src/main/java/com/cleanroommc/modularui/widgets/slot/ModularSlot.java @@ -11,9 +11,7 @@ import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.SlotItemHandler; - import net.minecraftforge.items.wrapper.PlayerInvWrapper; - import net.minecraftforge.items.wrapper.PlayerMainInvWrapper; import org.jetbrains.annotations.ApiStatus; diff --git a/src/main/java/com/cleanroommc/modularui/widgets/slot/PhantomItemSlot.java b/src/main/java/com/cleanroommc/modularui/widgets/slot/PhantomItemSlot.java index d86c90acf..e6f83f6e4 100644 --- a/src/main/java/com/cleanroommc/modularui/widgets/slot/PhantomItemSlot.java +++ b/src/main/java/com/cleanroommc/modularui/widgets/slot/PhantomItemSlot.java @@ -2,12 +2,12 @@ import com.cleanroommc.modularui.ModularUI; import com.cleanroommc.modularui.api.UpOrDown; +import com.cleanroommc.modularui.api.value.ISyncOrValue; import com.cleanroommc.modularui.integration.jei.ModularUIJeiPlugin; import com.cleanroommc.modularui.integration.recipeviewer.RecipeViewerGhostIngredientSlot; import com.cleanroommc.modularui.utils.MouseData; import com.cleanroommc.modularui.value.sync.ItemSlotSH; import com.cleanroommc.modularui.value.sync.PhantomItemSlotSH; -import com.cleanroommc.modularui.value.sync.SyncHandler; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.item.ItemStack; @@ -27,14 +27,14 @@ public void onInit() { } @Override - public boolean isValidSyncHandler(SyncHandler syncHandler) { - return syncHandler instanceof PhantomItemSlotSH; + public boolean isValidSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + return syncOrValue instanceof PhantomItemSlotSH; } @Override - protected void setSyncHandler(@Nullable SyncHandler syncHandler) { - super.setSyncHandler(syncHandler); - this.syncHandler = castIfTypeElseNull(syncHandler, PhantomItemSlotSH.class); + protected void setSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + super.setSyncOrValue(syncOrValue); + this.syncHandler = syncOrValue.castOrThrow(PhantomItemSlotSH.class); } @Override @@ -100,7 +100,7 @@ public PhantomItemSlot slot(ModularSlot slot) { @Override public PhantomItemSlot syncHandler(ItemSlotSH syncHandler) { - setSyncHandler(syncHandler); + setSyncOrValue(ISyncOrValue.orEmpty(syncHandler)); return this; } diff --git a/src/main/java/com/cleanroommc/modularui/widgets/textfield/TextFieldWidget.java b/src/main/java/com/cleanroommc/modularui/widgets/textfield/TextFieldWidget.java index 0d9cc5fc1..80f37355e 100644 --- a/src/main/java/com/cleanroommc/modularui/widgets/textfield/TextFieldWidget.java +++ b/src/main/java/com/cleanroommc/modularui/widgets/textfield/TextFieldWidget.java @@ -5,17 +5,15 @@ import com.cleanroommc.modularui.api.drawable.IKey; import com.cleanroommc.modularui.api.drawable.ITextLine; import com.cleanroommc.modularui.api.value.IStringValue; -import com.cleanroommc.modularui.api.value.IValue; +import com.cleanroommc.modularui.api.value.ISyncOrValue; import com.cleanroommc.modularui.screen.RichTooltip; import com.cleanroommc.modularui.screen.viewport.ModularGuiContext; import com.cleanroommc.modularui.utils.MathUtils; import com.cleanroommc.modularui.utils.ParseResult; import com.cleanroommc.modularui.value.StringValue; -import com.cleanroommc.modularui.value.sync.SyncHandler; import com.cleanroommc.modularui.value.sync.ValueSyncHandler; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.text.ParsePosition; import java.util.function.Consumer; @@ -64,14 +62,15 @@ public void onInit() { } @Override - public boolean isValidSyncHandler(SyncHandler syncHandler) { - return syncHandler instanceof IStringValue; + public boolean isValidSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + return syncOrValue.isTypeOrEmpty(IStringValue.class); } @Override - protected void setSyncHandler(@Nullable SyncHandler syncHandler) { - super.setSyncHandler(syncHandler); - if (syncHandler instanceof ValueSyncHandler valueSyncHandler) { + protected void setSyncOrValue(@NotNull ISyncOrValue syncOrValue) { + super.setSyncOrValue(syncOrValue); + this.stringValue = syncOrValue.castNullable(IStringValue.class); + if (syncOrValue instanceof ValueSyncHandler valueSyncHandler) { valueSyncHandler.setChangeListener(() -> { markTooltipDirty(); setText(this.stringValue.getValue().toString()); @@ -79,14 +78,6 @@ protected void setSyncHandler(@Nullable SyncHandler syncHandler) { } } - @Override - protected void setValue(IValue value) { - super.setValue(value); - if (value instanceof IStringValue stringValue1) { - this.stringValue = stringValue1; - } - } - @Override public void onUpdate() { super.onUpdate(); @@ -224,8 +215,7 @@ public TextFieldWidget setDefaultNumber(double defaultNumber) { } public TextFieldWidget value(IStringValue stringValue) { - this.stringValue = stringValue; - setValue(stringValue); + setSyncOrValue(ISyncOrValue.orEmpty(stringValue)); return this; }