95 lines
2.3 KiB
TypeScript
95 lines
2.3 KiB
TypeScript
import type { Client } from "../client.ts";
|
|
import { InputManager } from "../input_manager.ts";
|
|
import { ClientInventories } from "../inventory.ts";
|
|
import { Player } from "./player.ts";
|
|
|
|
// the position goes to the server every other tick
|
|
const SEND_POSITION_TICKS = 2;
|
|
|
|
// the player this client controls, like minecraft's LocalPlayer
|
|
export class LocalPlayer extends Player {
|
|
client: Client;
|
|
inventories = new ClientInventories();
|
|
|
|
move_speed = 4;
|
|
// blocks per second, peaks about 1.25 blocks up with the entity's gravity and drag
|
|
jump_force = 9.23;
|
|
|
|
#ticks_since_sent = 0;
|
|
|
|
constructor(client: Client, id: string, name: string) {
|
|
super(client.level, id, name);
|
|
this.client = client;
|
|
}
|
|
|
|
tick() {
|
|
if (!this.client.screen) {
|
|
this.#apply_input();
|
|
}
|
|
this.move();
|
|
this.#send_position();
|
|
}
|
|
|
|
// turns with the mouse every frame, not every tick, like minecraft's MouseHandler.turnPlayer
|
|
turn(mouse_dx: number, mouse_dy: number) {
|
|
this.yaw += -mouse_dx * 0.001;
|
|
this.pitch += -mouse_dy * 0.001;
|
|
|
|
const limit = Math.PI / 2 - 0.01;
|
|
this.pitch = Math.max(-limit, Math.min(limit, this.pitch));
|
|
}
|
|
|
|
// walking relative to where it's looking
|
|
#apply_input() {
|
|
const options = this.client.options;
|
|
let input_x = 0;
|
|
let input_z = 0;
|
|
|
|
if (InputManager.is_key_down(options.key_left)) {
|
|
input_x -= 1;
|
|
}
|
|
if (InputManager.is_key_down(options.key_right)) {
|
|
input_x += 1;
|
|
}
|
|
if (InputManager.is_key_down(options.key_forward)) {
|
|
input_z -= 1;
|
|
}
|
|
if (InputManager.is_key_down(options.key_back)) {
|
|
input_z += 1;
|
|
}
|
|
|
|
const size = Math.hypot(input_x, input_z);
|
|
if (size > 0) {
|
|
input_x /= size;
|
|
input_z /= size;
|
|
}
|
|
|
|
const sin = Math.sin(this.yaw);
|
|
const cos = Math.cos(this.yaw);
|
|
const speed = this.move_speed * (InputManager.is_key_down(options.key_sprint) ? 1.75 : 1);
|
|
|
|
this.vx = (sin * input_z + cos * input_x) * speed;
|
|
this.vz = (cos * input_z - sin * input_x) * speed;
|
|
|
|
if (InputManager.is_key_down(options.key_jump) && this.on_ground) {
|
|
this.vy += this.jump_force;
|
|
}
|
|
}
|
|
|
|
#send_position() {
|
|
this.#ticks_since_sent += 1;
|
|
if (this.#ticks_since_sent < SEND_POSITION_TICKS) {
|
|
return;
|
|
}
|
|
this.#ticks_since_sent = 0;
|
|
this.client.connection.send({
|
|
type: "move",
|
|
x: this.x,
|
|
y: this.y,
|
|
z: this.z,
|
|
yaw: this.yaw,
|
|
pitch: this.pitch,
|
|
});
|
|
}
|
|
}
|