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

CyclopsMC / IntegratedDynamics / 39473055233

20 Oct 2026 06:14PM UTC coverage: 48.366% (-0.3%) from 48.683%
39473055233

Pull #1766

github

claude
Place a clicked cursor at the nearest boundary between characters

Vanilla's text model places the cursor before the character under the
mouse, so a click on the opening bracket of x.fluidStack() put the
cursor before it, and only a click on the closing bracket put it
between them, where the footer shows the call. The cursor now goes to
the closest boundary, as in other editors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MHtucHo4Qy2pTfBMgeE54y
Pull Request #1766: Expression cards in the Logic Programmer, editable as text

4834 of 12742 branches covered (37.94%)

Branch coverage included in aggregate %.

15759 of 29835 relevant lines covered (52.82%)

2.59 hits per line

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

66.27
/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
        //  as expressions call this type item. This keeps the saved unique name, but changes names that scripts use.
34
        super("itemstack", ValueObjectTypeItemStack.ValueItemStack.class);
4 ✔
35
    }
1 ✔
36

37
    public static MutableComponent getItemStackDisplayNameUsSafe(ItemStack itemStack) throws NoSuchMethodException {
38
        return !itemStack.isEmpty()
×
39
                ? (itemStack.getHoverName().copy().append((itemStack.getCount() > 1 ? " (" + itemStack.getCount() + ")" : "")))
×
40
                : Component.literal("");
×
41
    }
42

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

53
    @Override
54
    public ValueItemStack getDefault() {
55
        return ValueItemStack.of(ItemStack.EMPTY);
×
56
    }
57

58
    @Override
59
    public MutableComponent toCompactString(ValueItemStack value) {
60
        return ValueObjectTypeItemStack.getItemStackDisplayNameSafe(value.getRawValue());
×
61
    }
62

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

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

102
    @Override
103
    public String getName(ValueItemStack a) {
104
        return toCompactString(a).getString();
×
105
    }
106

107
    @Override
108
    public boolean isNull(ValueItemStack a) {
109
        return a.getRawValue().isEmpty();
×
110
    }
111

112
    @Override
113
    public ValueTypeLPElementBase createLogicProgrammerElement() {
114
        return new ValueTypeItemStackLPElement<>(this, new ValueTypeItemStackLPElement.IItemStackToValue<ValueObjectTypeItemStack.ValueItemStack>() {
12 ✔
115
            @Override
116
            public boolean isNullable() {
117
                return true;
×
118
            }
119

120
            @Override
121
            public Component validate(ItemStack itemStack) {
122
                return null;
×
123
            }
124

125
            @Override
126
            public ValueObjectTypeItemStack.ValueItemStack getValue(ItemStack itemStack) {
127
                return ValueObjectTypeItemStack.ValueItemStack.of(itemStack);
×
128
            }
129

130
            @Override
131
            public ItemStack getValueAsItemStack(ValueItemStack value) {
132
                return value.getRawValue();
×
133
            }
134
        });
135
    }
136

137
    @Override
138
    public ValueItemStack materialize(ValueItemStack value) throws EvaluationException {
139
        return ValueItemStack.of(value.getRawValue().copy());
5 ✔
140
    }
141

142
    @Override
143
    public String getUniqueName(ValueItemStack value) {
144
        ItemStack itemStack = value.getRawValue();
×
145
        return !itemStack.isEmpty() ? BuiltInRegistries.ITEM.getKey(itemStack.getItem()).toString() : "";
×
146
    }
147

148
    @ToString
5 ✔
149
    public static class ValueItemStack extends ValueBase {
150

151
        private final ItemStack itemStack;
152

153
        private ValueItemStack(ItemStack itemStack) {
154
            super(ValueTypes.OBJECT_ITEMSTACK);
3 ✔
155
            this.itemStack = Objects.requireNonNull(itemStack, "Attempted to create a ValueItemStack for a null ItemStack.");
6 ✔
156
        }
1 ✔
157

158
        public static ValueItemStack of(ItemStack itemStack) {
159
            return new ValueItemStack(itemStack);
5 ✔
160
        }
161

162
        public ItemStack getRawValue() {
163
            return itemStack;
3 ✔
164
        }
165

166
        @Override
167
        public boolean equals(Object o) {
168
            return o instanceof ValueItemStack && ItemMatch.areItemStacksEqual(((ValueItemStack) o).itemStack, this.itemStack, ItemMatch.EXACT);
15 !
169
        }
170

171
        @Override
172
        public int hashCode() {
173
            return 37 + ItemStackHelpers.getItemStackHashCode(itemStack);
×
174
        }
175
    }
176

177
    public static class ValueItemStackPredicate extends ValuePredicate<ValueItemStack> {
178

179
        private final Optional<ItemPredicate> itemPredicate;
180

181
        public ValueItemStackPredicate(Optional<ItemPredicate> itemPredicate) {
182
            super(Optional.of(ValueTypes.OBJECT_ITEMSTACK), Optional.empty(), Optional.empty());
6 ✔
183
            this.itemPredicate = itemPredicate;
3 ✔
184
        }
1 ✔
185

186
        public Optional<ItemPredicate> getItemPredicate() {
187
            return itemPredicate;
×
188
        }
189

190
        @Override
191
        protected boolean testTyped(ValueItemStack value) {
192
            return super.testTyped(value) && (itemPredicate.isEmpty() || itemPredicate.get().test(value.getRawValue()));
20 !
193
        }
194
    }
195

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