forked from FabricMC/fabric
formalize the three states of player interaction events
This commit is contained in:
parent
686cba9c1b
commit
19bc18104d
2 changed files with 20 additions and 3 deletions
|
@ -32,10 +32,16 @@ import net.minecraft.world.World;
|
|||
*
|
||||
* These hook in BEFORE the spectator checks, so make sure to check for the player's game mode as well!
|
||||
*
|
||||
* In general, the events return an ActionResult with the following side effects:
|
||||
* - SUCCESS cancels further processing and, on the client, sends a packet to the server.
|
||||
* - PASS falls back to further processing.
|
||||
* - FAIL cancels further processing and does not send a packet to the server.
|
||||
*
|
||||
* CURRENT LIMITATIONS:
|
||||
*
|
||||
* - INTERACT_BLOCK/INTERACT_ITEM do not expect the ItemStack instance in the player's held hand to change!
|
||||
* If you must do that, consider returning an ActionResult.SUCCESS and re-emitting the event in some manner!
|
||||
* - ATTACK_BLOCK does not let you control the packet sending process yet.
|
||||
*/
|
||||
public final class PlayerInteractionEvent {
|
||||
@FunctionalInterface
|
||||
|
|
|
@ -26,6 +26,8 @@ import net.minecraft.client.world.ClientWorld;
|
|||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.server.network.packet.PlayerInteractBlockServerPacket;
|
||||
import net.minecraft.server.network.packet.PlayerInteractEntityServerPacket;
|
||||
import net.minecraft.server.network.packet.PlayerInteractItemServerPacket;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.HitResult;
|
||||
|
@ -100,11 +102,14 @@ public class MixinClientPlayerInteractionManager {
|
|||
}
|
||||
}
|
||||
|
||||
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;getStackInHand(Lnet/minecraft/util/Hand;)Lnet/minecraft/item/ItemStack;", ordinal = 0), method = "interactItem", cancellable = true)
|
||||
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/Packet;)V", ordinal = 0), method = "interactItem", cancellable = true)
|
||||
public void interactItem(PlayerEntity player, World world, Hand hand, CallbackInfoReturnable<ActionResult> info) {
|
||||
for (PlayerInteractionEvent.Item handler : ((HandlerArray<PlayerInteractionEvent.Item>) PlayerInteractionEvent.INTERACT_ITEM).getBackingArray()) {
|
||||
ActionResult result = handler.interact(player, world, hand);
|
||||
if (result != ActionResult.PASS) {
|
||||
if (result == ActionResult.SUCCESS) {
|
||||
this.networkHandler.sendPacket(new PlayerInteractItemServerPacket(hand));
|
||||
}
|
||||
info.setReturnValue(result);
|
||||
info.cancel();
|
||||
return;
|
||||
|
@ -112,18 +117,21 @@ public class MixinClientPlayerInteractionManager {
|
|||
}
|
||||
}
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "attackEntity", cancellable = true)
|
||||
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/Packet;)V", ordinal = 0), method = "attackEntity", cancellable = true)
|
||||
public void attackEntity(PlayerEntity player, Entity entity, CallbackInfo info) {
|
||||
for (PlayerInteractionEvent.Entity handler : ((HandlerArray<PlayerInteractionEvent.Entity>) PlayerInteractionEvent.ATTACK_ENTITY).getBackingArray()) {
|
||||
ActionResult result = handler.interact(player, player.getEntityWorld(), Hand.MAIN /* TODO */, entity);
|
||||
if (result != ActionResult.PASS) {
|
||||
if (result == ActionResult.SUCCESS) {
|
||||
this.networkHandler.sendPacket(new PlayerInteractEntityServerPacket(entity));
|
||||
}
|
||||
info.cancel();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "interactEntityAtLocation", cancellable = true)
|
||||
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/Packet;)V", ordinal = 0), method = "interactEntityAtLocation", cancellable = true)
|
||||
public void interactEntityAtLocation(PlayerEntity player, Entity entity, HitResult hitResult, Hand hand, CallbackInfoReturnable<ActionResult> info) {
|
||||
// TODO: Remove double Vec3d creation?
|
||||
Vec3d hitVec = new Vec3d(hitResult.pos.x - entity.x, hitResult.pos.y - entity.y, hitResult.pos.z - entity.z);
|
||||
|
@ -131,6 +139,9 @@ public class MixinClientPlayerInteractionManager {
|
|||
for (PlayerInteractionEvent.EntityPositioned handler : ((HandlerArray<PlayerInteractionEvent.EntityPositioned>) PlayerInteractionEvent.INTERACT_ENTITY_POSITIONED).getBackingArray()) {
|
||||
ActionResult result = handler.interact(player, player.getEntityWorld(), hand, entity, hitVec);
|
||||
if (result != ActionResult.PASS) {
|
||||
if (result == ActionResult.SUCCESS) {
|
||||
this.networkHandler.sendPacket(new PlayerInteractEntityServerPacket(entity, hand, hitVec));
|
||||
}
|
||||
info.setReturnValue(result);
|
||||
info.cancel();
|
||||
return;
|
||||
|
|
Loading…
Reference in a new issue