/
ItemWaypointCompass.java
270 lines (247 loc) · 9.34 KB
/
ItemWaypointCompass.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
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
package knightminer.inspirations.tools.item;
import knightminer.inspirations.common.Config;
import knightminer.inspirations.library.Util;
import knightminer.inspirations.library.util.TagUtil;
import knightminer.inspirations.tools.InspirationsTools;
import knightminer.inspirations.tools.client.WaypointCompassGetter;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.Entity;
import net.minecraft.init.Items;
import net.minecraft.item.EnumDyeColor;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityBeacon;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.DimensionType;
import net.minecraft.world.World;
import net.minecraftforge.common.DimensionManager;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
public class ItemWaypointCompass extends Item {
public static final String TAG_POS = "pos";
public static final String TAG_DIMENSION = "dimension";
public static final String TAG_CHECK_BEACON = "check_beacon";
public ItemWaypointCompass() {
this.setHasSubtypes(true);
this.setCreativeTab(CreativeTabs.TOOLS);
this.addPropertyOverride(new ResourceLocation("angle"), new WaypointCompassGetter());
}
@Override
public void onUpdate(ItemStack stack, World world, Entity entityIn, int itemSlot, boolean isSelected) {
if (world.isRemote || !stack.hasTagCompound() || world.getTotalWorldTime() % 160 != 20) {
return;
}
Integer dimension = getDimension(stack);
if (dimension != null) {
if (dimension == world.provider.getDimension()) {
checkPos(stack, world, getPos(stack));
// only update other dimensions half as often
} else if (Config.waypointCompassCrossDimension && world.getTotalWorldTime() % 320 == 20) {
World other = DimensionManager.getWorld(dimension);
// TODO: clear NBT if null?
if (other != null) {
checkPos(stack, other, getPos(stack, dimension, other.provider.getDimension()));
}
}
}
}
/** Checks a position in the world to see if the compass is valid */
private void checkPos(ItemStack stack, World world, BlockPos pos) {
if (pos != null && world.isBlockLoaded(pos, false)) {
TileEntity te = world.getTileEntity(pos);
if (te instanceof TileEntityBeacon) {
// if the beacon beam is just missing, wait another cycle before clearing, this sometimes happens on world load
NBTTagCompound tags = stack.getTagCompound();
if (((TileEntityBeacon)te).isComplete) {
tags.removeTag(TAG_CHECK_BEACON);
} else if (tags.getBoolean(TAG_CHECK_BEACON)) {
clearNBT(stack);
} else {
stack.getTagCompound().setBoolean(TAG_CHECK_BEACON, true);
}
} else {
// if the beacon is missing, clear immediately
clearNBT(stack);
}
}
}
@Override
@SideOnly(Side.CLIENT)
public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flag) {
DimensionType type = getDimensionType(stack);
if (type != null) {
String dimension = type.getName();
String key = "dimension." + dimension + ".name";
if (Util.canTranslate(key)) {
dimension = Util.translate(key);
}
String dimensionTooltip = dimension;
if (Config.waypointCompassAdvTooltip && flag == ITooltipFlag.TooltipFlags.ADVANCED) {
BlockPos pos = getPos(stack);
if (pos != null) {
dimensionTooltip = Util.translateFormatted(getUnlocalizedName() + ".pos.tooltip", dimension, pos.getX(), pos.getZ());
}
}
tooltip.add(dimensionTooltip);
} else {
tooltip.add(TextFormatting.ITALIC + Util.translate(getUnlocalizedName() + ".blank.tooltip"));
}
}
/* Utilities */
/**
* Gets the dimension ID from a stack, or null if it has none
* @param stack Stack containing dimension
* @return Dimension ID, or null if not present+
*/
@Nullable
public static Integer getDimension(ItemStack stack) {
if (!stack.hasTagCompound()) {
return null;
}
NBTTagCompound tags = stack.getTagCompound();
return tags.hasKey(TAG_DIMENSION, 99) ? tags.getInteger(TAG_DIMENSION) : null;
}
/**
* Gets the dimension from a given waypoint compass
* @param stack Compass stack
* @return Dimension type compass points to
*/
@Nullable
public static DimensionType getDimensionType(ItemStack stack) {
Integer dimension = getDimension(stack);
if (dimension != null) {
try {
return DimensionManager.getProviderType(dimension);
} catch (IllegalArgumentException e) {}
}
return null;
}
/**
* Gets the position from the given compass, ignoring dimension differences
* @param stack Compass stack
* @return Position from the compass
*/
@Nullable
public static BlockPos getPos(ItemStack stack) {
if (!stack.hasTagCompound()) {
return null;
}
return TagUtil.readPos(stack.getTagCompound().getCompoundTag(ItemWaypointCompass.TAG_POS));
}
/**
* Gets the position from the given compass, taking dimension differences into account
* @param stack Compass stack
* @param compassDimension Dimension on the compass
* @param worldDimension Dimension in the player's world
* @return Position for the compass, adjusted for the overworld/nether difference
*/
@Nullable
public static BlockPos getPos(ItemStack stack, int compassDimension, int worldDimension) {
BlockPos pos = getPos(stack);
if (pos == null) {
return null;
}
// if the types differ, we may have special logic
if (compassDimension != worldDimension) {
if (!Config.waypointCompassCrossDimension) {
return null;
}
// from nether coords
if (compassDimension == DimensionType.NETHER.getId()) {
return new BlockPos(pos.getX() * 8, pos.getY(), pos.getZ() * 8);
}
// to nether coords
if (worldDimension == DimensionType.NETHER.getId()) {
return new BlockPos(Math.round(pos.getX() / 8f), pos.getY(), Math.round(pos.getZ() / 8f));
}
}
return pos;
}
/**
* Sets the NBT for a compass based on the given world and block position
* @param stack Stack to modify
* @param world World
* @param pos Block pos
*/
public static void setNBT(@Nonnull ItemStack stack, @Nullable World world, @Nullable BlockPos pos) {
if (world == null || pos == null) {
clearNBT(stack);
return;
}
setNBT(stack, world.provider.getDimension(), pos);
}
/** Removes compass related NBT, but keeps the display name */
private static void clearNBT(ItemStack stack) {
if (stack.hasDisplayName()) {
String name = stack.getDisplayName();
stack.setTagCompound(null);
stack.setStackDisplayName(name);
} else {
stack.setTagCompound(null);
}
}
/**
* Copies the waypoint from one compass to another
* @param stack Stack to modify
* @param waypoint Stack to copy from
*/
public static void copyNBT(@Nonnull ItemStack stack, @Nonnull ItemStack waypoint) {
if (!waypoint.hasTagCompound()) {
return;
}
setNBT(stack, getDimension(waypoint), getPos(waypoint));
}
private static void setNBT(@Nonnull ItemStack stack, int dimension, BlockPos pos) {
if (pos == null) {
stack.setTagCompound(null);
return;
}
NBTTagCompound tags = TagUtil.getTagSafe(stack);
tags.setInteger(ItemWaypointCompass.TAG_DIMENSION, dimension);
tags.setTag(ItemWaypointCompass.TAG_POS, TagUtil.writePos(pos));
stack.setTagCompound(tags);
}
/**
* Gets the color of the needle to complement the compass color
* @param color Compass color
* @return Needle color int
*/
public static int getNeedleColor(EnumDyeColor color) {
switch(color) {
case WHITE: return 0xFFC100;
case SILVER: return EnumDyeColor.WHITE.colorValue;
case GRAY: return EnumDyeColor.SILVER.colorValue;
case BLACK: return EnumDyeColor.RED.colorValue;
case RED: return EnumDyeColor.ORANGE.colorValue;
case ORANGE: return EnumDyeColor.YELLOW.colorValue;
case YELLOW: return 0xDBA213;
case LIME: return EnumDyeColor.BROWN.colorValue;
case GREEN: return EnumDyeColor.LIME.colorValue;
case CYAN: return EnumDyeColor.LIGHT_BLUE.colorValue;
case LIGHT_BLUE: return 0x77A9FF;
case BLUE: return 0x7E54FF;
case PURPLE: return EnumDyeColor.MAGENTA.colorValue;
case MAGENTA: return EnumDyeColor.PINK.colorValue;
case PINK: return 0xF2BFCE;
case BROWN: return 0xA59072;
}
return -1;
}
/**
* Checks if the given stack is a valid base as a waypoint compass
* @param stack Stack to check
* @return True if it can be used as a waypoint compass, false otherwise
*/
public static boolean isWaypointCompass(ItemStack stack) {
Item item = stack.getItem();
return item == InspirationsTools.waypointCompass || (!Config.craftWaypointCompass && item == Items.COMPASS);
}
}