formalize the three states of player interaction events

This commit is contained in:
asie 2018-12-16 08:40:16 +01:00
parent 686cba9c1b
commit 19bc18104d
2 changed files with 20 additions and 3 deletions

View file

@ -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

View file

@ -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;