forked from FabricMC/fabric
implement PlayerInteractionEvents, BreakInteractable convienence itf
This commit is contained in:
parent
2f14adefaa
commit
8dbce0f433
9 changed files with 354 additions and 1 deletions
|
@ -31,7 +31,7 @@ minecraft {
|
|||
|
||||
dependencies {
|
||||
minecraft "com.mojang:minecraft:18w48b"
|
||||
mappings "net.fabricmc:pomf:18w48b.7"
|
||||
mappings "net.fabricmc:pomf:18w48b.16"
|
||||
modCompile "net.fabricmc:fabric-loader:0.1.0.49"
|
||||
}
|
||||
|
||||
|
|
49
src/main/java/net/fabricmc/fabric/FabricAPI.java
Normal file
49
src/main/java/net/fabricmc/fabric/FabricAPI.java
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.block.BreakInteractable;
|
||||
import net.fabricmc.fabric.events.PlayerInteractionEvent;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.network.ClientPlayerInteractionManager;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Facing;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class FabricAPI implements ModInitializer {
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
PlayerInteractionEvent.BREAK_BLOCK.register((player, world, hand, pos, facing) -> {
|
||||
BlockState state = world.getBlockState(pos);
|
||||
if (state instanceof BreakInteractable) {
|
||||
if (((BreakInteractable) state).onBreakInteract(state, world, pos, player, hand, facing)) {
|
||||
return ActionResult.FAILURE;
|
||||
}
|
||||
} else if (state.getBlock() instanceof BreakInteractable) {
|
||||
if (((BreakInteractable) state.getBlock()).onBreakInteract(state, world, pos, player, hand, facing)) {
|
||||
return ActionResult.FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return ActionResult.PASS;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.block;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Facing;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
/**
|
||||
* Convienence interface for blocks which listen to "break interactions" (left-click).
|
||||
*/
|
||||
public interface BreakInteractable {
|
||||
/**
|
||||
* @return True if the block accepted the interaction and it should no longer be processed.
|
||||
*/
|
||||
boolean onBreakInteract(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, Facing facing);
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.events;
|
||||
|
||||
import net.fabricmc.fabric.util.HandlerList;
|
||||
import net.fabricmc.fabric.util.HandlerRegistry;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Facing;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
/**
|
||||
* This is a class for INTERACTION EVENTS (think left-clicking/right-clicking). For block placement/break
|
||||
* events, look elsewhere - this just handles the interaction!
|
||||
*
|
||||
* 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!
|
||||
*/
|
||||
public final class PlayerInteractionEvent {
|
||||
@FunctionalInterface
|
||||
public interface Block {
|
||||
ActionResult interact(PlayerEntity player, World world, Hand hand, BlockPos pos, Facing facing);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface BlockPositioned {
|
||||
ActionResult interact(PlayerEntity player, World world, Hand hand, BlockPos pos, Facing facing, float hitX, float hitY, float hitZ);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Item {
|
||||
ActionResult interact(PlayerEntity player, World world, Hand hand);
|
||||
}
|
||||
|
||||
public static HandlerRegistry<Block> BREAK_BLOCK = new HandlerList<>();
|
||||
public static HandlerRegistry<BlockPositioned> INTERACT_BLOCK = new HandlerList<>();
|
||||
public static HandlerRegistry<Item> INTERACT_ITEM = new HandlerList<>();
|
||||
|
||||
private PlayerInteractionEvent() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.mixin.events;
|
||||
|
||||
import net.fabricmc.fabric.events.PlayerInteractionEvent;
|
||||
import net.fabricmc.fabric.util.HandlerList;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||
import net.minecraft.client.network.ClientPlayerEntity;
|
||||
import net.minecraft.client.network.ClientPlayerInteractionManager;
|
||||
import net.minecraft.client.network.packet.BlockUpdateClientPacket;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.network.ServerPlayerInteractionManager;
|
||||
import net.minecraft.server.network.packet.PlayerInteractBlockServerPacket;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Facing;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.GameMode;
|
||||
import net.minecraft.world.World;
|
||||
import org.lwjgl.system.CallbackI;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(ClientPlayerInteractionManager.class)
|
||||
public class MixinClientPlayerInteractionManager {
|
||||
@Shadow
|
||||
private MinecraftClient client;
|
||||
@Shadow
|
||||
private ClientPlayNetworkHandler networkHandler;
|
||||
@Shadow
|
||||
private GameMode gameMode;
|
||||
|
||||
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/world/GameMode;isCreative()Z", ordinal = 0), method = "attackBlock", cancellable = true)
|
||||
public void attackBlock(BlockPos pos, Facing facing, CallbackInfoReturnable<Boolean> info) {
|
||||
for (Object handler : ((HandlerList<PlayerInteractionEvent.Block>) PlayerInteractionEvent.BREAK_BLOCK).getBackingArray()) {
|
||||
PlayerInteractionEvent.Block event = (PlayerInteractionEvent.Block) handler;
|
||||
ActionResult result = event.interact(client.player, client.world, Hand.MAIN, pos, facing);
|
||||
if (result != ActionResult.PASS) {
|
||||
info.setReturnValue(result == ActionResult.SUCCESS);
|
||||
info.cancel();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/world/GameMode;isCreative()Z", ordinal = 0), method = "method_2902", cancellable = true)
|
||||
public void method_2902(BlockPos pos, Facing facing, CallbackInfoReturnable<Boolean> info) {
|
||||
if (!gameMode.isCreative()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Object handler : ((HandlerList<PlayerInteractionEvent.Block>) PlayerInteractionEvent.BREAK_BLOCK).getBackingArray()) {
|
||||
PlayerInteractionEvent.Block event = (PlayerInteractionEvent.Block) handler;
|
||||
ActionResult result = event.interact(client.player, client.world, Hand.MAIN, pos, facing);
|
||||
if (result != ActionResult.PASS) {
|
||||
info.setReturnValue(result == ActionResult.SUCCESS);
|
||||
info.cancel();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;getStackInHand(Lnet/minecraft/util/Hand;)Lnet/minecraft/item/ItemStack;", ordinal = 0), method = "interactBlock", cancellable = true)
|
||||
public void interactBlock(ClientPlayerEntity player, ClientWorld world, BlockPos pos, Facing facing, Vec3d vec, Hand hand, CallbackInfoReturnable<ActionResult> info) {
|
||||
Object[] backingArray = ((HandlerList<PlayerInteractionEvent.BlockPositioned>) PlayerInteractionEvent.INTERACT_BLOCK).getBackingArray();
|
||||
if (backingArray.length > 0) {
|
||||
float hitX = (float) (vec.x - pos.getX());
|
||||
float hitY = (float) (vec.y - pos.getY());
|
||||
float hitZ = (float) (vec.z - pos.getZ());
|
||||
|
||||
for (Object handler : backingArray) {
|
||||
PlayerInteractionEvent.BlockPositioned event = (PlayerInteractionEvent.BlockPositioned) handler;
|
||||
ActionResult result = event.interact(player, world, hand, pos, facing, hitX, hitY, hitZ);
|
||||
if (result != ActionResult.PASS) {
|
||||
if (result == ActionResult.SUCCESS) {
|
||||
this.networkHandler.sendPacket(new PlayerInteractBlockServerPacket(pos, facing, hand, hitX, hitY, hitZ));
|
||||
}
|
||||
info.setReturnValue(result);
|
||||
info.cancel();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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)
|
||||
public void interactItem(PlayerEntity player, World world, Hand hand, CallbackInfoReturnable<ActionResult> info) {
|
||||
for (Object handler : ((HandlerList<PlayerInteractionEvent.Item>) PlayerInteractionEvent.INTERACT_ITEM).getBackingArray()) {
|
||||
PlayerInteractionEvent.Item event = (PlayerInteractionEvent.Item) handler;
|
||||
ActionResult result = event.interact(player, world, hand);
|
||||
if (result != ActionResult.PASS) {
|
||||
info.setReturnValue(result);
|
||||
info.cancel();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.mixin.events;
|
||||
|
||||
import net.fabricmc.fabric.events.PlayerInteractionEvent;
|
||||
import net.fabricmc.fabric.util.HandlerList;
|
||||
import net.minecraft.client.network.packet.BlockUpdateClientPacket;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.network.ServerPlayerInteractionManager;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Facing;
|
||||
import net.minecraft.world.World;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(ServerPlayerInteractionManager.class)
|
||||
public class MixinServerPlayerInteractionManager {
|
||||
@Shadow
|
||||
public World world;
|
||||
@Shadow
|
||||
public ServerPlayerEntity player;
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "method_14263", cancellable = true)
|
||||
public void startBlockBreak(BlockPos pos, Facing facing, CallbackInfo info) {
|
||||
for (Object handler : ((HandlerList<PlayerInteractionEvent.Block>) PlayerInteractionEvent.BREAK_BLOCK).getBackingArray()) {
|
||||
PlayerInteractionEvent.Block event = (PlayerInteractionEvent.Block) handler;
|
||||
ActionResult result = event.interact(player, world, Hand.MAIN, pos, facing);
|
||||
if (result != ActionResult.PASS) {
|
||||
// The client might have broken the block on its side, so make sure to let it know.
|
||||
this.player.networkHandler.sendPacket(new BlockUpdateClientPacket(world, pos));
|
||||
info.cancel();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "interactBlock", cancellable = true)
|
||||
public void interactBlock(PlayerEntity player, World world, ItemStack stack, Hand hand, BlockPos pos, Facing facing, float hitX, float hitY, float hitZ, CallbackInfoReturnable<ActionResult> info) {
|
||||
for (Object handler : ((HandlerList<PlayerInteractionEvent.BlockPositioned>) PlayerInteractionEvent.INTERACT_BLOCK).getBackingArray()) {
|
||||
PlayerInteractionEvent.BlockPositioned event = (PlayerInteractionEvent.BlockPositioned) handler;
|
||||
ActionResult result = event.interact(player, world, hand, pos, facing, hitX, hitY, hitZ);
|
||||
if (result != ActionResult.PASS) {
|
||||
info.setReturnValue(result);
|
||||
info.cancel();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "interactItem", cancellable = true)
|
||||
public void interactItem(PlayerEntity player, World world, ItemStack stack, Hand hand, CallbackInfoReturnable<ActionResult> info) {
|
||||
for (Object handler : ((HandlerList<PlayerInteractionEvent.Item>) PlayerInteractionEvent.INTERACT_ITEM).getBackingArray()) {
|
||||
PlayerInteractionEvent.Item event = (PlayerInteractionEvent.Item) handler;
|
||||
ActionResult result = event.interact(player, world, hand);
|
||||
if (result != ActionResult.PASS) {
|
||||
info.setReturnValue(result);
|
||||
info.cancel();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
"version": "0.0.2",
|
||||
"side": "universal",
|
||||
"initializers": [
|
||||
"net.fabricmc.fabric.FabricAPI"
|
||||
],
|
||||
"mixins": {
|
||||
"client": "net.fabricmc.fabric.mixins.client.json",
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
"package": "net.fabricmc.fabric.mixin",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"mixins": [
|
||||
"events.MixinClientPlayerInteractionManager",
|
||||
"networking.MixinClientPlayNetworkHandler",
|
||||
"registry.client.MixinBlockColorMap",
|
||||
"registry.client.MixinItemColorMap",
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
"compatibilityLevel": "JAVA_8",
|
||||
"mixins": [
|
||||
"commands.MixinServerCommandManager",
|
||||
"events.MixinServerPlayerInteractionManager",
|
||||
"helpers.MixinBlock",
|
||||
"helpers.MixinBlockBuilder",
|
||||
"helpers.MixinItem",
|
||||
|
|
Loading…
Reference in a new issue