ScriptsLab
WikiDownloadsSourcesSupport
ScriptsLab
DocumentationDownloadsGitHubDiscord

© 2026 ScriptsLab

Back to src/main/java/com/scriptslab/core/item
J

CustomItemImpl.java

Java · 230 lines · 6.3 KB

src/main/java/com/scriptslab/core/item/CustomItemImpl.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
package com.scriptslab.core.item;

import com.scriptslab.api.item.CustomItem;
import com.scriptslab.api.item.ItemAbility;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * Immutable implementation of CustomItem.
 */
public record CustomItemImpl(
        String id,
        Material material,
        String displayName,
        List<String> lore,
        int customModelData,
        Map<String, Object> nbtData,
        List<ItemAbility> abilities,
        boolean unbreakable,
        Rarity rarity
) implements CustomItem {
    
    private static final LegacyComponentSerializer SERIALIZER = 
            LegacyComponentSerializer.legacyAmpersand();
    
    /**
     * Compact constructor with validation and defensive copying.
     */
    public CustomItemImpl {
        if (id == null || id.isBlank()) {
            throw new IllegalArgumentException("Item ID cannot be null or blank");
        }
        if (material == null) {
            throw new IllegalArgumentException("Material cannot be null");
        }
        if (displayName == null) {
            displayName = id;
        }
        
        // Defensive copies
        lore = lore != null ? List.copyOf(lore) : List.of();
        nbtData = nbtData != null ? Map.copyOf(nbtData) : Map.of();
        abilities = abilities != null ? List.copyOf(abilities) : List.of();
        
        if (rarity == null) {
            rarity = Rarity.COMMON;
        }
    }
    
    @Override
    public String getId() {
        return id;
    }
    
    @Override
    public Material getMaterial() {
        return material;
    }
    
    @Override
    public String getDisplayName() {
        return displayName;
    }
    
    @Override
    public List<String> getLore() {
        return lore;
    }
    
    @Override
    public int getCustomModelData() {
        return customModelData;
    }
    
    @Override
    public Map<String, Object> getNbtData() {
        return nbtData;
    }
    
    @Override
    public List<ItemAbility> getAbilities() {
        return abilities;
    }
    
    @Override
    public boolean isUnbreakable() {
        return unbreakable;
    }
    
    @Override
    public Rarity getRarity() {
        return rarity;
    }
    
    @Override
    public ItemStack toItemStack(int amount) {
        ItemStack item = new ItemStack(material, amount);
        ItemMeta meta = item.getItemMeta();
        
        if (meta != null) {
            // Display name with rarity color
            Component nameComponent = SERIALIZER.deserialize(rarity.getColor() + displayName);
            meta.displayName(nameComponent);
            
            // Lore
            if (!lore.isEmpty()) {
                List<Component> loreComponents = new ArrayList<>();
                for (String line : lore) {
                    loreComponents.add(SERIALIZER.deserialize(line));
                }
                
                // Add rarity to lore
                loreComponents.add(Component.empty());
                loreComponents.add(SERIALIZER.deserialize(rarity.getColor() + rarity.getDisplayName()));
                
                meta.lore(loreComponents);
            }
            
            // Custom model data
            if (customModelData > 0) {
                meta.setCustomModelData(customModelData);
            }
            
            // Unbreakable
            if (unbreakable) {
                meta.setUnbreakable(true);
            }
            
            item.setItemMeta(meta);
        }
        
        return item;
    }
    
    /**
     * Builder for creating CustomItem instances.
     */
    public static class Builder {
        private String id;
        private Material material = Material.STONE;
        private String displayName;
        private List<String> lore = new ArrayList<>();
        private int customModelData = 0;
        private Map<String, Object> nbtData = new java.util.HashMap<>();
        private List<ItemAbility> abilities = new ArrayList<>();
        private boolean unbreakable = false;
        private Rarity rarity = Rarity.COMMON;
        
        public Builder(String id) {
            this.id = id;
            this.displayName = id;
        }
        
        public Builder material(Material material) {
            this.material = material;
            return this;
        }
        
        public Builder displayName(String displayName) {
            this.displayName = displayName;
            return this;
        }
        
        public Builder lore(String... lore) {
            this.lore = new ArrayList<>(List.of(lore));
            return this;
        }
        
        public Builder lore(List<String> lore) {
            this.lore = new ArrayList<>(lore);
            return this;
        }
        
        public Builder addLore(String line) {
            this.lore.add(line);
            return this;
        }
        
        public Builder customModelData(int customModelData) {
            this.customModelData = customModelData;
            return this;
        }
        
        public Builder nbt(String key, Object value) {
            this.nbtData.put(key, value);
            return this;
        }
        
        public Builder nbtData(Map<String, Object> nbtData) {
            this.nbtData = new java.util.HashMap<>(nbtData);
            return this;
        }
        
        public Builder ability(ItemAbility ability) {
            this.abilities.add(ability);
            return this;
        }
        
        public Builder abilities(List<ItemAbility> abilities) {
            this.abilities = new ArrayList<>(abilities);
            return this;
        }
        
        public Builder unbreakable(boolean unbreakable) {
            this.unbreakable = unbreakable;
            return this;
        }
        
        public Builder rarity(Rarity rarity) {
            this.rarity = rarity;
            return this;
        }
        
        public CustomItem build() {
            return new CustomItemImpl(
                    id, material, displayName, lore, customModelData,
                    nbtData, abilities, unbreakable, rarity
            );
        }
    }
}