324 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			324 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package net.minecraft.world.waypoints;
 | |
| 
 | |
| import com.mojang.datafixers.util.Either;
 | |
| import com.mojang.logging.LogUtils;
 | |
| import io.netty.buffer.ByteBuf;
 | |
| import java.util.UUID;
 | |
| import net.minecraft.core.UUIDUtil;
 | |
| import net.minecraft.core.Vec3i;
 | |
| import net.minecraft.network.FriendlyByteBuf;
 | |
| import net.minecraft.network.VarInt;
 | |
| import net.minecraft.network.codec.StreamCodec;
 | |
| import net.minecraft.util.Mth;
 | |
| import net.minecraft.world.entity.Entity;
 | |
| import net.minecraft.world.level.ChunkPos;
 | |
| import net.minecraft.world.level.Level;
 | |
| import net.minecraft.world.phys.Vec3;
 | |
| import org.apache.commons.lang3.function.TriFunction;
 | |
| import org.slf4j.Logger;
 | |
| 
 | |
| public abstract class TrackedWaypoint implements Waypoint {
 | |
| 	static final Logger LOGGER = LogUtils.getLogger();
 | |
| 	public static StreamCodec<ByteBuf, TrackedWaypoint> STREAM_CODEC = StreamCodec.ofMember(TrackedWaypoint::write, TrackedWaypoint::read);
 | |
| 	protected final Either<UUID, String> identifier;
 | |
| 	private final Waypoint.Icon icon;
 | |
| 	private final TrackedWaypoint.Type type;
 | |
| 
 | |
| 	TrackedWaypoint(Either<UUID, String> identifier, Waypoint.Icon icon, TrackedWaypoint.Type type) {
 | |
| 		this.identifier = identifier;
 | |
| 		this.icon = icon;
 | |
| 		this.type = type;
 | |
| 	}
 | |
| 
 | |
| 	public Either<UUID, String> id() {
 | |
| 		return this.identifier;
 | |
| 	}
 | |
| 
 | |
| 	public abstract void update(TrackedWaypoint waypoint);
 | |
| 
 | |
| 	public void write(ByteBuf buffer) {
 | |
| 		FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(buffer);
 | |
| 		friendlyByteBuf.writeEither(this.identifier, UUIDUtil.STREAM_CODEC, FriendlyByteBuf::writeUtf);
 | |
| 		Waypoint.Icon.STREAM_CODEC.encode(friendlyByteBuf, this.icon);
 | |
| 		friendlyByteBuf.writeEnum(this.type);
 | |
| 		this.writeContents(buffer);
 | |
| 	}
 | |
| 
 | |
| 	public abstract void writeContents(ByteBuf buffer);
 | |
| 
 | |
| 	private static TrackedWaypoint read(ByteBuf buffer) {
 | |
| 		FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(buffer);
 | |
| 		Either<UUID, String> either = friendlyByteBuf.readEither(UUIDUtil.STREAM_CODEC, FriendlyByteBuf::readUtf);
 | |
| 		Waypoint.Icon icon = Waypoint.Icon.STREAM_CODEC.decode(friendlyByteBuf);
 | |
| 		TrackedWaypoint.Type type = friendlyByteBuf.readEnum(TrackedWaypoint.Type.class);
 | |
| 		return type.constructor.apply(either, icon, friendlyByteBuf);
 | |
| 	}
 | |
| 
 | |
| 	public static TrackedWaypoint setPosition(UUID uuid, Waypoint.Icon icon, Vec3i position) {
 | |
| 		return new TrackedWaypoint.Vec3iWaypoint(uuid, icon, position);
 | |
| 	}
 | |
| 
 | |
| 	public static TrackedWaypoint setChunk(UUID uuid, Waypoint.Icon icon, ChunkPos chunkPos) {
 | |
| 		return new TrackedWaypoint.ChunkWaypoint(uuid, icon, chunkPos);
 | |
| 	}
 | |
| 
 | |
| 	public static TrackedWaypoint setAzimuth(UUID uuid, Waypoint.Icon icon, float angle) {
 | |
| 		return new TrackedWaypoint.AzimuthWaypoint(uuid, icon, angle);
 | |
| 	}
 | |
| 
 | |
| 	public static TrackedWaypoint empty(UUID uuid) {
 | |
| 		return new TrackedWaypoint.EmptyWaypoint(uuid);
 | |
| 	}
 | |
| 
 | |
| 	public abstract double yawAngleToCamera(Level level, TrackedWaypoint.Camera camera);
 | |
| 
 | |
| 	public abstract TrackedWaypoint.PitchDirection pitchDirectionToCamera(Level level, TrackedWaypoint.Projector projector);
 | |
| 
 | |
| 	public abstract double distanceSquared(Entity entity);
 | |
| 
 | |
| 	public Waypoint.Icon icon() {
 | |
| 		return this.icon;
 | |
| 	}
 | |
| 
 | |
| 	static class AzimuthWaypoint extends TrackedWaypoint {
 | |
| 		private float angle;
 | |
| 
 | |
| 		public AzimuthWaypoint(UUID uuid, Waypoint.Icon icon, float angle) {
 | |
| 			super(Either.left(uuid), icon, TrackedWaypoint.Type.AZIMUTH);
 | |
| 			this.angle = angle;
 | |
| 		}
 | |
| 
 | |
| 		public AzimuthWaypoint(Either<UUID, String> identifier, Waypoint.Icon icon, FriendlyByteBuf buffer) {
 | |
| 			super(identifier, icon, TrackedWaypoint.Type.AZIMUTH);
 | |
| 			this.angle = buffer.readFloat();
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public void update(TrackedWaypoint waypoint) {
 | |
| 			if (waypoint instanceof TrackedWaypoint.AzimuthWaypoint azimuthWaypoint) {
 | |
| 				this.angle = azimuthWaypoint.angle;
 | |
| 			} else {
 | |
| 				TrackedWaypoint.LOGGER.warn("Unsupported Waypoint update operation: {}", waypoint.getClass());
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public void writeContents(ByteBuf buffer) {
 | |
| 			buffer.writeFloat(this.angle);
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public double yawAngleToCamera(Level level, TrackedWaypoint.Camera camera) {
 | |
| 			return Mth.degreesDifference(camera.yaw(), this.angle * (180.0F / (float)Math.PI));
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public TrackedWaypoint.PitchDirection pitchDirectionToCamera(Level level, TrackedWaypoint.Projector projector) {
 | |
| 			double d = projector.projectHorizonToScreen();
 | |
| 			if (d < -1.0) {
 | |
| 				return TrackedWaypoint.PitchDirection.DOWN;
 | |
| 			} else {
 | |
| 				return d > 1.0 ? TrackedWaypoint.PitchDirection.UP : TrackedWaypoint.PitchDirection.NONE;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public double distanceSquared(Entity entity) {
 | |
| 			return Double.POSITIVE_INFINITY;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public interface Camera {
 | |
| 		float yaw();
 | |
| 
 | |
| 		Vec3 position();
 | |
| 	}
 | |
| 
 | |
| 	static class ChunkWaypoint extends TrackedWaypoint {
 | |
| 		private ChunkPos chunkPos;
 | |
| 
 | |
| 		public ChunkWaypoint(UUID uuid, Waypoint.Icon icon, ChunkPos chunkPos) {
 | |
| 			super(Either.left(uuid), icon, TrackedWaypoint.Type.CHUNK);
 | |
| 			this.chunkPos = chunkPos;
 | |
| 		}
 | |
| 
 | |
| 		public ChunkWaypoint(Either<UUID, String> identifier, Waypoint.Icon icon, FriendlyByteBuf buffer) {
 | |
| 			super(identifier, icon, TrackedWaypoint.Type.CHUNK);
 | |
| 			this.chunkPos = new ChunkPos(buffer.readVarInt(), buffer.readVarInt());
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public void update(TrackedWaypoint waypoint) {
 | |
| 			if (waypoint instanceof TrackedWaypoint.ChunkWaypoint chunkWaypoint) {
 | |
| 				this.chunkPos = chunkWaypoint.chunkPos;
 | |
| 			} else {
 | |
| 				TrackedWaypoint.LOGGER.warn("Unsupported Waypoint update operation: {}", waypoint.getClass());
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public void writeContents(ByteBuf buffer) {
 | |
| 			VarInt.write(buffer, this.chunkPos.x);
 | |
| 			VarInt.write(buffer, this.chunkPos.z);
 | |
| 		}
 | |
| 
 | |
| 		private Vec3 position(double y) {
 | |
| 			return Vec3.atCenterOf(this.chunkPos.getMiddleBlockPosition((int)y));
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public double yawAngleToCamera(Level level, TrackedWaypoint.Camera camera) {
 | |
| 			Vec3 vec3 = camera.position();
 | |
| 			Vec3 vec32 = vec3.subtract(this.position(vec3.y())).rotateClockwise90();
 | |
| 			float f = (float)Mth.atan2(vec32.z(), vec32.x()) * (180.0F / (float)Math.PI);
 | |
| 			return Mth.degreesDifference(camera.yaw(), f);
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public TrackedWaypoint.PitchDirection pitchDirectionToCamera(Level level, TrackedWaypoint.Projector projector) {
 | |
| 			double d = projector.projectHorizonToScreen();
 | |
| 			if (d < -1.0) {
 | |
| 				return TrackedWaypoint.PitchDirection.DOWN;
 | |
| 			} else {
 | |
| 				return d > 1.0 ? TrackedWaypoint.PitchDirection.UP : TrackedWaypoint.PitchDirection.NONE;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public double distanceSquared(Entity entity) {
 | |
| 			return entity.distanceToSqr(Vec3.atCenterOf(this.chunkPos.getMiddleBlockPosition(entity.getBlockY())));
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	static class EmptyWaypoint extends TrackedWaypoint {
 | |
| 		private EmptyWaypoint(Either<UUID, String> identifier, Waypoint.Icon icon, FriendlyByteBuf buffer) {
 | |
| 			super(identifier, icon, TrackedWaypoint.Type.EMPTY);
 | |
| 		}
 | |
| 
 | |
| 		EmptyWaypoint(UUID uuid) {
 | |
| 			super(Either.left(uuid), Waypoint.Icon.NULL, TrackedWaypoint.Type.EMPTY);
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public void update(TrackedWaypoint waypoint) {
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public void writeContents(ByteBuf buffer) {
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public double yawAngleToCamera(Level level, TrackedWaypoint.Camera camera) {
 | |
| 			return Double.NaN;
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public TrackedWaypoint.PitchDirection pitchDirectionToCamera(Level level, TrackedWaypoint.Projector projector) {
 | |
| 			return TrackedWaypoint.PitchDirection.NONE;
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public double distanceSquared(Entity entity) {
 | |
| 			return Double.POSITIVE_INFINITY;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public static enum PitchDirection {
 | |
| 		NONE,
 | |
| 		UP,
 | |
| 		DOWN;
 | |
| 	}
 | |
| 
 | |
| 	public interface Projector {
 | |
| 		Vec3 projectPointToScreen(Vec3 point);
 | |
| 
 | |
| 		double projectHorizonToScreen();
 | |
| 	}
 | |
| 
 | |
| 	static enum Type {
 | |
| 		EMPTY(TrackedWaypoint.EmptyWaypoint::new),
 | |
| 		VEC3I(TrackedWaypoint.Vec3iWaypoint::new),
 | |
| 		CHUNK(TrackedWaypoint.ChunkWaypoint::new),
 | |
| 		AZIMUTH(TrackedWaypoint.AzimuthWaypoint::new);
 | |
| 
 | |
| 		final TriFunction<Either<UUID, String>, Waypoint.Icon, FriendlyByteBuf, TrackedWaypoint> constructor;
 | |
| 
 | |
| 		private Type(final TriFunction<Either<UUID, String>, Waypoint.Icon, FriendlyByteBuf, TrackedWaypoint> constructor) {
 | |
| 			this.constructor = constructor;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	static class Vec3iWaypoint extends TrackedWaypoint {
 | |
| 		private Vec3i vector;
 | |
| 
 | |
| 		public Vec3iWaypoint(UUID uuid, Waypoint.Icon icon, Vec3i vector) {
 | |
| 			super(Either.left(uuid), icon, TrackedWaypoint.Type.VEC3I);
 | |
| 			this.vector = vector;
 | |
| 		}
 | |
| 
 | |
| 		public Vec3iWaypoint(Either<UUID, String> identifier, Waypoint.Icon icon, FriendlyByteBuf buffer) {
 | |
| 			super(identifier, icon, TrackedWaypoint.Type.VEC3I);
 | |
| 			this.vector = new Vec3i(buffer.readVarInt(), buffer.readVarInt(), buffer.readVarInt());
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public void update(TrackedWaypoint waypoint) {
 | |
| 			if (waypoint instanceof TrackedWaypoint.Vec3iWaypoint vec3iWaypoint) {
 | |
| 				this.vector = vec3iWaypoint.vector;
 | |
| 			} else {
 | |
| 				TrackedWaypoint.LOGGER.warn("Unsupported Waypoint update operation: {}", waypoint.getClass());
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public void writeContents(ByteBuf buffer) {
 | |
| 			VarInt.write(buffer, this.vector.getX());
 | |
| 			VarInt.write(buffer, this.vector.getY());
 | |
| 			VarInt.write(buffer, this.vector.getZ());
 | |
| 		}
 | |
| 
 | |
| 		private Vec3 position(Level level) {
 | |
| 			return (Vec3)this.identifier
 | |
| 				.left()
 | |
| 				.map(level::getEntity)
 | |
| 				.map(entity -> entity.blockPosition().distManhattan(this.vector) > 3 ? null : entity.getEyePosition())
 | |
| 				.orElseGet(() -> Vec3.atCenterOf(this.vector));
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public double yawAngleToCamera(Level level, TrackedWaypoint.Camera camera) {
 | |
| 			Vec3 vec3 = camera.position().subtract(this.position(level)).rotateClockwise90();
 | |
| 			float f = (float)Mth.atan2(vec3.z(), vec3.x()) * (180.0F / (float)Math.PI);
 | |
| 			return Mth.degreesDifference(camera.yaw(), f);
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public TrackedWaypoint.PitchDirection pitchDirectionToCamera(Level level, TrackedWaypoint.Projector projector) {
 | |
| 			Vec3 vec3 = projector.projectPointToScreen(this.position(level));
 | |
| 			boolean bl = vec3.z > 1.0;
 | |
| 			double d = bl ? -vec3.y : vec3.y;
 | |
| 			if (d < -1.0) {
 | |
| 				return TrackedWaypoint.PitchDirection.DOWN;
 | |
| 			} else if (d > 1.0) {
 | |
| 				return TrackedWaypoint.PitchDirection.UP;
 | |
| 			} else {
 | |
| 				if (bl) {
 | |
| 					if (vec3.y > 0.0) {
 | |
| 						return TrackedWaypoint.PitchDirection.UP;
 | |
| 					}
 | |
| 
 | |
| 					if (vec3.y < 0.0) {
 | |
| 						return TrackedWaypoint.PitchDirection.DOWN;
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				return TrackedWaypoint.PitchDirection.NONE;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public double distanceSquared(Entity entity) {
 | |
| 			return entity.distanceToSqr(Vec3.atCenterOf(this.vector));
 | |
| 		}
 | |
| 	}
 | |
| }
 |