Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/RanvierMUD/core
Browse files Browse the repository at this point in the history
  • Loading branch information
Sean O'Donohue committed May 21, 2019
2 parents c4a37ff + 1875f26 commit d28f876
Show file tree
Hide file tree
Showing 18 changed files with 265 additions and 48 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"bugs": "https://github.com/ranviermud/core/issues",
"license": "MIT",
"author": "Shawn Biddle (http://shawnbiddle.com)",
"version": "3.0.3",
"version": "3.0.6",
"repository": "github:ranviermud/core",
"engines": {
"node": ">= 10.12.0"
Expand Down
15 changes: 15 additions & 0 deletions src/Area.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,23 @@ class Area extends GameEntity {
this.addRoom(room);
state.RoomManager.addRoom(room);
room.hydrate(state);
/**
* Fires after the room is hydrated and added to its area
* @event Room#ready
*/
room.emit('ready');
}
}

/**
* Get all possible broadcast targets within an area. This includes all npcs,
* players, rooms, and the area itself
* @return {Array<Broadcastable>}
*/
getBroadcastTargets() {
const roomTargets = [...this.rooms].reduce((acc, [, room]) => acc.concat(room.getBroadcastTargets()), []);
return [this, ...roomTargets];
}
}

module.exports = Area;
14 changes: 5 additions & 9 deletions src/AreaAudience.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,12 @@ const ChannelAudience = require('./ChannelAudience');
*/
class AreaAudience extends ChannelAudience {
getBroadcastTargets() {
// It would be more elegant to just pass the area but that could be very
// inefficient as it's much more likely that there are fewer players than
// there are rooms in the area
const players = this.state.PlayerManager.filter(player =>
player.room &&
(player.room.area === this.sender.room.area) &&
(player !== this.sender)
);
if (!this.sender.room) {
return [];
}

return players.concat(area.npcs);
const { area } = this.sender.room;
return area.getBroadcastTargets().filter(target => target !== this.sender);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/AreaFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class AreaFactory extends EntityFactory {
const area = new Area(definition.bundle, entityRef, definition.manifest);

if (this.scripts.has(entityRef)) {
this.scripts.get(entityRef).attach(entity);
this.scripts.get(entityRef).attach(area);
}

return area;
Expand Down
12 changes: 6 additions & 6 deletions src/BundleManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,13 +270,13 @@ class BundleManager {
const scriptPath = this._getAreaScriptPath(bundle, areaName);

if (manifest.script) {
const scriptPath = `${scriptPath}/${area.script}.js`;
if (!fs.existsSync(scriptPath)) {
Logger.warn(`\t\t\t[${areaName}] has non-existent script "${area.script}"`);
const areaScriptPath = `${scriptPath}/${manifest.script}.js`;
if (!fs.existsSync(areaScriptPath)) {
Logger.warn(`\t\t\t[${areaName}] has non-existent script "${manifest.script}"`);
}

Logger.verbose(`\t\t\tLoading Item Script [${entityRef}] ${item.script}`);
this.loadEntityScript(this.state.AreaFactory, entityRef, scriptPath);
Logger.verbose(`\t\t\tLoading Area Script for [${areaName}]: ${manifest.script}`);
this.loadEntityScript(this.state.AreaFactory, areaName, areaScriptPath);
}

Logger.verbose(`\t\tLOAD: Quests...`);
Expand Down Expand Up @@ -573,7 +573,7 @@ class BundleManager {
const loader = require(effectPath);

Logger.verbose(`\t\t${effectName}`);
this.state.EffectFactory.add(effectName, this._getLoader(loader, srcPath));
this.state.EffectFactory.add(effectName, this._getLoader(loader, srcPath), this.state);
}

Logger.verbose(`\tENDLOAD: Effects...`);
Expand Down
8 changes: 4 additions & 4 deletions src/Character.js
Original file line number Diff line number Diff line change
Expand Up @@ -524,12 +524,12 @@ class Character extends Metadatable(EventEmitter) {
}

/**
* @param {Character} target
* @param {Character} follower
* @fires Character#lostFollower
*/
removeFollower(target) {
this.followers.delete(target);
target.following = null;
removeFollower(follower) {
this.followers.delete(follower);
follower.following = null;
/**
* @event Character#lostFollower
* @param {Character} follower
Expand Down
66 changes: 54 additions & 12 deletions src/CommandQueue.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
'use strict';

/** @typedef {{ execute: function (), label: string, lag: number= }} */
var CommandExecutable;

/**
* Keeps track of the queue off commands to execute for a player
*/
Expand All @@ -11,7 +14,17 @@ class CommandQueue {
}

/**
* @param {{execute: function (), label: string}} executable Thing to run with an execute and a queue label
* Safely add lag to the current queue. This method will not let you add a
* negative amount as a safety measure. If you want to subtract lag you can
* directly manipulate the `lag` property.
* @param {number} amount milliseconds of lag
*/
addLag(amount) {
this.lag += Math.max(0, amount);
}

/**
* @param {CommandExecutable} executable Thing to run with an execute and a queue label
* @param {number} lag Amount of lag to apply to the queue after the command is run
*/
enqueue(executable, lag) {
Expand All @@ -28,7 +41,7 @@ class CommandQueue {
* @return {boolean} whether the command was executed
*/
execute() {
if (!this.commands.length || Date.now() - this.lastRun < this.lag) {
if (!this.commands.length || this.msTilNextRun > 0) {
return false;
}

Expand All @@ -48,40 +61,69 @@ class CommandQueue {
}

/**
* Flush all pending commands
* Flush all pending commands. Does _not_ reset lastRun/lag. Meaning that if
* the queue is flushed after a command was just run its lag will still have
* to expire before another command can be run. To fully reset the queue use
* the reset() method.
*/
flush() {
this.commands = [];
}

/**
* Completely reset the queue and any lag. This is fairly dangerous as if the
* player could reliably reset the queue they could negate any command lag. To
* clear commands without altering lag use flush()
*/
reset() {
this.flush();
this.lastRun = 0;
this.lag = 0;
// do not clear lastRun otherwise player's could exploit by immediately
// clearing after a command was executed
}

/**
* In seconds get how long until the next command will run, rounded to nearest tenth of a second
* Seconds until the next command can be executed
* @type {number}
*/
get lagRemaining() {
return this.commands.length ? this.getTimeTilRun(0) : 0;
return this.msTilNextRun / 1000;
}

/**
* Milliseconds til the next command can be executed
* @type {number}
*/
get msTilNextRun() {
return Math.max(0, (this.lastRun + this.lag) - Date.now());
}

/**
* For a given command index find how long until it will run
* For a given command index find how many seconds until it will run
* @param {number} commandIndex
* @param {boolean} milliseconds
* @return {number}
*/
getTimeTilRun(commandIndex) {
return this.getMsTilRun(commandIndex) / 1000;
}

/**
* Milliseconds until the command at the given index can be run
* @param {number} commandIndex
* @return {number}
*/
getMsTilRun(commandIndex) {
if (!this.commands[commandIndex]) {
throw new RangeError("Invalid command index");
}

let lagTotal = 0;
let lagTotal = this.msTilNextRun;
for (let i = 0; i < this.commands.length; i++) {
const command = this.commands[i];
lagTotal += command.lag;
if (i === commandIndex) {
return Math.max(0, this.lastRun + lagTotal - Date.now()) / 1000;
return lagTotal;
}

lagTotal += this.commands[i].lag;
}
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/EffectFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,19 @@ class EffectFactory {
/**
* @param {string} id
* @param {EffectConfig} config
* @param {GameState} state
*/
add(id, config) {
add(id, config, state) {
if (this.effects.has(id)) {
return;
}

let definition = Object.assign({}, config);
delete definition.listeners;
const listeners = config.listeners || {};
let listeners = config.listeners || {};
if (typeof listeners === 'function') {
listeners = listeners(state);
}

const eventManager = new EventManager();
for (const event in listeners) {
Expand Down
22 changes: 21 additions & 1 deletion src/HelpManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class HelpManager {
*/
find(search) {
const results = new Map();
for (const [ name, help ] of this.helps.entries()) {
for (const [name, help] of this.helps.entries()) {
if (name.indexOf(search) === 0) {
results.set(name, help);
continue;
Expand All @@ -39,6 +39,26 @@ class HelpManager {
}
return results;
}

/**
* Returns first help matching keywords
* @param {string} search
* @return {?string}
*/
getFirst(help) {
const results = this.find(help);

if (!results.size) {
/**
* No results found
*/
return null;
}

const [_, hfile] = [...results][0];

return hfile;
}
}

module.exports = HelpManager;
8 changes: 7 additions & 1 deletion src/Item.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,13 @@ class Item extends GameEntity {
this.room = item.room || null;
this.roomDesc = item.roomDesc || '';
this.script = item.script || null;
this.type = typeof item.type === 'string' ? ItemType[item.type] : (item.type || ItemType.OBJECT);

if (typeof item.type === 'string') {
this.type = ItemType[item.type] || item.type;
} else {
this.type = item.type || ItemType.OBJECT;
}

this.uuid = item.uuid || uuid();
this.closeable = item.closeable || item.closed || item.locked || false;
this.closed = item.closed || false;
Expand Down
14 changes: 7 additions & 7 deletions src/ItemType.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

/**
* @module ItemType
* @enum {Symbol}
* @enum {number}
*/
module.exports = {
ARMOR: Symbol("ARMOR"),
CONTAINER: Symbol("CONTAINER"),
OBJECT: Symbol("OBJECT"),
POTION: Symbol("POTION"),
WEAPON: Symbol("WEAPON"),
RESOURCE: Symbol("RESOURCE"),
OBJECT: 1,
CONTAINER: 2,
ARMOR: 3,
WEAPON: 4,
POTION: 5,
RESOURCE: 6,
};
10 changes: 10 additions & 0 deletions src/Metadatable.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class extends parentClass {
* @param {*} value Value must be JSON.stringify-able
* @throws Error
* @throws RangeError
* @fires Metadatable#metadataUpdate
*/
setMeta(key, value) {
if (!this.metadata) {
Expand All @@ -39,7 +40,16 @@ class extends parentClass {
base = base[part];
}

const oldValue = base[property];
base[property] = value;

/**
* @event Metadatable#metadataUpdate
* @param {string} key
* @param {*} newValue
* @param {*} oldValue
*/
this.emit('metadataUpdated', key, value, oldValue);
}

/**
Expand Down
4 changes: 3 additions & 1 deletion src/Npc.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class Npc extends Scriptable(Character) {
* @fires Npc#enterRoom
*/
moveTo(nextRoom, onMoved = _ => _) {
const prevRoom = this.room;
if (this.room) {
/**
* @event Room#npcLeave
Expand All @@ -66,8 +67,9 @@ class Npc extends Scriptable(Character) {
/**
* @event Room#npcEnter
* @param {Npc} npc
* @param {Room} prevRoom
*/
nextRoom.emit('npcEnter', this);
nextRoom.emit('npcEnter', this, prevRoom);
/**
* @event Npc#enterRoom
* @param {Room} room
Expand Down
4 changes: 3 additions & 1 deletion src/Player.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ class Player extends Character {
* @fires Player#enterRoom
*/
moveTo(nextRoom, onMoved = _ => _) {
const prevRoom = this.room;
if (this.room && this.room !== nextRoom) {
/**
* @event Room#playerLeave
Expand All @@ -151,8 +152,9 @@ class Player extends Character {
/**
* @event Room#playerEnter
* @param {Player} player
* @param {Room} prevRoom
*/
nextRoom.emit('playerEnter', this);
nextRoom.emit('playerEnter', this, prevRoom);
/**
* @event Player#enterRoom
* @param {Room} room
Expand Down
Loading

0 comments on commit d28f876

Please sign in to comment.