Skip to content

Instantly share code, notes, and snippets.

@iam4722202468
Created February 22, 2024 16:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iam4722202468/2f6cd17062d0194959605674051bf3b9 to your computer and use it in GitHub Desktop.
Save iam4722202468/2f6cd17062d0194959605674051bf3b9 to your computer and use it in GitHub Desktop.
force view
import net.minestom.server.MinecraftServer;
import net.minestom.server.collision.BoundingBox;
import net.minestom.server.collision.CollisionUtils;
import net.minestom.server.collision.PhysicsResult;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.coordinate.Vec;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.EntityType;
import net.minestom.server.entity.PlayerExtended;
import net.minestom.server.event.player.PlayerPacketEvent;
import net.minestom.server.network.packet.client.play.ClientPlayerRotationPacket;
import net.minestom.server.network.packet.client.play.ClientSteerVehiclePacket;
import net.minestom.server.timer.TaskSchedule;
import net.worldseed.contexts.ItemContext;
import net.worldseed.entities.WorldSeedFakePlayer;
import net.worldseed.regions.RegionAction;
import net.worldseed.regions.WorldSeedInstance;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
public class ForcedViewHandler {
private final PlayerExtended player;
private AtomicBoolean active = new AtomicBoolean(false);
private double distance = 5;
private Pos pos = null;
private Entity viewing = null;
private float yaw, pitch;
private static final BoundingBox cameraBoundingBox = new BoundingBox(0.5, 0.5, 0.5, new Pos(0, 1.5, 0));
private List<RegionAction> onJump;
private List<RegionAction> onSneak;
public ForcedViewHandler(PlayerExtended player) {
this.player = player;
player.eventNode().addListener(PlayerPacketEvent.class, (event) -> {
if (active.get()) {
if (event.getPacket() instanceof ClientPlayerRotationPacket rotation) {
updateView(rotation.yaw(), rotation.pitch());
}
if (event.getPacket() instanceof ClientSteerVehiclePacket packet) {
var fakePlayer = player.getFakePlayer();
if (fakePlayer != null && player.getInstance() instanceof WorldSeedInstance wsi) {
if (fakePlayer.isSneaking() && packet.flags() == 0) {
fakePlayer.setSneaking(false);
} else if (!fakePlayer.isSneaking() && packet.flags() == 2) {
fakePlayer.setSneaking(true);
var context = new ItemContext<>(wsi, player, null);
if (onSneak != null) player.getExecutor().executeActions(onSneak, context, UUID.randomUUID(), List.of());
} else if (player.isOnGround() && packet.flags() == 1) {
var context = new ItemContext<>(wsi, player, null);
if (onJump != null) player.getExecutor().executeActions(onJump, context, UUID.randomUUID(), List.of());
}
}
}
}
});
}
public void setPositionView(Pos p) {
this.pos = p;
if (!active.get()) {
active.set(true);
start();
}
}
public void stopView() {
if (viewing != null) {
player.teleport(player.getFakePlayer().getPosition().withView(yaw, pitch)).thenRun(() -> {
player.stopSpectating();
viewing.removePassenger(player);
viewing.remove();
viewing = null;
onJump = null;
onSneak = null;
active.set(false);
player.setInvisible(false);
});
player.getFakePlayer().remove();
player.setFakePlayer(null);
}
}
private void start() {
if (active.get()) stopView();
if (!(player.getInstance() instanceof WorldSeedInstance wsi)) return;
this.viewing = new Entity(EntityType.ZOMBIE);
viewing.setNoGravity(true);
viewing.setHasPhysics(false);
viewing.setHasCollision(false);
viewing.setInvisible(true);
this.yaw = 180-pos.yaw();
this.pitch = pos.pitch();
viewing.setInstance(player.getInstance(), player.getPosition().sub(0, 1.5, 0).withView(-pos.yaw(), pos.pitch())).thenRun(() -> {
MinecraftServer.getSchedulerManager().scheduleTask(() -> {
player.setInvisible(true);
viewing.addPassenger(player);
player.spectate(viewing);
}, TaskSchedule.tick(4), TaskSchedule.stop());
var fakePlayer = new WorldSeedFakePlayer(player, wsi, player.getPosition(), 4);
player.setFakePlayer(fakePlayer);
fakePlayer.setHasPhysics(true);
fakePlayer.setNoGravity(false);
redraw();
});
}
private void updateView(float yaw, float pitch) {
this.yaw = 180-yaw;
this.pitch = pitch;
redraw();
}
private void redraw() {
if (viewing == null) return;
if (pos == null) return;
double pr = Math.toRadians(yaw);
double yr = Math.toRadians(pitch);
final double xz = Math.cos(yr);
double x = xz * Math.sin(pr) * distance + pos.x();
double y = Math.sin(yr) * distance + pos.y() - 1.5;
double z = xz * Math.cos(pr) * distance + pos.z();
Vec desiredPos = new Vec(x, y, z);
PhysicsResult result = CollisionUtils.handlePhysics(player.getInstance(), player.getInstance().getChunkAt(pos), cameraBoundingBox, pos, desiredPos.sub(pos), null, true);
viewing.setView(180 - yaw, pitch);
viewing.teleport(result.newPosition().withView(180 - yaw, pitch));
if (player.getFakePlayer() != null) player.getFakePlayer().setView(180 - yaw, pitch);
}
public void setSneakHandler(List<RegionAction> actionListSneak) {
this.onSneak = actionListSneak;
}
public void setJumpHandler(List<RegionAction> actionListJump) {
this.onJump = actionListJump;
}
public void setDistanceView(double distance) {
this.distance = distance;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment