Comparing version 0.10.5 to 0.10.6
58
admin.js
@@ -34,2 +34,60 @@ /** Require external modules */ | ||
new world.Command({ | ||
name: `dlist`, | ||
execute: async (world, user, buffer, args) => { | ||
/** Determine length of longest area id number */ | ||
const areaIdLength = Math.max(...world.areas().map(x => x.id())).toString().length; | ||
/** Create array of all areas in the world with deployments */ | ||
const areas = world.areas().filter(x => x.deployments().length > 0); | ||
/** Loop through each area... */ | ||
areas.forEach((area, index) => { | ||
/** If this is not the first area, send new line */ | ||
if ( index > 0 ) | ||
user.send(`\r\n`); | ||
/** Send area id and name */ | ||
user.send(`Area: [${area.id().toString().padEnd(areaIdLength)}] ${area.name()}\r\n`); | ||
user.send(`******` + `*`.repeat(areaIdLength + 3 + area.name().length) + `\r\n`); | ||
/** Determine length of longest room id number */ | ||
const deploymentIdLength = Math.max(...area.deployments().map(x => x.id())).toString().length; | ||
/** Loop through each deployment in the area... */ | ||
area.deployments().forEach((deployment) => { | ||
user.send(` [${deployment.id().toString().padEnd(deploymentIdLength)}] ${world.constants().deploymentNames[deployment.type()]} - (${deployment.count()}) of subject ID #${deployment.subject()} to target ID #${deployment.target()} - ${deployment.refresh()}s refresh\r\n`); | ||
}); | ||
}); | ||
/** If there were no areas with rooms, send error */ | ||
if ( areas.length == 0 ) | ||
user.send(`There are no deployments in this world.\r\n`); | ||
} | ||
}), | ||
new world.Command({ | ||
name: `dstat`, | ||
execute: async (world, user, buffer, args) => { | ||
/** If no argument was provided, send error and return */ | ||
if ( typeof args[0] != `string` ) | ||
return user.send(`Dstat what?\r\n`); | ||
/** Parse name and count of first argument */ | ||
const [name, count] = world.parseName(user, args, 0); | ||
/** Parse depth of second argument for util inspect */ | ||
const depth = world.parseDepth(user, args, 1); | ||
/** If depth was parsed successfully... */ | ||
if ( depth >= 0 ) { | ||
/** If the number of items is less than the count, send error */ | ||
if ( world.deployments().length < count ) | ||
user.send(`You can't find a reference to that deployment anywhere.\r\n`); | ||
/** Otherwise, send util inspect of item */ | ||
else | ||
user.send(`${util.inspect(world.deployments()[count - 1], { depth: depth })}\r\n`); | ||
} | ||
} | ||
}), | ||
new world.Command({ | ||
name: `goto`, | ||
@@ -36,0 +94,0 @@ execute: async (world, user, buffer, args) => { |
@@ -9,2 +9,3 @@ /** Configure Area object */ | ||
{ name: `created`, type: `datetime`, default: new Date() }, | ||
{ name: `deployments`, type: `array`, arrayOf: { instanceOf: `Deployment` } }, | ||
{ name: `description`, type: `varchar`, length: 512, default: `This area is totally boring, who would visit here?` }, | ||
@@ -11,0 +12,0 @@ { name: `flags`, type: `Array`, arrayOf: { type: `int` } }, |
684
building.js
@@ -0,1 +1,4 @@ | ||
/** Require external modules */ | ||
const moment = require(`moment`); | ||
module.exports.createCommands = (world) => { | ||
@@ -41,6 +44,4 @@ return [ | ||
/** If a room already exists the direction specified, send error and return */ | ||
if ( user.room().exits().find(x => x.direction() == world.constants().directionShortNames.indexOf(args[1])) ) { | ||
user.send(`There is already a room in that direction.\r\n`); | ||
return; | ||
} | ||
if ( user.room().exits().find(x => x.direction() == world.constants().directionShortNames.indexOf(args[1])) ) | ||
return user.send(`There is already a room in that direction.\r\n`); | ||
@@ -65,3 +66,3 @@ /** Create area */ | ||
/** Create incoming exit */ | ||
const exit2 = await world.creatExit({ | ||
const exit2 = await world.createExit({ | ||
direction: world.constants().directionOpposites[world.constants().directionShortNames.indexOf(args[1])], | ||
@@ -71,24 +72,3 @@ room: room, | ||
}); | ||
/** Add outgoing exit to user's room */ | ||
user.room().exits().push(exit1); | ||
/** Add incoming exit to new room */ | ||
room.exits().push(exit2); | ||
/** Save user's room */ | ||
await user.room().update(world.database()); | ||
/** Save new room */ | ||
await room.update(world.database()); | ||
/** Add room to world */ | ||
world.rooms().push(room); | ||
/** Add room to area */ | ||
area.rooms().push(room); | ||
/** Save area */ | ||
await area.update(world.database()); | ||
/** Send action to user */ | ||
@@ -109,5 +89,235 @@ user.send(`You draw in ambient energy and manifest a room to the ${world.constants().directionNames[world.constants().directionShortNames.indexOf(args[1])]}.\r\n`); | ||
else if ( `deployment`.startsWith(args[0]) ) { | ||
/** Todo */ | ||
} | ||
/** If no second argument was provided, send error */ | ||
if ( typeof args[1] != `string` ) { | ||
user.send(`Create what kind of prototype deployment? [item|mobile]\r\n`); | ||
} | ||
/** Otherwise, if the second argument is 'item'... */ | ||
else if ( `item`.startsWith(args[1]) ) { | ||
/** If no third argument was provided, send error */ | ||
if ( typeof args[2] != `string` ) | ||
return user.send(`Where should this item be deployed to? [area|container|equipment|inventory|room]\r\n`); | ||
/** Otherwise, if the third argument was invalid, send error */ | ||
else if ( ![`area`, `container`, `equipment`, `inventory`, `room`].some(x => x.startsWith(args[2]) ) ) | ||
return user.send(`That's not a valid item deployment location.\r\n`); | ||
/** Otherwise, if no fourth argument was provided, send error */ | ||
else if ( typeof args[3] != `string` ) | ||
return user.send(`Where item prototype ID # is being deployed?\r\n`); | ||
/** Otherwise, if the fourth argument is not a number, send error */ | ||
else if ( isNaN(args[3]) ) | ||
return user.send(`That is not a valid item prototype ID #.\r\n`); | ||
/** Attempt to find item prototype in world with that ID # */ | ||
const itemPrototype = world.itemPrototypes().find(x => x.id() == parseInt(args[3])); | ||
/** If item prototype doesn't exist, send error */ | ||
if ( !itemPrototype ) | ||
return user.send(`That item prototype ID # does not exist.\r\n`); | ||
/** If the second argument statred with 'area'... */ | ||
if ( `area`.startsWith(args[2]) ) { | ||
/** Assume area is user's area, count is 1, and refresh is 60 seconds */ | ||
let area = user.room().area(); | ||
let count = 1; | ||
let refresh = 600; | ||
/** If there was a fifth argument provided... */ | ||
if ( typeof args[4] == `string` ) { | ||
/** Attempt to find area in the world with that ID # */ | ||
area = world.areas().find(x => x.id() == parseInt(args[4])); | ||
/** If area does not exist, send error */ | ||
if ( !area ) | ||
return user.send(`There is no area in the world with that ID #.\r\n`); | ||
} | ||
/** If there was a sixth argument provided... */ | ||
if ( typeof args[5] == `string` ) { | ||
/** If the sixth argument is not a number, send error */ | ||
if ( isNaN(args[5]) ) | ||
return user.send(`That is not a valid count number.\r\n`); | ||
/** Otherwise, if the sixth argument is not between 1 and 500, send error */ | ||
else if ( parseInt(args[5]) < 1 || parseInt(args[5]) > 500 ) | ||
return user.send(`The item count is restricted to be between 1 and 500.\r\n`); | ||
/** Set count to sixth argument */ | ||
count = parseInt(args[5]); | ||
} | ||
/** If there was a seventh argument provided... */ | ||
if ( typeof args[6] == `string` ) { | ||
/** If the seventh argument is not a number, send error */ | ||
if ( isNaN(args[6]) ) | ||
return user.send(`That is not a valid refresh interval number.\r\n`); | ||
/** Otherwise, if the seventh argument is not greater than or equal to 30, send error */ | ||
else if ( parseInt(args[6]) >= 500 ) | ||
return user.send(`The refresh interval must be greater than 30 seconds.\r\n`); | ||
/** Set refresh to seventh argument */ | ||
refresh = parseInt(args[6]); | ||
} | ||
world.log().verbose(`Creating item to area deployment of (${count}) ID #${itemPrototype.id()} to #${area.id()} [${refresh}s]${parentDeployment ? ` (Parent: ` + parentDeployment.id() + `)` : ``}.`); | ||
/** Create deployment */ | ||
const deployment = world.createDeployment({ | ||
count: count, | ||
refresh: refresh, | ||
type: world.constants().DEPLOY_ITEMS_TO_AREA, | ||
subject: itemPrototype.id(), | ||
target: area.id() | ||
}); | ||
/** Insert deployment into database */ | ||
await deployment.insert(world.database()); | ||
/** Send success */ | ||
user.send(`That item to area deployment has been successfully created.\r\n`); | ||
} | ||
/** Otherwise, send error */ | ||
else { | ||
user.send(`You don't know how to create that kind of deployment.\r\n`); | ||
} | ||
} | ||
/** Otherwise, if the second argument is 'mobile'... */ | ||
else if ( `mobile`.startsWith(args[1]) ) { | ||
/** If no third argument was provided, send error */ | ||
if ( typeof args[2] != `string` ) | ||
return user.send(`Where should this mobile be deployed to? [area|room]\r\n`); | ||
/** Otherwise, if the third argument was invalid, send error */ | ||
else if ( ![`area`, `room`].some(x => x.startsWith(args[2]) ) ) | ||
return user.send(`That's not a valid mobile deployment location.\r\n`); | ||
/** Otherwise, if no fourth argument was provided, send error */ | ||
else if ( typeof args[3] != `string` ) | ||
return user.send(`Where mobile prototype ID # is being deployed?\r\n`); | ||
/** Otherwise, if the fourth argument is not a number, send error */ | ||
else if ( isNaN(args[3]) ) | ||
return user.send(`That is not a valid mobile prototype ID #.\r\n`); | ||
const mobilePrototype = world.mobilePrototypes().find(x => x.id() == parseInt(args[3])); | ||
if ( !mobilePrototype ) | ||
return user.send(`That mobile prototype ID # does not exist.\r\n`); | ||
/** If the second argument statred with 'area'... */ | ||
if ( `area`.startsWith(args[2]) ) { | ||
/** Assume area is user's area, count is 1, and refresh is 60 seconds */ | ||
let area = user.room().area(); | ||
let count = 1; | ||
let refresh = 600; | ||
/** If there was a fifth argument provided... */ | ||
if ( typeof args[4] == `string` ) { | ||
/** Attempt to find area in the world with that ID # */ | ||
area = world.areas().find(x => x.id() == parseInt(args[4])); | ||
/** If area does not exist, send error */ | ||
if ( !area ) | ||
return user.send(`There is no area in the world with that ID #.\r\n`); | ||
} | ||
/** If there was a sixth argument provided... */ | ||
if ( typeof args[5] == `string` ) { | ||
/** If the sixth argument is not a number, send error */ | ||
if ( isNaN(args[5]) ) | ||
return user.send(`That is not a valid count number.\r\n`); | ||
/** Otherwise, if the sixth argument is not between 1 and 500, send error */ | ||
else if ( parseInt(args[5]) < 1 || parseInt(args[5]) > 500 ) | ||
return user.send(`The item count is restricted to be between 1 and 500.\r\n`); | ||
/** Set count to sixth argument */ | ||
count = parseInt(args[5]); | ||
} | ||
/** If there was a seventh argument provided... */ | ||
if ( typeof args[6] == `string` ) { | ||
/** If the seventh argument is not a number, send error */ | ||
if ( isNaN(args[6]) ) | ||
return user.send(`That is not a valid refresh interval number.\r\n`); | ||
/** Otherwise, if the seventh argument is not greater than or equal to 30, send error */ | ||
else if ( parseInt(args[6]) >= 500 ) | ||
return user.send(`The refresh interval must be greater than 30 seconds.\r\n`); | ||
/** Set refresh to seventh argument */ | ||
refresh = parseInt(args[6]); | ||
} | ||
world.log().verbose(`Creating mobile to area deployment of (${count}) ID #${mobilePrototype.id()} to #${area.id()} [${refresh}s]${parentDeployment ? ` (Parent: ` + parentDeployment.id() + `)` : ``}.`); | ||
/** Create deployment */ | ||
const deployment = world.createDeployment({ | ||
count: count, | ||
refresh: refresh, | ||
type: world.constants().DEPLOY_ITEMS_TO_AREA, | ||
subject: mobilePrototype.id(), | ||
target: area.id() | ||
}); | ||
/** Insert deployment into database */ | ||
await deployment.insert(world.database()); | ||
/** Send success */ | ||
user.send(`That mobile to area deployment has been successfully created.\r\n`); | ||
} | ||
/** Otherwise, send error */ | ||
else { | ||
user.send(`You don't know how to create that kind of deployment.\r\n`); | ||
} | ||
} | ||
} | ||
/** Otherwise, if the first argument is 'exit'... */ | ||
else if ( `exit`.startsWith(args[0]) ) { | ||
/** If no second argument was provided, send error */ | ||
if ( typeof args[1] != `string` ) | ||
return user.send(`Create exit in which direction? [d|e|n|ne|nw|s|se|sw|u|w]\r\n`); | ||
/** Otherwise, if the second argument is not a valid direction name, send error */ | ||
else if ( !world.constants().directionShortNames.includes(args[1]) ) | ||
return user.send(`That is not a valid direction.\r\n`); | ||
/** Otherwise, if no third argument was provided, send error */ | ||
else if ( typeof args[2] != `string` ) | ||
return user.send(`What room ID # should this exit connect to?\r\n`); | ||
/** Otherwise, if third argument is not a number, send error */ | ||
else if ( isNaN(args[2]) ) | ||
return user.send(`That is not a valid number.\r\n`); | ||
/** Attempt to find target room based on ID # */ | ||
const target = world.rooms().find(x => x.id() == parseInt(args[2])); | ||
/** If target room doesn't exist, send error */ | ||
if ( !target ) | ||
return user.send(`There is no room in this world with that ID #.\r\n`); | ||
world.log().verbose(`Building new exit from room id #${user.room().id()} to #${target.id()}.`); | ||
/** Find numeric direction value */ | ||
const direction = world.constants().directionShortNames.findIndex(x => x == args[1]); | ||
/** Create exit */ | ||
const exit = world.createExit({ | ||
direction: direction, | ||
room: user.room(), | ||
target: target | ||
}); | ||
/** Send success */ | ||
user.send(`A path ${world.constants().directionNames[direction]} begins to form as what was impassible dissolves away.\r\n`); | ||
} | ||
/** Otherwise, if the first argument is 'item'... */ | ||
@@ -123,6 +333,4 @@ else if ( `item`.startsWith(args[0]) ) { | ||
/** If no third argument was provided, send error and return */ | ||
if ( typeof args[2] != `string` ) { | ||
user.send(`Create an instance of what item prototype ID?\r\n`); | ||
return; | ||
} | ||
if ( typeof args[2] != `string` ) | ||
return user.send(`Create an instance of what item prototype ID?\r\n`); | ||
@@ -133,6 +341,4 @@ /** Find item prototype in world by id */ | ||
/** If item prototype not found, send error and return */ | ||
if ( !prototype ) { | ||
user.send(`There is not an item prototype with that ID.\r\n`); | ||
return; | ||
} | ||
if ( !prototype ) | ||
return user.send(`There is not an item prototype with that ID.\r\n`); | ||
@@ -183,6 +389,4 @@ /** If there is a fourth argument called 'room', set room item boolean to true */ | ||
/** If no third argument was provided, send error and return */ | ||
if ( typeof args[2] != `string` ) { | ||
user.send(`Create an instance of what mobile prototype ID?\r\n`); | ||
return; | ||
} | ||
if ( typeof args[2] != `string` ) | ||
return user.send(`Create an instance of what mobile prototype ID?\r\n`); | ||
@@ -193,6 +397,4 @@ /** Find mobile prototype in world by id */ | ||
/** If mobile prototype not found, send error and return */ | ||
if ( !prototype ) { | ||
user.send(`There is not a mobile prototype with that ID.\r\n`); | ||
return; | ||
} | ||
if ( !prototype ) | ||
return user.send(`There is not a mobile prototype with that ID.\r\n`); | ||
@@ -245,6 +447,4 @@ /** Create mobile instance from mobile prototype */ | ||
/** If a room already exists the direction specified, send error and return */ | ||
if ( user.room().exits().find(x => x.direction() == world.constants().directionShortNames.indexOf(args[1])) ) { | ||
user.send(`There is already a room in that direction.\r\n`); | ||
return; | ||
} | ||
if ( user.room().exits().find(x => x.direction() == world.constants().directionShortNames.indexOf(args[1])) ) | ||
return user.send(`There is already a room in that direction.\r\n`); | ||
@@ -270,14 +470,2 @@ /** Create room */ | ||
/** Add outgoing exit to user's room */ | ||
user.room().exits().push(exit1); | ||
/** Add incoming exit to new room */ | ||
room.exits().push(exit2); | ||
/** Save user's room */ | ||
await user.room().update(world.database()); | ||
/** Save new room */ | ||
await room.update(world.database()); | ||
/** Send action to user */ | ||
@@ -425,3 +613,3 @@ user.send(`You draw in ambient energy and manifest a room to the ${world.constants().directionNames[world.constants().directionShortNames.indexOf(args[1])]}.\r\n`); | ||
if ( typeof args[3] != `string` ) | ||
return user.send(`Edit what? [desc|details|flags|name|names|roomdesc]\r\n`); | ||
return user.send(`Edit what? [desc|details|flags|name|names|roomdesc|slot|type]\r\n`); | ||
@@ -471,19 +659,3 @@ /** Otherwise, if the fourth argument is 'description'... */ | ||
} | ||
/** Otherwise, if the fourth argument is 'roomdescription'... */ | ||
else if ( `roomdescription`.startsWith(args[3]) ) { | ||
/** If no fifth argument was provided, send error */ | ||
if ( typeof args[4] != `string` ) | ||
return user.send(`Change the item's room description to what?\r\n`); | ||
const roomDescription = buffer.toString().split(` `).slice(4).join(` `); | ||
/** If the room description is invalid, send error */ | ||
if ( !roomDescription.match(/^[\x20-\x7E]+$/) ) | ||
return user.send(`That is an invalid item room description, must consist of printable ASCII.\r\n`); | ||
/** Set the item's room description */ | ||
item.roomDescription(roomDescription); | ||
} | ||
/** Otherwise, if the fourth argument is 'flags'... */ | ||
@@ -528,2 +700,18 @@ else if ( `flags`.startsWith(args[3]) ) { | ||
/** Otherwise, if the fourth argument is 'roomdescription'... */ | ||
else if ( `roomdescription`.startsWith(args[3]) ) { | ||
/** If no fifth argument was provided, send error */ | ||
if ( typeof args[4] != `string` ) | ||
return user.send(`Change the item's room description to what?\r\n`); | ||
const roomDescription = buffer.toString().split(` `).slice(4).join(` `); | ||
/** If the room description is invalid, send error */ | ||
if ( !roomDescription.match(/^[\x20-\x7E]+$/) ) | ||
return user.send(`That is an invalid item room description, must consist of printable ASCII.\r\n`); | ||
/** Set the item's room description */ | ||
item.roomDescription(roomDescription); | ||
} | ||
/** Otherwise, if the fourth argument is 'slot'... */ | ||
@@ -533,6 +721,10 @@ else if ( `slot`.startsWith(args[3]) ) { | ||
if ( typeof args[4] != `string` ) | ||
return user.send(`Change the item's slot to what?\r\n`); | ||
return user.send(`Change the item's slot to what? [${world.constants().slotShortcuts.join(`|`)}]\r\n`); | ||
/** Set the item's name */ | ||
item.slot(parseInt(args[4])); | ||
/** Otherwise, if the third argument is not a valid item slot shortcut, send error */ | ||
else if ( !world.constants().slotShortcuts.some(x => x.startsWith(args[4])) ) | ||
return user.send(`That is not a valid item type.\r\n`); | ||
/** Set the item's slot */ | ||
item.slot(world.constants().slotShortcuts.findIndex(x => x.startsWith(args[4]))); | ||
} | ||
@@ -544,6 +736,10 @@ | ||
if ( typeof args[4] != `string` ) | ||
return user.send(`Change the item's slot to what?\r\n`); | ||
return user.send(`Change the item's type to what? [${world.constants().itemTypeShortcuts.join(`|`)}]\r\n`); | ||
/** Set the item's name */ | ||
item.type(parseInt(args[4])); | ||
/** Otherwise, if the third argument is not a valid item type shortcut, send error */ | ||
else if ( !world.constants().itemTypeShortcuts.some(x => x.startsWith(args[4])) ) | ||
return user.send(`That is not a valid item type.\r\n`); | ||
/** Set the item's type */ | ||
item.type(world.constants().itemTypeShortcuts.findIndex(x => x.startsWith(args[4]))); | ||
} | ||
@@ -570,15 +766,12 @@ | ||
/** Create a new item prototype */ | ||
const itemPrototype = new world.ItemPrototype(); | ||
/** Attempt to find item prototype in the world */ | ||
const itemPrototype = world.itemPrototypes().find(x => x.id() == parseInt(args[2])); | ||
/** Attempt to load the item prototype */ | ||
const exists = await itemPrototype.load(parseInt(args[2]), world.database()); | ||
/** If the item prototype doesn't exist, send error */ | ||
if ( !exists ) | ||
return user.send(`That item prototype does not exist.\r\n`); | ||
if ( !itemPrototype ) | ||
return user.send(`That item prototype does not exist in this world.\r\n`); | ||
/** If no fourth argument was provided, send error */ | ||
if ( typeof args[3] != `string` ) | ||
return user.send(`Edit what? [author|date|desc|details|flags|name|names|roomdesc]\r\n`); | ||
return user.send(`Edit what? [author|date|desc|details|flags|name|names|roomdesc|slot|type]\r\n`); | ||
@@ -605,3 +798,13 @@ /** Otherwise, if the fourth argument is 'author'... */ | ||
if ( typeof args[4] != `string` ) | ||
return user.send(`Change the item's creation date to when?\r\n`); | ||
return user.send(`Change the item's creation date to when? [YYYY-MM-DD]\r\n`); | ||
/** Parse date argument with moment */ | ||
const created = moment(args[4]); | ||
/** If the fifth argument is invalid, send error */ | ||
if ( !date.isValid() ) | ||
return user.send(`That is not a valid item creation date.\r\n`); | ||
/** Set the item prototype's creation date */ | ||
itemPrototype.created(created.toDate()); | ||
} | ||
@@ -652,3 +855,42 @@ | ||
} | ||
/** Otherwise, if the fourth argument is 'flags'... */ | ||
else if ( `flags`.startsWith(args[3]) ) { | ||
/** If no third argument was provided, send error */ | ||
if ( typeof args[4] != `string` ) | ||
return user.send(`Change which item flag?\r\n`); | ||
} | ||
/** Otherwise, if the fourth argument is 'name'... */ | ||
else if ( `name`.startsWith(args[3]) ) { | ||
/** If no third argument was provided, send error */ | ||
if ( typeof args[4] != `string` ) | ||
return user.send(`Change the item's name to what?\r\n`); | ||
const name = buffer.toString().split(` `).slice(4).join(` `); | ||
/** If the name is invalid, send error */ | ||
if ( !name.match(/^[\x20-\x7E]+$/) ) | ||
return user.send(`That is an invalid item name, must consist of printable ASCII.\r\n`); | ||
/** Set the item prototype's name */ | ||
itemPrototype.name(name); | ||
} | ||
/** Otherwise, if the fourth argument is 'names'... */ | ||
else if ( `names`.startsWith(args[3]) ) { | ||
/** If no third argument was provided, send error */ | ||
if ( typeof args[4] != `string` ) | ||
return user.send(`Change the item's names to what?\r\n`); | ||
const names = args.slice(4); | ||
/** If the names are invalid, send error */ | ||
if ( !names.every(x => x.match(/^[\x20-\x7E]+$/)) ) | ||
return user.send(`That is an invalid item name, must consist of printable ASCII.\r\n`); | ||
/** Set the item prototype's names */ | ||
itemPrototype.names(names); | ||
} | ||
/** Otherwise, if the fourth argument is 'roomdescription'... */ | ||
@@ -669,3 +911,89 @@ else if ( `roomdescription`.startsWith(args[3]) ) { | ||
} | ||
/** Otherwise, if the fourth argument is 'slot'... */ | ||
else if ( `slot`.startsWith(args[3]) ) { | ||
/** If no third argument was provided, send error */ | ||
if ( typeof args[4] != `string` ) | ||
return user.send(`Change the item's slot to what? [${world.constants().slotShortcuts.join(`|`)}]\r\n`); | ||
/** Otherwise, if the third argument is not a valid item slot shortcut, send error */ | ||
else if ( !world.constants().slotShortcuts.some(x => x.startsWith(args[4])) ) | ||
return user.send(`That is not a valid item type.\r\n`); | ||
/** Set the item prototype's slot */ | ||
itemPrototype.slot(world.constants().slotShortcuts.findIndex(x => x.startsWith(args[4]))); | ||
} | ||
/** Otherwise, if the fourth argument is 'type'... */ | ||
else if ( `type`.startsWith(args[3]) ) { | ||
/** If no third argument was provided, send error */ | ||
if ( typeof args[4] != `string` ) | ||
return user.send(`Change the item's type to what? [${world.constants().itemTypeShortcuts.join(`|`)}]\r\n`); | ||
/** Otherwise, if the third argument is not a valid item type shortcut, send error */ | ||
else if ( !world.constants().itemTypeShortcuts.some(x => x.startsWith(args[4])) ) | ||
return user.send(`That is not a valid item type.\r\n`); | ||
/** Set the item prototype's type */ | ||
itemPrototype.type(world.constants().itemTypeShortcuts.findIndex(x => x.startsWith(args[4]))); | ||
} | ||
/** Otherwise, send error */ | ||
else { | ||
return user.send(`You do not know how to edit that.\r\n`); | ||
} | ||
world.log().verbose(`Saving Item Prototype ID #${itemPrototype.id()} - ${itemPrototype.name()}`); | ||
/** Update item prototype in database */ | ||
await itemPrototype.update(world.database()); | ||
user.send(`Done.\r\n`); | ||
} | ||
} | ||
/** Otherwise, if the first argument is 'mobile'... */ | ||
else if ( `mobile`.startsWith(args[0]) ) { | ||
/** If no second argument was provided, send error */ | ||
if ( typeof args[1] != `string` ) | ||
return user.send(`Edit what kind of mobile? [instance|prototype]\r\n`); | ||
/** Otherwise, if the second argument is 'instance'... */ | ||
else if ( `instance`.startsWith(args[1]) ) { | ||
/** If no third argument was provided, send error */ | ||
if ( typeof args[2] != `string` ) | ||
return user.send(`Edit what mobile?\r\n`); | ||
/** Parse name and count of second argument */ | ||
const [name, count] = world.parseName(user, args, 2); | ||
/** Grab mobiles array */ | ||
const mobiles = user.room().mobiles(); | ||
/** If the number of mobiles is less than the count, send error */ | ||
if ( mobiles.length < count ) | ||
return user.send(`You can't find that mobile anywhere.\r\n`); | ||
const mobile = mobiles[count - 1]; | ||
/** If no fourth argument was provided, send error */ | ||
if ( typeof args[3] != `string` ) | ||
return user.send(`Edit what? [desc|flags|name|names|roomdesc]\r\n`); | ||
/** Otherwise, if the fourth argument is 'description'... */ | ||
else if ( `description`.startsWith(args[3]) ) { | ||
/** If no fifth argument was provided, send error */ | ||
if ( typeof args[4] != `string` ) | ||
return user.send(`Change the mobile's description to what?\r\n`); | ||
const description = buffer.toString().split(` `).slice(4).join(` `); | ||
/** If the description is invalid, send error */ | ||
if ( !description.match(/^[\x20-\x7E]+$/) ) | ||
return user.send(`That is an invalid mobile description, must consist of printable ASCII.\r\n`); | ||
/** Set the mobile's description */ | ||
mobile.description(description); | ||
} | ||
/** Otherwise, if the fourth argument is 'flags'... */ | ||
@@ -675,3 +1003,3 @@ else if ( `flags`.startsWith(args[3]) ) { | ||
if ( typeof args[4] != `string` ) | ||
return user.send(`Change which item flag?\r\n`); | ||
return user.send(`Change which mobile flag?\r\n`); | ||
} | ||
@@ -683,3 +1011,3 @@ | ||
if ( typeof args[4] != `string` ) | ||
return user.send(`Change the item's name to what?\r\n`); | ||
return user.send(`Change the mobile's name to what?\r\n`); | ||
@@ -690,6 +1018,6 @@ const name = buffer.toString().split(` `).slice(4).join(` `); | ||
if ( !name.match(/^[\x20-\x7E]+$/) ) | ||
return user.send(`That is an invalid item name, must consist of printable ASCII.\r\n`); | ||
return user.send(`That is an invalid mobile name, must consist of printable ASCII.\r\n`); | ||
/** Set the item prototype's name */ | ||
itemPrototype.name(name); | ||
/** Set the mobile's name */ | ||
mobile.name(name); | ||
} | ||
@@ -701,3 +1029,3 @@ | ||
if ( typeof args[4] != `string` ) | ||
return user.send(`Change the item's names to what?\r\n`); | ||
return user.send(`Change the mobile's names to what?\r\n`); | ||
@@ -708,28 +1036,158 @@ const names = args.slice(4); | ||
if ( !names.every(x => x.match(/^[\x20-\x7E]+$/)) ) | ||
return user.send(`That is an invalid item name, must consist of printable ASCII.\r\n`); | ||
return user.send(`That is an invalid mobile name, must consist of printable ASCII.\r\n`); | ||
/** Set the item prototype's names */ | ||
itemPrototype.names(names); | ||
/** Set the mobile's names */ | ||
mobile.names(names); | ||
} | ||
/** Otherwise, if the fourth argument is 'slot'... */ | ||
else if ( `slot`.startsWith(args[3]) ) { | ||
/** Otherwise, if the fourth argument is 'roomdescription'... */ | ||
else if ( `roomdescription`.startsWith(args[3]) ) { | ||
/** If no fifth argument was provided, send error */ | ||
if ( typeof args[4] != `string` ) | ||
return user.send(`Change the mobile's room description to what?\r\n`); | ||
const roomDescription = buffer.toString().split(` `).slice(4).join(` `); | ||
/** If the room description is invalid, send error */ | ||
if ( !roomDescription.match(/^[\x20-\x7E]+$/) ) | ||
return user.send(`That is an invalid mobile room description, must consist of printable ASCII.\r\n`); | ||
/** Set the mobile's room description */ | ||
mobile.roomDescription(roomDescription); | ||
} | ||
/** Otherwise, send error */ | ||
else { | ||
return user.send(`You do not know how to edit that.\r\n`); | ||
} | ||
world.log().verbose(`Saving Mobile Instance ID #${mobile.id()} - ${mobile.name()}`); | ||
/** Update item in database */ | ||
await mobile.update(world.database()); | ||
user.send(`Done.\r\n`); | ||
} | ||
/** Otherwise, if the second argument is 'prototype'... */ | ||
else if ( `prototype`.startsWith(args[1]) ) { | ||
/** If no third argument was provided, send error */ | ||
if ( typeof args[2] != `string` ) | ||
return user.send(`Edit what mobile prototype ID #?\r\n`); | ||
/** Attempt to find mobile prototype in the world */ | ||
const mobilePrototype = world.mobilePrototypes().find(x => x.id() == parseInt(args[2])); | ||
/** If the mobile prototype doesn't exist, send error */ | ||
if ( !mobilePrototype ) | ||
return user.send(`That mobile prototype does not exist in this world.\r\n`); | ||
/** If no fourth argument was provided, send error */ | ||
if ( typeof args[3] != `string` ) | ||
return user.send(`Edit what? [author|date|desc|flags|name|names|roomdesc]\r\n`); | ||
/** Otherwise, if the fourth argument is 'author'... */ | ||
else if ( `author`.startsWith(args[3]) ) { | ||
/** If no fifth argument was provided, send error */ | ||
if ( typeof args[4] != `string` ) | ||
return user.send(`Change the mobile's author to whom?\r\n`); | ||
const author = buffer.toString().split(` `).slice(4).join(` `); | ||
/** If the author is invalid, send error */ | ||
if ( !author.match(/^[\x20-\x7E]+$/) ) | ||
return user.send(`That is an invalid mobile author name, must consist of printable ASCII.\r\n`); | ||
/** Set the item prototype's author */ | ||
mobilePrototype.author(author); | ||
} | ||
/** Otherwise, if the fourth argument is 'date'... */ | ||
else if ( `date`.startsWith(args[3]) ) { | ||
/** If no fifth argument was provided, send error */ | ||
if ( typeof args[4] != `string` ) | ||
return user.send(`Change the mobile's creation date to when? [YYYY-MM-DD]\r\n`); | ||
/** Parse date argument with moment */ | ||
const created = moment(args[4]); | ||
/** If the fifth argument is invalid, send error */ | ||
if ( !date.isValid() ) | ||
return user.send(`That is not a valid mobile creation date.\r\n`); | ||
/** Set the mobile prototype's creation date */ | ||
mobilePrototype.created(created.toDate()); | ||
} | ||
/** Otherwise, if the fourth argument is 'description'... */ | ||
else if ( `description`.startsWith(args[3]) ) { | ||
/** If no fifth argument was provided, send error */ | ||
if ( typeof args[4] != `string` ) | ||
return user.send(`Change the mobile's description to what?\r\n`); | ||
const description = buffer.toString().split(` `).slice(4).join(` `); | ||
/** If the description is invalid, send error */ | ||
if ( !description.match(/^[\x20-\x7E]+$/) ) | ||
return user.send(`That is an invalid mobile description, must consist of printable ASCII.\r\n`); | ||
/** Set the mobile prototype's description */ | ||
mobilePrototype.description(description); | ||
} | ||
/** Otherwise, if the fourth argument is 'flags'... */ | ||
else if ( `flags`.startsWith(args[3]) ) { | ||
/** If no third argument was provided, send error */ | ||
if ( typeof args[4] != `string` ) | ||
return user.send(`Change the item's slot to what?\r\n`); | ||
return user.send(`Change which mobile flag?\r\n`); | ||
} | ||
/** Otherwise, if the fourth argument is 'name'... */ | ||
else if ( `name`.startsWith(args[3]) ) { | ||
/** If no third argument was provided, send error */ | ||
if ( typeof args[4] != `string` ) | ||
return user.send(`Change the mobile's name to what?\r\n`); | ||
const name = buffer.toString().split(` `).slice(4).join(` `); | ||
/** If the name is invalid, send error */ | ||
if ( !name.match(/^[\x20-\x7E]+$/) ) | ||
return user.send(`That is an invalid mobile name, must consist of printable ASCII.\r\n`); | ||
/** Set the item prototype's name */ | ||
itemPrototype.slot(parseInt(args[4])); | ||
mobilePrototype.name(name); | ||
} | ||
/** Otherwise, if the fourth argument is 'type'... */ | ||
else if ( `type`.startsWith(args[3]) ) { | ||
/** Otherwise, if the fourth argument is 'names'... */ | ||
else if ( `names`.startsWith(args[3]) ) { | ||
/** If no third argument was provided, send error */ | ||
if ( typeof args[4] != `string` ) | ||
return user.send(`Change the item's slot to what?\r\n`); | ||
return user.send(`Change the mobile's names to what?\r\n`); | ||
/** Set the item prototype's name */ | ||
itemPrototype.type(parseInt(args[4])); | ||
const names = args.slice(4); | ||
/** If the names are invalid, send error */ | ||
if ( !names.every(x => x.match(/^[\x20-\x7E]+$/)) ) | ||
return user.send(`That is an invalid mobile name, must consist of printable ASCII.\r\n`); | ||
/** Set the item prototype's names */ | ||
mobilePrototype.names(names); | ||
} | ||
/** Otherwise, if the fourth argument is 'roomdescription'... */ | ||
else if ( `roomdescription`.startsWith(args[3]) ) { | ||
/** If no fifth argument was provided, send error */ | ||
if ( typeof args[4] != `string` ) | ||
return user.send(`Change the mobile's room description to what?\r\n`); | ||
const roomDescription = buffer.toString().split(` `).slice(4).join(` `); | ||
/** If the room description is invalid, send error */ | ||
if ( !roomDescription.match(/^[\x20-\x7E]+$/) ) | ||
return user.send(`That is an invalid mobile room description, must consist of printable ASCII.\r\n`); | ||
/** Set the mobile prototype's room description */ | ||
mobilePrototype.roomDescription(roomDescription); | ||
} | ||
/** Otherwise, send error */ | ||
@@ -740,6 +1198,6 @@ else { | ||
world.log().verbose(`Saving Item Prototype ID #${itemPrototype.id()} - ${itemPrototype.name()}`); | ||
world.log().verbose(`Saving Mobile Prototype ID #${mobilePrototype.id()} - ${mobilePrototype.name()}`); | ||
/** Update item prototype in database */ | ||
await itemPrototype.update(world.database()); | ||
/** Update mobile prototype in database */ | ||
await mobilePrototype.update(world.database()); | ||
@@ -746,0 +1204,0 @@ user.send(`Done.\r\n`); |
@@ -6,2 +6,3 @@ /** Configure Character object */ | ||
properties: [ | ||
{ name: `air`, type: `int`, default: 1, store: false }, | ||
{ name: `accuracy`, type: `int`, default: 1, store: false }, | ||
@@ -12,12 +13,14 @@ { name: `affects`, type: `Array`, arrayOf: { type: `int` } }, | ||
{ name: `deflection`, type: `int`, default: 1, store: false }, | ||
{ name: `earth`, type: `int`, default: 1, store: false }, | ||
{ name: `energy`, type: `int`, default: 100 }, | ||
{ name: `fighting`, instanceOf: `Character`, store: false }, | ||
{ name: `fire`, type: `int`, default: 1, store: false }, | ||
{ name: `health`, type: `int`, default: 100 }, | ||
{ name: `id`, type: `int` }, | ||
{ name: `level`, type: `int`, default: 1 }, | ||
{ name: `lineage`, type: `int` }, | ||
{ name: `life`, type: `int`, default: 1, store: false }, | ||
{ name: `mana`, type: `int`, default: 100 }, | ||
{ name: `maxEnergy`, type: `int`, default: 100 }, | ||
{ name: `maxHealth`, type: `int`, default: 100 }, | ||
{ name: `maxMana`, type: `int`, default: 100 }, | ||
{ name: `maxEnergy`, type: `int`, default: 100, store: false }, | ||
{ name: `maxHealth`, type: `int`, default: 100, store: false }, | ||
{ name: `maxMana`, type: `int`, default: 100, store: false }, | ||
{ name: `name`, type: `varchar`, length: 32, default: `a boring person` }, | ||
@@ -27,6 +30,8 @@ { name: `path`, type: `int` }, | ||
{ name: `power`, type: `int`, default: 1, store: false }, | ||
{ name: `race`, type: `int` }, | ||
{ name: `sex`, type: `tinyint` }, | ||
{ name: `speed`, type: `int`, default: 1, store: false } | ||
{ name: `speed`, type: `int`, default: 1, store: false }, | ||
{ name: `water`, type: `int`, default: 1, store: false }, | ||
] | ||
}; | ||
}; |
448
constants.js
/** Export our constants as a plain object */ | ||
module.exports = { | ||
/** Deployment types */ | ||
/** Define affect flags */ | ||
AFFECT_CLOAKED: 0, | ||
AFFECT_SAFE: 1, | ||
affectNames: [ | ||
`Cloaked`, | ||
`Safe` | ||
], | ||
affectShortcuts: [ | ||
`cloaked`, | ||
`safe` | ||
], | ||
/** Define default port */ | ||
DEFAULT_PORT: 7000, | ||
/** Define default welcome */ | ||
DEFAULT_WELCOME: [`\r\n`.repeat(3), | ||
` W E L C O M E T O\r\n`, | ||
`\r\n`.repeat(2), | ||
` _ _\r\n`, | ||
` /\\/\\ _ _ __| | __| |_ _\r\n`, | ||
` / \\| | | |/ _' |/ _' | | | |\r\n`, | ||
` / /\\/\\ \\ |_| | (_| | (_| | |_| |\r\n`, | ||
` \\/ \\/\\__,_|\\__,_|\\__,_|\\__, |\r\n`, | ||
` |___/\r\n`, | ||
`\r\n`, | ||
` Created by Rich Lowe\r\n`, | ||
` MIT Licensed\r\n`, | ||
`\r\n`.repeat(8), | ||
`Hello, what is your name? `].join(``), | ||
/** Define default message of the day */ | ||
DEFAULT_MOTD: [`\r\n`, | ||
`--------------------------------------------------------------------------------\r\n`, | ||
`Message of the day:\r\n`, | ||
`\r\n`, | ||
`Current features:\r\n`, | ||
` * #CC#Bo#Pl#Ro#Yr#Gs#W!#n\r\n`, | ||
` * Movement in all directions\r\n`, | ||
` * Full get/drop/put/wear/remove/wield object interaction\r\n`, | ||
` * Looking at rooms, items, mobiles, users, in containers\r\n`, | ||
` * Admin commands for goto, alist, astat, rlist, rstat, ilist, istat, mlist, \r\n`, | ||
` mstat, and ustat\r\n`, | ||
` * Create command can so far create areas/rooms/prototypes/instances\r\n`, | ||
` * Ability to look at rooms, or at item/user/mobile descriptions\r\n`, | ||
` * Saving of users, new and existing, taking over body\r\n`, | ||
`\r\n`, | ||
`--------------------------------------------------------------------------------\r\n`, | ||
`Press ENTER to continue...\r\n`, | ||
`--------------------------------------------------------------------------------`].join(``), | ||
/** Define deployment types */ | ||
DEPLOY_ITEMS_TO_ROOM: 0, | ||
@@ -10,3 +63,3 @@ DEPLOY_MOBILES_TO_ROOM: 1, | ||
DEPLOY_ITEMS_TO_INVENTORY: 3, | ||
DEPLOY_ITEMS_TO_ITEM: 4, | ||
DEPLOY_ITEMS_TO_CONTAINER: 4, | ||
@@ -20,46 +73,68 @@ deploymentNames: [ | ||
`Items To Inventory`, | ||
`Items To Item` | ||
`Items To Container` | ||
], | ||
/** Socket states */ | ||
STATE_NAME: 0, | ||
STATE_OLD_PASSWORD: 1, | ||
STATE_NEW_PASSWORD: 2, | ||
STATE_CONFIRM_PASSWORD: 3, | ||
STATE_MOTD: 4, | ||
STATE_CONNECTED: 5, | ||
STATE_DISCONNECTED: 6, | ||
/** Define direction flags */ | ||
DIR_NORTH: 0, /** n */ | ||
DIR_NORTHEAST: 1, /** ne */ | ||
DIR_EAST: 2, /** e */ | ||
DIR_SOUTHEAST: 3, /** se */ | ||
DIR_SOUTH: 4, /** s */ | ||
DIR_SOUTHWEST: 5, /** sw */ | ||
DIR_WEST: 6, /** w */ | ||
DIR_NORTHWEST: 7, /** nw */ | ||
DIR_UP: 8, /** u */ | ||
DIR_DOWN: 9, /** d */ | ||
/** Positions */ | ||
POSITION_DEAD: -7, | ||
POSITION_INCAPACITATED: -6, | ||
POSITION_SLEEPING: -5, | ||
POSITION_MEDITATING: -4, | ||
POSITION_LYING_DOWN: -3, | ||
POSITION_KNEELING: -2, | ||
POSITION_SITTING: -1, | ||
POSITION_STANDING: 0, | ||
POSITION_FIGHTING: 1, | ||
POSITIONS_ALL: [-7, -6, -5, -4, -3, -2, -1, 0, 1], | ||
POSITIONS_AWAKE: [-3, -2, -1, 0, 1], | ||
POSITIONS_MOBILE: [-2, -1, 0, 1], | ||
POSITIONS_SAFE: [-5, -4, -3, -2, -1, 0], | ||
POSITIONS_AWAKE_AND_SAFE: [-3, -2, -1, 0], | ||
/** Define direction flag lookup by name */ | ||
directions: { | ||
north: 0, | ||
northeast: 1, | ||
east: 2, | ||
southeast: 3, | ||
south: 4, | ||
southwest: 5, | ||
west: 6, | ||
northwest: 7, | ||
up: 8, | ||
down: 9, | ||
ne: 1, | ||
se: 3, | ||
sw: 5, | ||
nw: 7 | ||
}, | ||
/** Sex */ | ||
SEX_MALE: 0, | ||
SEX_FEMALE: 1, | ||
/** Define direction name lookup by direction flag */ | ||
directionNames: [`north`, `northeast`, `east`, `southeast`, `south`, | ||
`southwest`, `west`, `northwest`, `up`, `down`], | ||
/** Define VT100 terminal modifiers */ | ||
VT100_CLEAR: `\x1b[0m`, | ||
VT100_HIDE_TEXT: `\x1b[8m`, | ||
/** Define direction short name lookup by direction flag */ | ||
directionShortNames: [`n`, `ne`, `e`, `se`, `s`, `sw`, `w`, `nw`, `u`, `d`], | ||
/** Define item rarities */ | ||
RARITY_COMMON: 0, | ||
RARITY_UNCOMMON: 1, | ||
RARITY_RARE: 2, | ||
RARITY_EPIC: 3, | ||
RARITY_LEGENDARY: 4, | ||
/** Define direction opposites by direction flag */ | ||
directionOpposites: [4, 5, 6, 7, 0, 1, 2, 3, 9, 8], | ||
/** Define element flags */ | ||
ELEMENT_AIR: 0, | ||
ELEMENT_EARTH: 1, | ||
ELEMENT_FIRE: 2, | ||
ELEMENT_LIFE: 3, | ||
ELEMENT_WATER: 4, | ||
elementNames: [ | ||
`Air`, | ||
`Earth`, | ||
`Fire`, | ||
`Life`, | ||
`Water` | ||
], | ||
elementShortcuts: [ | ||
`air`, | ||
`earth`, | ||
`fire`, | ||
`life`, | ||
`water` | ||
], | ||
/** Define item flags */ | ||
@@ -77,2 +152,33 @@ ITEM_CONTAINER: 0, | ||
ITEM_CAN_LOCK: 10, | ||
ITEM_FLAMMABLE: 11, | ||
itemFlagNames: [ | ||
`Container`, | ||
`Fixed`, | ||
`Closed`, | ||
`Locked`, | ||
`Can Drink`, | ||
`Can Eat`, | ||
`Can Lay Down On`, | ||
`Can Kneel On`, | ||
`Can Sit On`, | ||
`Can Open/Close`, | ||
`Can Lock`, | ||
`Flammable` | ||
], | ||
itemFlagShortcuts: [ | ||
`container`, | ||
`fixed`, | ||
`closed`, | ||
`locked`, | ||
`candrink`, | ||
`caneat`, | ||
`canlaydown`, | ||
`cankneel`, | ||
`cansit`, | ||
`canopenclose`, | ||
`canlock`, | ||
`flammable` | ||
], | ||
@@ -87,3 +193,5 @@ /** Define item types */ | ||
itemNames: [ | ||
itemTypesWieldable: [2, 3, 4, 5], | ||
itemTypeNames: [ | ||
`Other`, | ||
@@ -97,3 +205,119 @@ `Armor`, | ||
/** Define slot flags */ | ||
itemTypeShortcuts: [ | ||
`other`, | ||
`armor`, | ||
`1hweapon`, | ||
`2hweapon`, | ||
`held`, | ||
`shield` | ||
], | ||
/** Define paths */ | ||
PATH_DRUID: 0, | ||
PATH_MAGE: 1, | ||
PATH_NECROMANCER: 2, | ||
PATH_RANGER: 3, | ||
PATH_SHAMAN: 4, | ||
PATH_WARRIOR: 5, | ||
PATH_WIZARD: 6, | ||
pathNames: [ | ||
`Druid`, | ||
`Mage`, | ||
`Necromancer`, | ||
`Ranger`, | ||
`Shaman`, | ||
`Warrior`, | ||
`Wizard` | ||
], | ||
pathShortcuts: [ | ||
`druid`, | ||
`mage`, | ||
`necromancer`, | ||
`ranger`, | ||
`shaman`, | ||
`warrior`, | ||
`wizard` | ||
], | ||
/** Define positions */ | ||
POSITION_DEAD: -7, | ||
POSITION_INCAPACITATED: -6, | ||
POSITION_SLEEPING: -5, | ||
POSITION_MEDITATING: -4, | ||
POSITION_LYING_DOWN: -3, | ||
POSITION_KNEELING: -2, | ||
POSITION_SITTING: -1, | ||
POSITION_STANDING: 0, | ||
POSITION_FIGHTING: 1, | ||
POSITIONS_ALL: [-7, -6, -5, -4, -3, -2, -1, 0, 1], | ||
POSITIONS_AWAKE: [-3, -2, -1, 0, 1], | ||
POSITIONS_MOBILE: [-2, -1, 0, 1], | ||
POSITIONS_SAFE: [-5, -4, -3, -2, -1, 0], | ||
POSITIONS_AWAKE_AND_SAFE: [-3, -2, -1, 0], | ||
positionNames: { | ||
'-7': `Dead`, | ||
'-6': `Incapacitated`, | ||
'-5': `Sleeping`, | ||
'-4': `Meditating`, | ||
'-3': `Lying Down`, | ||
'-2': `Kneeling`, | ||
'-1': `Sitting`, | ||
'0': `Standing`, | ||
'1': `Fighting` | ||
}, | ||
/** Define item rarities */ | ||
RARITY_COMMON: 0, | ||
RARITY_UNCOMMON: 1, | ||
RARITY_RARE: 2, | ||
RARITY_EPIC: 3, | ||
RARITY_LEGENDARY: 4, | ||
/** Define races */ | ||
RACE_CENTAUR: 0, | ||
RACE_DRAGONKIN: 1, | ||
RACE_DWARF: 2, | ||
RACE_ELF: 3, | ||
RACE_GIANT: 4, | ||
RACE_GOBLIN: 5, | ||
RACE_HALFLING: 6, | ||
RACE_HUMAN: 7, | ||
RACE_MERFOLK: 8, | ||
RACE_ORC: 9, | ||
racesAllowed: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], | ||
raceNames: [ | ||
`Dwarf`, | ||
`Elf`, | ||
`Halfling`, | ||
`Human` | ||
], | ||
raceShortcuts: [ | ||
`dwarf`, | ||
`elf`, | ||
`halfling`, | ||
`human` | ||
], | ||
/** Define sexes */ | ||
SEX_MALE: 0, | ||
SEX_FEMALE: 1, | ||
sexNames: [ | ||
`Male`, | ||
`Female` | ||
], | ||
sexShortcuts: [ | ||
`male`, | ||
`female` | ||
], | ||
/** Define item slots */ | ||
SLOT_NONE: 0, | ||
@@ -131,124 +355,34 @@ SLOT_HEAD: 1, | ||
/** Define affect flags */ | ||
AFFECT_CLOAKED: 0, | ||
AFFECT_SAFE: 1, | ||
affectNames: [ | ||
`Cloaked`, | ||
`Safe` | ||
slotShortcuts: [ | ||
`none`, | ||
`head`, | ||
`face`, | ||
`neck`, | ||
`shoulders`, | ||
`chest`, | ||
`back`, | ||
`arms`, | ||
`forearms`, | ||
`gloves`, | ||
`waist`, | ||
`legs`, | ||
`feet`, | ||
`wield` | ||
], | ||
/** Define element flags */ | ||
ELEMENT_AIR: 0, | ||
ELEMENT_EARTH: 1, | ||
ELEMENT_FIRE: 2, | ||
ELEMENT_LIFE: 3, | ||
ELEMENT_WATER: 4, | ||
/** Define paths */ | ||
PATH_DRUID: 0, /** Air, Earth, & Water */ | ||
PATH_MAGE: 1, /** Air, Fire, & Water */ | ||
PATH_NECROMANCER: 2, /** Air, Fire, & Life */ | ||
PATH_PRIEST: 3, /** Air, Life, & Water */ | ||
PATH_RANGER: 4, /** Air, Earth, & Life */ | ||
PATH_SHAMAN: 5, /** Earth, Fire, & Life */ | ||
PATH_SORCERER: 6, /** Earth, Fire, & Water */ | ||
PATH_THIEF: 7, /** Fire, Life, & Water */ | ||
PATH_WARRIOR: 8, /** Air, Earth, & Fire */ | ||
PATH_WIZARD: 9, /** Earth, Life, & Water */ | ||
pathNames: [ | ||
`Druid`, | ||
`Mage`, | ||
`Necromancer`, | ||
`Priest`, | ||
`Ranger`, | ||
`Shaman`, | ||
`Sorcerer`, | ||
`Thief`, | ||
`Warrior`, | ||
`Wizard` | ||
], | ||
/** Define direction flags */ | ||
DIR_NORTH: 0, /** n */ | ||
DIR_NORTHEAST: 1, /** ne */ | ||
DIR_EAST: 2, /** e */ | ||
DIR_SOUTHEAST: 3, /** se */ | ||
DIR_SOUTH: 4, /** s */ | ||
DIR_SOUTHWEST: 5, /** sw */ | ||
DIR_WEST: 6, /** w */ | ||
DIR_NORTHWEST: 7, /** nw */ | ||
DIR_UP: 8, /** u */ | ||
DIR_DOWN: 9, /** d */ | ||
/** Define direction flag lookup by name */ | ||
directions: { | ||
north: 0, | ||
northeast: 1, | ||
east: 2, | ||
southeast: 3, | ||
south: 4, | ||
southwest: 5, | ||
west: 6, | ||
northwest: 7, | ||
up: 8, | ||
down: 9, | ||
ne: 1, | ||
se: 3, | ||
sw: 5, | ||
nw: 7 | ||
}, | ||
/** Define direction name lookup by direction flag */ | ||
directionNames: [`north`, `northeast`, `east`, `southeast`, `south`, | ||
`southwest`, `west`, `northwest`, `up`, `down`], | ||
/** Define direction short name lookup by direction flag */ | ||
directionShortNames: [`n`, `ne`, `e`, `se`, `s`, `sw`, `w`, `nw`, `u`, `d`], | ||
/** Define direction opposites by direction flag */ | ||
directionOpposites: [4, 5, 6, 7, 0, 1, 2, 3, 9, 8], | ||
/** Define start room */ | ||
START_ROOM: 1, | ||
/** Define default port */ | ||
DEFAULT_PORT: 7000, | ||
/** Define socket states */ | ||
STATE_NAME: 0, | ||
STATE_OLD_PASSWORD: 1, | ||
STATE_NEW_PASSWORD: 2, | ||
STATE_CONFIRM_PASSWORD: 3, | ||
STATE_MOTD: 4, | ||
STATE_CONNECTED: 5, | ||
STATE_DISCONNECTED: 6, | ||
/** Define default welcome */ | ||
DEFAULT_WELCOME: [`\r\n`.repeat(3), | ||
` W E L C O M E T O\r\n`, | ||
`\r\n`.repeat(2), | ||
` _ _\r\n`, | ||
` /\\/\\ _ _ __| | __| |_ _\r\n`, | ||
` / \\| | | |/ _' |/ _' | | | |\r\n`, | ||
` / /\\/\\ \\ |_| | (_| | (_| | |_| |\r\n`, | ||
` \\/ \\/\\__,_|\\__,_|\\__,_|\\__, |\r\n`, | ||
` |___/\r\n`, | ||
`\r\n`, | ||
` Created by Rich Lowe\r\n`, | ||
` MIT Licensed\r\n`, | ||
`\r\n`.repeat(8), | ||
`Hello, what is your name? `].join(``), | ||
/** Define default message of the day */ | ||
DEFAULT_MOTD: [`\r\n`, | ||
`--------------------------------------------------------------------------------\r\n`, | ||
`Message of the day:\r\n`, | ||
`\r\n`, | ||
`Current features:\r\n`, | ||
` * #CC#Bo#Pl#Ro#Yr#Gs#W!#n\r\n`, | ||
` * Movement in all directions\r\n`, | ||
` * Full get/drop/put/wear/remove/wield object interaction\r\n`, | ||
` * Looking at rooms, items, mobiles, users, in containers\r\n`, | ||
` * Admin commands for goto, alist, astat, rlist, rstat, ilist, istat, mlist, \r\n`, | ||
` mstat, and ustat\r\n`, | ||
` * Create command can so far create areas/rooms/prototypes/instances\r\n`, | ||
` * Ability to look at rooms, or at item/user/mobile descriptions\r\n`, | ||
` * Saving of users, new and existing, taking over body\r\n`, | ||
`\r\n`, | ||
`--------------------------------------------------------------------------------\r\n`, | ||
`Press ENTER to continue...\r\n`, | ||
`--------------------------------------------------------------------------------`].join(``) | ||
/** Define VT100 terminal modifiers */ | ||
VT100_CLEAR: `\x1b[0m`, | ||
VT100_HIDE_TEXT: `\x1b[8m` | ||
}; |
@@ -7,9 +7,9 @@ /** Configure Deployment object */ | ||
properties: [ | ||
{ name: `count`, type: `int`, default: -1 }, | ||
{ name: `interval`, type: `int`, default: -1 }, | ||
{ name: `type`, type: `int`, default: -1 }, | ||
{ name: `what`, type: `int`, default: -1 }, | ||
{ name: `where`, type: `int`, default: -1 }, | ||
{ name: `count`, type: `int` }, | ||
{ name: `refresh`, type: `int` }, | ||
{ name: `subject`, type: `int` }, | ||
{ name: `target`, type: `int` }, | ||
{ name: `type`, type: `int` }, | ||
] | ||
}; | ||
}; |
98
info.js
@@ -26,4 +26,102 @@ module.exports.createCommands = (world) => { | ||
priority: 0 | ||
}), | ||
new world.Command({ | ||
name: `help`, | ||
execute: async (world, user, buffer, args) => { | ||
/** If no first argument was provided, send error */ | ||
if ( typeof args[0] != `string` ) { | ||
/** Attempt to find help in world */ | ||
const help = world.help().find(x => x.name() == ``); | ||
/** If help not found, send error */ | ||
if ( !help ) { | ||
world.log().error(`The default help record is missing from the database`); | ||
return user.send(`There is no help, you are on your own for now...\r\n`); | ||
} | ||
/** Add border to text */ | ||
const text = help.text().replace(/\r/g, ``).split(`\n`).map(x => `#r|#n ` + x.padEnd(77 + x.length - world.colorizedLength(x)) + `#r|`).join(`\r\n`); | ||
/** Send help text */ | ||
user.send(world.colorize(`#r~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n`)); | ||
user.send(world.colorize(`#r| #WHELP ${help.name().toUpperCase().padEnd(32)} #r|\r\n`)); | ||
user.send(world.colorize(`#r~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n`)); | ||
user.send(world.colorize(`#r| #r|\r\n`)); | ||
user.send(world.colorize(text + `\r\n`)); | ||
const suggestedSubjects = [`MUDDY`, `COMMANDS`, `MOVEMENT`, `EQUIPMENT`, `AREAS`, `COMBAT`]; | ||
let subjects = `\r\n`; | ||
suggestedSubjects.forEach((value, index) => { | ||
subjects += value.padEnd(14); | ||
if ( (index + 1) % 5 == 0 ) | ||
subjects += `\r\n\r\n`; | ||
else | ||
subjects += ` `; | ||
}); | ||
subjects += `\r\n`; | ||
subjects = subjects.replace(/\r/g, ``).split(`\n`).map(x => `#r|#n ` + x.padEnd(77 + x.length - world.colorizedLength(x)) + `#r|`).join(`\r\n`); | ||
/** Send subjects and new line */ | ||
user.send(world.colorize(subjects) + `\r\n`); | ||
user.send(world.colorize(`#r~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n`)); | ||
return; | ||
} | ||
/** Attempt to find help in world */ | ||
const help = world.help().find(x => x.name().toLowerCase().startsWith(args[0])); | ||
/** If help not found, send error */ | ||
if ( !help ) | ||
return user.send(`There is no help topic matching that name.\r\n`); | ||
/** Add border to text */ | ||
const text = help.text().replace(/\r/g, ``).split(`\n`).map(x => `#r|#n ` + x.padEnd(77 + x.length - world.colorizedLength(x)) + `#r|`).join(`\r\n`); | ||
/** Send help text */ | ||
user.send(world.colorize(`#r~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n`)); | ||
user.send(world.colorize(`#r| #WHELP ${help.name().toUpperCase().padEnd(32)} #r|\r\n`)); | ||
user.send(world.colorize(`#r~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n`)); | ||
user.send(world.colorize(text)); | ||
}, | ||
priority: 0 | ||
}), | ||
new world.Command({ | ||
name: `score`, | ||
execute: async (world, user, buffer, args) => { | ||
/** Send top border */ | ||
user.send(world.colorize(`#r~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n`)); | ||
user.send(world.colorize(`#r| |\r\n`)); | ||
/** Send user name and stats header */ | ||
user.send(world.colorize(`#r| #wName: #W${user.name().padEnd(16)} #wSex: #W${world.constants().sexNames[user.sex()].padStart(6)} #wLevel: #W${user.level().toString().padStart(5)} #r|\r\n`)); | ||
user.send(world.colorize(`#r| |\r\n`)); | ||
user.send(world.colorize(`#r| #wHealth: ${(world.colorStat(user.health(), user.maxHealth()) + `#w/#C` + user.maxHealth()).padStart(21)} #wCombat Stats: #r|\r\n`)); | ||
user.send(world.colorize(`#r| #wMana: ${(world.colorStat(user.mana(), user.maxMana()) + `#w/#C` + user.maxMana()).padStart(21)} #r|\r\n`)); | ||
user.send(world.colorize(`#r| #wEnergy: ${(world.colorStat(user.energy(), user.maxEnergy()) + `#w/#C` + user.maxEnergy()).padStart(21)} #wAccuracy: #G${user.accuracy().toString().padStart(5)} #wArmor: #G${user.armor().toString().padStart(5)} #r|\r\n`)); | ||
user.send(world.colorize(`#r| #wPower: #G${user.power().toString().padStart(5)} #wDeflection: #G${user.deflection().toString().padStart(5)} #r|\r\n`)); | ||
user.send(world.colorize(`#r| #wExperience: #C${user.experience().toString().padStart(9)} #wSpeed: #G${user.speed().toString().padStart(5)} #wDodge: #G${user.accuracy().toString().padStart(5)} #r|\r\n`)); | ||
user.send(world.colorize(`#r| |\r\n`)); | ||
user.send(world.colorize(`#r~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n`)); | ||
user.send(world.colorize(`#r| |\r\n`)); | ||
user.send(world.colorize(`#r| #wElemental Attunement: #r|\r\n`)); | ||
user.send(world.colorize(`#r| |\r\n`)); | ||
user.send(world.colorize(`#r| #WAir: #G${user.air().toString().padStart(5)} #yEarth: #G${user.earth().toString().padStart(5)} #RFire: #G${user.fire().toString().padStart(5)}#n #gLife: #G${user.life().toString().padStart(5)} #cWater: #G${user.water().toString().padStart(5)} #r|\r\n`)); | ||
user.send(world.colorize(`#r| |\r\n`)); | ||
user.send(world.colorize(`#r~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n`)); | ||
user.send(world.colorize(`#r| |\r\n`)); | ||
user.send(world.colorize(`#r| #wPosition: #W${world.constants().positionNames[user.position()].padEnd(13)} #r|\r\n`)); | ||
user.send(world.colorize(`#r| |\r\n`)); | ||
/** Send first bottom border */ | ||
user.send(world.colorize(`#r~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n`)); | ||
}, | ||
priority: 0 | ||
}) | ||
]; | ||
}; |
@@ -347,13 +347,13 @@ module.exports.createCommands = (world) => { | ||
} | ||
/** Verify item is equippable */ | ||
else if ( items[count - 1].slot() == world.constants().SLOT_NONE ) { | ||
user.send(`That item is not equippable.\r\n`); | ||
} | ||
/** Verify item is wearable */ | ||
else if ( items[count - 1].slot() == world.constants().SLOT_WIELD ) { | ||
else if ( items[count - 1].slot() == world.constants().SLOT_WIELD && world.constants().itemTypesWieldable.includes(items[count - 1].type()) ) { | ||
user.send(`You need to 'wield' weapons and held items, not 'wear' them.\r\n`); | ||
} | ||
/** Verify item is equippable */ | ||
else if ( items[count - 1].slot() != world.constants().SLOT_ARMOR ) { | ||
user.send(`That item is not equippable.\r\n`); | ||
} | ||
/** Verify the appropriate slot is available */ | ||
@@ -437,2 +437,7 @@ else if ( user.equipment().find(x => x.slot() == items[count - 1].slot()) ) { | ||
/** Verify item is a weapon */ | ||
else if ( !world.constants().itemTypesWieldable.includes(items[count - 1].type()) ) { | ||
user.send(`That item is not wieldable.\r\n`); | ||
} | ||
/** Try to wield item */ | ||
@@ -439,0 +444,0 @@ else { |
@@ -13,2 +13,3 @@ /** Configure ItemInstance object */ | ||
{ name: `deflection`, type: `int` }, | ||
{ name: `deployment`, type: `Deployment`, store: false }, | ||
{ name: `description`, type: `varchar`, length: 512, default: `It looks like a wieghtless and translucent spherical form of bound energy.` }, | ||
@@ -15,0 +16,0 @@ { name: `details`, type: `object` }, |
@@ -8,3 +8,2 @@ /** Configure ItemPrototype object */ | ||
{ name: `author`, type: `varchar`, length: 32, default: `Anonymous` }, | ||
{ name: `contents`, type: `Array`, arrayOf: { instanceOf: `ItemPrototype` } }, | ||
{ name: `created`, type: `datetime`, default: new Date() }, | ||
@@ -11,0 +10,0 @@ { name: `description`, type: `varchar`, length: 512, default: `It looks like a wieghtless and translucent spherical form of bound energy.` }, |
@@ -9,2 +9,3 @@ /** Configure MobileInstance object as extension of Mobile */ | ||
properties: [ | ||
{ name: `deployment`, type: `Deployment`, store: false }, | ||
{ name: `description`, type: `varchar`, length: 512, default: `They look like the most boring person you could possibly imagine.` }, | ||
@@ -11,0 +12,0 @@ { name: `equipment`, type: `Array`, arrayOf: { instanceOf: `ItemInstance` } }, |
@@ -12,4 +12,2 @@ /** Configure MobilePrototype object as extension of Character */ | ||
{ name: `description`, type: `varchar`, length: 512, default: `They look like the most boring person you could possibly imagine.` }, | ||
{ name: `equipment`, type: `Array`, arrayOf: { instanceOf: `ItemPrototype` } }, | ||
{ name: `inventory`, type: `Array`, arrayOf: { instanceOf: `ItemPrototype` } }, | ||
{ name: `names`, type: `Array`, arrayOf: { type: `varchar`, length: 32 }, default: [`person`] }, | ||
@@ -16,0 +14,0 @@ { name: `room`, instanceOf: `Room`, store: false }, |
{ | ||
"name": "muddy", | ||
"version": "0.10.5", | ||
"version": "0.10.6", | ||
"description": "A Node.js Multi-User Dungeon (MUD) Framework", | ||
@@ -8,3 +8,3 @@ "main": "index.js", | ||
"start": "node example.js", | ||
"test": "node_modules/.bin/eslint admin.js areas.js building.js characters.js commands.js constants.js deployments.js example.js exits.js fighting.js index.js info.js input.js interaction.js item-instances.js item-prototypes.js mobile-instances.js mobile-prototypes.js movement.js rooms.js senses.js system.js users.js web.js world.js" | ||
"test": "node_modules/.bin/eslint admin.js areas.js building.js characters.js commands.js constants.js deployments.js example.js exits.js fighting.js help.js index.js info.js input.js interaction.js item-instances.js item-prototypes.js mobile-instances.js mobile-prototypes.js movement.js rooms.js senses.js system.js users.js web.js world.js" | ||
}, | ||
@@ -32,4 +32,4 @@ "repository": { | ||
"devDependencies": { | ||
"docket-parser": "^0.7.1", | ||
"eslint": "^5.15.3" | ||
"docket-parser": "^0.7.2", | ||
"eslint": "^5.16.0" | ||
}, | ||
@@ -41,9 +41,9 @@ "jshintConfig": { | ||
"dependencies": { | ||
"body-parser": "^1.18.3", | ||
"body-parser": "^1.19.0", | ||
"express": "^4.16.4", | ||
"ezobjects-mysql": "^6.1.16", | ||
"moment": "^2.24.0", | ||
"strapped": "^0.6.4", | ||
"strapped": "^0.6.8", | ||
"winston": "^2.4.4" | ||
} | ||
} |
@@ -1,2 +0,2 @@ | ||
# Muddy v0.10.5 [![HitCount](http://hits.dwyl.com/om-mani-padme-hum/muddy.svg)](http://hits.dwyl.com/om-mani-padme-hum/muddy) | ||
# Muddy v0.10.6 [![HitCount](http://hits.dwyl.com/om-mani-padme-hum/muddy.svg)](http://hits.dwyl.com/om-mani-padme-hum/muddy) | ||
@@ -8,3 +8,3 @@ A Node.js Multi-User Dungeon (MUD) Framework | ||
* A good amount of basic functionality in place, but still under development. | ||
* Ability to build onto world while in game partially in place, now can edit rooms and areas. | ||
* Ability to build onto world while in game partially in place, now can edit items, rooms, and areas. | ||
* Web-based builder interface partially in place, not very useful just yet but some editing is possible. | ||
@@ -64,3 +64,3 @@ * Basic fighting has now been added, including incapacitated state and natural healing over time! | ||
* east | ||
* edit (partly functional) | ||
* edit | ||
* equipment | ||
@@ -70,2 +70,3 @@ * get | ||
* look | ||
* help | ||
* ilist | ||
@@ -86,2 +87,3 @@ * inventory | ||
* save | ||
* score | ||
* shutdown | ||
@@ -101,2 +103,6 @@ * south | ||
* Added mobile instance and prototype editing in game | ||
* Ability to create exits in game | ||
* Added elemental properties to characters | ||
* Added help and score commands, default help added, many more to do | ||
* Fixed bugs with capitalization and colors on new character logins | ||
@@ -118,3 +124,3 @@ * Ability to look at item details | ||
* Advanced mobile scripting capabilities, along with dynamic weather and other periodic events, all customizable | ||
* Paths and lineages, each with their unique benefits, deficiencies, and skillsets, again completely customizable | ||
* Paths and races, each with their unique benefits, deficiencies, and skillsets, again completely customizable | ||
@@ -121,0 +127,0 @@ # License |
@@ -109,2 +109,3 @@ module.exports.createCommands = (world) => { | ||
/** Send target mobile's description */ | ||
user.send(`${world.terminalWrap(world.colorize(targets[count - 1].name()))}\r\n`); | ||
user.send(`${world.terminalWrap(world.colorize(targets[count - 1].description()))}\r\n\r\n`); | ||
@@ -122,4 +123,6 @@ | ||
/** Parse detail name and count */ | ||
const [detailName, detailCount] = world.parseName(user, args, 1); | ||
/** Attempt to find detail on target */ | ||
const detail = Object.keys(targets[count - 1].details()).filter(x => x.startsWith(detailName))[detailCount - 1]; | ||
@@ -135,15 +138,24 @@ | ||
/** Otherwise, send target description */ | ||
/** Otherwise... */ | ||
else { | ||
/** Send item description */ | ||
user.send(`${world.terminalWrap(world.colorize(targets[count - 1].description()))}\r\n`); | ||
/** Create array of detail keys */ | ||
const keys = Object.keys(targets[count - 1].details()); | ||
/** If there are details, output heading */ | ||
if ( keys.length > 0 ) | ||
user.send(`\r\nDetails: `); | ||
keys.forEach((key) => { | ||
/** Loop through each detail key and output */ | ||
keys.forEach((key, index) => { | ||
user.send(`${key} `); | ||
/** Output new line after every fifth key */ | ||
if ( (index + 1) % 6 == 0 && index != keys.length - 1 ) | ||
user.send(`\r\n`); | ||
}); | ||
/** If we output some detail keys, send new line */ | ||
if ( keys.length > 0 ) | ||
@@ -203,5 +215,23 @@ user.send(`\r\n`); | ||
/** Loop through each mobile in user's room and send room description */ | ||
/** Loop through each mobile in user's room... */ | ||
user.room().mobiles().forEach((mobile) => { | ||
user.send(` ${mobile.roomDescription()}\r\n`); | ||
/** Send description based on mobile's position and who they're fighting */ | ||
if ( mobile.position() == world.constants().POSITION_INCAPACITATED ) | ||
user.send(` ${mobile.name()} is lying here incapacitated!\r\n`); | ||
else if ( mobile.position() == world.constants().POSITION_SLEEPING ) | ||
user.send(` ${mobile.name()} is lying here sleeping\r\n`); | ||
else if ( mobile.position() == world.constants().POSITION_MEDITATING ) | ||
user.send(` ${mobile.name()} is meditating here\r\n`); | ||
else if ( mobile.position() == world.constants().POSITION_LYING_DOWN ) | ||
user.send(` ${mobile.name()} is lying down here\r\n`); | ||
else if ( mobile.position() == world.constants().POSITION_KNEELING ) | ||
user.send(` ${mobile.name()} is kneeling here\r\n`); | ||
else if ( mobile.position() == world.constants().POSITION_SITTING ) | ||
user.send(` ${mobile.name()} is sitting here\r\n`); | ||
else if ( mobile.fighting() && mobile.fighting() == user ) | ||
user.send(` ${mobile.name()} is here fighting YOU!\r\n`); | ||
else if ( mobile.fighting() ) | ||
user.send(` ${mobile.name()} is here fighting ${mobile.fighting().name()}!\r\n`); | ||
else | ||
user.send(` ${mobile.roomDescription()}\r\n`); | ||
}); | ||
@@ -211,4 +241,5 @@ | ||
user.room().users().forEach((other) => { | ||
/** If user in room is not the looking user, send user name */ | ||
/** If user in room is not the looking user... */ | ||
if ( user != other ) { | ||
/** Send description based on user's position and who they're fighting */ | ||
if ( other.position() == world.constants().POSITION_INCAPACITATED ) | ||
@@ -288,3 +319,3 @@ user.send(` ${other.name()} is lying here incapacitated!\r\n`); | ||
/** Send top border */ | ||
user.send(world.colorize(`#r~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\r\n`)); | ||
user.send(world.colorize(`#r~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n\r\n`)); | ||
@@ -291,0 +322,0 @@ /** Keep track of the number of visible other users */ |
@@ -502,3 +502,3 @@ /** Require external modules */ | ||
world.constants().itemNames.forEach((name, value) => { | ||
world.constants().itemTypeNames.forEach((name, value) => { | ||
p.option().value(value).text(name); | ||
@@ -505,0 +505,0 @@ }); |
215
world.js
@@ -13,4 +13,6 @@ /** Require external modules */ | ||
const constants = require(`./constants`); | ||
const deployments = require(`./deployments`); | ||
const exits = require(`./exits`); | ||
const fighting = require(`./fighting`); | ||
const help = require(`./help`); | ||
const info = require(`./info`); | ||
@@ -38,2 +40,4 @@ const input = require(`./input`); | ||
{ name: `database`, type: `MySQLConnection` }, | ||
{ name: `deployments`, type: `Array`, arrayOf: { instanceOf: `Deployment` } }, | ||
{ name: `help`, type: `Array`, arrayOf: { instanceOf: `Help` } }, | ||
{ name: `itemPrototypes`, type: `Array`, arrayOf: { instanceOf: `ItemPrototype` } }, | ||
@@ -74,3 +78,3 @@ { name: `log`, instanceOf: `Object` }, | ||
for ( let i = 0, i_max = areaList.length; i < i_max; i++ ) { | ||
for ( let i = 0, iMax = areaList.length; i < iMax; i++ ) { | ||
/** Load area from database */ | ||
@@ -82,10 +86,13 @@ const area = await new this.Area().load(areaList[i], this.database()); | ||
for ( let j = 0, j_max = area.mobilePrototypes().length; j < j_max; j++ ) | ||
for ( let j = 0, jMax = area.mobilePrototypes().length; j < jMax; j++ ) | ||
this.mobilePrototypes().push(area.mobilePrototypes()[j]); | ||
for ( let j = 0, j_max = area.itemPrototypes().length; j < j_max; j++ ) | ||
for ( let j = 0, jMax = area.itemPrototypes().length; j < jMax; j++ ) | ||
this.itemPrototypes().push(area.itemPrototypes()[j]); | ||
for ( let j = 0, jMax = area.deployments().length; j < jMax; j++ ) | ||
this.deployments().push(area.deployments()[j]); | ||
/** Loop through area rooms */ | ||
for ( let i = 0, i_max = area.rooms().length; i < i_max; i++ ) { | ||
for ( let i = 0, iMax = area.rooms().length; i < iMax; i++ ) { | ||
/** Set area of room */ | ||
@@ -131,2 +138,14 @@ area.rooms()[i].area(area); | ||
}); | ||
/** Load help */ | ||
const helpList = await this.database().query(`SELECT * FROM help`); | ||
/** Load help from database */ | ||
for ( let i = 0, iMax = helpList.length; i < iMax; i++ ) { | ||
/** Load help data into object */ | ||
const help = await new this.Help().load(helpList[i]); | ||
/** Add help to world */ | ||
this.help().push(help); | ||
} | ||
}; | ||
@@ -196,5 +215,15 @@ | ||
/** If item is part of the equipment, remove it from the equipment list */ | ||
if ( item.character().equipment().indexOf(item) !== -1 ) | ||
/** If item is part of the equipment... */ | ||
if ( item.character().equipment().indexOf(item) !== -1 ) { | ||
/** Subtract item stats from character's stats */ | ||
item.character().accuracy(item.character().accuracy() - item.accuracy()); | ||
item.character().armor(item.character().armor() - item.armor()); | ||
item.character().deflection(item.character().deflection() - item.deflection()); | ||
item.character().dodge(item.character().dodge() - item.dodge()); | ||
item.character().power(item.character().power() - item.power()); | ||
item.character().speed(item.character().speed() - item.speed()); | ||
/** Remove item from equipment list */ | ||
item.character().equipment().splice(item.character().equipment().indexOf(item), 1); | ||
} | ||
@@ -260,2 +289,10 @@ /** Save character */ | ||
/** Add item stats to character's stats */ | ||
character.accuracy(character.accuracy() + item.accuracy()); | ||
character.armor(character.armor() + item.armor()); | ||
character.deflection(character.deflection() + item.deflection()); | ||
character.dodge(character.dodge() + item.dodge()); | ||
character.power(character.power() + item.power()); | ||
character.speed(character.speed() + item.speed()); | ||
/** Save character */ | ||
@@ -292,5 +329,2 @@ await character.update(this.database()); | ||
for ( let i = 0, i_max = prototype.contents().length; i < i_max; i++ ) | ||
itemInstance.contents().push(await this.itemInstanceFromPrototype(prototype.contents()[i])); | ||
await itemInstance.insert(this.database()); | ||
@@ -332,14 +366,14 @@ | ||
user.send(this.colorize(` #y[Head ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_HEAD) ? other.equipment().find(x => x.slot() == this.constants().SLOT_HEAD).name() : `none`}\r\n`)); | ||
user.send(this.colorize(` #y[Face ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_FACE) ? other.equipment().find(x => x.slot() == this.constants().SLOT_FACE).name() : `none`}\r\n`)); | ||
user.send(this.colorize(` #y[Neck ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_NECK) ? other.equipment().find(x => x.slot() == this.constants().SLOT_NECK).name() : `none`}\r\n`)); | ||
user.send(this.colorize(` #y[Shoulders ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_SHOULDERS) ? other.equipment().find(x => x.slot() == this.constants().SLOT_SHOULDERS).name() : `none`}\r\n`)); | ||
user.send(this.colorize(` #y[Chest ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_CHEST) ? other.equipment().find(x => x.slot() == this.constants().SLOT_CHEST).name() : `none`}\r\n`)); | ||
user.send(this.colorize(` #y[Back ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_BACK) ? other.equipment().find(x => x.slot() == this.constants().SLOT_BACK).name() : `none`}\r\n`)); | ||
user.send(this.colorize(` #y[Arms ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_ARMS) ? other.equipment().find(x => x.slot() == this.constants().SLOT_ARMS).name() : `none`}\r\n`)); | ||
user.send(this.colorize(` #y[Wrists ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_WRISTS) ? other.equipment().find(x => x.slot() == this.constants().SLOT_WRISTS).name() : `none`}\r\n`)); | ||
user.send(this.colorize(` #y[Gloves ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_GLOVES) ? other.equipment().find(x => x.slot() == this.constants().SLOT_GLOVES).name() : `none`}\r\n`)); | ||
user.send(this.colorize(` #y[Waist ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_WAIST) ? other.equipment().find(x => x.slot() == this.constants().SLOT_WAIST).name() : `none`}\r\n`)); | ||
user.send(this.colorize(` #y[Legs ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_LEGS) ? other.equipment().find(x => x.slot() == this.constants().SLOT_LEGS).name() : `none`}\r\n`)); | ||
user.send(this.colorize(` #y[Feet ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_FEET) ? other.equipment().find(x => x.slot() == this.constants().SLOT_FEET).name() : `none`}\r\n`)); | ||
user.send(this.colorize(` #y[Head ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_HEAD) ? other.equipment().find(x => x.slot() == this.constants().SLOT_HEAD).name() : `nothing`}\r\n`)); | ||
user.send(this.colorize(` #y[Face ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_FACE) ? other.equipment().find(x => x.slot() == this.constants().SLOT_FACE).name() : `nothing`}\r\n`)); | ||
user.send(this.colorize(` #y[Neck ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_NECK) ? other.equipment().find(x => x.slot() == this.constants().SLOT_NECK).name() : `nothing`}\r\n`)); | ||
user.send(this.colorize(` #y[Shoulders ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_SHOULDERS) ? other.equipment().find(x => x.slot() == this.constants().SLOT_SHOULDERS).name() : `nothing`}\r\n`)); | ||
user.send(this.colorize(` #y[Chest ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_CHEST) ? other.equipment().find(x => x.slot() == this.constants().SLOT_CHEST).name() : `nothing`}\r\n`)); | ||
user.send(this.colorize(` #y[Back ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_BACK) ? other.equipment().find(x => x.slot() == this.constants().SLOT_BACK).name() : `nothing`}\r\n`)); | ||
user.send(this.colorize(` #y[Arms ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_ARMS) ? other.equipment().find(x => x.slot() == this.constants().SLOT_ARMS).name() : `nothing`}\r\n`)); | ||
user.send(this.colorize(` #y[Wrists ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_WRISTS) ? other.equipment().find(x => x.slot() == this.constants().SLOT_WRISTS).name() : `nothing`}\r\n`)); | ||
user.send(this.colorize(` #y[Gloves ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_GLOVES) ? other.equipment().find(x => x.slot() == this.constants().SLOT_GLOVES).name() : `nothing`}\r\n`)); | ||
user.send(this.colorize(` #y[Waist ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_WAIST) ? other.equipment().find(x => x.slot() == this.constants().SLOT_WAIST).name() : `nothing`}\r\n`)); | ||
user.send(this.colorize(` #y[Legs ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_LEGS) ? other.equipment().find(x => x.slot() == this.constants().SLOT_LEGS).name() : `nothing`}\r\n`)); | ||
user.send(this.colorize(` #y[Feet ]#n ${other.equipment().find(x => x.slot() == this.constants().SLOT_FEET) ? other.equipment().find(x => x.slot() == this.constants().SLOT_FEET).name() : `nothing`}\r\n`)); | ||
@@ -351,9 +385,10 @@ const wieldedItems = other.equipment().filter(x => x.slot() == this.constants().SLOT_WIELD); | ||
user.send(this.colorize(` #y[Left Hand ]#n ${wieldedItems[1].name()}\r\n`)); | ||
} else if ( wieldedItems.length == 1 && wieldedItems[0].type() == this.constants().ITEM_2H_WEAPON ) { | ||
user.send(this.colorize(` #y[Hands ]#n ${wieldedItems[0].name()}\r\n`)); | ||
} else if ( wieldedItems.length == 1 ) { | ||
if ( wieldedItems[0].type() == this.constants().ITEM_2H_WEAPON ) | ||
user.send(this.colorize(` #y[Hands ]#n ${wieldedItems[0].name()}\r\n`)); | ||
else | ||
user.send(this.colorize(` #y[Right Hand ]#n ${wieldedItems[0].name()}\r\n`)); | ||
user.send(this.colorize(` #y[Right Hand ]#n ${wieldedItems[0].name()}\r\n`)); | ||
user.send(this.colorize(` #y[Left Hand ]#n nothing\r\n`)); | ||
} else { | ||
user.send(this.colorize(` #y[Hands ]#n none\r\n`)); | ||
user.send(this.colorize(` #y[Right Hand ]#n nothing\r\n`)); | ||
user.send(this.colorize(` #y[Left Hand ]#n nothing\r\n`)); | ||
} | ||
@@ -459,2 +494,24 @@ }; | ||
World.prototype.colorizedLength = function (text) { | ||
let newText = ``; | ||
/** Loop through original text one character at a time... */ | ||
for ( let i = 0; i < text.length; i++ ) { | ||
/** If this is not the last character and it's a '#' or '%'... */ | ||
if ( i < text.length - 1 && ( text[i] == `#` || text[i] == `%` ) ) { | ||
/** Skip past second character of color code */ | ||
i++; | ||
/** Move on to the next character */ | ||
continue; | ||
} | ||
/** Append the current character of the old text to the new text */ | ||
newText += text[i]; | ||
} | ||
/** Return new text length */ | ||
return newText.length; | ||
}; | ||
World.prototype.createArea = async function (params) { | ||
@@ -474,10 +531,33 @@ /** Create new area */ | ||
World.prototype.createDeployment = async function (area, params) { | ||
/** Create new deployment */ | ||
const deployment = new this.Deployment(params); | ||
/** Insert deployment into the database */ | ||
await deployment.insert(this.database()); | ||
/** Add deployment to area */ | ||
area.deployments().push(deployment); | ||
/** Update area in database */ | ||
await area.update(this.database()); | ||
/** Return room */ | ||
return deployment; | ||
}; | ||
World.prototype.createExit = async function (params) { | ||
/** Create new exit */ | ||
const exit = new this.Exit(params); | ||
/** Insert exit into the database */ | ||
await exit.insert(this.database()); | ||
/** Return room */ | ||
/** Add outgoing exit to user's room */ | ||
exit.room().exits().push(exit); | ||
/** Save exit's room */ | ||
await exit.room().update(this.database()); | ||
/** Return exit */ | ||
return exit; | ||
@@ -584,2 +664,5 @@ }; | ||
const room = new this.Room(params); | ||
/** Set room's area */ | ||
room.area(area); | ||
@@ -602,2 +685,19 @@ /** Insert room into the database */ | ||
World.prototype.colorStat = function (value, maxValue) { | ||
const ratio = value / maxValue; | ||
if ( ratio < 0.2 ) | ||
return `#R${value}#n`; | ||
else if ( ratio < 0.4 ) | ||
return `#P${value}#n`; | ||
else if ( ratio < 0.6 ) | ||
return `#B${value}#n`; | ||
else if ( ratio < 0.8 ) | ||
return `#Y${value}#n`; | ||
else if ( ratio < 1 ) | ||
return `#G${value}#n`; | ||
return `#C${value}#n`; | ||
}; | ||
/** | ||
@@ -643,3 +743,5 @@ * @signature world.listen() | ||
const configCommand = commands.configCommand(this); | ||
const configDeployment = deployments.configDeployment(this); | ||
const configExit = exits.configExit(this); | ||
const configHelp = help.configHelp(this); | ||
const configItemPrototype = itemPrototypes.configItemPrototype(this); | ||
@@ -649,3 +751,5 @@ const configRoom = rooms.configRoom(this); | ||
await ezobjects.createTable(configArea, this.database()); | ||
await ezobjects.createTable(configDeployment, this.database()); | ||
await ezobjects.createTable(configExit, this.database()); | ||
await ezobjects.createTable(configHelp, this.database()); | ||
await ezobjects.createTable(configItemPrototype, this.database()); | ||
@@ -658,3 +762,5 @@ await ezobjects.createTable(configRoom, this.database()); | ||
ezobjects.createClass(configCommand); | ||
ezobjects.createClass(configDeployment); | ||
ezobjects.createClass(configExit); | ||
ezobjects.createClass(configHelp); | ||
ezobjects.createClass(configItemPrototype); | ||
@@ -680,53 +786,8 @@ ezobjects.createClass(configRoom); | ||
User.prototype.prompt = function (world) { | ||
const healthRatio = this.health() / this.maxHealth(); | ||
const manaRatio = this.mana() / this.maxMana(); | ||
const energyRatio = this.energy() / this.maxEnergy(); | ||
let health, mana, energy; | ||
if ( healthRatio < 0.2 ) | ||
health = `#R${this.health()}#n`; | ||
else if ( healthRatio < 0.4 ) | ||
health = `#P${this.health()}#n`; | ||
else if ( healthRatio < 0.6 ) | ||
health = `#B${this.health()}#n`; | ||
else if ( healthRatio < 0.8 ) | ||
health = `#Y${this.health()}#n`; | ||
else if ( healthRatio < 1 ) | ||
health = `#G${this.health()}#n`; | ||
else | ||
health = `#C${this.health()}#n`; | ||
if ( manaRatio < 0.2 ) | ||
mana = `#R${this.mana()}#n`; | ||
else if ( manaRatio < 0.4 ) | ||
mana = `#P${this.mana()}#n`; | ||
else if ( manaRatio < 0.6 ) | ||
mana = `#B${this.mana()}#n`; | ||
else if ( manaRatio < 0.8 ) | ||
mana = `#Y${this.mana()}#n`; | ||
else if ( manaRatio < 1 ) | ||
mana = `#G${this.mana()}#n`; | ||
else | ||
mana = `#C${this.mana()}#n`; | ||
if ( energyRatio < 0.2 ) | ||
energy = `#R${this.energy()}#n`; | ||
else if ( energyRatio < 0.4 ) | ||
energy = `#P${this.energy()}#n`; | ||
else if ( energyRatio < 0.6 ) | ||
energy = `#B${this.energy()}#n`; | ||
else if ( energyRatio < 0.8 ) | ||
energy = `#Y${this.energy()}#n`; | ||
else if ( energyRatio < 1 ) | ||
energy = `#G${this.energy()}#n`; | ||
else | ||
energy = `#C${this.energy()}#n`; | ||
let prompt = `\r\n` + this.promptFormat(); | ||
prompt = prompt.replace(/\$xp/g, `#c${this.experience()}#n`); | ||
prompt = prompt.replace(/\$hp/g, health); | ||
prompt = prompt.replace(/\$m/g, mana); | ||
prompt = prompt.replace(/\$e/g, energy); | ||
prompt = prompt.replace(/\$hp/g, world.colorStat(this.health(), this.maxHealth())); | ||
prompt = prompt.replace(/\$m/g, world.colorStat(this.mana(), this.maxMana())); | ||
prompt = prompt.replace(/\$e/g, world.colorStat(this.energy(), this.maxEnergy())); | ||
@@ -767,3 +828,5 @@ this.send(world.colorize(prompt)); | ||
this.Command = Command; | ||
this.Deployment = Deployment; | ||
this.Exit = Exit; | ||
this.Help = Help; | ||
this.ItemPrototype = ItemPrototype; | ||
@@ -770,0 +833,0 @@ this.ItemInstance = ItemInstance; |
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
267440
36
4737
123
38
+ Addedobject-inspect@1.13.3(transitive)
- Removedobject-inspect@1.13.4(transitive)
Updatedbody-parser@^1.19.0
Updatedstrapped@^0.6.8