/
PlayerInteractEvent.java
359 lines (321 loc) · 12.5 KB
/
PlayerInteractEvent.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
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
package net.minecraftforge.event.entity.player;
import com.google.common.base.Preconditions;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraftforge.fml.relauncher.Side;
import javax.annotation.Nullable;
import static net.minecraftforge.fml.common.eventhandler.Event.Result.DEFAULT;
import static net.minecraftforge.fml.common.eventhandler.Event.Result.DENY;
/**
* PlayerInteractEvent is fired when a player interacts in some way.
* All subclasses are fired on {@link MinecraftForge#EVENT_BUS}.
* See the individual documentation on each subevent for more details.
**/
public class PlayerInteractEvent extends PlayerEvent
{
private final EnumHand hand;
private final ItemStack stack;
private final BlockPos pos;
private final EnumFacing face;
private PlayerInteractEvent(EntityPlayer player, EnumHand hand, ItemStack stack, BlockPos pos, EnumFacing face)
{
super(Preconditions.checkNotNull(player, "Null player in PlayerInteractEvent!"));
this.hand = Preconditions.checkNotNull(hand, "Null hand in PlayerInteractEvent!");
this.stack = stack;
this.pos = Preconditions.checkNotNull(pos, "Null position in PlayerInteractEvent!");
this.face = face;
}
/**
* This event is fired on both sides whenever a player right clicks an entity.
*
* "Interact at" is an interact where the local vector (which part of the entity you clicked) is known.
* The state of this event affects whether {@link Entity#applyPlayerInteraction} is called.
* If {@link Entity#applyPlayerInteraction} returns {@link net.minecraft.util.EnumActionResult#SUCCESS}, then processing ends.
* Otherwise processing will continue to {@link EntityInteract}
*
* Canceling the event clientside will cause processing to continue to {@link EntityInteract},
* while canceling serverside will simply do no further processing.
*/
@Cancelable
public static class EntityInteractSpecific extends PlayerInteractEvent
{
private final Vec3d localPos;
private final Entity target;
public EntityInteractSpecific(EntityPlayer player, EnumHand hand, ItemStack stack, Entity target, Vec3d localPos)
{
super(player, hand, stack, new BlockPos(target), null);
this.localPos = localPos;
this.target = target;
}
/**
* Returns the local interaction position. This is a 3D vector, where (0, 0, 0) is centered exactly at the
* center of the entity's bounding box at their feet. This means the X and Z values will be in the range
* [-width / 2, width / 2] while Y values will be in the range [0, height]
* @return The local position
*/
public Vec3d getLocalPos()
{
return localPos;
}
public Entity getTarget()
{
return target;
}
}
/**
* This event is fired on both sides when the player right clicks an entity.
* It is responsible for all general entity interactions.
*
* This event is fired completely independently of the above {@link EntityInteractSpecific}, except for the case
* where the above call to {@link Entity#applyPlayerInteraction} returns {@link net.minecraft.util.EnumActionResult#SUCCESS}.
* In that case, general entity interactions, and hence this event, will not be called. See the above javadoc for more details.
*
* This event's state affects whether {@link Entity#processInitialInteract} and {@link net.minecraft.item.Item#itemInteractionForEntity} are called.
*
* Canceling the event clientside will cause processing to continue to {@link RightClickItem},
* while canceling serverside will simply do no further processing.
*/
@Cancelable
public static class EntityInteract extends PlayerInteractEvent
{
private final Entity target;
public EntityInteract(EntityPlayer player, EnumHand hand, ItemStack stack, Entity target)
{
super(player, hand, stack, new BlockPos(target), null);
this.target = target;
}
public Entity getTarget()
{
return target;
}
}
/**
* This event is fired on both sides whenever the player right clicks while targeting a block.
* This event controls which of {@link net.minecraft.block.Block#onBlockActivated} and/or {@link net.minecraft.item.Item#onItemUse}
* will be called after {@link net.minecraft.item.Item#onItemUseFirst} is called.
* Canceling the event will cause none of the above three to be called.
* There are various results to this event, see the getters below.
* Note that handling things differently on the client vs server may cause desynchronizations!
*/
@Cancelable
public static class RightClickBlock extends PlayerInteractEvent
{
private Result useBlock = DEFAULT;
private Result useItem = DEFAULT;
private final Vec3d hitVec;
public RightClickBlock(EntityPlayer player, EnumHand hand, ItemStack stack,
BlockPos pos, EnumFacing face, Vec3d hitVec) {
super(player, hand, stack, pos, face);
this.hitVec = hitVec;
}
/**
* @return The hit vector of this click
*/
public Vec3d getHitVec()
{
return hitVec;
}
/**
* @return If {@link net.minecraft.block.Block#onBlockActivated} should be called
*/
public Result getUseBlock()
{
return useBlock;
}
/**
* @return If {@link net.minecraft.item.Item#onItemUse} should be called
*/
public Result getUseItem()
{
return useItem;
}
/**
* DENY: Block will never be used.
* DEFAULT: Default behaviour (sneak will not use block, unless all items return true in {@link net.minecraft.item.Item#doesSneakBypassUse}).
* ALLOW: Block will always be used, regardless of sneaking and doesSneakBypassUse.
*/
public void setUseBlock(Result triggerBlock)
{
this.useBlock = triggerBlock;
}
/**
* DENY: The item will never be used.
* DEFAULT: The item will be used if the block fails.
* ALLOW: The item will always be used.
*/
public void setUseItem(Result triggerItem)
{
this.useItem = triggerItem;
}
@Override
public void setCanceled(boolean canceled)
{
super.setCanceled(canceled);
if (canceled)
{
useBlock = DENY;
useItem = DENY;
}
}
}
/**
* This event is fired on both sides before the player triggers {@link net.minecraft.item.Item#onItemRightClick}.
* Note that this is NOT fired if the player is targeting a block. For that case, see {@link RightClickBlock}.
* Canceling the event clientside causes processing to continue to the other hands,
* while canceling serverside will simply do no further processing.
*/
@Cancelable
public static class RightClickItem extends PlayerInteractEvent
{
public RightClickItem(EntityPlayer player, EnumHand hand, ItemStack stack)
{
super(player, hand, stack, new BlockPos(player), null);
}
}
/**
* This event is fired on the client side when the player right clicks empty space with an empty hand.
* The server is not aware of when the client right clicks empty space with an empty hand, you will need to tell the server yourself.
* This event cannot be canceled.
*/
public static class RightClickEmpty extends PlayerInteractEvent
{
public RightClickEmpty(EntityPlayer player, EnumHand hand)
{
super(player, hand, null, new BlockPos(player), null);
}
}
/**
* This event is fired when a player left clicks while targeting a block.
* This event controls which of {@link net.minecraft.block.Block#onBlockClicked} and/or the item harvesting methods will be called
* Canceling the event will cause none of the above noted methods to be called.
* There are various results to this event, see the getters below.
*
* Note that if the event is canceled and the player holds down left mouse, the event will continue to fire.
* This is due to how vanilla calls the left click handler methods.
*
* Also note that creative mode directly breaks the block without running any other logic.
* Therefore, in creative mode, {@link #setUseBlock} and {@link #setUseItem} have no effect.
*/
@Cancelable
public static class LeftClickBlock extends PlayerInteractEvent
{
private Result useBlock = DEFAULT;
private Result useItem = DEFAULT;
private final Vec3d hitVec;
public LeftClickBlock(EntityPlayer player, BlockPos pos, EnumFacing face, Vec3d hitVec)
{
super(player, EnumHand.MAIN_HAND, player.getHeldItem(EnumHand.MAIN_HAND), pos, face);
this.hitVec = hitVec;
}
/**
* @return The local hit vector of this click
*/
public Vec3d getHitVec()
{
return hitVec;
}
/**
* @return If {@link net.minecraft.block.Block#onBlockClicked} should be called. Changing this has no effect in creative mode
*/
public Result getUseBlock()
{
return useBlock;
}
/**
* @return If the block should be attempted to be mined with the current item. Changing this has no effect in creative mode
*/
public Result getUseItem()
{
return useItem;
}
public void setUseBlock(Result triggerBlock)
{
this.useBlock = triggerBlock;
}
public void setUseItem(Result triggerItem)
{
this.useItem = triggerItem;
}
@Override
public void setCanceled(boolean canceled)
{
super.setCanceled(canceled);
if (canceled)
{
useBlock = DENY;
useItem = DENY;
}
}
}
/**
* This event is fired on the client side when the player left clicks empty space with any ItemStack.
* The server is not aware of when the client left clicks empty space, you will need to tell the server yourself.
* This event cannot be canceled.
*/
public static class LeftClickEmpty extends PlayerInteractEvent
{
public LeftClickEmpty(EntityPlayer player, ItemStack stack)
{
super(player, EnumHand.MAIN_HAND, stack, new BlockPos(player), null);
}
}
/**
* @return The hand involved in this interaction. Will never be null.
*/
public EnumHand getHand()
{
return hand;
}
/**
* @return The itemstack involved in this interaction, or null if the hand was empty.
*/
@Nullable
public ItemStack getItemStack()
{
return stack;
}
/**
* If the interaction was on an entity, will be a BlockPos centered on the entity.
* If the interaction was on a block, will be the position of that block.
* Otherwise, will be a BlockPos centered on the player.
* Will never be null.
* @return The position involved in this interaction.
*/
public BlockPos getPos()
{
return pos;
}
/**
* @return The face involved in this interaction. For all non-block interactions, this will return null.
*/
@Nullable
public EnumFacing getFace()
{
return face;
}
/**
* @return Convenience method to get the world of this interaction.
*/
public World getWorld()
{
return getEntityPlayer().getEntityWorld();
}
/**
* @return The effective, i.e. logical, side of this interaction. This will be {@link Side#CLIENT} on the client thread, and {@link Side#SERVER} on the server thread.
*/
public Side getSide()
{
return getWorld().isRemote ? Side.CLIENT : Side.SERVER;
}
}