342 lines
9.8 KiB
JavaScript
342 lines
9.8 KiB
JavaScript
|
|
require("./util/util");
|
|
const db = require("./util/data");
|
|
WORLD = {
|
|
USERS: [],
|
|
COMMANDS: {},
|
|
SKILLS: {},
|
|
ROOMS: {},
|
|
RUN_ROOMS: [],
|
|
DEFAULT_SKILLS: {},
|
|
AREAS: [],
|
|
TASKS: [],
|
|
SYSTEMTASKS: [],
|
|
USER_EVENTS: [],
|
|
OBJ_STROE: new Map(),
|
|
NPC_STROE: new Map(),
|
|
HEARTBEATCOUNT: 0,
|
|
RECEIVED: [],
|
|
LOGS: [],
|
|
SERVERID: 0,
|
|
SERVERS: [],
|
|
CONNECT_COUNT: 0,
|
|
DATA: require('./data'),
|
|
USERLOGIN: require('./login'),
|
|
DB: db,
|
|
SocketCount: 0,
|
|
LISTENER: require("./ws"),
|
|
max_connect_count: 1100,
|
|
max_user_count: 5100,
|
|
MESSAGE: {
|
|
stores: new Map(),
|
|
NOTICES: [],
|
|
},
|
|
STATS: {
|
|
TOPS: [],
|
|
EXP: [],
|
|
SCORE: [],
|
|
WEAPON: [],
|
|
},
|
|
status: -1,//-1关闭 0正常 >1 用户等级>连接
|
|
SocketIn: function () {
|
|
this.SocketCount++;
|
|
},
|
|
connect: function (socket) {
|
|
if (WORLD.status < 0)
|
|
return socket.end();
|
|
if (!WORLD.check_connect(socket))
|
|
return socket.end();
|
|
|
|
socket.user = new USER();
|
|
|
|
socket.user.socket = socket;
|
|
socket.user.wait_input = this.USERLOGIN.check_session.bind(this.USERLOGIN);
|
|
|
|
socket.setTimeout(60000);
|
|
},
|
|
check_connect: function (socket) {
|
|
return true;
|
|
},
|
|
before_login: function (user) {
|
|
if (this.status < 0) return false;
|
|
if (this.status === 0) return true;
|
|
return this.status <= user.user_level;
|
|
},
|
|
disconnect: function (socket) {
|
|
if (socket.user) {
|
|
socket.user.socket = null;
|
|
socket.user.disconnect();
|
|
}
|
|
this.SocketCount--;
|
|
if (socket.oserver) {
|
|
socket.oserver.disconnect();
|
|
socket.oserver = null;
|
|
}
|
|
}, request: function (request, socket) {
|
|
if (!request) return;
|
|
var user = socket.user;
|
|
if (!user) {
|
|
return;
|
|
}
|
|
if (user.request_count > 20) {
|
|
return user.send("不要急,慢慢来。");
|
|
}
|
|
user.request_count = user.request_count + 1;
|
|
var time = Date.now();
|
|
try {
|
|
user.command(request);
|
|
} catch (e) {
|
|
console.log(user.name, "命令错误:", request, e.message, e.stack);
|
|
WORLD.log(user, request, e.message + e.stack);
|
|
}
|
|
WORLD.RECEIVED.push({
|
|
time: time,
|
|
cmd: request + " " + (Date.now() - time).toString(),
|
|
user: user.id
|
|
});
|
|
if (WORLD.RECEIVED.length > 1000) {
|
|
WORLD.saveRequest();
|
|
}
|
|
}, saveRequest: function () {
|
|
db.saveRequest(WORLD.RECEIVED);
|
|
WORLD.RECEIVED.length = 0;
|
|
},
|
|
startup: async function (sid) {
|
|
if (sid) {
|
|
sid = parseInt(sid);
|
|
this.SERVERS = await db.getServers();
|
|
this.SERVER = this.getServer(sid);
|
|
} else {
|
|
this.SERVER = __CONFIG.def_server;
|
|
}
|
|
|
|
if (!this.SERVER) throw "服务器设置错误,无法启动";
|
|
this.SERVERID = this.SERVER.id;
|
|
|
|
await db.initDataDir();
|
|
loadResource();
|
|
await this.DATA.load();
|
|
await this.LISTENER.start(this.SERVER.port);
|
|
console.log("服务", this.SERVER.name, "(" + this.SERVERID + ")启动");
|
|
console.log("ws://" + this.SERVER.ip + ":" + this.SERVER.port);
|
|
this.heart_beat_service = setInterval(WORLD.heart_beat, __CONFIG.HEARTBEAT);
|
|
|
|
this.status = __CONFIG.CONNECT_LEVEL ?? 0;
|
|
this.on_startup();
|
|
if (this.status > 0)
|
|
console.log('当前允许级别' + this.status + "账号登陆");
|
|
},
|
|
|
|
|
|
sendAll: function (msg) {
|
|
for (var i = 0; i < WORLD.USERS.length; i++) {
|
|
WORLD.USERS[i].send(msg);
|
|
}
|
|
},
|
|
getUser: function (id) {
|
|
if (!id) return;
|
|
for (var i = 0; i < WORLD.USERS.length; i++) {
|
|
if (WORLD.USERS[i].id == id) return WORLD.USERS[i];
|
|
}
|
|
|
|
}, find_user: function (name) {
|
|
if (!name) return;
|
|
for (var i = 0; i < WORLD.USERS.length; i++) {
|
|
if (WORLD.USERS[i].name == name) return WORLD.USERS[i];
|
|
}
|
|
},
|
|
on_user_login: function (user) {
|
|
|
|
},
|
|
on_user_cross_login: function (user) {
|
|
|
|
},
|
|
on_startup: function () {
|
|
|
|
},
|
|
on_user_quit: function (user) {
|
|
|
|
},
|
|
on_user_relogin: function (user) {
|
|
|
|
}
|
|
,
|
|
on_heart_beat: function (user) {
|
|
|
|
},
|
|
heart_beat: function () {
|
|
var avtived_obj = null;
|
|
try {
|
|
const dt = Date.now();
|
|
WORLD.CONNECT_COUNT = 0;
|
|
for (let i = 0; i < WORLD.USERS.length; i++) {
|
|
avtived_obj = WORLD.USERS[i];
|
|
if (avtived_obj.socket) WORLD.CONNECT_COUNT++;
|
|
avtived_obj.heart_beat(dt);
|
|
}
|
|
WORLD.on_heart_beat(dt);
|
|
for (let i = 0; i < WORLD.RUN_ROOMS.length; i++) {
|
|
avtived_obj = WORLD.RUN_ROOMS[i];
|
|
avtived_obj.heart_beat(dt);
|
|
}
|
|
WORLD.HEARTBEATCOUNT++;
|
|
if (WORLD.HEARTBEATCOUNT > 720) {
|
|
WORLD.HEARTBEATCOUNT = 0;
|
|
WORLD.save();
|
|
console.log("数据已备份%d", Date.now() - dt);
|
|
}
|
|
} catch (e) {
|
|
console.log(avtived_obj ? (avtived_obj.path ?? avtived_obj.name) : "", "心跳错误:", e, e.stack);
|
|
WORLD.log(null, e.message, e.stack);
|
|
}
|
|
|
|
},
|
|
login_out: function (user) {
|
|
this.on_user_quit(user);
|
|
if (user.serverid === WORLD.SERVERID) {
|
|
user.save();
|
|
}
|
|
WORLD.USERS.remove(user);
|
|
|
|
if (user.socket) {
|
|
try {
|
|
user.socket.end();
|
|
user.socket.destroy();
|
|
} catch (e) {
|
|
console.log(e.message, e.stack);
|
|
}
|
|
}
|
|
}, send: function (text) {
|
|
for (var i = 0; i < this.USERS.length; i++) {
|
|
this.USERS[i].send(text);
|
|
}
|
|
}, log: function (user, cmd, msg) {
|
|
WORLD.LOGS.push({
|
|
time: Date.now(),
|
|
cmd: cmd,
|
|
user: user ? user.name : "",
|
|
msg: msg
|
|
});
|
|
if (WORLD.LOGS.length > 500) {
|
|
db.saveLogs(WORLD.LOGS);
|
|
WORLD.LOGS.length = 0;
|
|
}
|
|
}, saveLog: function () {
|
|
db.saveLogs(WORLD.LOGS);
|
|
WORLD.LOGS.length = 0;
|
|
}
|
|
,
|
|
is_server: function (user) {
|
|
return user.serverid == WORLD.SERVERID;
|
|
},
|
|
save: async function () {
|
|
|
|
var roles = [];
|
|
for (var i = 0; i < WORLD.USERS.length; i++) {
|
|
if (WORLD.USERS[i].serverid != WORLD.SERVERID) continue;
|
|
roles.push(WORLD.USERS[i].getData());
|
|
}
|
|
try {
|
|
console.time('saved');
|
|
await db.saveRoles(roles);
|
|
console.log('玩家数据已保存');
|
|
await this.DATA.save();
|
|
console.log('全局数据已经保存');
|
|
await this.saveLog();
|
|
await this.saveRequest();
|
|
console.log('日志数据已经保存');
|
|
console.timeEnd('saved');
|
|
return true;
|
|
} catch (error) {
|
|
console.error('玩家数据保存失败', error.message);
|
|
return false;
|
|
}
|
|
},
|
|
writeHeapSnapshot: function () {
|
|
let v8 = UTIL.require('v8');
|
|
let dt = new Date();
|
|
let fname = __PATH.DATA + "/" + dt.getFullYear() + "_" + dt.getMonth() + "_"
|
|
+ dt.getDate() + "_" + dt.getHours() + "_" + dt.getMinutes() + ".heapsnapshot";
|
|
v8.writeHeapSnapshot(fname);
|
|
console.log('快照保存到', fname);
|
|
}
|
|
,
|
|
loadLocalData: function () {
|
|
let data = db.getLocalRoles();
|
|
if (!data || !data.length) return;
|
|
console.log("加载上次未保存的本地用户%d", data.length);
|
|
for (let i = 0; i < data.length; i++) {
|
|
let user = new USER();
|
|
user.loadData(data[i]);
|
|
this.USERS.push(user);
|
|
}
|
|
db.deleteLocalRoles();
|
|
},
|
|
on_cross_response: function (id, sid) {
|
|
//允许跨服
|
|
},
|
|
can_cross: function (id) {
|
|
//允许跨服
|
|
}, on_user_die: function (me, killer, corpse) {
|
|
|
|
}, on_resource_loaded: function () {
|
|
|
|
}
|
|
};
|
|
function loadResource() {
|
|
let fs = require("fs");
|
|
function readdir(basePath, path) {
|
|
path = path || basePath;
|
|
let files = fs.readdirSync(path);
|
|
let count = 0;
|
|
for (let i = 0; i < files.length; i++) {
|
|
let sub_path = path + files[i];
|
|
let stat = fs.statSync(sub_path);
|
|
if (stat.isDirectory()) {
|
|
count += readdir(basePath, sub_path + "/");
|
|
} else {
|
|
let fname = sub_path.replace(basePath, "").replace(".js", "");
|
|
BASE.CREATE(basePath, fname);
|
|
count++;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
try {
|
|
let sum = 0;
|
|
let count = readdir(__PATH.EXTENDS);
|
|
console.log("%s %d ", __PATH.EXTENDS, count);
|
|
sum += count;
|
|
count = readdir(__PATH.COMMAND);
|
|
console.log("%s%d ", __PATH.COMMAND, count);
|
|
sum += count;
|
|
count = readdir(__PATH.FAMILY);
|
|
console.log("%s %d ", __PATH.FAMILY, count);
|
|
sum += count;
|
|
|
|
|
|
count = readdir(__PATH.OBJ);
|
|
console.log("%s %d ", __PATH.OBJ, count);
|
|
sum += count;
|
|
|
|
count = readdir(__PATH.AREA);
|
|
console.log("%s %d ", __PATH.AREA, count);
|
|
sum += count;
|
|
|
|
count = readdir(__PATH.SKILL);
|
|
console.log("%s %d ", __PATH.SKILL, count);
|
|
sum += count;
|
|
|
|
count = readdir(__PATH.MAP);
|
|
console.log("%s %d ", __PATH.MAP, count);
|
|
sum += count;
|
|
count = readdir(__PATH.TASK);
|
|
console.log("%s %d ", __PATH.TASK, count);
|
|
sum += count;
|
|
console.log('资源脚本加载%d', sum);
|
|
WORLD.on_resource_loaded();
|
|
} catch (e) {
|
|
console.log("error: ", e, e.stack);
|
|
}
|
|
}
|