403 lines
9.3 KiB
JavaScript
403 lines
9.3 KiB
JavaScript
(function () {
|
|
var WebSocketServer = require("ws").Server;
|
|
var wss = new WebSocketServer({ port: 8080 });
|
|
var bannedKeys = [];
|
|
var bannedIps = [];
|
|
|
|
var rooms = [];
|
|
var events = [];
|
|
var clients = {};
|
|
var bannedKeyWords = [];
|
|
var messages = {
|
|
create: function (key, nickname, avatar, config, mode) {
|
|
if (this.onlineKey != key) return;
|
|
this.nickname = util.getNickname(nickname);
|
|
this.avatar = avatar;
|
|
var room = {};
|
|
rooms.push(room);
|
|
this.room = room;
|
|
delete this.status;
|
|
room.owner = this;
|
|
room.key = key;
|
|
this.sendl("createroom", key);
|
|
},
|
|
enter: function (key, nickname, avatar) {
|
|
this.nickname = util.getNickname(nickname);
|
|
this.avatar = avatar;
|
|
var room = false;
|
|
for (var i of rooms) {
|
|
if (i.key == key) {
|
|
room = i;
|
|
break;
|
|
}
|
|
}
|
|
if (!room) {
|
|
this.sendl("enterroomfailed");
|
|
return;
|
|
}
|
|
this.room = room;
|
|
delete this.status;
|
|
if (room.owner) {
|
|
if (
|
|
room.servermode &&
|
|
!room.owner._onconfig &&
|
|
config &&
|
|
mode
|
|
) {
|
|
room.owner.sendl("createroom", index, config, mode);
|
|
room.owner._onconfig = this;
|
|
room.owner.nickname = util.getNickname(nickname);
|
|
room.owner.avatar = avatar;
|
|
} else if (
|
|
!room.config ||
|
|
(room.config.gameStarted &&
|
|
(!room.config.observe || !room.config.observeReady))
|
|
) {
|
|
this.sendl("enterroomfailed");
|
|
} else {
|
|
this.owner = room.owner;
|
|
this.owner.sendl("onconnection", this.wsid);
|
|
}
|
|
util.updaterooms();
|
|
}
|
|
},
|
|
changeAvatar: function (nickname, avatar) {
|
|
this.nickname = util.getNickname(nickname);
|
|
this.avatar = avatar;
|
|
util.updateclients();
|
|
},
|
|
server: function (cfg) {
|
|
if (cfg) {
|
|
this.servermode = true;
|
|
var room = rooms[cfg[0]];
|
|
if (!room || room.owner) {
|
|
this.sendl("reloadroom", true);
|
|
} else {
|
|
room.owner = this;
|
|
this.room = room;
|
|
this.nickname = util.getNickname(cfg[1]);
|
|
this.avatar = cfg[2];
|
|
this.sendl("createroom", cfg[0], {}, "auto");
|
|
}
|
|
} else {
|
|
for (var i = 0; i < rooms.length; i++) {
|
|
if (!rooms[i].owner) {
|
|
rooms[i].owner = this;
|
|
rooms[i].servermode = true;
|
|
this.room = rooms[i];
|
|
this.servermode = true;
|
|
break;
|
|
}
|
|
}
|
|
util.updaterooms();
|
|
}
|
|
},
|
|
key: function (id) {
|
|
if (!id || typeof id != "object") {
|
|
this.sendl("denied", "key");
|
|
this.close();
|
|
clearTimeout(this.keyCheck);
|
|
delete this.keyCheck;
|
|
return;
|
|
} else if (bannedKeys.indexOf(id[0]) != -1) {
|
|
bannedIps.push(this._socket.remoteAddress);
|
|
this.close();
|
|
}
|
|
this.onlineKey = id[0];
|
|
clearTimeout(this.keyCheck);
|
|
delete this.keyCheck;
|
|
},
|
|
events: function (cfg, id, type) {
|
|
if (
|
|
bannedKeys.indexOf(id) != -1 ||
|
|
typeof id != "string" ||
|
|
this.onlineKey != id
|
|
) {
|
|
bannedIps.push(this._socket.remoteAddress);
|
|
console.log(id, this._socket.remoteAddress);
|
|
this.close();
|
|
return;
|
|
}
|
|
var changed = false;
|
|
var time = new Date().getTime();
|
|
if (cfg && id) {
|
|
if (typeof cfg == "string") {
|
|
for (var i = 0; i < events.length; i++) {
|
|
if (events[i].id == cfg) {
|
|
if (type == "join") {
|
|
if (events[i].members.indexOf(id) == -1) {
|
|
events[i].members.push(id);
|
|
}
|
|
changed = true;
|
|
} else if (type == "leave") {
|
|
var index = events[i].members.indexOf(id);
|
|
if (index != -1) {
|
|
events[i].members.splice(index, 1);
|
|
if (events[i].members.length == 0) {
|
|
events.splice(i--, 1);
|
|
}
|
|
}
|
|
changed = true;
|
|
}
|
|
}
|
|
}
|
|
} else if (
|
|
cfg.hasOwnProperty("utc") &&
|
|
cfg.hasOwnProperty("day") &&
|
|
cfg.hasOwnProperty("hour") &&
|
|
cfg.hasOwnProperty("content")
|
|
) {
|
|
if (events.length >= 20) {
|
|
this.sendl("eventsdenied", "total");
|
|
} else if (cfg.utc <= time) {
|
|
this.sendl("eventsdenied", "time");
|
|
} else if (util.isBanned(cfg.content)) {
|
|
this.sendl("eventsdenied", "ban");
|
|
} else {
|
|
cfg.nickname = util.getNickname(cfg.nickname);
|
|
cfg.avatar = cfg.nickname || "caocao";
|
|
cfg.creator = id;
|
|
cfg.id = util.getid();
|
|
cfg.members = [id];
|
|
events.unshift(cfg);
|
|
changed = true;
|
|
}
|
|
}
|
|
}
|
|
if (changed) {
|
|
util.updateevents();
|
|
}
|
|
},
|
|
config: function (config) {
|
|
var room = this.room;
|
|
if (room && room.owner == this) {
|
|
if (room.servermode) {
|
|
room.servermode = false;
|
|
if (this._onconfig) {
|
|
if (clients[this._onconfig.wsid]) {
|
|
this._onconfig.owner = this;
|
|
this.sendl("onconnection", this._onconfig.wsid);
|
|
}
|
|
delete this._onconfig;
|
|
}
|
|
}
|
|
room.config = config;
|
|
}
|
|
util.updaterooms();
|
|
},
|
|
status: function (str) {
|
|
if (typeof str == "string") {
|
|
this.status = str;
|
|
} else {
|
|
delete this.status;
|
|
}
|
|
util.updateclients();
|
|
},
|
|
send: function (id, message) {
|
|
if (clients[id] && clients[id].owner == this) {
|
|
try {
|
|
clients[id].send(message);
|
|
} catch (e) {
|
|
clients[id].close();
|
|
}
|
|
}
|
|
},
|
|
close: function (id) {
|
|
if (clients[id] && clients[id].owner == this) {
|
|
clients[id].close();
|
|
}
|
|
},
|
|
};
|
|
var util = {
|
|
getNickname: function (str) {
|
|
return typeof str == "string" ? str.slice(0, 12) : "无名玩家";
|
|
},
|
|
isBanned: function (str) {
|
|
for (var i of bannedKeyWords) {
|
|
if (str.indexOf(i) != -1) return true;
|
|
}
|
|
return false;
|
|
},
|
|
sendl: function () {
|
|
var args = [];
|
|
for (var i = 0; i < arguments.length; i++) {
|
|
args.push(arguments[i]);
|
|
}
|
|
try {
|
|
this.send(JSON.stringify(args));
|
|
} catch (e) {
|
|
this.close();
|
|
}
|
|
},
|
|
getid: function () {
|
|
return Math.floor(
|
|
1000000000 + 9000000000 * Math.random()
|
|
).toString();
|
|
},
|
|
getroomlist: function () {
|
|
var roomlist = [];
|
|
for (var i = 0; i < rooms.length; i++) {
|
|
rooms[i]._num = 0;
|
|
}
|
|
for (var i in clients) {
|
|
if (clients[i].room && !clients[i].servermode) {
|
|
clients[i].room._num++;
|
|
}
|
|
}
|
|
for (var i = 0; i < rooms.length; i++) {
|
|
if (rooms[i].servermode) {
|
|
roomlist[i] = "server";
|
|
} else if (rooms[i].owner && rooms[i].config) {
|
|
if (rooms[i]._num == 0) {
|
|
rooms[i].owner.sendl("reloadroom");
|
|
}
|
|
roomlist.push([
|
|
rooms[i].owner.nickname,
|
|
rooms[i].owner.avatar,
|
|
rooms[i].config,
|
|
rooms[i]._num,
|
|
rooms[i].key,
|
|
]);
|
|
}
|
|
delete rooms[i]._num;
|
|
}
|
|
return roomlist;
|
|
},
|
|
getclientlist: function () {
|
|
var clientlist = [];
|
|
for (var i in clients) {
|
|
clientlist.push([
|
|
clients[i].nickname,
|
|
clients[i].avatar,
|
|
!clients[i].room,
|
|
clients[i].status,
|
|
clients[i].wsid,
|
|
clients[i].onlineKey,
|
|
]);
|
|
}
|
|
return clientlist;
|
|
},
|
|
updaterooms: function () {
|
|
var roomlist = util.getroomlist();
|
|
var clientlist = util.getclientlist();
|
|
for (var i in clients) {
|
|
if (!clients[i].room) {
|
|
clients[i].sendl("updaterooms", roomlist, clientlist);
|
|
}
|
|
}
|
|
},
|
|
updateclients: function () {
|
|
var clientlist = util.getclientlist();
|
|
for (var i in clients) {
|
|
if (!clients[i].room) {
|
|
clients[i].sendl("updateclients", clientlist);
|
|
}
|
|
}
|
|
},
|
|
checkevents: function () {
|
|
if (events.length) {
|
|
var time = new Date().getTime();
|
|
for (var i = 0; i < events.length; i++) {
|
|
if (events[i].utc <= time) {
|
|
events.splice(i--, 1);
|
|
}
|
|
}
|
|
}
|
|
return events;
|
|
},
|
|
updateevents: function () {
|
|
util.checkevents();
|
|
for (var i in clients) {
|
|
if (!clients[i].room) {
|
|
clients[i].sendl("updateevents", events);
|
|
}
|
|
}
|
|
},
|
|
};
|
|
wss.on("connection", function (ws) {
|
|
ws.sendl = util.sendl;
|
|
if (bannedIps.indexOf(ws._socket.remoteAddress) != -1) {
|
|
ws.sendl("denied", "banned");
|
|
setTimeout(function () {
|
|
ws.close();
|
|
}, 500);
|
|
return;
|
|
}
|
|
ws.keyCheck = setTimeout(function () {
|
|
ws.sendl("denied", "key");
|
|
setTimeout(function () {
|
|
ws.close();
|
|
}, 500);
|
|
}, 2000);
|
|
ws.wsid = util.getid();
|
|
clients[ws.wsid] = ws;
|
|
ws.sendl(
|
|
"roomlist",
|
|
util.getroomlist(),
|
|
util.checkevents(),
|
|
util.getclientlist(ws),
|
|
ws.wsid
|
|
);
|
|
ws.heartbeat = setInterval(function () {
|
|
if (ws.beat) {
|
|
ws.close();
|
|
clearInterval(ws.heartbeat);
|
|
} else {
|
|
ws.beat = true;
|
|
try {
|
|
ws.send("heartbeat");
|
|
} catch (e) {
|
|
ws.close();
|
|
}
|
|
}
|
|
}, 60000);
|
|
ws.on("message", function (message) {
|
|
if (!clients[this.wsid]) return;
|
|
if (message == "heartbeat") {
|
|
this.beat = false;
|
|
} else if (this.owner) {
|
|
this.owner.sendl("onmessage", this.wsid, message);
|
|
} else {
|
|
var arr;
|
|
try {
|
|
arr = JSON.parse(message);
|
|
if (!Array.isArray(arr)) {
|
|
throw "err";
|
|
}
|
|
} catch (e) {
|
|
this.sendl("denied", "banned");
|
|
return;
|
|
}
|
|
if (arr.shift() == "server") {
|
|
var type = arr.shift();
|
|
if (messages[type]) {
|
|
messages[type].apply(this, arr);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
ws.on("close", function () {
|
|
for (var i = 0; i < rooms.length; i++) {
|
|
if (rooms[i].owner == this) {
|
|
for (var j in clients) {
|
|
if (clients[j].room == rooms[i] && clients[j] != this) {
|
|
clients[j].sendl("selfclose");
|
|
// clients[j].close();
|
|
// delete clients[j];
|
|
}
|
|
}
|
|
rooms.splice(i--, 1);
|
|
}
|
|
}
|
|
if (clients[this.wsid]) {
|
|
if (this.owner) {
|
|
this.owner.sendl("onclose", this.wsid);
|
|
}
|
|
delete clients[this.wsid];
|
|
}
|
|
if (this.room) util.updaterooms();
|
|
else util.updateclients();
|
|
});
|
|
});
|
|
})();
|