minecraft-src/net/minecraft/world/waypoints/WaypointTransmitter.java
2025-09-18 12:27:44 +00:00

198 lines
6.3 KiB
Java

package net.minecraft.world.waypoints;
import java.util.Optional;
import net.minecraft.core.BlockPos;
import net.minecraft.network.protocol.game.ClientboundTrackedWaypointPacket;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.phys.Vec3;
public interface WaypointTransmitter extends Waypoint {
int REALLY_FAR_DISTANCE = 332;
boolean isTransmittingWaypoint();
Optional<WaypointTransmitter.Connection> makeWaypointConnectionWith(ServerPlayer player);
Waypoint.Icon waypointIcon();
static boolean doesSourceIgnoreReceiver(LivingEntity entity, ServerPlayer player) {
if (player.isSpectator()) {
return false;
} else if (!entity.isSpectator() && !entity.hasIndirectPassenger(player)) {
double d = Math.min(entity.getAttributeValue(Attributes.WAYPOINT_TRANSMIT_RANGE), player.getAttributeValue(Attributes.WAYPOINT_RECEIVE_RANGE));
return entity.distanceTo(player) >= d;
} else {
return true;
}
}
static boolean isChunkVisible(ChunkPos pos, ServerPlayer player) {
return player.getChunkTrackingView().isInViewDistance(pos.x, pos.z);
}
static boolean isReallyFar(LivingEntity entity, ServerPlayer player) {
return entity.distanceTo(player) > 332.0F;
}
public interface BlockConnection extends WaypointTransmitter.Connection {
int distanceManhattan();
@Override
default boolean isBroken() {
return this.distanceManhattan() > 1;
}
}
public interface ChunkConnection extends WaypointTransmitter.Connection {
int distanceChessboard();
@Override
default boolean isBroken() {
return this.distanceChessboard() > 1;
}
}
public interface Connection {
void connect();
void disconnect();
void update();
boolean isBroken();
}
public static class EntityAzimuthConnection implements WaypointTransmitter.Connection {
private final LivingEntity source;
private final Waypoint.Icon icon;
private final ServerPlayer receiver;
private float lastAngle;
public EntityAzimuthConnection(LivingEntity source, Waypoint.Icon icon, ServerPlayer reciever) {
this.source = source;
this.icon = icon;
this.receiver = reciever;
Vec3 vec3 = reciever.position().subtract(source.position()).rotateClockwise90();
this.lastAngle = (float)Mth.atan2(vec3.z(), vec3.x());
}
@Override
public boolean isBroken() {
return WaypointTransmitter.doesSourceIgnoreReceiver(this.source, this.receiver)
|| WaypointTransmitter.isChunkVisible(this.source.chunkPosition(), this.receiver)
|| !WaypointTransmitter.isReallyFar(this.source, this.receiver);
}
@Override
public void connect() {
this.receiver.connection.send(ClientboundTrackedWaypointPacket.addWaypointAzimuth(this.source.getUUID(), this.icon, this.lastAngle));
}
@Override
public void disconnect() {
this.receiver.connection.send(ClientboundTrackedWaypointPacket.removeWaypoint(this.source.getUUID()));
}
@Override
public void update() {
Vec3 vec3 = this.receiver.position().subtract(this.source.position()).rotateClockwise90();
float f = (float)Mth.atan2(vec3.z(), vec3.x());
if (Mth.abs(f - this.lastAngle) > 0.008726646F) {
this.receiver.connection.send(ClientboundTrackedWaypointPacket.updateWaypointAzimuth(this.source.getUUID(), this.icon, f));
this.lastAngle = f;
}
}
}
public static class EntityBlockConnection implements WaypointTransmitter.BlockConnection {
private final LivingEntity source;
private final Waypoint.Icon icon;
private final ServerPlayer receiver;
private BlockPos lastPosition;
public EntityBlockConnection(LivingEntity source, Waypoint.Icon icon, ServerPlayer reciever) {
this.source = source;
this.receiver = reciever;
this.icon = icon;
this.lastPosition = source.blockPosition();
}
@Override
public void connect() {
this.receiver.connection.send(ClientboundTrackedWaypointPacket.addWaypointPosition(this.source.getUUID(), this.icon, this.lastPosition));
}
@Override
public void disconnect() {
this.receiver.connection.send(ClientboundTrackedWaypointPacket.removeWaypoint(this.source.getUUID()));
}
@Override
public void update() {
BlockPos blockPos = this.source.blockPosition();
if (blockPos.distManhattan(this.lastPosition) > 0) {
this.receiver.connection.send(ClientboundTrackedWaypointPacket.updateWaypointPosition(this.source.getUUID(), this.icon, blockPos));
this.lastPosition = blockPos;
}
}
@Override
public int distanceManhattan() {
return this.lastPosition.distManhattan(this.source.blockPosition());
}
@Override
public boolean isBroken() {
return WaypointTransmitter.BlockConnection.super.isBroken() || WaypointTransmitter.doesSourceIgnoreReceiver(this.source, this.receiver);
}
}
public static class EntityChunkConnection implements WaypointTransmitter.ChunkConnection {
private final LivingEntity source;
private final Waypoint.Icon icon;
private final ServerPlayer receiver;
private ChunkPos lastPosition;
public EntityChunkConnection(LivingEntity source, Waypoint.Icon icon, ServerPlayer receiver) {
this.source = source;
this.icon = icon;
this.receiver = receiver;
this.lastPosition = source.chunkPosition();
}
@Override
public int distanceChessboard() {
return this.lastPosition.getChessboardDistance(this.source.chunkPosition());
}
@Override
public void connect() {
this.receiver.connection.send(ClientboundTrackedWaypointPacket.addWaypointChunk(this.source.getUUID(), this.icon, this.lastPosition));
}
@Override
public void disconnect() {
this.receiver.connection.send(ClientboundTrackedWaypointPacket.removeWaypoint(this.source.getUUID()));
}
@Override
public void update() {
ChunkPos chunkPos = this.source.chunkPosition();
if (chunkPos.getChessboardDistance(this.lastPosition) > 0) {
this.receiver.connection.send(ClientboundTrackedWaypointPacket.updateWaypointChunk(this.source.getUUID(), this.icon, chunkPos));
this.lastPosition = chunkPos;
}
}
@Override
public boolean isBroken() {
return !WaypointTransmitter.ChunkConnection.super.isBroken() && !WaypointTransmitter.doesSourceIgnoreReceiver(this.source, this.receiver)
? WaypointTransmitter.isChunkVisible(this.lastPosition, this.receiver)
: true;
}
}
}