• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

CyclopsMC / IntegratedDynamics / 42508761336

08 Nov 2026 06:11PM UTC coverage: 58.584% (+0.3%) from 58.308%
42508761336

Pull #1781

github

claude
Merge remote-tracking branch 'origin/master-1.21-lts' into master-26-lts

Ports the expressions of the Logic Programmer (#1766) to Minecraft 26.1:
- Client-only classes of the expression panel move to core.logicprogrammer.client,
  the typed text is kept by the screen instead of the container, and the card
  facades get client classes for their model overlays.
- Expression trees are written with ValueOutput and ValueInput, so values and
  operators in them are serialized as everywhere else in 26.1.
- Values written with their type in the text leave out the "v" field of the
  serialized value, and items are written as their stack, so the text form is
  the same as in 1.21, such as @Item{id: "minecraft:diamond"}.
- Rendering uses GuiGraphicsExtractor, with strata instead of depth for the
  popups and dragged parameters, and input uses the new event types.
- Tests use JUnit 5 and the game test API of 26.1. Unknown items, invalid entity
  ids and non-compound lists can no longer be read at all, so their error is
  bad_value instead of value_changed, and an empty entity is written as @Entity{}.
- The icons of the expression advancements are converted to the 26.1 format, and
  an unreadable operator makes an expression card invalid instead of throwing,
  which crashed the book on the Expressions tutorial.
- The expression action packet no longer uses @OnlyIn, which NeoForge 26.1 warns
  about on every start.

Also fixes the invisible operator symbol in the Logic Programmer, which was drawn
with color 0, fully transparent since 26.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MHtucHo4Qy2pTfBMgeE54y
Pull Request #1781: Upmerge expressions in the Logic Programmer to 26.1

5828 of 13562 branches covered (42.97%)

Branch coverage included in aggregate %.

26150 of 41023 relevant lines covered (63.74%)

3.34 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

67.65
/src/main/java/org/cyclops/integrateddynamics/core/evaluate/variable/ValueObjectTypeItemStack.java
1
package org.cyclops.integrateddynamics.core.evaluate.variable;
2

3
import net.minecraft.advancements.criterion.ItemPredicate;
4
import net.minecraft.core.registries.BuiltInRegistries;
5
import net.minecraft.network.chat.Component;
6
import net.minecraft.network.chat.MutableComponent;
7
import net.minecraft.world.item.ItemStack;
8
import net.minecraft.world.level.storage.ValueInput;
9
import net.minecraft.world.level.storage.ValueOutput;
10
import org.cyclops.commoncapabilities.api.capability.itemhandler.ItemMatch;
11
import org.cyclops.cyclopscore.helper.IModHelpers;
12
import org.cyclops.integrateddynamics.api.advancement.criterion.ValuePredicate;
13
import org.cyclops.integrateddynamics.api.evaluate.EvaluationException;
14
import org.cyclops.integrateddynamics.api.evaluate.variable.IValueTypeNamed;
15
import org.cyclops.integrateddynamics.api.evaluate.variable.IValueTypeNullable;
16
import org.cyclops.integrateddynamics.api.evaluate.variable.IValueTypeUniquelyNamed;
17
import org.cyclops.integrateddynamics.core.logicprogrammer.ValueTypeItemStackLPElement;
18
import org.cyclops.integrateddynamics.core.logicprogrammer.ValueTypeLPElementBase;
19

20
import java.util.Objects;
21
import java.util.Optional;
22

23
/**
24
 * Value type with values that are itemstacks.
25
 * @author rubensworks
26
 */
27
public class ValueObjectTypeItemStack extends ValueObjectTypeBase<ValueObjectTypeItemStack.ValueItemStack> implements
28
        IValueTypeNamed<ValueObjectTypeItemStack.ValueItemStack>,
29
        IValueTypeUniquelyNamed<ValueObjectTypeItemStack.ValueItemStack>,
30
        IValueTypeNullable<ValueObjectTypeItemStack.ValueItemStack> {
31

32
    public ValueObjectTypeItemStack() {
33
        // TODO: in next major, prefix the global interact names of operators on items with item instead of itemstack.
34
        super("itemstack", ValueObjectTypeItemStack.ValueItemStack.class);
4 ✔
35
    }
1 ✔
36

37
    @Override
38
    public String getExpressionName() {
39
        return "Item";
2 ✔
40
    }
41

42
    public static MutableComponent getItemStackDisplayNameUsSafe(ItemStack itemStack) throws NoSuchMethodException {
43
        return !itemStack.isEmpty()
4 !
44
                ? (itemStack.getHoverName().copy().append((itemStack.getCount() > 1 ? " (" + itemStack.getCount() + ")" : "")))
×
45
                : Component.literal("");
2 ✔
46
    }
47

48
    public static MutableComponent getItemStackDisplayNameSafe(ItemStack itemStack) {
49
        // Certain mods may call client-side only methods,
50
        // so call a server-side-safe fallback method if that fails.
51
        try {
52
            return getItemStackDisplayNameUsSafe(itemStack);
3 ✔
53
        } catch (NoSuchMethodException e) {
×
54
            return Component.translatable(itemStack.getItem().getDescriptionId());
×
55
        }
56
    }
57

58
    @Override
59
    public ValueItemStack getDefault() {
60
        return ValueItemStack.of(ItemStack.EMPTY);
×
61
    }
62

63
    @Override
64
    public MutableComponent toCompactString(ValueItemStack value) {
65
        return ValueObjectTypeItemStack.getItemStackDisplayNameSafe(value.getRawValue());
4 ✔
66
    }
67

68
    @Override
69
    public void serialize(ValueOutput valueOutput, ValueItemStack value) {
70
        valueOutput = valueOutput.child("v");
4 ✔
71
        ItemStack itemStack;
72
        itemStack = value.getRawValue();
3 ✔
73
        int count = itemStack.getCount();
3 ✔
74
        if (itemStack.getCount() > 99) {
4 ✔
75
            itemStack = itemStack.copy();
3 ✔
76
            itemStack.setCount(99);
3 ✔
77
        }
78
        if (count > 99) {
3 ✔
79
            valueOutput.putInt("ExtendedCount", count);
4 ✔
80
        }
81
        valueOutput.store("stack", ItemStack.OPTIONAL_CODEC, itemStack);
5 ✔
82
    }
1 ✔
83

84
    @Override
85
    public ValueItemStack deserialize(ValueInput valueInput) {
86
        valueInput = valueInput.child("v").orElseThrow();
6 ✔
87
        ItemStack itemStack = valueInput.read("stack", ItemStack.OPTIONAL_CODEC).orElseThrow();
7 ✔
88
        valueInput.getInt("ExtendedCount").ifPresent(itemStack::setCount);
9 ✔
89
        return ValueItemStack.of(itemStack);
3 ✔
90
    }
91

92
    @Override
93
    public String getName(ValueItemStack a) {
94
        return toCompactString(a).getString();
×
95
    }
96

97
    @Override
98
    public boolean isNull(ValueItemStack a) {
99
        return a.getRawValue().isEmpty();
×
100
    }
101

102
    @Override
103
    public ValueTypeLPElementBase createLogicProgrammerElement() {
104
        return new ValueTypeItemStackLPElement<>(this, new ValueTypeItemStackLPElement.IItemStackToValue<ValueObjectTypeItemStack.ValueItemStack>() {
17 ✔
105
            @Override
106
            public boolean isNullable() {
107
                return true;
×
108
            }
109

110
            @Override
111
            public Component validate(ItemStack itemStack) {
112
                return null;
×
113
            }
114

115
            @Override
116
            public ValueObjectTypeItemStack.ValueItemStack getValue(ItemStack itemStack) {
117
                return ValueObjectTypeItemStack.ValueItemStack.of(itemStack);
×
118
            }
119

120
            @Override
121
            public ItemStack getValueAsItemStack(ValueItemStack value) {
122
                return value.getRawValue();
×
123
            }
124
        });
125
    }
126

127
    @Override
128
    public ValueItemStack materialize(ValueItemStack value) throws EvaluationException {
129
        return ValueItemStack.of(value.getRawValue().copy());
5 ✔
130
    }
131

132
    @Override
133
    public String getUniqueName(ValueItemStack value) {
134
        ItemStack itemStack = value.getRawValue();
×
135
        return !itemStack.isEmpty() ? BuiltInRegistries.ITEM.getKey(itemStack.getItem()).toString() : "";
×
136
    }
137

138
    public static class ValueItemStack extends ValueBase {
139

140
        private final ItemStack itemStack;
141

142
        private ValueItemStack(ItemStack itemStack) {
143
            super(ValueTypes.OBJECT_ITEMSTACK);
3 ✔
144
            this.itemStack = Objects.requireNonNull(itemStack, "Attempted to create a ValueItemStack for a null ItemStack.");
6 ✔
145
        }
1 ✔
146

147
        public static ValueItemStack of(ItemStack itemStack) {
148
            return new ValueItemStack(itemStack);
5 ✔
149
        }
150

151
        public ItemStack getRawValue() {
152
            return itemStack;
3 ✔
153
        }
154

155
        @Override
156
        public boolean equals(Object o) {
157
            return o instanceof ValueItemStack && ItemMatch.areItemStacksEqual(((ValueItemStack) o).itemStack, this.itemStack, ItemMatch.EXACT);
15 !
158
        }
159

160
        @Override
161
        public int hashCode() {
162
            return 37 + IModHelpers.get().getItemStackHelpers().getItemStackHashCode(itemStack);
×
163
        }
164

165
        @Override
166
        public String toString() {
167
            return "ValueItemStack(itemStack=" + this.itemStack + ")";
5 ✔
168
        }
169
    }
170

171
    public static class ValueItemStackPredicate extends ValuePredicate<ValueItemStack> {
172

173
        private final Optional<ItemPredicate> itemPredicate;
174

175
        public ValueItemStackPredicate(Optional<ItemPredicate> itemPredicate) {
176
            super(Optional.of(ValueTypes.OBJECT_ITEMSTACK), Optional.empty(), Optional.empty());
6 ✔
177
            this.itemPredicate = itemPredicate;
3 ✔
178
        }
1 ✔
179

180
        public Optional<ItemPredicate> getItemPredicate() {
181
            return itemPredicate;
×
182
        }
183

184
        @Override
185
        protected boolean testTyped(ValueItemStack value) {
186
            return super.testTyped(value) && (itemPredicate.isEmpty() || itemPredicate.get().test(value.getRawValue()));
20 !
187
        }
188
    }
189

190
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc