'use strict';

/**
 * This class handles tying together the networking clients with the
 * actual game world and GameObjectManager.
 *
 * @private
 */
function _NetManager() {
  this.world = null;
}

/**
 * @private
 */
_NetManager.prototype._destroyWorld = function() {
  throw new Error('Not Yet Supported');
};

/**
 * Begins watching a WorldClient and GameClient for events.
 *
 * Note: You must set the world property before calling this!
 *
 * @param {WorldClient} wn
 * @param {GameClient} gn
 */
_NetManager.prototype.watch = function(wn, gn) {
  var self = this;
  wn.on('end', function() {
    gn.end();
    self._destroyWorld();
  });
  gn.on('end', function() {
    wn.end();
    self._destroyWorld();
  });

  gn.on('spawn_npc', function(data) {
    var npc = new NpcObject(self.world);
    npc.serverObjectIdx = data.objectIdx;
    if (data.charIdx > 0) {
      npc.charIdx = data.charIdx;
    } else {
      npc.charIdx = -data.charIdx;
      npc.hidden = true;
    }
    npc.eventIdx = data.eventIdx;
    npc.stats = new NpcStats(npc);
    npc.setPosition(data.position.x, data.position.y, 10);
    npc.setDirection(data.modelDir / 180 * Math.PI);
    npc.dropFromSky();
    if (data.command !== 0) {
      npc._moveTo(data.posTo.x, data.posTo.y);
    }
    GOM.addObject(npc);
  });

  gn.on('spawn_char', function(data) {
    var char = new CharObject(self.world);
    char.serverObjectIdx = data.objectIdx;
    char.name = data.name;
    char.level = data.level;
    char.moveSpeed = data.runSpeed;
    char.setPosition(data.position.x, data.position.y, 10);
    char.gender = data.gender;
    char.hp = data.hp;
    char.job = data.job;
    char.hairColor = data.hairColor;
    char.visParts = data.parts;
    char.stats = new CharStats(char);
    char.stats.attackSpeed = data.attackSpeed;
    char.stats.attackSpeedBase = data.attackSpeedBase;
    char.debugValidate();
    char.dropFromSky();
    if (data.command !== 0) {
      char._moveTo(data.posTo.x, data.posTo.y);
    }
    GOM.addObject(char);
  });

  gn.on('spawn_mob', function(data) {
    var mob = new MobObject(self.world);
    mob.serverObjectIdx = data.objectIdx;
    if (data.charIdx > 0) {
      mob.charIdx = data.charIdx;
    } else {
      mob.charIdx = -data.charIdx;
      mob.hidden = true;
    }
    mob.stats = new NpcStats(mob);
    mob.setPosition(data.position.x, data.position.y, 10);
    mob.dropFromSky();
    if (data.command !== 0) {
      mob._moveTo(data.posTo.x, data.posTo.y);
    }
    GOM.addObject(mob);
  });

  gn.on('obj_remove', function(data) {
    var obj = GOM.findByServerObjectIdx(data.objectIdx);
    if (obj) {
      GOM.removeObject(obj);
    }
  });

  gn.on('obj_moveto', function(data) {
    var obj = GOM.findByServerObjectIdx(data.objectIdx);
    if (obj) {
      var targetObj = null;
      if (data.targetObjectIdx) {
        targetObj = GOM.getRefByServerObjectIdx(
            data.targetObjectIdx,
            new THREE.Vector3(data.posTo.x, data.posTo.y, data.posZ));
      }
      if (targetObj) {
        obj._moveToObj(targetObj);
      } else {
        obj._moveTo(data.posTo.x, data.posTo.y);
      }
    }
  });
};

/**
 * @type {_NetManager}
 */
var NetManager = new _NetManager();

@@ -8,16 +8,204 @@
 rict';%0A%0A
+var OBJECT_COMMAND = %7B%0A    STOP: 0,%0A    ATTACK: 1,%0A    SIT: 2,%0A    STAND: 3,%0A    MOVE: 4,%0A    DIE: 5,%0A    TOGGLE: 6,%0A    Skill2SELF: 7,%0A    Skill2OBJ: 8,%0A    Skill2POS: 9,%0A    MAX: 10%0A%7D;%0A%0A
 /**%0A * T
@@ -1381,37 +1381,55 @@
 f (data.command 
-!== 0
+=== OBJECT_COMMAND.MOVE
 ) %7B%0A      npc._m
@@ -2128,37 +2128,55 @@
 f (data.command 
-!== 0
+=== OBJECT_COMMAND.MOVE
 ) %7B%0A      char._
@@ -2653,13 +2653,31 @@
 and 
-!== 0
+=== OBJECT_COMMAND.MOVE
 ) %7B%0A

Fix bug causing issues with objects running to nowhere and beyond.