Skip to content

Commit cc439bb

Browse files
committed
implements fabric-events-interaction-v0 api
1 parent 867ad61 commit cc439bb

21 files changed

Lines changed: 1329 additions & 2 deletions
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--- a/net/minecraft/server/PlayerAdvancements.java
2+
+++ b/net/minecraft/server/PlayerAdvancements.java
3+
@@ -23,6 +_,8 @@
4+
import java.util.Map.Entry;
5+
import java.util.function.BiConsumer;
6+
import javax.annotation.Nullable;
7+
+
8+
+import net.fabricmc.fabric.api.entity.FakePlayer;
9+
import net.minecraft.FileUtil;
10+
import net.minecraft.advancements.Advancement;
11+
import net.minecraft.advancements.AdvancementHolder;
12+
@@ -73,6 +_,10 @@
13+
}
14+
15+
public void setPlayer(ServerPlayer player) {
16+
+ if (player instanceof FakePlayer) {
17+
+ // Prevent fake players with the same UUID as a real player from stealing the real player's advancement tracker.
18+
+ return;
19+
+ }
20+
this.player = player;
21+
}
22+
23+
@@ -167,6 +_,10 @@
24+
}
25+
26+
public boolean award(AdvancementHolder advancement, String criterionKey) {
27+
+ if (player instanceof FakePlayer) {
28+
+ // Prevent granting advancements to fake players.
29+
+ return false;
30+
+ }
31+
boolean flag = false;
32+
AdvancementProgress orStartProgress = this.getOrStartProgress(advancement);
33+
boolean isDone = orStartProgress.isDone();

tenet-server/minecraft-patches/sources/net/minecraft/server/level/ServerPlayer.java.patch

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
--- a/net/minecraft/server/level/ServerPlayer.java
22
+++ b/net/minecraft/server/level/ServerPlayer.java
3-
@@ -24,6 +_,12 @@
3+
@@ -24,6 +_,13 @@
44
import java.util.stream.Collectors;
55
import javax.annotation.Nonnull;
66
import javax.annotation.Nullable;
77
+
8+
+import net.fabricmc.fabric.api.entity.FakePlayer;
89
+import net.fabricmc.fabric.api.entity.event.v1.EntitySleepEvents;
910
+import net.fabricmc.fabric.api.entity.event.v1.ServerEntityCombatEvents;
1011
+import net.fabricmc.fabric.api.entity.event.v1.ServerEntityLevelChangeEvents;
@@ -99,3 +100,14 @@
99100
}
100101

101102
@Override
103+
@@ -2690,6 +_,10 @@
104+
}
105+
106+
private GameType calculateGameModeForNewPlayer(@Nullable GameType gameType) {
107+
+ // Set the default game mode of the fake player to survival, regardless of the servers forced game mode.
108+
+ if ((Object) this instanceof FakePlayer) {
109+
+ return GameType.SURVIVAL;
110+
+ }
111+
GameType forcedGameType = this.server.getForcedGameType();
112+
if (forcedGameType != null) {
113+
return forcedGameType;
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
--- a/net/minecraft/server/level/ServerPlayerGameMode.java
2+
+++ b/net/minecraft/server/level/ServerPlayerGameMode.java
3+
@@ -4,10 +_,17 @@
4+
import java.util.List;
5+
import java.util.Objects;
6+
import javax.annotation.Nullable;
7+
+
8+
+import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
9+
+import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents;
10+
+import net.fabricmc.fabric.api.event.player.UseBlockCallback;
11+
+import net.fabricmc.fabric.api.event.player.UseItemCallback;
12+
import net.minecraft.SharedConstants;
13+
import net.minecraft.advancements.CriteriaTriggers;
14+
import net.minecraft.core.BlockPos;
15+
import net.minecraft.core.Direction;
16+
+import net.minecraft.network.protocol.Packet;
17+
+import net.minecraft.network.protocol.game.ClientGamePacketListener;
18+
import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket;
19+
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
20+
import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket;
21+
@@ -179,6 +_,27 @@
22+
}
23+
24+
public void handleBlockBreakAction(BlockPos pos, ServerboundPlayerActionPacket.Action action, Direction face, int maxBuildHeight, int sequence) {
25+
+ if (action != ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK) return;
26+
+ InteractionResult result = AttackBlockCallback.EVENT.invoker().interact(player, level, InteractionHand.MAIN_HAND, pos, face);
27+
+
28+
+ if (result != InteractionResult.PASS) {
29+
+ // The client might have broken the block on its side, so make sure to let it know.
30+
+ this.player.connection.send(new ClientboundBlockUpdatePacket(level, pos));
31+
+
32+
+ if (level.getBlockState(pos).hasBlockEntity()) {
33+
+ BlockEntity blockEntity = level.getBlockEntity(pos);
34+
+
35+
+ if (blockEntity != null) {
36+
+ Packet<ClientGamePacketListener> updatePacket = blockEntity.getUpdatePacket();
37+
+
38+
+ if (updatePacket != null) {
39+
+ this.player.connection.send(updatePacket);
40+
+ }
41+
+ }
42+
+ }
43+
+
44+
+ return;
45+
+ }
46+
if (!this.player.canInteractWithBlock(pos, 1.0)) {
47+
if (true) return; // Paper - Don't allow digging into unloaded chunks; Don't notify if unreasonably far away
48+
this.debugLogging(pos, false, sequence, "too far");
49+
@@ -388,6 +_,13 @@
50+
org.bukkit.block.BlockState state = bblock.getState();
51+
this.level.captureDrops = new java.util.ArrayList<>();
52+
// CraftBukkit end
53+
+ boolean result = PlayerBlockBreakEvents.BEFORE.invoker().beforeBlockBreak(this.level, this.player, pos, blockState, blockEntity);
54+
+
55+
+ if (!result) {
56+
+ PlayerBlockBreakEvents.CANCELED.invoker().onBlockBreakCanceled(this.level, this.player, pos, blockState, blockEntity);
57+
+
58+
+ return false;
59+
+ }
60+
BlockState blockState1 = block.playerWillDestroy(this.level, pos, blockState, this.player);
61+
boolean flag = this.level.removeBlock(pos, false);
62+
if (SharedConstants.DEBUG_BLOCK_BREAK) {
63+
@@ -395,6 +_,7 @@
64+
}
65+
66+
if (flag) {
67+
+ PlayerBlockBreakEvents.AFTER.invoker().afterBlockBreak(this.level, this.player, pos, blockState1, blockEntity);
68+
block.destroy(this.level, pos, blockState1);
69+
}
70+
71+
@@ -441,6 +_,11 @@
72+
}
73+
74+
public InteractionResult useItem(ServerPlayer player, Level level, ItemStack stack, InteractionHand hand) {
75+
+ InteractionResult result = UseItemCallback.EVENT.invoker().interact(player, level, hand);
76+
+
77+
+ if (result != InteractionResult.PASS) {
78+
+ return result;
79+
+ }
80+
if (this.gameModeForPlayer == GameType.SPECTATOR) {
81+
return InteractionResult.PASS;
82+
} else if (player.getCooldowns().isOnCooldown(stack)) {
83+
@@ -485,6 +_,11 @@
84+
public InteractionHand interactHand;
85+
public ItemStack interactItemStack;
86+
public InteractionResult useItemOn(ServerPlayer player, Level level, ItemStack stack, InteractionHand hand, BlockHitResult hitResult) {
87+
+ InteractionResult result = UseBlockCallback.EVENT.invoker().interact(player, level, hand, hitResult);
88+
+
89+
+ if (result != InteractionResult.PASS) {
90+
+ return result;
91+
+ }
92+
BlockPos blockPos = hitResult.getBlockPos();
93+
BlockState blockState = level.getBlockState(blockPos);
94+
boolean cancelledBlock = false;
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
2+
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
3+
@@ -28,6 +_,9 @@
4+
import java.util.stream.Collectors;
5+
import java.util.stream.Stream;
6+
import javax.annotation.Nullable;
7+
+
8+
+import net.fabricmc.fabric.api.event.player.PlayerPickItemEvents;
9+
+import net.fabricmc.fabric.api.event.player.UseEntityCallback;
10+
import net.minecraft.ChatFormatting;
11+
import net.minecraft.Util;
12+
import net.minecraft.advancements.AdvancementHolder;
13+
@@ -205,6 +_,7 @@
14+
import net.minecraft.world.level.storage.TagValueOutput;
15+
import net.minecraft.world.phys.AABB;
16+
import net.minecraft.world.phys.BlockHitResult;
17+
+import net.minecraft.world.phys.EntityHitResult;
18+
import net.minecraft.world.phys.Vec3;
19+
import net.minecraft.world.phys.shapes.BooleanOp;
20+
import net.minecraft.world.phys.shapes.Shapes;
21+
@@ -1013,7 +_,7 @@
22+
if (serverLevel.isLoaded(blockPos)) {
23+
BlockState blockState = serverLevel.getBlockState(blockPos);
24+
boolean flag = this.player.hasInfiniteMaterials() && packet.includeData();
25+
- ItemStack cloneItemStack = blockState.getCloneItemStack(serverLevel, blockPos, flag);
26+
+ ItemStack cloneItemStack = onPickItemFromBlock(blockState, blockPos, blockState.getCloneItemStack(serverLevel, blockPos, flag), packet);
27+
if (!cloneItemStack.isEmpty()) {
28+
if (flag && this.player.getBukkitEntity().hasPermission("minecraft.nbt.copy")) { // Spigot
29+
addBlockDataToItem(blockState, serverLevel, blockPos, cloneItemStack);
30+
@@ -1025,6 +_,18 @@
31+
}
32+
}
33+
34+
+ public ItemStack onPickItemFromBlock(BlockState state, BlockPos pos, ItemStack original, ServerboundPickItemFromBlockPacket packet) {
35+
+ ItemStack stack = PlayerPickItemEvents.BLOCK.invoker().onPickItemFromBlock(player, pos, state, packet.includeData());
36+
+ if (stack == null) {
37+
+ return original;
38+
+ } else if (!stack.isEmpty()) {
39+
+ this.tryPickItem(stack, pos, null, packet.includeData());
40+
+ }
41+
+
42+
+ // Prevent vanilla data-inclusion behavior
43+
+ return ItemStack.EMPTY;
44+
+ }
45+
+
46+
private static void addBlockDataToItem(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack) {
47+
BlockEntity blockEntity = state.hasBlockEntity() ? level.getBlockEntity(pos) : null;
48+
if (blockEntity != null) {
49+
@@ -1044,13 +_,26 @@
50+
PacketUtils.ensureRunningOnSameThread(packet, this, serverLevel);
51+
Entity entityOrPart = serverLevel.getEntityOrPart(packet.id());
52+
if (entityOrPart != null && this.player.canInteractWithEntity(entityOrPart, 3.0)) {
53+
- ItemStack pickResult = entityOrPart.getPickResult();
54+
+ ItemStack pickResult = onPickItemFromEntity(entityOrPart, entityOrPart.getPickResult(), packet);
55+
if (pickResult != null && !pickResult.isEmpty()) {
56+
this.tryPickItem(pickResult, null, entityOrPart, packet.includeData()); // Paper - Extend PlayerPickItemEvent API
57+
}
58+
}
59+
}
60+
61+
+ public ItemStack onPickItemFromEntity(Entity entity, ItemStack original, ServerboundPickItemFromEntityPacket packet) {
62+
+ ItemStack stack = PlayerPickItemEvents.ENTITY.invoker().onPickItemFromEntity(player, entity, packet.includeData());
63+
+
64+
+ if (stack == null) {
65+
+ return original;
66+
+ } else if (!stack.isEmpty()) {
67+
+ this.tryPickItem(stack, null, entity, packet.includeData());
68+
+ }
69+
+
70+
+ // Prevent vanilla data-inclusion behavior
71+
+ return ItemStack.EMPTY;
72+
+ }
73+
+
74+
private void tryPickItem(ItemStack stack, @Nullable BlockPos blockPos, @Nullable Entity entity, boolean includeData) { // Paper - Extend PlayerPickItemEvent API
75+
if (stack.isItemEnabled(this.player.level().enabledFeatures())) {
76+
Inventory inventory = this.player.getInventory();
77+
@@ -2826,11 +_,21 @@
78+
79+
@Override
80+
public void onInteraction(InteractionHand hand) {
81+
+ InteractionResult result = UseEntityCallback.EVENT.invoker().interact(player, player.level(), hand, target, null);
82+
+ if (result != InteractionResult.PASS) {
83+
+ return;
84+
+ }
85+
this.performInteraction(hand, Player::interactOn, new PlayerInteractEntityEvent(ServerGamePacketListenerImpl.this.getCraftPlayer(), target.getBukkitEntity(), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand))); // CraftBukkit
86+
}
87+
88+
@Override
89+
public void onInteraction(InteractionHand hand, Vec3 interactionLocation) {
90+
+ EntityHitResult hitResult = new EntityHitResult(target, interactionLocation.add(target.getX(), target.getY(), target.getZ()));
91+
+ InteractionResult result = UseEntityCallback.EVENT.invoker().interact(player, player.level(), hand, target, hitResult);
92+
+
93+
+ if (result != InteractionResult.PASS) {
94+
+ return;
95+
+ }
96+
this.performInteraction(
97+
hand, (player, entity, interactionHand) -> entity.interactAt(player, interactionLocation, interactionHand), new PlayerInteractAtEntityEvent(ServerGamePacketListenerImpl.this.getCraftPlayer(), target.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(interactionLocation), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand)) // CraftBukkit
98+
);

tenet-server/minecraft-patches/sources/net/minecraft/world/entity/player/Player.java.patch

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,29 @@
11
--- a/net/minecraft/world/entity/player/Player.java
22
+++ b/net/minecraft/world/entity/player/Player.java
3-
@@ -13,6 +_,8 @@
3+
@@ -13,6 +_,9 @@
44
import java.util.function.Predicate;
55
import javax.annotation.Nonnull;
66
import javax.annotation.Nullable;
77
+
88
+import net.fabricmc.fabric.api.entity.event.v1.EntitySleepEvents;
9+
+import net.fabricmc.fabric.api.event.player.AttackEntityCallback;
910
import net.minecraft.Util;
1011
import net.minecraft.core.BlockPos;
1112
import net.minecraft.core.Direction;
13+
@@ -1020,6 +_,13 @@
14+
}
15+
16+
public void attack(Entity target) {
17+
+ if ((Object) this instanceof ServerPlayer player) {
18+
+ InteractionResult result = AttackEntityCallback.EVENT.invoker().interact(player, player.level(), InteractionHand.MAIN_HAND, target, null);
19+
+
20+
+ if (result != InteractionResult.PASS) {
21+
+ return;
22+
+ }
23+
+ }
24+
// Paper start - PlayerAttackEntityEvent
25+
boolean willAttack = target.isAttackable() && !target.skipAttackInteraction(this); // Vanilla logic
26+
io.papermc.paper.event.player.PrePlayerAttackEntityEvent playerAttackEntityEvent = new io.papermc.paper.event.player.PrePlayerAttackEntityEvent(
1227
@@ -1344,6 +_,11 @@
1328

1429
public Either<Player.BedSleepingProblem, Unit> startSleepInBed(BlockPos bedPos, boolean force) {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--- a/net/minecraft/world/item/ItemStack.java
2+
+++ b/net/minecraft/world/item/ItemStack.java
3+
@@ -19,6 +_,8 @@
4+
import java.util.function.UnaryOperator;
5+
import java.util.stream.Stream;
6+
import javax.annotation.Nullable;
7+
+
8+
+import net.fabricmc.fabric.api.event.player.ItemEvents;
9+
import net.minecraft.ChatFormatting;
10+
import net.minecraft.advancements.CriteriaTriggers;
11+
import net.minecraft.core.BlockPos;
12+
@@ -547,6 +_,11 @@
13+
ItemStack itemStack = this.copy();
14+
boolean flag = this.getUseDuration(player) <= 0;
15+
InteractionResult interactionResult = this.getItem().use(level, player, hand);
16+
+ InteractionResult result = ItemEvents.USE.invoker().use(level, player, hand);
17+
+
18+
+ if (result != null) {
19+
+ return result;
20+
+ }
21+
return (InteractionResult)(flag && interactionResult instanceof InteractionResult.Success success
22+
? success.heldItemTransformedTo(
23+
success.heldItemTransformedTo() == null
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--- a/net/minecraft/world/level/block/state/BlockBehaviour.java
2+
+++ b/net/minecraft/world/level/block/state/BlockBehaviour.java
3+
@@ -16,6 +_,8 @@
4+
import java.util.function.ToIntFunction;
5+
import java.util.stream.Stream;
6+
import javax.annotation.Nullable;
7+
+
8+
+import net.fabricmc.fabric.api.event.player.BlockEvents;
9+
import net.minecraft.Util;
10+
import net.minecraft.core.BlockPos;
11+
import net.minecraft.core.Direction;
12+
@@ -899,10 +_,19 @@
13+
}
14+
15+
public InteractionResult useItemOn(ItemStack stack, Level level, Player player, InteractionHand hand, BlockHitResult hitResult) {
16+
+ InteractionResult result = BlockEvents.USE_ITEM_ON.invoker().useItemOn(stack, this.asState(), level, hitResult.getBlockPos(), player, hand, hitResult);
17+
+
18+
+ if (result != null) {
19+
+ return result;
20+
+ }
21+
return this.getBlock().useItemOn(stack, this.asState(), level, hitResult.getBlockPos(), player, hand, hitResult);
22+
}
23+
24+
public InteractionResult useWithoutItem(Level level, Player player, BlockHitResult hitResult) {
25+
+ InteractionResult result = BlockEvents.USE_WITHOUT_ITEM.invoker().useWithoutItem(this.asState(), level, hitResult.getBlockPos(), player, hitResult);
26+
+ if (result != null) {
27+
+ return result;
28+
+ }
29+
return this.getBlock().useWithoutItem(this.asState(), level, hitResult.getBlockPos(), player, hitResult);
30+
}
31+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package net.fabricmc.fabric.api.block;
18+
19+
import net.minecraft.core.BlockPos;
20+
import net.minecraft.core.Direction;
21+
import net.minecraft.world.InteractionHand;
22+
import net.minecraft.world.entity.player.Player;
23+
import net.minecraft.world.level.Level;
24+
import net.minecraft.world.level.block.state.BlockState;
25+
26+
import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
27+
28+
/**
29+
* Convenience interface for blocks which listen to "break interactions" (left-click).
30+
*
31+
* @deprecated Use {@link AttackBlockCallback} instead and check for the block.
32+
* This gives more control over the different cancellation outcomes.
33+
*/
34+
@Deprecated
35+
public interface BlockAttackInteractionAware {
36+
/**
37+
* @return True if the block accepted the player and it should no longer be processed.
38+
*/
39+
boolean onAttackInteraction(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, Direction direction);
40+
}

0 commit comments

Comments
 (0)