移植TACZ的延迟补偿
This commit is contained in:
parent
7707a24a3d
commit
7094e0d832
5 changed files with 107 additions and 27 deletions
|
@ -5,6 +5,8 @@ import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.entity.LivingEntity;
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
import net.minecraft.world.phys.EntityHitResult;
|
import net.minecraft.world.phys.EntityHitResult;
|
||||||
|
|
||||||
|
//from TACZ
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用于进行一些并非 {@link LivingEntity} 但是可被子弹击中的特殊实体的处理
|
* 用于进行一些并非 {@link LivingEntity} 但是可被子弹击中的特殊实体的处理
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -2,6 +2,7 @@ package net.mcreator.target.entity;
|
||||||
|
|
||||||
import net.mcreator.target.TargetMod;
|
import net.mcreator.target.TargetMod;
|
||||||
import net.mcreator.target.api.entity.ITargetEntity;
|
import net.mcreator.target.api.entity.ITargetEntity;
|
||||||
|
import net.mcreator.target.tools.HitboxHelper;
|
||||||
import net.mcreator.target.headshot.BoundingBoxManager;
|
import net.mcreator.target.headshot.BoundingBoxManager;
|
||||||
import net.mcreator.target.headshot.IHeadshotBox;
|
import net.mcreator.target.headshot.IHeadshotBox;
|
||||||
import net.mcreator.target.init.TargetModDamageTypes;
|
import net.mcreator.target.init.TargetModDamageTypes;
|
||||||
|
@ -154,8 +155,8 @@ public class ProjectileEntity extends Entity implements IEntityAdditionalSpawnDa
|
||||||
// hitbox 延迟补偿。只有射击者是玩家(且被击中者也是玩家)才进行此类延迟补偿计算
|
// hitbox 延迟补偿。只有射击者是玩家(且被击中者也是玩家)才进行此类延迟补偿计算
|
||||||
if (entity instanceof ServerPlayer player && this.shooter instanceof ServerPlayer serverPlayerOwner) {
|
if (entity instanceof ServerPlayer player && this.shooter instanceof ServerPlayer serverPlayerOwner) {
|
||||||
int ping = Mth.floor((serverPlayerOwner.latency / 1000.0) * 20.0 + 0.5);
|
int ping = Mth.floor((serverPlayerOwner.latency / 1000.0) * 20.0 + 0.5);
|
||||||
boundingBox = BoundingBoxManager.getBoundingBox(player, ping);
|
boundingBox = HitboxHelper.getBoundingBox(player, ping);
|
||||||
velocity = BoundingBoxManager.getVelocity(player, ping);
|
velocity = HitboxHelper.getVelocity(player, ping);
|
||||||
}
|
}
|
||||||
// 应用蹲伏导致的 hitbox 变形
|
// 应用蹲伏导致的 hitbox 变形
|
||||||
boundingBox = boundingBox.expandTowards(0, expandHeight, 0);
|
boundingBox = boundingBox.expandTowards(0, expandHeight, 0);
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,12 +26,6 @@ public class BoundingBoxManager {
|
||||||
private static final Map<EntityType<?>, IHeadshotBox<?>> headshotBoxes = new HashMap<>();
|
private static final Map<EntityType<?>, IHeadshotBox<?>> headshotBoxes = new HashMap<>();
|
||||||
private static final WeakHashMap<Player, LinkedList<AABB>> playerBoxes = new WeakHashMap<>();
|
private static final WeakHashMap<Player, LinkedList<AABB>> playerBoxes = new WeakHashMap<>();
|
||||||
|
|
||||||
private static final WeakHashMap<Player, LinkedList<Vec3>> PLAYER_POSITION = new WeakHashMap<>();
|
|
||||||
// 玩家命中箱缓存表
|
|
||||||
private static final WeakHashMap<Player, LinkedList<AABB>> PLAYER_HITBOXES = new WeakHashMap<>();
|
|
||||||
// 玩家速度缓存表
|
|
||||||
private static final WeakHashMap<Player, LinkedList<Vec3>> PLAYER_VELOCITY = new WeakHashMap<>();
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
/* Player */
|
/* Player */
|
||||||
registerHeadshotBox(EntityType.PLAYER, (entity) -> {
|
registerHeadshotBox(EntityType.PLAYER, (entity) -> {
|
||||||
|
@ -124,16 +118,6 @@ public class BoundingBoxManager {
|
||||||
playerBoxes.remove(event.getEntity());
|
playerBoxes.remove(event.getEntity());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Vec3 getPlayerVelocity(Player entity) {
|
|
||||||
LinkedList<Vec3> 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) {
|
public static AABB getBoundingBox(Player entity, int ping) {
|
||||||
if (playerBoxes.containsKey(entity)) {
|
if (playerBoxes.containsKey(entity)) {
|
||||||
LinkedList<AABB> boxes = playerBoxes.get(entity);
|
LinkedList<AABB> boxes = playerBoxes.get(entity);
|
||||||
|
@ -142,13 +126,4 @@ public class BoundingBoxManager {
|
||||||
}
|
}
|
||||||
return entity.getBoundingBox();
|
return entity.getBoundingBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Vec3 getVelocity(Player entity, int ping) {
|
|
||||||
if (PLAYER_VELOCITY.containsKey(entity)) {
|
|
||||||
LinkedList<Vec3> velocities = PLAYER_VELOCITY.get(entity);
|
|
||||||
int index = Mth.clamp(ping, 0, velocities.size() - 1);
|
|
||||||
return velocities.get(index);
|
|
||||||
}
|
|
||||||
return getPlayerVelocity(entity);
|
|
||||||
}
|
|
||||||
}
|
}
|
79
src/main/java/net/mcreator/target/tools/HitboxHelper.java
Normal file
79
src/main/java/net/mcreator/target/tools/HitboxHelper.java
Normal file
|
@ -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, LinkedList<Vec3>> PLAYER_POSITION = new WeakHashMap<>();
|
||||||
|
// 玩家命中箱缓存表
|
||||||
|
private static final WeakHashMap<Player, LinkedList<AABB>> PLAYER_HITBOXES = new WeakHashMap<>();
|
||||||
|
// 玩家速度缓存表
|
||||||
|
private static final WeakHashMap<Player, LinkedList<Vec3>> 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<Vec3> positions = PLAYER_POSITION.computeIfAbsent(player, p -> new LinkedList<>());
|
||||||
|
LinkedList<AABB> boxes = PLAYER_HITBOXES.computeIfAbsent(player, p -> new LinkedList<>());
|
||||||
|
LinkedList<Vec3> 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<Vec3> 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<AABB> 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<Vec3> velocities = PLAYER_VELOCITY.get(entity);
|
||||||
|
int index = Mth.clamp(ping, 0, velocities.size() - 1);
|
||||||
|
return velocities.get(index);
|
||||||
|
}
|
||||||
|
return getPlayerVelocity(entity);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue