UNPKG

moomooio-client

Version:

MooMooIO-Client is a client-side wrapper API designed for the game MooMoo.io. This package aims to provide a simple yet powerful API for creating clones, mods, or plugins for MooMoo.io.

283 lines (253 loc) 9.09 kB
import InitializePlayer from "../ServerPackets/InitializePlayer"; import { PlayerData } from "../ServerPackets/UpdatePlayers"; import PropertyTracker from "../utils/PropertyTracker"; import UnifyEmitter, { EventsObject } from "unify-emitter"; import Team from "./Team"; import GameObject from "./GameObject"; export interface PlayerEvents { move: { /** * The direction where the player is moving (in radians) */ direction: number /** * The player instance */ player: ThisType<Player<PlayerEvents>>; /** * player position on y-axis */ y: number; /** * player position on x-axis */ x: number; }; rotate: { /** * The angle where the player is facing (in radians) */ angle: number; /** * The player instance */ player: ThisType<Player<PlayerEvents>>; }; punch: { /** * the punch direction (in radians) */ direction: number; /** * tells if the player successfully hit something */ didHit: boolean; /** * The player instance */ player: ThisType<Player<PlayerEvents>>; // TODO: Add weapons field }; chat: { /** * the content of message the player sent */ message: string; /** * The player instance of who sent the message */ player: ThisType<Player<PlayerEvents>>; }; healthChange: { /** * a boolean value indicating whether the player is healing or taking damage. */ isHealing: boolean; /** * a positive number representing the magnitude of the health change. */ amount: number; /** * the player instance who initiated the health change. */ player: ThisType<Player<PlayerEvents>>; }; hatChange: { /** * The previous hat Id that the player was wearing. */ previous: number; /** * The current hat Id that the player is wearing. */ current: number; /** * The player instance who initiated the hat change. */ player: ThisType<Player<PlayerEvents>>; }; tailChange: { /** * The previous accessory Id that the player was wearing. */ previous: number; /** * The current accessory Id that the player is wearing. */ current: number; /** * the player instance who initiated the health change. */ player: ThisType<Player<PlayerEvents>>; }; place: GameObject; destroyed: null; update: ThisType<Player<PlayerEvents>>; } /** * @member `buildType` The type of object the player is currently holding. If it's -1, it means the player is not holding anything. * @member `hatType` Specifies the type of hat the player is wearing, such as a boost hat or soldier hat. * @member `weaponType` The type of weapon the player has, which can be used to obtain weapon data. * @member `isBestKiller` Indicates whether the player is the best killer, shown by a skull icon. * @member `isLeader` Indicates whether the player is the owner of a clan, shown by a crown icon. * @member `weaponVariant` Shows the level of the player's weapon (such as stone, gold, etc.). * @member `playerID` is a unique identifier for the player (similar to initID). * @member `tailType` Describes the type of tail the player has, like wings. * @member `maxHealth` the maximum health that the player can have. * @member `angle` indicates the direction the player is facing. * @member `isMyPlayer` indicates whether the player is yours. * @member `initID` is a unique identifier for the player. * @member `skinID` the ID or index of the player's skin. * @member `layer` Represents the layer of the player. * @member `health` the current health of the player. * @member `scale` indicates the size of the player. * @member `x` the player's position on the x-axis. * @member `y` the player's position on the y-axis. * @member `teamID` The ID of the player's team. * @member `playerName` the name of the player. * @member `isInitialized` tells where or not a player have basic information like `id`, `name`, `skinID`, ...etc */ export type PlayerType = Player<PlayerEvents>; export default class Player<T extends PlayerEvents> extends UnifyEmitter< EventsObject<PlayerEvents, T> > { #teamID: null | string = null; #isBestKiller = false; #weaponVariant = 0; #isLeader = false; #isMyPlayer = false; #playerName!: string; #weaponType = 0; #buildType = -1; #maxHealth = 100; #playerID!: number; #tailType = new PropertyTracker(0); #hatType = new PropertyTracker(0); #health = new PropertyTracker(100); #initID!: string; #skinID = 0; #scale = 35; #layer = 0; #angle = new PropertyTracker(0); #x = new PropertyTracker(0); #y = new PropertyTracker(0); #isInitialized = false; initialize(initializePlayer: InitializePlayer) { this.#isMyPlayer = initializePlayer.isMyPlayer; this.#playerName = initializePlayer.playerName; this.#maxHealth = initializePlayer.maxHealth; this.#playerID = initializePlayer.playerID; this.#initID = initializePlayer.initID; this.#skinID = initializePlayer.skinID; this.#scale = initializePlayer.scale; this.#health = new PropertyTracker(initializePlayer.health); this.#angle = new PropertyTracker(initializePlayer.angle); this.#x = new PropertyTracker(initializePlayer.x); this.#y = new PropertyTracker(initializePlayer.y); this.#isInitialized = true; } update(playerData: PlayerData) { this.#weaponVariant = playerData.weaponVariant; this.#isBestKiller = playerData.isBestKiller; this.#weaponType = playerData.weaponType; this.#tailType.set(playerData.tailType); this.#buildType = playerData.buildType; this.#hatType.set(playerData.hatType); this.#isLeader = playerData.isLeader; this.#angle.set(playerData.angle); this.#teamID = playerData.teamID; this.#layer = playerData.layer; this.#x.set(playerData.x); this.#y.set(playerData.y); if (this.#x.isDiff() || this.#y.isDiff()) { const deltaX = this.#x.current - (this.#x.previous || 0); const deltaY = this.#y.current - (this.#y.previous || 0); this.emit("move", { direction: Math.atan2(deltaY, deltaX), x: this.x, y: this.y, player: this, }); } if (this.#hatType.isDiff()) { this.emit("hatChange", { previous: this.#hatType.previous ?? 0, current: this.#hatType.current, player: this, }); } if (this.#tailType.isDiff()) { this.emit("tailChange", { previous: this.#tailType.previous ?? 0, current: this.#tailType.current, player: this, }); } if (this.#angle.isDiff()) { this.emit("rotate", { angle: this.angle, player: this, }); } this.emit("update", this); } clear() { this.emit("destroyed", null); this.#isInitialized = false; this.removeListeners(); } /* prettier-ignore */ get weaponVariant() { return this.#weaponVariant } /* prettier-ignore */ get isInitialized() { return this.#isInitialized } /* prettier-ignore */ get isBestKiller() { return this.#isBestKiller } /* prettier-ignore */ get tailType() { return this.#tailType.current } /* prettier-ignore */ get hatType() { return this.#hatType.current } /* prettier-ignore */ get weaponType() { return this.#weaponType } /* prettier-ignore */ get isMyPlayer() { return this.#isMyPlayer } /* prettier-ignore */ get playerName() { return this.#playerName } /* prettier-ignore */ get health() { return this.#health.current} /* prettier-ignore */ get buildType() { return this.#buildType } /* prettier-ignore */ get maxHealth() { return this.#maxHealth } /* prettier-ignore */ get angle() { return this.#angle.current } /* prettier-ignore */ get isLeader() { return this.#isLeader } /* prettier-ignore */ get playerID() { return this.#playerID } /* prettier-ignore */ get teamID() { return this.#teamID } /* prettier-ignore */ get initID() { return this.#initID } /* prettier-ignore */ get skinID() { return this.#skinID } /* prettier-ignore */ get layer() { return this.#layer } /* prettier-ignore */ get scale() { return this.#scale } /* prettier-ignore */ get x() { return this.#x.current } /* prettier-ignore */ get y() { return this.#y.current } setHealth(health: number): void { this.#health.set(Math.min(this.maxHealth, Math.max(health, 0))); const prev = this.#health.previous ?? 100; const curr = this.#health.current; this.emit("healthChange", { isHealing: prev - curr < 0, amount: Math.abs(prev - curr), player: this, }); } getTeam(teams: Map<string, Team>): Team | null { return (this.teamID && teams.get(this.teamID)) || null; } }