From 7094e0d83210c68d535b26cc0b7f3b23fd3a5049 Mon Sep 17 00:00:00 2001 From: Atsuihsio <842960157@qq.com> Date: Mon, 3 Jun 2024 04:01:59 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=BB=E6=A4=8DTACZ=E7=9A=84=E5=BB=B6?= =?UTF-8?q?=E8=BF=9F=E8=A1=A5=E5=81=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../target/api/entity/ITargetEntity.java | 2 + .../target/entity/ProjectileEntity.java | 5 +- .../target/event/HitboxHelperEvent.java | 23 ++++++ .../target/headshot/BoundingBoxManager.java | 25 ------ .../mcreator/target/tools/HitboxHelper.java | 79 +++++++++++++++++++ 5 files changed, 107 insertions(+), 27 deletions(-) create mode 100644 src/main/java/net/mcreator/target/event/HitboxHelperEvent.java create mode 100644 src/main/java/net/mcreator/target/tools/HitboxHelper.java diff --git a/src/main/java/net/mcreator/target/api/entity/ITargetEntity.java b/src/main/java/net/mcreator/target/api/entity/ITargetEntity.java index 6649fb7e2..94781e7bd 100644 --- a/src/main/java/net/mcreator/target/api/entity/ITargetEntity.java +++ b/src/main/java/net/mcreator/target/api/entity/ITargetEntity.java @@ -5,6 +5,8 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.phys.EntityHitResult; +//from TACZ + /** * 用于进行一些并非 {@link LivingEntity} 但是可被子弹击中的特殊实体的处理 */ diff --git a/src/main/java/net/mcreator/target/entity/ProjectileEntity.java b/src/main/java/net/mcreator/target/entity/ProjectileEntity.java index 2eeddbae7..accaa49b1 100644 --- a/src/main/java/net/mcreator/target/entity/ProjectileEntity.java +++ b/src/main/java/net/mcreator/target/entity/ProjectileEntity.java @@ -2,6 +2,7 @@ package net.mcreator.target.entity; import net.mcreator.target.TargetMod; import net.mcreator.target.api.entity.ITargetEntity; +import net.mcreator.target.tools.HitboxHelper; import net.mcreator.target.headshot.BoundingBoxManager; import net.mcreator.target.headshot.IHeadshotBox; import net.mcreator.target.init.TargetModDamageTypes; @@ -154,8 +155,8 @@ public class ProjectileEntity extends Entity implements IEntityAdditionalSpawnDa // hitbox 延迟补偿。只有射击者是玩家(且被击中者也是玩家)才进行此类延迟补偿计算 if (entity instanceof ServerPlayer player && this.shooter instanceof ServerPlayer serverPlayerOwner) { int ping = Mth.floor((serverPlayerOwner.latency / 1000.0) * 20.0 + 0.5); - boundingBox = BoundingBoxManager.getBoundingBox(player, ping); - velocity = BoundingBoxManager.getVelocity(player, ping); + boundingBox = HitboxHelper.getBoundingBox(player, ping); + velocity = HitboxHelper.getVelocity(player, ping); } // 应用蹲伏导致的 hitbox 变形 boundingBox = boundingBox.expandTowards(0, expandHeight, 0); diff --git a/src/main/java/net/mcreator/target/event/HitboxHelperEvent.java b/src/main/java/net/mcreator/target/event/HitboxHelperEvent.java new file mode 100644 index 000000000..aad23b6e5 --- /dev/null +++ b/src/main/java/net/mcreator/target/event/HitboxHelperEvent.java @@ -0,0 +1,23 @@ +package net.mcreator.target.event; + +import net.mcreator.target.tools.HitboxHelper; +import net.minecraftforge.event.TickEvent; +import net.minecraftforge.event.entity.player.PlayerEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.LogicalSide; +import net.minecraftforge.fml.common.Mod; + +@Mod.EventBusSubscriber +public class HitboxHelperEvent { + @SubscribeEvent(receiveCanceled = true) + public static void onPlayerTick(TickEvent.PlayerTickEvent event) { + if (event.side == LogicalSide.SERVER && event.phase == TickEvent.Phase.END) { + HitboxHelper.onPlayerTick(event.player); + } + } + + @SubscribeEvent(receiveCanceled = true) + public static void onPlayerLoggedOut(PlayerEvent.PlayerLoggedOutEvent event) { + HitboxHelper.onPlayerLoggedOut(event.getEntity()); + } +} diff --git a/src/main/java/net/mcreator/target/headshot/BoundingBoxManager.java b/src/main/java/net/mcreator/target/headshot/BoundingBoxManager.java index e4010ddc7..5342a3cd7 100644 --- a/src/main/java/net/mcreator/target/headshot/BoundingBoxManager.java +++ b/src/main/java/net/mcreator/target/headshot/BoundingBoxManager.java @@ -26,12 +26,6 @@ public class BoundingBoxManager { private static final Map, IHeadshotBox> headshotBoxes = new HashMap<>(); private static final WeakHashMap> playerBoxes = new WeakHashMap<>(); - private static final WeakHashMap> PLAYER_POSITION = new WeakHashMap<>(); - // 玩家命中箱缓存表 - private static final WeakHashMap> PLAYER_HITBOXES = new WeakHashMap<>(); - // 玩家速度缓存表 - private static final WeakHashMap> PLAYER_VELOCITY = new WeakHashMap<>(); - static { /* Player */ registerHeadshotBox(EntityType.PLAYER, (entity) -> { @@ -124,16 +118,6 @@ public class BoundingBoxManager { playerBoxes.remove(event.getEntity()); } - public static Vec3 getPlayerVelocity(Player entity) { - LinkedList positions = PLAYER_POSITION.computeIfAbsent(entity, player -> new LinkedList<>()); - if (positions.size() > 1) { - Vec3 currPos = positions.getFirst(); - Vec3 prevPos = positions.getLast(); - return new Vec3(currPos.x - prevPos.x, currPos.y - prevPos.y, currPos.z - prevPos.z); - } - return new Vec3(0, 0, 0); - } - public static AABB getBoundingBox(Player entity, int ping) { if (playerBoxes.containsKey(entity)) { LinkedList boxes = playerBoxes.get(entity); @@ -142,13 +126,4 @@ public class BoundingBoxManager { } return entity.getBoundingBox(); } - - public static Vec3 getVelocity(Player entity, int ping) { - if (PLAYER_VELOCITY.containsKey(entity)) { - LinkedList velocities = PLAYER_VELOCITY.get(entity); - int index = Mth.clamp(ping, 0, velocities.size() - 1); - return velocities.get(index); - } - return getPlayerVelocity(entity); - } } \ No newline at end of file diff --git a/src/main/java/net/mcreator/target/tools/HitboxHelper.java b/src/main/java/net/mcreator/target/tools/HitboxHelper.java new file mode 100644 index 000000000..80cd85f1a --- /dev/null +++ b/src/main/java/net/mcreator/target/tools/HitboxHelper.java @@ -0,0 +1,79 @@ +package net.mcreator.target.tools; + +import net.minecraft.util.Mth; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +import java.util.LinkedList; +import java.util.WeakHashMap; + +//from TACZ +public final class HitboxHelper { + // 玩家位置缓存表 + private static final WeakHashMap> PLAYER_POSITION = new WeakHashMap<>(); + // 玩家命中箱缓存表 + private static final WeakHashMap> PLAYER_HITBOXES = new WeakHashMap<>(); + // 玩家速度缓存表 + private static final WeakHashMap> PLAYER_VELOCITY = new WeakHashMap<>(); + // 命中箱缓存 Tick 上限 + private static final int SAVE_TICK = Mth.floor(1000 / 1000 * 20 + 0.5); + + public static void onPlayerTick(Player player) { + if (player.isSpectator()) { + PLAYER_POSITION.remove(player); + PLAYER_HITBOXES.remove(player); + PLAYER_VELOCITY.remove(player); + return; + } + LinkedList positions = PLAYER_POSITION.computeIfAbsent(player, p -> new LinkedList<>()); + LinkedList boxes = PLAYER_HITBOXES.computeIfAbsent(player, p -> new LinkedList<>()); + LinkedList velocities = PLAYER_VELOCITY.computeIfAbsent(player, p -> new LinkedList<>()); + positions.addFirst(player.position()); + boxes.addFirst(player.getBoundingBox()); + velocities.addFirst(getPlayerVelocity(player)); + // Position 用于速度计算,所以只需要缓存 2 个位置 + if (positions.size() > 2) { + positions.removeLast(); + } + // 命中箱和速度缓存数量限制 + if (boxes.size() > SAVE_TICK) { + boxes.removeLast(); + velocities.removeLast(); + } + } + + public static void onPlayerLoggedOut(Player player) { + PLAYER_POSITION.remove(player); + PLAYER_HITBOXES.remove(player); + PLAYER_VELOCITY.remove(player); + } + + public static Vec3 getPlayerVelocity(Player entity) { + LinkedList positions = PLAYER_POSITION.computeIfAbsent(entity, player -> new LinkedList<>()); + if (positions.size() > 1) { + Vec3 currPos = positions.getFirst(); + Vec3 prevPos = positions.getLast(); + return new Vec3(currPos.x - prevPos.x, currPos.y - prevPos.y, currPos.z - prevPos.z); + } + return new Vec3(0, 0, 0); + } + + public static AABB getBoundingBox(Player entity, int ping) { + if (PLAYER_HITBOXES.containsKey(entity)) { + LinkedList boxes = PLAYER_HITBOXES.get(entity); + int index = Mth.clamp(ping, 0, boxes.size() - 1); + return boxes.get(index); + } + return entity.getBoundingBox(); + } + + public static Vec3 getVelocity(Player entity, int ping) { + if (PLAYER_VELOCITY.containsKey(entity)) { + LinkedList velocities = PLAYER_VELOCITY.get(entity); + int index = Mth.clamp(ping, 0, velocities.size() - 1); + return velocities.get(index); + } + return getPlayerVelocity(entity); + } +}