/
ItemMetaDynamic.java
135 lines (116 loc) · 4.59 KB
/
ItemMetaDynamic.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
package slimeknights.mantle.item;
import gnu.trove.map.hash.TIntObjectHashMap;
import gnu.trove.procedure.TIntObjectProcedure;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.util.text.translation.I18n;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import java.util.Arrays;
import java.util.List;
import slimeknights.mantle.util.LocUtils;
/**
* Item representing a dynamic amount of different items represented by meta.
* Only returns valid metadatas. The validity is determined by a bitmask.
* Current maximum is 64 metas - that should suffice for most applications.
*/
public class ItemMetaDynamic extends Item {
private static int MAX = (2 << 16) - 1;
protected boolean[] availabilityMask; // boolean[] actually is much more performant for our case than BitSet
protected TIntObjectHashMap<String> names;
public ItemMetaDynamic() {
availabilityMask = new boolean[1];
names = new TIntObjectHashMap<String>();
this.setHasSubtypes(true);
}
/**
* Add a valid metadata.
*
* @param meta The metadata value
* @param name The name used for registering the itemmodel as well as the unlocalized name of the meta. The unlocalized name will be lowercased and stripped of whitespaces.
* @return An itemstack representing the Item-Meta combination.
*/
public ItemStack addMeta(int meta, String name) {
if(meta > MAX) {
throw new IllegalArgumentException(String
.format("Metadata for %s too high, highest supported value is %d. Meta was %d", name, MAX, meta));
}
else if(isValid(meta)) {
throw new IllegalArgumentException(String
.format("Metadata for %s is already taken. Meta %d is %s", name, meta, names
.get(meta)));
}
while(meta >= availabilityMask.length) {
availabilityMask = Arrays.copyOf(availabilityMask, availabilityMask.length * 2);
}
setValid(meta);
names.put(meta, name);
return new ItemStack(this, 1, meta);
}
@Override
public String getUnlocalizedName(ItemStack stack) {
int meta = stack.getMetadata(); // should call getMetadata below
if(isValid(meta)) {
return super.getUnlocalizedName(stack) + "." + LocUtils.makeLocString(names.get(meta));
}
else {
return super.getUnlocalizedName(stack);
}
}
@Override
public void getSubItems(Item itemIn, CreativeTabs tab, List<ItemStack> subItems) {
for(int i = 0; i <= availabilityMask.length; i++) {
if(isValid(i)) {
subItems.add(new ItemStack(itemIn, 1, i));
}
}
}
@Override
public int getMetadata(int damage) {
int meta = super.getMetadata(damage);
return isValid(meta) ? meta : 0;
}
protected void setValid(int meta) {
availabilityMask[meta] = true;
}
protected boolean isValid(int meta) {
if(meta > MAX || meta >= availabilityMask.length) {
return false;
}
return availabilityMask[meta];
}
@SideOnly(Side.CLIENT)
public void registerItemModels() {
registerItemModels(this);
}
@SideOnly(Side.CLIENT)
protected void registerItemModels(final Item item) {
final String resourceId = Loader.instance().activeModContainer().getModId().toLowerCase();
names.forEachEntry(new TIntObjectProcedure<String>() {
@Override
public boolean execute(int meta, String name) {
// tell the game which model to use for this item-meta combination
ModelLoader.setCustomModelResourceLocation(item, meta, new ModelResourceLocation(item.getRegistryName(), name));
return true;
}
});
}
@Override
public void addInformation(ItemStack stack, EntityPlayer playerIn, List<String> tooltip, boolean advanced) {
if(I18n.canTranslate(this.getUnlocalizedName(stack) + ".tooltip")) {
tooltip.add(TextFormatting.GRAY.toString() +
LocUtils.translateRecursive(this.getUnlocalizedName(stack) + ".tooltip"));
}
else if(I18n.canTranslate(super.getUnlocalizedName(stack) + ".tooltip")) {
tooltip.add(
TextFormatting.GRAY.toString() + LocUtils.translateRecursive(super.getUnlocalizedName(stack) + ".tooltip"));
}
super.addInformation(stack, playerIn, tooltip, advanced);
}
}