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

CyclopsMC / IntegratedDynamics / 42496019643

08 Nov 2026 03:40PM UTC coverage: 49.451% (+0.07%) from 49.377%
42496019643

push

github

web-flow
Add Expressions support to the Logic Programmer (#1766)

This allows constant values and multiple nested operators
to be combined within a single variable card, without having
to combine multiple variable cards.

These expressions can either be created through the existing
Logic Programmer interface, or they can be written in a text-form
for easy exchange across worlds and players.

5080 of 13034 branches covered (38.97%)

Branch coverage included in aggregate %.

16343 of 30288 relevant lines covered (53.96%)

2.65 hits per line

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

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

3
import lombok.ToString;
4
import net.minecraft.advancements.critereon.ItemPredicate;
5
import net.minecraft.core.registries.BuiltInRegistries;
6
import net.minecraft.nbt.CompoundTag;
7
import net.minecraft.nbt.Tag;
8
import net.minecraft.network.chat.Component;
9
import net.minecraft.network.chat.MutableComponent;
10
import net.minecraft.world.item.ItemStack;
11
import org.cyclops.commoncapabilities.api.capability.itemhandler.ItemMatch;
12
import org.cyclops.cyclopscore.helper.ItemStackHelpers;
13
import org.cyclops.integrateddynamics.api.advancement.criterion.ValuePredicate;
14
import org.cyclops.integrateddynamics.api.evaluate.EvaluationException;
15
import org.cyclops.integrateddynamics.api.evaluate.variable.*;
16
import org.cyclops.integrateddynamics.core.logicprogrammer.ValueTypeItemStackLPElement;
17
import org.cyclops.integrateddynamics.core.logicprogrammer.ValueTypeLPElementBase;
18

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

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

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

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

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

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

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

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

67
    @Override
68
    public Tag serialize(ValueDeseralizationContext valueDeseralizationContext, ValueItemStack value) {
69
        CompoundTag tag = new CompoundTag();
4 ✔
70
        ItemStack itemStack = value.getRawValue();
3 ✔
71
        if(!itemStack.isEmpty()) {
3 ✔
72
            tag.putInt("count", itemStack.getCount());
5 ✔
73
            int count = itemStack.getCount();
3 ✔
74
            if (itemStack.getCount() > 99) {
4 ✔
75
                tag.putInt("ExtendedCount", count);
4 ✔
76
                itemStack = itemStack.copy();
3 ✔
77
                itemStack.setCount(99);
3 ✔
78
            }
79
            return itemStack.save(valueDeseralizationContext.holderLookupProvider(), tag);
6 ✔
80
        }
81
        return tag;
2 ✔
82
    }
83

84
    @Override
85
    public ValueItemStack deserialize(ValueDeseralizationContext valueDeseralizationContext, Tag value) {
86
        if (value instanceof CompoundTag tag && !tag.isEmpty()) {
9 !
87
            // Forge returns air for tags with negative count,
88
            // so we set it to 1 for deserialization and fix it afterwards.
89
            int realCount = tag.getInt("count");
4 ✔
90
            // Consider the tag immutable, to avoid changes elsewhere
91
            tag = tag.copy();
3 ✔
92
            tag.putInt("count", 1);
4 ✔
93
            ItemStack itemStack = ItemStack.parseOptional(valueDeseralizationContext.holderLookupProvider(), tag);
5 ✔
94
            if (!itemStack.isEmpty()) {
3 ✔
95
                itemStack.setCount(realCount);
3 ✔
96
            }
97
            if (tag.contains("ExtendedCount", Tag.TAG_INT)) {
5 ✔
98
                itemStack.setCount(tag.getInt("ExtendedCount"));
5 ✔
99
            }
100
            return ValueItemStack.of(itemStack);
3 ✔
101
        } else {
102
            return ValueItemStack.of(ItemStack.EMPTY);
3 ✔
103
        }
104
    }
105

106
    @Override
107
    public String getName(ValueItemStack a) {
108
        return toCompactString(a).getString();
×
109
    }
110

111
    @Override
112
    public boolean isNull(ValueItemStack a) {
113
        return a.getRawValue().isEmpty();
×
114
    }
115

116
    @Override
117
    public ValueTypeLPElementBase createLogicProgrammerElement() {
118
        return new ValueTypeItemStackLPElement<>(this, new ValueTypeItemStackLPElement.IItemStackToValue<ValueObjectTypeItemStack.ValueItemStack>() {
12 ✔
119
            @Override
120
            public boolean isNullable() {
121
                return true;
×
122
            }
123

124
            @Override
125
            public Component validate(ItemStack itemStack) {
126
                return null;
×
127
            }
128

129
            @Override
130
            public ValueObjectTypeItemStack.ValueItemStack getValue(ItemStack itemStack) {
131
                return ValueObjectTypeItemStack.ValueItemStack.of(itemStack);
×
132
            }
133

134
            @Override
135
            public ItemStack getValueAsItemStack(ValueItemStack value) {
136
                return value.getRawValue();
×
137
            }
138
        });
139
    }
140

141
    @Override
142
    public ValueItemStack materialize(ValueItemStack value) throws EvaluationException {
143
        return ValueItemStack.of(value.getRawValue().copy());
5 ✔
144
    }
145

146
    @Override
147
    public String getUniqueName(ValueItemStack value) {
148
        ItemStack itemStack = value.getRawValue();
×
149
        return !itemStack.isEmpty() ? BuiltInRegistries.ITEM.getKey(itemStack.getItem()).toString() : "";
×
150
    }
151

152
    @ToString
5 ✔
153
    public static class ValueItemStack extends ValueBase {
154

155
        private final ItemStack itemStack;
156

157
        private ValueItemStack(ItemStack itemStack) {
158
            super(ValueTypes.OBJECT_ITEMSTACK);
3 ✔
159
            this.itemStack = Objects.requireNonNull(itemStack, "Attempted to create a ValueItemStack for a null ItemStack.");
6 ✔
160
        }
1 ✔
161

162
        public static ValueItemStack of(ItemStack itemStack) {
163
            return new ValueItemStack(itemStack);
5 ✔
164
        }
165

166
        public ItemStack getRawValue() {
167
            return itemStack;
3 ✔
168
        }
169

170
        @Override
171
        public boolean equals(Object o) {
172
            return o instanceof ValueItemStack && ItemMatch.areItemStacksEqual(((ValueItemStack) o).itemStack, this.itemStack, ItemMatch.EXACT);
15 !
173
        }
174

175
        @Override
176
        public int hashCode() {
177
            return 37 + ItemStackHelpers.getItemStackHashCode(itemStack);
×
178
        }
179
    }
180

181
    public static class ValueItemStackPredicate extends ValuePredicate<ValueItemStack> {
182

183
        private final Optional<ItemPredicate> itemPredicate;
184

185
        public ValueItemStackPredicate(Optional<ItemPredicate> itemPredicate) {
186
            super(Optional.of(ValueTypes.OBJECT_ITEMSTACK), Optional.empty(), Optional.empty());
6 ✔
187
            this.itemPredicate = itemPredicate;
3 ✔
188
        }
1 ✔
189

190
        public Optional<ItemPredicate> getItemPredicate() {
191
            return itemPredicate;
×
192
        }
193

194
        @Override
195
        protected boolean testTyped(ValueItemStack value) {
196
            return super.testTyped(value) && (itemPredicate.isEmpty() || itemPredicate.get().test(value.getRawValue()));
20 !
197
        }
198
    }
199

200
}
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