import Module from '../utils/Module' import { IDelta, IPosition, IState } from '../utils/types' // MAYBE: split interface IDifficulty { level: number, locked: boolean } interface IAbilities { // TODO: Flags Byte Bit mask. 0x08: damage disabled (god mode), 0x04: can fly, 0x02: is flying, 0x01: is Creative flyingSpeed: number, walkingSpeed: number } interface IPositionPacket extends IPosition { flags: number teleportId: number } // TODO: player_info /** Handle client state and position */ export default class State extends Module<{ positionConfirm: boolean }> { private _state!: IState public get state() { return this._state } private _difficulty!: IDifficulty public get difficulty() { return this._difficulty } private _abilities!: IDifficulty public get abilities() { return this._abilities } private _position!: IPosition public get position() { return this._position } public translate(delta: IDelta, onGround: boolean = true) { this.client.write('position', { onGround, x: this.position.x += delta.dX, y: this.position.y += delta.dY, z: this.position.z += delta.dZ, }) } protected mount() { this.client.on('login', data => this._state = data) this.client.on('difficulty', data => this._difficulty = { level: data.difficulty, locked: data.difficultyLocked, }) this.client.on('abilities', data => this._abilities = data) this.client.on('position', (data: IPositionPacket) => { if (this._position == null) { if (data.flags) { this.logger.error('first position is relative') return } else { this._position = data } } else { // tslint:disable: no-bitwise this._position = { x: data.x + (data.flags & 0x01 ? this._position.x : 0), y: data.y + (data.flags & 0x02 ? this._position.y : 0), z: data.z + (data.flags & 0x04 ? this._position.z : 0), yaw: data.yaw + (data.flags & 0x08 ? this._position.yaw : 0), pitch: data.pitch + (data.flags & 0x10 ? this._position.pitch : 0), } } if (this.conf.positionConfirm) { this.client.write('teleport_confirm', { teleportId: data.teleportId }) } this.logger.debug({ type: 'teleported', position: this.position }) }) } protected getConf() { return { positionConfirm: true } } } // TODO: vehicule_move