Skip to content

Commit

Permalink
feat✨(rules): 添加 fakePlayerInteractLikeClient 规则以修复假人交互与客户端行为的不一致
Browse files Browse the repository at this point in the history
在假人的use命令中调用interact()和interactAt()函数并获取其ActionResult,但是部分实体(本次主要是盔甲架、船和矿车)的交互结果在客户端和服务器端存在不一致。本规则将把假人的行为与正常客户端行为同步。
在未来遇到任何类似问题时,同样可以
  • Loading branch information
wendavid552 committed Aug 17, 2024
1 parent 329d7b6 commit 1715cf0
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/main/java/club/mcams/carpet/AmsServerSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,9 @@ public class AmsServerSettings {
@Rule(categories = {AMS, FEATURE})
public static boolean mitePearl = false;

@Rule(categories = {AMS, FEATURE, BUGFIX})
public static boolean fakePlayerInteractLikeClient = false;

//#if MC<12000
@GameVersion(version = "Minecraft < 1.20")
@Rule(categories = {AMS, FEATURE})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* This file is part of the Carpet AMS Addition project, licensed under the
* GNU Lesser General Public License v3.0
*
* Copyright (C) 2024 A Minecraft Server and contributors
*
* Carpet AMS Addition is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Carpet AMS Addition is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Carpet AMS Addition. If not, see <https://www.gnu.org/licenses/>.
*/

package club.mcams.carpet.mixin.rule.fakePlayerInteractLikeClient;

import net.minecraft.entity.vehicle.BoatEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;

@Mixin(BoatEntity.class)
public interface BoatEntityInvoker {
@Accessor("ticksUnderwater")
float getTicksUnderwater();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* This file is part of the Carpet AMS Addition project, licensed under the
* GNU Lesser General Public License v3.0
*
* Copyright (C) 2024 A Minecraft Server and contributors
*
* Carpet AMS Addition is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Carpet AMS Addition is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Carpet AMS Addition. If not, see <https://www.gnu.org/licenses/>.
*/

package club.mcams.carpet.mixin.rule.fakePlayerInteractLikeClient;

import club.mcams.carpet.AmsServerSettings;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.entity.Entity;
import net.minecraft.entity.decoration.ArmorStandEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.vehicle.BoatEntity;
import net.minecraft.entity.vehicle.MinecartEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.math.Vec3d;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;

@Mixin(targets = "carpet.helpers.EntityPlayerActionPack$ActionType$1")
public class EntityPlayerActionPackActionTypeMixin {
@WrapOperation(
method = "execute(Lnet/minecraft/server/network/ServerPlayerEntity;Lcarpet/helpers/EntityPlayerActionPack$Action;)Z",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/entity/Entity;interactAt(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/util/math/Vec3d;Lnet/minecraft/util/Hand;)Lnet/minecraft/util/ActionResult;"
)
)
private ActionResult onInteractAt(Entity instance, PlayerEntity player, Vec3d hitPos, Hand hand, Operation<ActionResult> original) {
//有一部分是直接在interact里面进行一些操作,所以先call一遍
ActionResult originalResult = original.call(instance, player, hitPos, hand);
if (AmsServerSettings.fakePlayerInteractLikeClient) {
if (instance instanceof ArmorStandEntity) {
ArmorStandEntity stand = (ArmorStandEntity) instance;
ItemStack handItem = player.getStackInHand(hand);
if (!stand.isMarker() && handItem.getItem() != Items.NAME_TAG && !player.isSpectator()) {
//1.21之类的版本应改为SUCCESS_SERVER,但是就这里而言应该效果一致
return ActionResult.CONSUME;
}
}
}
return originalResult;
}

@WrapOperation(
method = "execute(Lnet/minecraft/server/network/ServerPlayerEntity;Lcarpet/helpers/EntityPlayerActionPack$Action;)Z",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/network/ServerPlayerEntity;interact(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/Hand;)Lnet/minecraft/util/ActionResult;"
)
)
private ActionResult onInteract(ServerPlayerEntity player, Entity entity, Hand hand, Operation<ActionResult> original) {
//有一部分是直接在interact里面进行一些操作,所以先call一遍
ActionResult originalResult = original.call(player, entity, hand);
if (AmsServerSettings.fakePlayerInteractLikeClient) {
if (entity instanceof BoatEntity) {
BoatEntity boat = (BoatEntity) entity;
ItemStack handItem = player.getStackInHand(hand);
if (!player.shouldCancelInteraction() && ((BoatEntityInvoker) boat).getTicksUnderwater() < 60.0F) {
return ActionResult.SUCCESS;
}
}
else if (entity instanceof MinecartEntity) {
MinecartEntity minecart = (MinecartEntity) entity;
if (!player.shouldCancelInteraction() && !minecart.hasPassengers()) {
return ActionResult.SUCCESS;
}
}
}
return originalResult;
}
}
2 changes: 2 additions & 0 deletions src/main/resources/amscarpet.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
"rule.experimentalContentCheckDisabled.ToggleableFeatureMixin",
"rule.extinguishedCampfire_campfireSmokeParticleDisabled.CampfireBlockMixin",
"rule.fakePeace.AbstractBlockStateMixin",
"rule.fakePlayerInteractLikeClient.BoatEntityInvoker",
"rule.fakePlayerInteractLikeClient.EntityPlayerActionPackActionTypeMixin",
"rule.fakePlayerNoScoreboardCounter.PlayerEntityMixin",
"rule.fakePlayerPickUpController.ItemEntityMixin",
"rule.fancyFakePlayerName.CarpetMod_PlayerCommandMixin",
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/assets/carpetamsaddition/lang/en_us.yml
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,8 @@ carpetamsaddition:
desc: Preventing Endermen from picking up blocks
mitePearl:
desc: Using an Ender Pearl each time will spawn an Endermite
fakePlayerInteractLikeClient:
desc: Fix some cases that fake player interact differently from the client
stackableDiscounts:
desc: Reintroduce the stackable discounts feature in <23w31a
enderPearlSoundEffect:
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/assets/carpetamsaddition/lang/zh_cn.yml
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,9 @@ carpetamsaddition:
stackableDiscounts:
name: 村民折扣叠加
desc: 重新引入<23w31a的打骨折机制,让治疗村民的折扣可以叠加
fakePlayerInteractLikeClient:
name: 假人交互同步客户端行为
desc: 修复几个假人和盔甲架、矿车、船在特定情况下与客户端相应行为结果不一样的问题
commandGetSystemInfo:
name: 获取系统信息
desc: 使用“/getSystemInfo”命令获取服务器的系统信息
Expand Down

0 comments on commit 1715cf0

Please sign in to comment.