Files
dflike/shared/src/types.ts
T
2026-03-07 04:33:42 +00:00

104 lines
2.3 KiB
TypeScript

import type { AccessorySlot, PortraitSlot } from './constants.js';
// Entity is just a numeric ID
export type EntityId = number;
// Components
export interface Position {
x: number;
y: number;
}
export interface Velocity {
dx: number;
dy: number;
}
export interface Appearance {
skinId: string; // e.g. "shape00_skin02"
accessories: Partial<Record<AccessorySlot, string>>; // slot -> filename without extension
portraitFeatures?: Partial<Record<PortraitSlot, string>>; // portrait-only facial features
}
export interface Needs {
hunger: number; // 0-100
energy: number; // 0-100
}
export type MovementState = 'idle' | 'walking';
export type GoalType = 'wander' | 'eat' | 'rest';
export interface Movement {
state: MovementState;
target: Position | null;
path: Position[];
direction: number; // Direction enum value
moveProgress: number; // fractional tile accumulator
}
export interface PlayerControlled {
playerId: string;
mode: 'avatar' | 'camera';
}
export interface NPCBrain {
currentGoal: GoalType | null;
goalQueue: GoalType[];
}
// Network protocol messages
export interface EntityState {
id: EntityId;
position: Position;
movement: Movement;
appearance: Appearance;
needs?: Needs;
npcBrain?: NPCBrain;
playerControlled?: PlayerControlled;
name?: string; // NPC display name
}
export interface WorldState {
entities: EntityState[];
worldWidth: number;
worldHeight: number;
tileSize: number;
obstacles: Position[];
pointsOfInterest: { type: 'food' | 'rest'; position: Position }[];
}
export interface StateUpdate {
entities: EntityState[];
tick: number;
}
export interface PlayerJoined {
playerId: string;
entityId: EntityId;
}
export interface PlayerLeft {
playerId: string;
}
export interface PlayerInput {
type: 'move' | 'toggle-mode' | 'follow' | 'interact';
direction?: { dx: number; dy: number };
targetPlayerId?: string;
targetEntityId?: EntityId;
}
// Server -> Client events
export interface ServerEvents {
'world-state': (data: WorldState) => void;
'state-update': (data: StateUpdate) => void;
'player-joined': (data: PlayerJoined) => void;
'player-left': (data: PlayerLeft) => void;
'npc-recomposed': (data: { entityId: EntityId; appearance: Appearance }) => void;
}
// Client -> Server events
export interface ClientEvents {
'player-input': (data: PlayerInput) => void;
}