Skip to content

Commit

Permalink
Merge pull request #74 from zly2006/use-item-on-player-fix
Browse files Browse the repository at this point in the history
fix: use item on players
  • Loading branch information
Gu-ZT authored Oct 24, 2024
2 parents 98ff846 + 12d61db commit 1e509e3
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin({ItemFrame.class})
@Mixin(ItemFrame.class)
abstract class ItemFrameMixin extends Entity {
public ItemFrameMixin(EntityType<?> entityType, Level level) {
super(entityType, level);
Expand Down
37 changes: 15 additions & 22 deletions src/main/java/dev/dubhe/gugle/carpet/mixin/PlayerMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import dev.dubhe.gugle.carpet.GcaExtension;
import dev.dubhe.gugle.carpet.GcaSetting;
import dev.dubhe.gugle.carpet.api.tools.text.ComponentTranslate;
import dev.dubhe.gugle.carpet.tools.ClientUtils;
import dev.dubhe.gugle.carpet.tools.FakePlayerEnderChestContainer;
import dev.dubhe.gugle.carpet.tools.FakePlayerInventoryContainer;
import dev.dubhe.gugle.carpet.tools.FakePlayerInventoryMenu;
Expand Down Expand Up @@ -40,30 +41,22 @@ private void tick(CallbackInfo ci) {

@WrapOperation(method = "interactOn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;interact(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/InteractionHand;)Lnet/minecraft/world/InteractionResult;"))
private InteractionResult interactOn(Entity entity, Player player, InteractionHand hand, Operation<InteractionResult> original) {
// 此处不能直接使用entity instanceof EntityPlayerMPFake
// 第一次entity instanceof Player是为了排除掉非玩家实体,避免影响非玩家实体的交互逻辑,第二次instanceof在interact方法中,用来判断交互玩家是否为假玩家
// 在服务端,entity instanceof Player可能是多余的
// 但是在客户端中,如果直接entity instanceof EntityPlayerMPFake,那么在右键假玩家时,客户端并不知道当前交互的玩家是不是假玩家
// 因此右键交互时可能会应用玩家手中的物品功能,例如使用熔岩桶右键玩家时可能在假玩家位置放置岩浆,使用风弹右键玩家时可能发射风弹
// 所以客户端在交互前要先判断一下当前交互的实体是不是玩家,这用来防止意外的使用物品功能
// 尽管这带来了一些新的问题,例如玩家飞行时不能对着玩家使用烟花,不能对着玩家吃食物,但是这相比意外使用物品是小问题
if (entity instanceof Player interactPlayer && (GcaSetting.openFakePlayerInventory || GcaSetting.openFakePlayerEnderChest)) {
return interact(interactPlayer, player, hand, original);
}
return original.call(entity, player, hand);
}

@Unique
private InteractionResult interact(Player entity, Player player, InteractionHand hand, Operation<InteractionResult> original) {
InteractionResult result;
if (entity instanceof EntityPlayerMPFake fakePlayer) {
// 打开物品栏
result = this.openInventory(player, fakePlayer);
if (player.level().isClientSide()) {
// 客户端在交互前要先判断一下当前交互的实体是不是玩家,这用来防止意外的使用物品功能
if (entity instanceof Player && ClientUtils.isFakePlayer(player)) {
return InteractionResult.CONSUME;
}
} else {
// 怎么判断一个客户端玩家是不是假玩家?
return InteractionResult.SUCCESS;
if ((GcaSetting.openFakePlayerInventory || GcaSetting.openFakePlayerEnderChest) && entity instanceof EntityPlayerMPFake fakePlayer) {
// 打开物品栏
InteractionResult result = this.openInventory(player, fakePlayer);
if (result != InteractionResult.PASS) {
player.stopUsingItem();
return result;
}
}
}
return result == InteractionResult.PASS ? original.call(entity, player, hand) : result;
return original.call(entity, player, hand);
}

@Unique
Expand Down
26 changes: 26 additions & 0 deletions src/main/java/dev/dubhe/gugle/carpet/tools/ClientUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package dev.dubhe.gugle.carpet.tools;

import carpet.patches.EntityPlayerMPFake;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.PlayerInfo;
import net.minecraft.world.entity.player.Player;
import org.jetbrains.annotations.Nullable;

import java.util.UUID;

public class ClientUtils {
private static @Nullable PlayerInfo getPlayerInfo(UUID uuid) {
if (Minecraft.getInstance().getConnection() != null) {
return Minecraft.getInstance().getConnection().getPlayerInfo(uuid);
}
return null;
}

public static boolean isFakePlayer(Player player) {
if (player.level().isClientSide()) {
PlayerInfo info = getPlayerInfo(player.getUUID());
return info != null && info.getLatency() == 0;
}
return player instanceof EntityPlayerMPFake;
}
}

0 comments on commit 1e509e3

Please sign in to comment.