/**
 * CustomEntity — an entity whose mesh and behavior were authored IN-WORLD.
 *
 * This is the payoff of "everything is editable from the inside." A type defined
 * through the in-world editor (a mesh spec + a JS behavior body) is instantiated
 * here; each tick we run the user's behavior `function(self, world){ ... }`,
 * which can move the entity, read terrain, keep its own `state`, spawn more, etc.
 *
 * Running user code via `new Function` is god-mode: it's your world on your
 * machine (Garry's-Mod-Lua energy). For shared/agent servers a sandbox matters —
 * see VISION.md "scripting sandbox / safety". world.step() already wraps update()
 * in try/catch so a bad behavior can't take the tick down.
 */
'use strict';

class CustomEntity {
  /** @param {{id:string,type:string,x:number,y:number,z:number,scale?:number,rot?:number}} o
   *  @param {Function|null} behaviorFn  compiled (self, world) => void */
  constructor(o, behaviorFn) {
    this.id = o.id;
    this.kind = o.type; // the type name IS the kind the renderer keys on
    this.type = o.type;
    this.x = o.x;
    this.y = o.y;
    this.z = o.z;
    this.rot = o.rot || 0;
    this.scale = o.scale || 1;
    this.state = {}; // scratch space the behavior owns
    this.age = 0;
    this._fn = behaviorFn || null;
  }

  update(world) {
    this.age += 1;
    if (this._fn) this._fn(this, world); // throws are caught by world.step()
  }

  serialize() {
    return {
      id: this.id,
      kind: this.kind,
      type: this.type,
      pose: { x: this.x, y: this.y, z: this.z, rot: this.rot },
      scale: this.scale,
    };
  }
}

module.exports = { CustomEntity };
