-------------------------------------------------------- -- obj.ownerUuid 存在的话,只有指定人能看到 -------------------------------------------------------- local Util = require("common.Util") local Timer = require("core.Timer") local Msg = require("core.Msg") local ObjHuman = require("core.ObjHuman") TYPE_HUMAN = 1 TYPE_COLLECT = 2 objs = objs or {} -- obj_id转换成对象 scenes = scenes or {} -- 所有的场景 [sceneID][objId] = obj scenes_fds = scenes_fds or {} -- 场景fd [sceneID][fd] = obj local q_cap = 65536 local function q_push(id) if q_b + 1 == q_f or q_b == q_cap and q_f == 1 then assert() end q[q_b] = id q_b = q_b + 1 if q_b == q_cap + 1 then q_b = 1 end end function q_pop() if q_f + 1 == q_b or q_f == q_cap and q_b == 1 then assert() end local t = q[q_f] q_f = q_f + 1 if q_f == q_cap + 1 then q_f = 1 end return t end local function q_init() if q then return end q = {} q_b = q_cap q_f = 1 for i = 1, q_cap do q[i] = 1000 + i -- 这里的objid从1001开始 0-1000留给客户端的剧情动画角色 end end q_init() obj_envs = { require("core.ObjHuman"), } function getObj(obj_id, obj_uid) local obj = objs[obj_id] if not obj then return end if obj_uid and obj_uid ~= obj.uid then return end return obj end function create(obj, obj_type) local id = q_pop() if objs[id] then assert() end objs[id] = obj obj.id = id obj.obj_type = obj_type obj.uid = Timer.now return obj end function destroy(obj) if objs[obj.id] ~= obj then assert() end objs[obj.id] = nil q_push(obj.id) end function destroyAllType(obj) if obj_envs[obj.obj_type].destroy then obj_envs[obj.obj_type].destroy(obj) else destroy(obj) end end function getBodyInfo(obj) return obj_envs[obj.obj_type].getBodyInfo(obj) end function getObjAdd(obj) return obj_envs[obj.obj_type].getObjAdd(obj) end local function getObjDel(obj) local mm = Msg.gc.GC_DEL_OBJ mm.obj_id = obj.id return mm end function getSpeed(obj) return obj_envs[obj.obj_type].getSpeed(obj) end -- 取场景所有obj fd列表 local sceneFdObjs = {} function getSceneObjFds(sceneID, exceptObj) for k in ipairs(sceneFdObjs) do sceneFdObjs[k] = nil end if not scenes_fds[sceneID] then return sceneFdObjs end local len = 0 for _, obj in pairs(scenes_fds[sceneID]) do if obj ~= exceptObj then len = len + 1 sceneFdObjs[len] = obj end end return sceneFdObjs end local sceneObjs = {} function getSceneObjs(sceneID, obj_type, ownerUuid) for k in ipairs(sceneObjs) do sceneObjs[k] = nil end if not scenes[sceneID] then return sceneObjs end local len = 0 for _, obj in pairs(scenes[sceneID]) do if (obj_type == nil or obj.obj_type == obj_type) and (ownerUuid == nil or obj.ownerUuid == ownerUuid) then len = len + 1 sceneObjs[len] = obj end end return sceneObjs end -- 清除归属的对象 function clearOwnerObjs(sceneID, obj, noSend) if not sceneID then return end local scene = scenes[sceneID] if not scene then return end if not obj.fd or not obj.db then return end for _, tobj in pairs(scene) do if not tobj.fd and tobj.ownerUuid and tobj.ownerUuid == obj.db._id then scene[tobj.id] = nil destroyAllType(tobj) if not noSend then Msg.send(getObjDel(tobj), obj.fd) end end end end function enterScene(obj, sceneID, x, y) if obj.sceneID then print("ERROR:has enterScene") return end if obj.fd and obj.db then -- 把周围的活动obj告诉这个玩家 local sceneFdObjs = getSceneObjFds(sceneID, obj) for _, sceneObj in ipairs(sceneFdObjs) do if not sceneObj.ownerUuid or sceneObj.ownerUuid == obj.db._id then Msg.send(getObjAdd(sceneObj), obj.fd) sendMove(sceneObj, obj) end end end resetPathParam(obj) obj.sceneID = sceneID obj.x = x obj.y = y if obj.fd then obj.way = 4 end -- 把这个对象进入场景的信息告诉别的玩家 if obj.ownerUuid then local ownerObj = ObjHuman.onlineUuid[obj.ownerUuid] if ownerObj and ownerObj.fd then Msg.send(getObjAdd(obj), ownerObj.fd) end else sendScene(getObjAdd(obj), sceneID) end scenes[sceneID] = scenes[sceneID] or {} scenes[sceneID][obj.id] = obj scenes_fds[sceneID] = scenes_fds[sceneID] or {} if obj.fd then scenes_fds[sceneID][obj.fd] = obj end end function leaveScene(obj) local sceneID = obj.sceneID if not sceneID then return end local scene = scenes[sceneID] if not scene then return end obj.sceneID = nil if not scene[obj.id] then return end scene[obj.id] = nil if obj.fd then scenes_fds[sceneID][obj.fd] = nil clearOwnerObjs(sceneID, obj, true) end -- 告诉附近玩家 这个对象离开场景了 if obj.ownerUuid then local ownerObj = ObjHuman.onlineUuid[obj.ownerUuid] if ownerObj and ownerObj.fd then Msg.send(getObjDel(obj), ownerObj.fd) end else sendScene(getObjDel(obj), sceneID) end return true, sceneID end function sendScene(mm, sceneID, exceptObj) local objs = scenes[sceneID] if not objs then return end local list = Msg.list local len = 0 for _, obj in pairs(objs) do if obj.fd and obj ~= exceptObj then len = len + 1 list[len] = obj.fd end end list[0] = len Msg.sendMulti(mm, list) end function resetPathParam(obj) obj.pathLen = 0 obj.pathPoints = nil end function walk(during) for sceneID, sceneObjs in pairs(scenes) do for objid, obj in pairs(sceneObjs) do if obj.pathLen > 0 then local speed = getSpeed(obj) local oldx = obj.x local oldy = obj.y local nearx = obj.pathPoints[obj.pathLen * 2 - 1] local neary = obj.pathPoints[obj.pathLen * 2] local dx = oldx - nearx local dy = oldy - neary local way = Util.getWay(oldx - nearx, oldy - neary) local moveLen = math.floor(speed / 1000 * during) if dx * dx + dy * dy <= moveLen * moveLen then obj.pathLen = obj.pathLen - 1 oldx = nearx oldy = neary else oldx, oldy = Util.getTargetPoint(nearx, neary, oldx, oldy, moveLen) end obj.x = oldx obj.y = oldy obj.way = way end end end end function stop(obj) if obj.path_len == 0 then return end if not obj.sceneID then return end resetPathParam(obj) local msgRet = Msg.gc.GC_STOP_MOVE msgRet.way = obj.way or 4 msgRet.obj_id = obj.id msgRet.x = obj.x msgRet.y = obj.y sendScene(msgRet, obj.sceneID) end function sendMove(obj, target) if not obj.sceneID then return end if not obj.pathLen or obj.pathLen < 1 then return end local msgRet = Msg.gc.GC_MOVE msgRet.obj_id = obj.id msgRet.points[0] = obj.pathLen * 2 for i = 1, obj.pathLen do local j = obj.pathLen + 1 - i msgRet.points[2 * i - 1] = obj.pathPoints[2 * j - 1] msgRet.points[2 * i] = obj.pathPoints[2 * j] end if target then Msg.send(msgRet, target.fd) else sendScene(msgRet, obj.sceneID, obj) end end