123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603 |
- var glob = require('glob'),
- fs = require('fs'),
- crypto = require('crypto');
- session = {
- "updateRate": 3000,
- "players": {},
- "rooms": {},
- "mobiles": {},
- "mobileIds": 1,
- "items": {},
- "itemIds": 1
- };
- builder = require('./builder');
- admin = require('./admin');
- commands = require('./commands');
- rooms = require(config.worldDataPath + '/rooms');
- items = require(config.worldDataPath + '/items');
- mobiles = require(config.worldDataPath + '/mobiles');
- class World {
- constructor() {
- this.time = 0;
- this.blacklist = ["constructor"];
- this.blacklistPrefix = "mud_";
- this.timerId = -1;
- }
- mud_load() {
- if(this.timerId != -1 ) {
- clearInterval(this.timerId);
- }
- session.updateRate = 3000;
- session.rooms = {};
- session.items = {};
- session.mobiles = {};
- session.players = {};
- session.mobileIds = 1;
- session.itemIds = 1;
- //populate rooms
- for(var roomName in rooms) {
- var room = builder.mud_spawnRoom(roomName);
- if(typeof room.mud_init == 'function') {
- room.mud_init();
- }
- }
- //populate mobiles
- for(var mobileName in mobiles) {
- if(mobileName == "PlayerMobile") {
- continue;
- }
- var mobile = builder.mud_spawnMobile(mobileName);
- if(typeof mobile.mud_init == 'function') {
- mobile.mud_init(mobileName);
- } else {
- world.mud_destroyMobile(mobile.id);
- }
- }
-
- //populate items
- for(var itemName in items) {
- var item = builder.mud_spawnItem(itemName);
- if(typeof item.mud_init == 'function') {
- item.mud_init();
- } else {
- world.mud_destroyItem(item.id);
- }
- }
- this.timerId = setInterval(function() {
- world.mud_tick(Date.now());
- }, session.updateRate);
- }
- mud_handleInput(roomName, mobileId, input) {
- var room = this.mud_getRoom(roomName);
- var mobile = this.mud_getMobile(mobileId);
- var command = input.shift();
- if(command.indexOf(this.blacklistPrefix) != -1) {
- libs.Output.toMobile(mobile.id, "I didn't understand that.");
- return true;
- }
- if(this.blacklist.indexOf(command) != -1) {
- libs.Output.toMobile(mobile.id, "I didn't understand that.");
- return true;
- }
- if (world.mud_mobileHasRole(mobile.id, "admin") && typeof admin[command] == 'function') {
- try {
- if(admin[command](room, mobile, input)) {
- return true;
- }
- } catch (error) {
- libs.Output.toServerError("Exception in admin tools - ", error);
- libs.Output.toMobile(mobile.id, "The administration tools are misbehaving.");
- if(world.mud_mobileHasRole(mobile.id, "admin")) {
- libs.Output.toMobile(mobile.id, error.code + " " + error.stack + "\n");
- }
- }
- }
- if (world.mud_mobileHasRole(mobile.id, "builder") && typeof builder[command] == 'function') {
- try {
- if(builder[command](room, mobile, input)) {
- return true;
- }
- } catch (error) {
- libs.Output.toServerError("Exception in builder tools - ", error);
- libs.Output.toMobile(mobile.id, "The build tools are misbehaving.");
- if(world.mud_mobileHasRole(mobile.id, "admin")) {
- libs.Output.toMobile(mobile.id, error.code + " " + error.stack + "\n");
- }
- }
- }
- for (var itemIndex in mobile.items) {
- var otherItem = this.mud_getItem(mobile.items[itemIndex]);
- if(typeof otherItem[command] == 'function') {
- try {
- if(otherItem[command](room, mobile, input)) {
- return true;
- }
- } catch (error) {
- libs.Output.toServerError("Exception in mobile item: " + mobile.constructor.name + ":" +mobile.id+","+otherItem.constructor.name+":"+otherItem.id+" - ", error);
- libs.Output.toMobile(mobile.id, otherItem.name + " you are holding {error}glitches{/error} for a second.");
- if(world.mud_mobileHasRole(mobile.id, "builder")) {
- libs.Output.toMobile(mobile.id, error.code + " " + error.stack + "\n");
- }
- }
- }
- }
- if(typeof mobile[command] == 'function') {
- try {
- if(mobile[command](room, mobile, input)) {
- return true;
- }
- } catch (error) {
- libs.Output.toServerError("Exception in mobile: " + mobile.constructor.name + ":" +mobile.id+" - ", error);
- libs.Output.toMobile(mobile.id, "You feel funny and {error}not quite right{/error}.");
- if(world.mud_mobileHasRole(mobile.id, "builder")) {
- libs.Output.toMobile(mobile.id, error.code + " " + error.stack + "\n");
- }
- }
- }
- for (var itemIndex in room.items) {
- var otherItem = this.mud_getItem(room.items[itemIndex]);
- if(typeof otherItem[command] == 'function') {
- try {
- if(otherItem[command](room, mobile, input)) {
- return true;
- }
- } catch (error) {
- libs.Output.toServerError("Exception in room item: " + room.constructor.name + ","+otherItem.constructor.name+":"+otherItem.id+" - ", error);
- libs.Output.toMobile(mobile.id, otherItem.name + " here {error}glitches{/error} for a second.");
- if(world.mud_mobileHasRole(mobile.id, "builder")) {
- libs.Output.toMobile(mobile.id, error.code + " " + error.stack + "\n");
- }
- }
- }
- }
- for (var mobileIndex in room.mobiles) {
- var otherMobile = this.mud_getMobile(room.mobiles[mobileIndex]);
- if(typeof otherMobile[command] == 'function') {
- try {
- if(otherMobile[command](room, mobile, input)) {
- return true;
- }
- } catch (error) {
- libs.Output.toServerError("Exception in room mobile: " + room.constructor.name + "," + otherMobile.constructor.name +":"+otherMobile.id+" - ", error);
- libs.Output.toMobile(mobile.id, otherMobile.name + " {error}staggers{/error} in and out of reality.");
- if(world.mud_mobileHasRole(mobile.id, "builder")) {
- libs.Output.toMobile(mobile.id, error.code + " " + error.stack + "\n");
- }
- }
- }
- }
- if(typeof room[command] == 'function') {
- try {
- if(room[command](room, mobile, input)) {
- return true;
- }
- } catch (error) {
- libs.Output.toServerError("Exception in room: " + room.id + " - ", error);
- libs.Output.toMobile(mobile.id, "You see strange {error}glitch errors{/error} in the surrounding area.");
- if(world.mud_mobileHasRole(mobile.id, "builder")) {
- libs.Output.toMobile(mobile.id, error.code + " " + error.stack + "\n");
- }
- }
- }
- for(var commanderClass in commands) {
- var commander = new commands[commanderClass]();
- if (typeof commander[command] == 'function') {
- try {
- if(commander[command](room, mobile, input)) {
- return true;
- }
- } catch (error) {
- libs.Output.toServerError("Exception in command: " + commanderClass + " - ", error);
- libs.Output.toMobile(mobile.id, commander.mud_getErrorMessage());
- if(world.mud_mobileHasRole(mobile.id, "builder")) {
- libs.Output.toMobile(mobile.id, error.code + " " + error.stack + "\n");
- }
- }
- }
- }
- libs.Output.toMobile(mobile.id, "I didn't understand that.");
- return true;
- }
- mud_tick(time) {
- try {
- for(var roomName in session.rooms) {
- var room = this.mud_getRoom(roomName);
- if(typeof room.mud_tick == 'function') {
- room.mud_tick(time);
- }
- }
- } catch (error) {
- libs.Output.worldToMobiles("The flow of time seems to {error}stutter{/error} a second.");
- libs.Output.toBuildersError("Room tick error", error);
- libs.Output.toServerError("Room tick error", error);
- }
- try {
- for(var mobileId in session.mobiles) {
- var mobile = this.mud_getMobile(mobileId);
- if(mobile == null) {
- console.log("null mobile", mobile);
- continue;
- }
- if(typeof mobile.mud_tick == 'function') {
- mobile.mud_tick(time);
- }
- }
- } catch (error) {
- libs.Output.worldToMobiles("Lifeforms in the universe {error}skip{/error} a unified heartbeat.");
- libs.Output.toBuildersError("Mobile tick error", error);
- libs.Output.toServerError("Mobile tick error", error);
- }
- try {
- for(var itemId in session.items) {
- var item = this.mud_getItem(itemId);
- if(item == null) {
- console.log("null item", item);
- continue;
- }
- if(typeof item.mud_tick == 'function') {
- item.mud_tick(time);
- }
- }
- } catch (error) {
- libs.Output.worldToMobiles("Items everywhere {error}flicker{/error} out of reality for a second.");
- libs.Output.toBuildersError("Item tick error", error);
- libs.Output.toServerError("Item tick error", error);
- }
- this.time++;
- this.time %= 640;
- switch(this.time) {
- case 0:
- //text must include dawn
- libs.Output.worldToMobiles("{global}Dawn breaks as the sun begins to rise.{/global}");
- this.mud_allPlayersSave();
- break;
- case 160:
- //text must include midday
- libs.Output.worldToMobiles("{global}The sky is a clear, crisp cerulean to hold the bright midday sun.{/global}");
- this.mud_allPlayersSave();
- break;
- case 320:
- //text must include twilight
- libs.Output.worldToMobiles("{global}Twilight creeps in slowly as the sun begins to set.{/global}");
- this.mud_allPlayersSave();
- break;
- case 480:
- //text must include midnight
- libs.Output.worldToMobiles("{global}Stars twinkle in the midnight sky.{/global}");
- this.mud_allPlayersSave();
- break;
- }
- }
- mud_moveMobile(mobileId, sourceRoom, destinationRoom, outDirection, inDirection) {
- if(session.rooms[destinationRoom] == null) {
- libs.Output.toMobile(mobileId, destinationRoom + " doesn't seem to exist yet.");
- return;
- }
- this.mud_moveMobileFromRoom(sourceRoom, mobileId, outDirection);
- this.mud_moveMobileToRoom(destinationRoom, mobileId, inDirection);
- }
- mud_moveMobileToRoom(roomName, mobileId, direction) {
- var mobileObj = this.mud_getMobile(mobileId);
- if(typeof mobileObj.mud_enterRoom == "function") {
- libs.Output.toRoom(roomName, mobileObj.mud_enterRoom(direction), mobileObj);
- } else {
- if(direction != null) {
- libs.Output.toRoom(roomName, mobileObj.mud_getName() + " " + direction + ".");
- } else {
- libs.Output.toRoom(roomName, mobileObj.mud_getName() + " arrives.", mobileObj);
- }
- }
- this.mud_addMobileToRoom(roomName, mobileId);
- this.mud_handleInput(roomName, mobileId, ["look"]);
- }
- mud_moveMobileFromRoom(roomName, mobileId, direction) {
- var mobileObj = this.mud_getMobile(mobileId);
- this.mud_removeMobileFromRoom(roomName, mobileId);
- if(typeof mobileObj.mud_leaveRoom == "function") {
- libs.Output.toRoom(roomName, mobileObj.mud_leaveRoom(direction), mobileObj);
- } else {
- if(direction != null) {
- libs.Output.toRoom(roomName, mobileObj.mud_getName() + " " + direction + ".");
- } else {
- libs.Output.toRoom(roomName, mobileObj.mud_getName() + " leaves.", mobileObj);
- }
- }
- }
- mud_getItem(itemId) {
- var item = session.items[itemId];
- if(item == null) {
- throw new Error("Item '"+itemId+"' not defined.");
- }
- return item;
- }
- mud_getMobile(mobileId) {
- var mobile = session.mobiles[mobileId];
- if(mobile == null) {
- throw new Error("Mobile '"+mobileId+"' not defined.");
- }
- return mobile;
- }
- mud_getRoom(roomName) {
- var room = session.rooms[roomName];
- if(room == null) {
- throw new Error("Room '"+roomName+"' not defined.");
- }
- return room;
- }
- mud_addMobileToRoom(roomName, mobileId) {
- var mobileObj = this.mud_getMobile(mobileId);
- var roomObj = this.mud_getRoom(roomName);
- mobileObj.roomId = roomName;
- roomObj.mobiles.push(mobileId);
- }
- mud_removeMobileFromRoom(roomName, mobileId) {
- var room = this.mud_getRoom(roomName);
- room.mobiles.splice(room.mobiles.indexOf(mobileId), 1);
- }
- mud_addItemToRoom(roomName, itemId) {
- var room = this.mud_getRoom(roomName);
- if(room.items.indexOf(itemId) == -1) {
- room.items.push(itemId);
- var item = world.mud_getItem(itemId);
- item.inRoom = roomName;
- }
- }
- mud_addItemToMobile(mobileId, itemId) {
- var mobile = this.mud_getMobile(mobileId);
- if(mobile.items.indexOf(itemId) == -1) {
- mobile.items.push(itemId);
- var item = world.mud_getItem(itemId);
- item.heldBy = mobileId;
- }
- }
- mud_removeItemFromMobile(mobileId, itemId) {
- var mobile = session.mobiles[mobileId];
- for(var slotIndex in mobile.itemSlots) {
- var slot = mobile.itemSlots[slotIndex];
- if(slot == itemId) {
- mobile.itemSlots[slotIndex] = null;
- var item = world.mud_getItem(itemId);
- item.isWorn = -1;
- item.heldBy = -1;
- }
- }
- if(mobile.items.indexOf(itemId) != -1) {
- mobile.items.splice(mobile.items.indexOf(itemId), 1);
- }
- }
- mud_removeItemFromRoom(roomId, itemId) {
- var room = session.rooms[roomId];
- room.items.splice(room.items.indexOf(itemId), 1);
- var item = world.mud_getItem(itemId);
- item.inRoom = -1;
- }
- mud_destroyItem(itemId) {
- delete session.items[itemId];
- }
- mud_destroyMobile(mobileId) {
- delete session.mobiles[mobileId];
- }
- mud_mobileHasRole(mobileId, role) {
- var mobile = session.mobiles[mobileId];
- if(mobile.roles != null) {
- return mobile.roles.indexOf(role) != -1;
- }
- return false;
- }
- mud_generateHash(input) {
- return crypto.createHash('sha256').update(input).digest("base64");
- }
- mud_getUserData(username) {
- var playerFilename = config.playerDataPath+ "/"+username.toLowerCase().trim()+".json";
- var files = glob.sync(playerFilename, {} );
- if(files.length == 1) {
- var fileData = fs.readFileSync(files[0], "utf8");
- return JSON.parse(fileData);
- }
- return null;
- }
- mud_isValidLogin(userData, password) {
- var hash = crypto.createHash('sha256').update(userData.username.toLowerCase().trim() + password).digest("base64");
- if(userData.password == hash) {
- return true;
- }
- return false;
- }
- mud_playerLoad(login, userData) {
- for(var activePlayerId in session.players) {
- var activePlayer = session.players[activePlayerId];
- if(activePlayer.password == userData.password) {
- libs.Output.toMobile(activePlayer.id, "You are being booted by another login.");
- var oldLogin = activePlayer.login.reconnect(login);
- login.player = activePlayer;
- login.setConnectionTimeout(activePlayer.connectionTimeout);
- return;
- }
- }
- var player = builder.mud_spawnMobile("PlayerMobile");
- player.login = login;
- player.connectionTimeout = userData.connectionTimeout || 0;
- player.login.setConnectionTimeout(player.connectionTimeout);
- player.name = userData.username;
- player.description = userData.description || "A player";
- player.password = userData.password;
- player.roomId = userData.roomName || "ZebedeeTemple";
- player.hintColor = userData.hintColor || "FgMagenta";
- player.terminalWidthPreference = userData.terminalWidthPreference || 78;
- player.connectionTimeout = userData.connectionTimeout || 0;
-
- player.keywords.push(player.name.toLowerCase());
- player.roles = userData.roles || [];
- player.title = userData.title || "the Player";
- player.pubKeys = userData.pubKeys || [];
- player.account = parseInt(userData.account) || 0;
- for(var itemIdIndex in userData.items) {
- var loadedItemData = userData.items[itemIdIndex];
- var loadedItem = builder.mud_spawnItem(loadedItemData.classname);
- if(typeof loadedItem.mud_loadItem == "function") {
- loadedItem.mud_loadItem(loadedItemData);
- }
- this.mud_addItemToMobile(player.id, loadedItem.id);
- }
- player.aliases = userData.aliases;
- for(var aliasKey in userData.aliases) {
- player.mud_setAlias(aliasKey, userData.aliases[aliasKey]);
- }
- login.player = player;
- world.mud_attachPlayer(player);
- }
- mud_attachPlayer(player) {
- this.mud_addMobileToRoom(player.roomId, player.id);
- session.players[player.id] = player;
- var joinMessage = player.name + " joined the server.";
- libs.Output.toServer(joinMessage);
- libs.Output.worldToMobiles(joinMessage, player);
- this.mud_handleInput(player.roomId, player.id, ["look"]);
- }
- mud_playerSave(player) {
- var playerFilename = config.playerDataPath+ "/"+player.name.toLowerCase().trim()+".json";
- var userData = {};
- userData.username = player.name;
- userData.password = player.password,
- userData.roomName = session.rooms[player.roomId].constructor.name;
- userData.hintColor = player.hintColor;
- userData.description = player.description;
- userData.terminalWidthPreference = player.terminalWidthPreference;
- userData.connectionTimeout = player.connectionTimeout;
- userData.roles = player.roles;
- userData.title = player.title;
- userData.pubKeys = player.pubKeys;
- userData.account = player.account;
- var items = [];
- for(var itemIdIndex in player.items) {
- var savedItem = {};
- if(typeof session.items[player.items[itemIdIndex]].mud_saveItem == "function") {
- savedItem = session.items[player.items[itemIdIndex]].mud_saveItem();
- }
- savedItem.classname = session.items[player.items[itemIdIndex]].constructor.name;
- items.push(savedItem);
- }
- userData.items = items;
- userData.aliases = player.aliases;
-
- fs.writeFile(playerFilename, JSON.stringify(userData, null, "\t"), (err) => {
- if (err) {
- throw err;
- }
- libs.Output.toServer("saved player data " + playerFilename);
- });
- }
- mud_allPlayersSave() {
- for(var index in session.players) {
- var player = session.players[index];
- this.mud_playerSave(player);
- }
- }
- mud_playerQuit(player) {
- this.mud_playerSave(player);
- var playerId = player.id;
- for(var itemIdIndex in player.items) {
- var item = session.items[player.items[itemIdIndex]];
- this.mud_removeItemFromMobile(player.id, item.id);
- this.mud_destroyItem(item.id);
- }
- this.mud_removeMobileFromRoom(player.roomId, player.id);
- delete session.players[player.id];
- this.mud_destroyMobile(playerId);
- libs.Output.toServer(player.mud_getName() + " left the server.");
- libs.Output.worldToMobiles(player.mud_getName() + " left the server.", player);
- return true;
- }
- mud_rollRandom(probabilitySet) {
- var rollValue = parseInt(Math.random() * 100) + 1;
- var probabilityTotal = 0;
- var sortedSet = probabilitySet.sort(function(a, b) {
- return (a.probability < b.probability) ? 1 : ((a.probability > b.probability) ? -1 : 0);
- });
- for(var index in sortedSet) {
- var row = sortedSet[index];
- probabilityTotal += row.probability;
- if(rollValue <= probabilityTotal) {
- return row.value;
- }
- }
- }
- mud_replaceRoomItem(roomId, itemName) {
- var isFound = false;
- var room = this.mud_getRoom(roomId);
- for(var i in room.items) {
- var itemId = room.items[i];
- if(this.mud_getItem(itemId).constructor.name == itemName) {
- isFound = true;
- }
- }
- if(!isFound) {
- world.mud_addItemToRoom(roomId, builder.mud_spawnItem(itemName).id);
- }
- }
- }
- module.exports = new World();
|