diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/IGTTool.java b/src/main/java/com/gregtechceu/gtceu/api/item/IGTTool.java index ccd1fadee73..ba949336c4c 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/IGTTool.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/IGTTool.java @@ -102,6 +102,8 @@ default ItemStack getRaw() { ItemStack stack = new ItemStack(asItem()); stack.set(DataComponents.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.EMPTY); stack.set(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY); + stack.set(GTDataComponents.MAX_AOE, AoESymmetrical.ZERO); + stack.remove(DataComponents.MAX_DAMAGE); stack.remove(DataComponents.DAMAGE); stack.remove(DataComponents.UNBREAKABLE); @@ -737,10 +739,13 @@ default ModularScreen createScreen(PlayerInventoryGuiData data, ModularPanel< default @Nullable ModularPanel buildUI(PlayerInventoryGuiData data, PanelSyncManager syncManager, UISettings settings) { for (var behavior : getToolStats().getBehaviors()) { - if (!(behavior instanceof IToolUIBehavior uiBehavior) || - !uiBehavior.shouldOpenUI(data.getPlayer(), data.getPlayer().getUsedItemHand())) { + if (!(behavior instanceof IToolUIBehavior uiBehavior)) { + continue; + } + if (!uiBehavior.shouldOpenUI(data.getPlayer(), data.getPlayer().getUsedItemHand())) { continue; } + return uiBehavior.buildUI(data, syncManager, settings); } return null; diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/datacomponents/AoESymmetrical.java b/src/main/java/com/gregtechceu/gtceu/api/item/datacomponents/AoESymmetrical.java index 2c6058e03a3..7aa4b923f3c 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/datacomponents/AoESymmetrical.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/datacomponents/AoESymmetrical.java @@ -1,5 +1,6 @@ package com.gregtechceu.gtceu.api.item.datacomponents; +import net.minecraft.Util; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.util.ExtraCodecs; @@ -11,29 +12,41 @@ import lombok.*; import lombok.experimental.Accessors; -public record AoESymmetrical(int maxColumn, int maxRow, int maxLayer, int column, int row, int layer) { - - public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - ExtraCodecs.NON_NEGATIVE_INT.fieldOf("max_column").forGetter(AoESymmetrical::maxColumn), - ExtraCodecs.NON_NEGATIVE_INT.fieldOf("max_row").forGetter(AoESymmetrical::maxRow), - ExtraCodecs.NON_NEGATIVE_INT.fieldOf("max_layer").forGetter(AoESymmetrical::maxLayer), +import java.util.List; + +public record AoESymmetrical(int column, int row, int layer) { + + // spotless:off + private static final Codec ARRAY_CODEC = Codec.INT + .listOf() + .comapFlatMap(list -> Util.fixedSize(list, 3) + .map(l -> new AoESymmetrical(l.get(0), l.get(1), l.get(2))), + aoe -> List.of(aoe.column, aoe.row, aoe.layer) + ); + private static final Codec NAMED_CODEC = RecordCodecBuilder.create(instance -> instance.group( + ExtraCodecs.NON_NEGATIVE_INT.fieldOf("additional_columns").forGetter(AoESymmetrical::column), + ExtraCodecs.NON_NEGATIVE_INT.fieldOf("additional_rows").forGetter(AoESymmetrical::row), + ExtraCodecs.NON_NEGATIVE_INT.fieldOf("additional_layers").forGetter(AoESymmetrical::layer) + ).apply(instance, AoESymmetrical::new)); + private static final Codec LEGACY_CODEC = RecordCodecBuilder.create(instance -> instance.group( ExtraCodecs.NON_NEGATIVE_INT.fieldOf("column").forGetter(AoESymmetrical::column), ExtraCodecs.NON_NEGATIVE_INT.fieldOf("row").forGetter(AoESymmetrical::row), - ExtraCodecs.NON_NEGATIVE_INT.fieldOf("layer").forGetter(AoESymmetrical::layer)) - .apply(instance, AoESymmetrical::new)); + ExtraCodecs.NON_NEGATIVE_INT.fieldOf("layer").forGetter(AoESymmetrical::layer) + ).apply(instance, AoESymmetrical::new)); + public static final Codec CODEC = Codec.withAlternative(NAMED_CODEC, Codec.withAlternative(ARRAY_CODEC, LEGACY_CODEC)); + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( - ByteBufCodecs.VAR_INT, AoESymmetrical::maxColumn, - ByteBufCodecs.VAR_INT, AoESymmetrical::maxRow, - ByteBufCodecs.VAR_INT, AoESymmetrical::maxLayer, ByteBufCodecs.VAR_INT, AoESymmetrical::column, ByteBufCodecs.VAR_INT, AoESymmetrical::row, ByteBufCodecs.VAR_INT, AoESymmetrical::layer, - AoESymmetrical::new); + AoESymmetrical::new + ); + // spotless:on - public static final AoESymmetrical ZERO = new AoESymmetrical(0, 0, 0, 0, 0, 0); + public static final AoESymmetrical ZERO = new AoESymmetrical(0, 0, 0); public boolean isZero() { - return this == ZERO || (this.maxColumn == 0 && this.maxRow == 0 && this.maxLayer == 0); + return this == ZERO || (this.column == 0 && this.row == 0 && this.layer == 0); } public static AoESymmetrical of(int column, int row, int layer) { @@ -41,11 +54,20 @@ public static AoESymmetrical of(int column, int row, int layer) { Preconditions.checkArgument(row >= 0, "Width cannot be negative."); Preconditions.checkArgument(layer >= 0, "Depth cannot be negative."); return column == 0 && row == 0 && layer == 0 ? ZERO : - new AoESymmetrical(column, row, layer, column, row, layer); + new AoESymmetrical(column, row, layer); + } + + public AoESymmetrical min(AoESymmetrical other) { + if (this.isZero() || other.isZero()) return AoESymmetrical.ZERO; + if (this.equals(other)) return this; + + return new AoESymmetrical(Math.min(column, other.column), + Math.min(row, other.row), + Math.min(layer, other.layer)); } - public Mutable toMutable() { - return new Mutable(maxColumn, maxRow, maxLayer, column, row, layer); + public Mutable toMutable(AoESymmetrical max) { + return new Mutable(max.column, max.row, max.layer, this.column, this.row, this.layer); } @Override @@ -53,20 +75,16 @@ public boolean equals(Object o) { if (this == o) return true; // noinspection PatternVariableHidesField - if (!(o instanceof AoESymmetrical(int maxColumn, int maxRow, int maxLayer, int column, int row, int layer))) { + if (!(o instanceof AoESymmetrical(int column, int row, int layer))) { return false; } - return this.maxColumn == maxColumn && this.maxRow == maxRow && this.maxLayer == maxLayer && - this.column == column && this.row == row && this.layer == layer; + return this.column == column && this.row == row && this.layer == layer; } @Override public int hashCode() { - int result = maxColumn; - result = 31 * result + maxRow; - result = 31 * result + maxLayer; - result = 31 * result + column; + int result = column; result = 31 * result + row; result = 31 * result + layer; return result; @@ -126,7 +144,9 @@ public Mutable decreaseLayer() { } public AoESymmetrical toImmutable() { - return new AoESymmetrical(maxColumn, maxRow, maxLayer, column, row, layer); + return new AoESymmetrical(Math.clamp(column, 0, maxColumn), + Math.clamp(row, 0, maxRow), + Math.clamp(layer, 0, maxLayer)); } } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/datacomponents/ToolBehaviors.java b/src/main/java/com/gregtechceu/gtceu/api/item/datacomponents/ToolBehaviors.java index bd488728923..18ac465ed97 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/datacomponents/ToolBehaviors.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/datacomponents/ToolBehaviors.java @@ -25,7 +25,7 @@ public record ToolBehaviors(@Unmodifiable Map, IToolBehavior public static final ToolBehaviors EMPTY = new ToolBehaviors(Map.of()); // spotless:off - public static final Codec, IToolBehavior>> MAP_CODEC = Codec + private static final Codec, IToolBehavior>> MAP_CODEC = Codec .dispatchedMap(GTRegistries.TOOL_BEHAVIORS.byNameCodec(), ToolBehaviorType::getCodec); public static final Codec CODEC = MAP_CODEC.xmap(ToolBehaviors::new, ToolBehaviors::behaviors); @@ -41,6 +41,14 @@ public ToolBehaviors(List> behaviors) { this(behaviors.stream().collect(Collectors.toMap(IToolBehavior::getType, Function.identity()))); } + public ToolBehaviors(Map, IToolBehavior> behaviors) { + this.behaviors = Collections.unmodifiableMap(behaviors); + } + + public boolean isEmpty() { + return this.behaviors.isEmpty(); + } + public boolean hasBehavior(ToolBehaviorType type) { return behaviors.containsKey(type); } diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/tool/ToolHelper.java b/src/main/java/com/gregtechceu/gtceu/api/item/tool/ToolHelper.java index 38a2fc34a4a..621f8f10492 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/tool/ToolHelper.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/tool/ToolHelper.java @@ -126,8 +126,9 @@ public static ToolBehaviors getBehaviorsComponent(ItemStack stack) { return stack.getOrDefault(GTDataComponents.TOOL_BEHAVIORS, ToolBehaviors.EMPTY); } + @SuppressWarnings("BooleanMethodIsAlwaysInverted") public static boolean hasBehaviorsComponent(ItemStack stack) { - return stack.has(GTDataComponents.TOOL_BEHAVIORS); + return !getBehaviorsComponent(stack).isEmpty(); } public static ItemStack get(GTToolType toolType, Material material) { @@ -281,7 +282,17 @@ else if (!ItemStack.isSameItem(player.getMainHandItem(), stack)) { } public static AoESymmetrical getAoEDefinition(ItemStack stack) { - return stack.getOrDefault(GTDataComponents.AOE, AoESymmetrical.ZERO); + AoESymmetrical value = stack.getOrDefault(GTDataComponents.AOE, AoESymmetrical.ZERO); + if (stack.has(GTDataComponents.MAX_AOE)) { + AoESymmetrical max = stack.getOrDefault(GTDataComponents.MAX_AOE, AoESymmetrical.ZERO); + return value.min(max); + } else { + return value; + } + } + + public static AoESymmetrical.Mutable getAoEStateMutable(ItemStack stack) { + return getAoEDefinition(stack).toMutable(stack.getOrDefault(GTDataComponents.MAX_AOE, AoESymmetrical.ZERO)); } public static List iterateAoE(AoESymmetrical aoeDefinition, Predicate predicate, diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/GTMaterialItems.java b/src/main/java/com/gregtechceu/gtceu/common/data/GTMaterialItems.java index c6944106574..7dc215929d9 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/GTMaterialItems.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTMaterialItems.java @@ -134,12 +134,10 @@ private static void generateTool(final Material material, final GTToolType toolT TOOL_ITEMS.put(material, toolType, (ItemProviderEntry) (ItemProviderEntry) registrate .item(toolType.idFormat.formatted(tier.material.getName()), p -> toolType.constructor.create(toolType, tier, material, toolType.toolDefinition, p).asItem()) .properties(p -> { - if (!toolType.toolDefinition.getAoEDefinition().isZero()) { - p.component(GTDataComponents.AOE, toolType.toolDefinition.getAoEDefinition()); - } - return p.craftRemainder(Items.AIR); - }) - .properties(p -> { + p.component(GTDataComponents.MAX_AOE, toolType.toolDefinition.getAoEDefinition()); + p.component(GTDataComponents.AOE, toolType.toolDefinition.getAoEDefinition()); + p.craftRemainder(Items.AIR); + IGTToolDefinition toolStats = toolType.toolDefinition; // Set other tool stats (durability) ToolProperty toolProperty = material.getProperty(PropertyKey.TOOL); diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/item/GTDataComponents.java b/src/main/java/com/gregtechceu/gtceu/common/data/item/GTDataComponents.java index ec21f58b6c5..8ad5a06ceac 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/item/GTDataComponents.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/item/GTDataComponents.java @@ -51,6 +51,9 @@ public class GTDataComponents { public static final DeferredHolder, DataComponentType> AOE = DATA_COMPONENTS .registerComponentType("aoe", builder -> builder.persistent(AoESymmetrical.CODEC) .networkSynchronized(AoESymmetrical.STREAM_CODEC)); + public static final DeferredHolder, DataComponentType> MAX_AOE = DATA_COMPONENTS + .registerComponentType("max_aoe", builder -> builder.persistent(AoESymmetrical.CODEC) + .networkSynchronized(AoESymmetrical.STREAM_CODEC)); public static final DeferredHolder, DataComponentType> DISALLOW_CONTAINER_ITEM = DATA_COMPONENTS .registerComponentType("disallow_container_item", builder -> builder.persistent(Unit.CODEC) .networkSynchronized(UNIT_STREAM_CODEC)); diff --git a/src/main/java/com/gregtechceu/gtceu/common/item/tool/behavior/AOEConfigUIBehavior.java b/src/main/java/com/gregtechceu/gtceu/common/item/tool/behavior/AOEConfigUIBehavior.java index df80eddfc4d..974a1467231 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/item/tool/behavior/AOEConfigUIBehavior.java +++ b/src/main/java/com/gregtechceu/gtceu/common/item/tool/behavior/AOEConfigUIBehavior.java @@ -14,19 +14,19 @@ import brachy.modularui.api.drawable.Text; import brachy.modularui.drawable.GuiTextures; +import brachy.modularui.drawable.Icon; import brachy.modularui.factory.PlayerInventoryGuiData; import brachy.modularui.screen.ModularPanel; import brachy.modularui.screen.UISettings; import brachy.modularui.value.sync.InteractionSyncHandler; import brachy.modularui.value.sync.PanelSyncManager; import brachy.modularui.widgets.ButtonWidget; -import brachy.modularui.widgets.TextWidget; import brachy.modularui.widgets.layout.Flow; import com.mojang.serialization.Codec; import io.netty.buffer.ByteBuf; import org.jetbrains.annotations.NotNull; -import static com.gregtechceu.gtceu.api.item.tool.ToolHelper.*; +import static com.gregtechceu.gtceu.api.item.tool.ToolHelper.getAoEStateMutable; public class AOEConfigUIBehavior implements IToolUIBehavior { @@ -36,14 +36,16 @@ public class AOEConfigUIBehavior implements IToolUIBehavior @Override public boolean shouldOpenUI(@NotNull Player player, @NotNull InteractionHand hand) { - return player.isShiftKeyDown() && !player.getItemInHand(hand) - .getOrDefault(GTDataComponents.AOE, AoESymmetrical.ZERO).isZero(); + return player.isShiftKeyDown() && + !player.getItemInHand(hand).getOrDefault(GTDataComponents.MAX_AOE, AoESymmetrical.ZERO).isZero(); } @Override public ModularPanel buildUI(PlayerInventoryGuiData data, PanelSyncManager syncManager, UISettings settings) { ItemStack held = data.getUsedItemStack(); - final AoESymmetrical.Mutable definition = getAoEDefinition(held).toMutable(); + final AoESymmetrical.Mutable definition = getAoEStateMutable(held); + + // spotless:off InteractionSyncHandler minusCols = new InteractionSyncHandler(); minusCols.setOnMousePressed(data1 -> held.set(GTDataComponents.AOE, definition.decreaseColumn().toImmutable())); InteractionSyncHandler plusCols = new InteractionSyncHandler(); @@ -53,10 +55,13 @@ public ModularPanel buildUI(PlayerInventoryGuiData data, PanelSyncManager InteractionSyncHandler plusRows = new InteractionSyncHandler(); plusRows.setOnMousePressed(data1 -> held.set(GTDataComponents.AOE, definition.increaseRow().toImmutable())); InteractionSyncHandler minusLayers = new InteractionSyncHandler(); - minusLayers - .setOnMousePressed(data1 -> held.set(GTDataComponents.AOE, definition.decreaseLayer().toImmutable())); + minusLayers.setOnMousePressed(data1 -> held.set(GTDataComponents.AOE, definition.decreaseLayer().toImmutable())); InteractionSyncHandler plusLayers = new InteractionSyncHandler(); plusLayers.setOnMousePressed(data1 -> held.set(GTDataComponents.AOE, definition.increaseLayer().toImmutable())); + + final Icon addOverlay = GuiTextures.ADD.asIcon().size(10); + final Icon removeOverlay = GuiTextures.REMOVE.asIcon().size(10); + return new ModularPanel<>("aoe_config") .coverChildren() .child(Flow.row() @@ -78,58 +83,47 @@ public ModularPanel buildUI(PlayerInventoryGuiData data, PanelSyncManager .childPadding(2) .child(new ButtonWidget<>() .size(12) - .background(GuiTextures.MC_BUTTON, - GuiTextures.REMOVE.asIcon().size(10)) - .hoverBackground(GuiTextures.MC_BUTTON_HOVERED, - GuiTextures.REMOVE.asIcon().size(10)) + .background(GuiTextures.MC_BUTTON, removeOverlay) + .hoverBackground(GuiTextures.MC_BUTTON_HOVERED, removeOverlay) .syncHandler(minusCols)) - .child(new TextWidget<>(Text.dynamic(() -> Component.literal(Integer.toString( - 2 * definition.column() + 1))))) + .child(Text.dynamic(() -> Component.literal(Integer.toString(2 * definition.column() + 1))) + .asWidget()) .child(new ButtonWidget<>() .size(12) - .background(GuiTextures.MC_BUTTON, - GuiTextures.ADD.asIcon().size(10)) - .hoverBackground(GuiTextures.MC_BUTTON_HOVERED, - GuiTextures.ADD.asIcon().size(10)) + .background(GuiTextures.MC_BUTTON, addOverlay) + .hoverBackground(GuiTextures.MC_BUTTON_HOVERED, addOverlay) .syncHandler(plusCols))) .child(Flow.row() .coverChildren() .childPadding(2) .child(new ButtonWidget<>() .size(12) - .background(GuiTextures.MC_BUTTON, - GuiTextures.REMOVE.asIcon().size(10)) - .hoverBackground(GuiTextures.MC_BUTTON_HOVERED, - GuiTextures.REMOVE.asIcon().size(10)) + .background(GuiTextures.MC_BUTTON, removeOverlay) + .hoverBackground(GuiTextures.MC_BUTTON_HOVERED, removeOverlay) .syncHandler(minusRows)) - .child(new TextWidget<>(Text.dynamic(() -> Component.literal(Integer.toString( - 2 * definition.row + 1))))) + .child(Text.dynamic(() -> Component.literal(Integer.toString(2 * definition.row + 1))) + .asWidget()) .child(new ButtonWidget<>() .size(12) - .background(GuiTextures.MC_BUTTON, - GuiTextures.ADD.asIcon().size(10)) - .hoverBackground(GuiTextures.MC_BUTTON_HOVERED, - GuiTextures.ADD.asIcon().size(10)) + .background(GuiTextures.MC_BUTTON, addOverlay) + .hoverBackground(GuiTextures.MC_BUTTON_HOVERED, addOverlay) .syncHandler(plusRows))) .child(Flow.row() .coverChildren() .childPadding(2) .child(new ButtonWidget<>() .size(12) - .background(GuiTextures.MC_BUTTON, - GuiTextures.REMOVE.asIcon().size(10)) - .hoverBackground(GuiTextures.MC_BUTTON_HOVERED, - GuiTextures.REMOVE.asIcon().size(10)) + .background(GuiTextures.MC_BUTTON, removeOverlay) + .hoverBackground(GuiTextures.MC_BUTTON_HOVERED, removeOverlay) .syncHandler(minusLayers)) - .child(new TextWidget<>(Text.dynamic(() -> Component.literal(Integer.toString( - 2 * definition.layer + 1))))) + .child(Text.dynamic(() -> Component.literal(Integer.toString(2 * definition.layer + 1))) + .asWidget()) .child(new ButtonWidget<>() .size(12) - .background(GuiTextures.MC_BUTTON, - GuiTextures.ADD.asIcon().size(10)) - .hoverBackground(GuiTextures.MC_BUTTON_HOVERED, - GuiTextures.ADD.asIcon().size(10)) + .background(GuiTextures.MC_BUTTON, addOverlay) + .hoverBackground(GuiTextures.MC_BUTTON_HOVERED, addOverlay) .syncHandler(plusLayers))))); + // spotless:on } @Override