feat: add shared types and constants for ECS, networking, and assets
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
export const TILE_SIZE = 48;
|
||||
export const WORLD_WIDTH = 64;
|
||||
export const WORLD_HEIGHT = 64;
|
||||
export const TICK_RATE = 10; // server ticks per second
|
||||
export const BROADCAST_EVERY_N_TICKS = 3; // state broadcast frequency
|
||||
export const SPRITE_FRAME_WIDTH = 48;
|
||||
export const SPRITE_FRAME_HEIGHT = 48;
|
||||
export const SPRITE_COLS = 6;
|
||||
export const SPRITE_ROWS = 4;
|
||||
|
||||
// NPC needs
|
||||
export const HUNGER_DECAY_PER_TICK = 0.05;
|
||||
export const ENERGY_DECAY_PER_TICK = 0.03;
|
||||
export const HUNGER_THRESHOLD = 30;
|
||||
export const ENERGY_THRESHOLD = 20;
|
||||
export const NEED_RECOVERY_RATE = 0.5;
|
||||
|
||||
// Directions (row index in spritesheet)
|
||||
export const Direction = {
|
||||
DOWN: 0,
|
||||
LEFT: 1,
|
||||
RIGHT: 2,
|
||||
UP: 3,
|
||||
} as const;
|
||||
export type Direction = (typeof Direction)[keyof typeof Direction];
|
||||
|
||||
// Accessory slot names in z-order (bottom to top rendering)
|
||||
export const ACCESSORY_SLOTS = [
|
||||
'bottom', 'feet', 'chest', 'arm', 'shoulder',
|
||||
'waist', 'back', 'facialHair', 'haircut', 'hat',
|
||||
] as const;
|
||||
export type AccessorySlot = (typeof ACCESSORY_SLOTS)[number];
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './constants.js';
|
||||
export * from './types.js';
|
||||
@@ -0,0 +1,100 @@
|
||||
import type { AccessorySlot } 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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user