Skip to content

Commit

Permalink
Fix: track with player sensor correctly, don't freeze if player goes …
Browse files Browse the repository at this point in the history
…offscreen
  • Loading branch information
Gegy committed Nov 22, 2024
1 parent 4356ce9 commit d7408f2
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import net.neoforged.neoforge.event.entity.EntityLeaveLevelEvent;
import org.joml.Vector3f;

import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -158,18 +159,26 @@ public static <T extends LivingEntity> void captureModelPose(T entity, EntityMod
return;
}
if (model instanceof HumanoidModel<T> humanoidModel) {
CAPTURED_SCREEN_POS.add(capturePlayerPose(entity, poseStack, humanoidModel));
CapturedScreenBoxes capture = capturePlayerPose(entity, poseStack, humanoidModel);
if (capture != null) {
CAPTURED_SCREEN_POS.add(capture);
}
}
}

@Nullable
private static CapturedScreenBoxes capturePlayerPose(LivingEntity entity, PoseStack poseStack, HumanoidModel<?> humanoidModel) {
poseStack.pushPose();
humanoidModel.head.translateAndRotate(poseStack);
ScreenBox faceBox = toScreenBox(poseStack, -4.0f, -8.0f, -4.0f, 4.0f, 0.0f, 4.0f);
poseStack.popPose();
return new CapturedScreenBoxes(entity.getUUID(), faceBox);
if (faceBox != null) {
return new CapturedScreenBoxes(entity.getUUID(), faceBox);
}
return null;
}

@Nullable
private static ScreenBox toScreenBox(PoseStack poseStack, float x0, float y0, float z0, float x1, float y1, float z1) {
Vector3f[] vertices = {
toScreenPos(poseStack, x0, y0, z0),
Expand All @@ -186,6 +195,11 @@ private static ScreenBox toScreenBox(PoseStack poseStack, float x0, float y0, fl
float maxX = -Float.MAX_VALUE;
float maxY = -Float.MAX_VALUE;
for (Vector3f vertex : vertices) {
if (vertex.z >= 1.0f || vertex.z <= 0.1f) {
return null;
} else if (vertex.x <= -2.0f || vertex.x >= 2.0f || vertex.y <= -2.0f || vertex.y >= 2.0f) {
return null;
}
minX = Math.min(minX, vertex.x);
minY = Math.min(minY, vertex.y);
maxX = Math.max(maxX, vertex.x);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import net.neoforged.neoforge.event.entity.player.PlayerEvent;
import net.neoforged.neoforge.event.tick.PlayerTickEvent;

import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
Expand All @@ -33,30 +34,23 @@ public static void onPlayerLoggedOut(PlayerEvent.PlayerLoggedOutEvent event) {
@SubscribeEvent
public static void onPlayerTick(PlayerTickEvent.Post event) {
if (event.getEntity() instanceof ServerPlayer player) {
if (player.tickCount % REFRESH_INTERVAL_TICKS != 0) {
return;
}
ItemStack headItem = player.getItemBySlot(EquipmentSlot.HEAD);
PlayerSensor sensor = headItem.get(ExtraDataComponents.PLAYER_SENSOR);
if (sensor != null) {
SensorState sensorState = SENSOR_STATES.computeIfAbsent(player.getUUID(), playerId -> new SensorState(sensor));
sensorState.activeSensor = sensor;
if (player.tickCount % REFRESH_INTERVAL_TICKS == 0) {
sensorState.refresh(player);
}
} else {
SensorState sensorState = SENSOR_STATES.remove(player.getUUID());
if (sensorState != null) {
sensorState.clearAllMarked(player);
}
SensorState sensorState = SENSOR_STATES.get(player.getUUID());
if (sensorState != null) {
sensorState.refresh(player, sensor);
}
}
}

@SubscribeEvent
public static void onPlayerTracked(PlayerEvent.StartTracking event) {
if (event.getEntity() instanceof ServerPlayer player && event.getTarget() instanceof ServerPlayer target) {
SensorState state = SENSOR_STATES.get(player.getUUID());
if (state != null) {
state.startTracking(player, target);
}
SensorState state = SENSOR_STATES.computeIfAbsent(player.getUUID(), playerId -> new SensorState());
state.startTracking(player, target);
}
}

Expand All @@ -71,23 +65,22 @@ public static void onPlayerUntracked(PlayerEvent.StopTracking event) {
}

private static class SensorState {
@Nullable
private PlayerSensor activeSensor;
private final Set<UUID> trackedPlayers = new HashSet<>();
private final Set<UUID> markedPlayers = new HashSet<>();

private SensorState(PlayerSensor activeSensor) {
this.activeSensor = activeSensor;
}
public void refresh(ServerPlayer player, @Nullable PlayerSensor sensor) {
activeSensor = sensor;

public void refresh(ServerPlayer player) {
ServerLevel level = player.serverLevel();

markedPlayers.removeIf(playerId -> {
if (!(level.getPlayerByUUID(playerId) instanceof ServerPlayer target)) {
// Shouldn't get here - but the client probably forgot about the player if we did too
return true;
}
if (!activeSensor.matches(target)) {
if (activeSensor == null || !activeSensor.matches(target)) {
player.connection.send(new ClientboundSetEntityMarkedPacket(target.getId(), Optional.empty()));
return true;
}
Expand All @@ -98,7 +91,7 @@ public void refresh(ServerPlayer player) {
if (markedPlayers.contains(playerId)) {
continue;
}
if (level.getPlayerByUUID(playerId) instanceof ServerPlayer target && activeSensor.matches(target)) {
if (level.getPlayerByUUID(playerId) instanceof ServerPlayer target && activeSensor != null && activeSensor.matches(target)) {
markedPlayers.add(playerId);
player.connection.send(new ClientboundSetEntityMarkedPacket(target.getId(), Optional.of(activeSensor.appearance())));
}
Expand All @@ -107,22 +100,13 @@ public void refresh(ServerPlayer player) {

public void startTracking(ServerPlayer player, ServerPlayer target) {
trackedPlayers.add(target.getUUID());
refresh(player);
refresh(player, activeSensor);
}

public void stopTracking(ServerPlayer target) {
// Client will forget the entity, we don't need to send anything
trackedPlayers.remove(target.getUUID());
markedPlayers.remove(target.getUUID());
}

public void clearAllMarked(ServerPlayer player) {
for (UUID playerId : markedPlayers) {
if (player.level().getPlayerByUUID(playerId) instanceof ServerPlayer target) {
player.connection.send(new ClientboundSetEntityMarkedPacket(target.getId(), Optional.empty()));
}
}
markedPlayers.clear();
}
}
}

0 comments on commit d7408f2

Please sign in to comment.