@@ -9,6 +9,7 @@ define([ | |||
'js/system/events', | |||
'js/resources', | |||
'js/sound/sound', | |||
'js/system/globals', | |||
'ui/templates/online/online', | |||
'ui/templates/tooltips/tooltips' | |||
], function ( | |||
@@ -21,7 +22,8 @@ define([ | |||
input, | |||
events, | |||
resources, | |||
sound | |||
sound, | |||
globals | |||
) { | |||
return { | |||
hasFocus: true, | |||
@@ -36,13 +38,14 @@ define([ | |||
onClientReady: function () { | |||
client.request({ | |||
module: 'clientConfig', | |||
method: 'getResourcesList', | |||
callback: this.onGetResourceList.bind(this) | |||
method: 'getClientConfig', | |||
callback: this.onGetClientConfig.bind(this) | |||
}); | |||
}, | |||
onGetResourceList: function (list) { | |||
resources.init(list); | |||
onGetClientConfig: function (config) { | |||
globals.clientConfig = config; | |||
resources.init(config.resourceList); | |||
events.on('onResourcesLoaded', this.start.bind(this)); | |||
}, | |||
@@ -61,7 +64,7 @@ define([ | |||
numbers.init(); | |||
uiFactory.init(); | |||
uiFactory.init(null, globals.clientConfig.uiList); | |||
uiFactory.build('login', 'body'); | |||
this.update(); | |||
@@ -5,14 +5,54 @@ define([ | |||
uiBase, | |||
events | |||
) { | |||
const startupUis = [ | |||
'inventory', | |||
'equipment', | |||
'hud', | |||
'target', | |||
'menu', | |||
'spells', | |||
'messages', | |||
'online', | |||
'mainMenu', | |||
'context', | |||
'party', | |||
'help', | |||
'dialogue', | |||
'buffs', | |||
'tooltips', | |||
'tooltipInfo', | |||
'tooltipItem', | |||
'announcements', | |||
'quests', | |||
'events', | |||
'progressBar', | |||
'stash', | |||
'smithing', | |||
'talk', | |||
'trade', | |||
'overlay', | |||
'death', | |||
'leaderboard', | |||
'reputation', | |||
'mail', | |||
'wardrobe', | |||
'passives', | |||
'workbench', | |||
'middleHud', | |||
'options' | |||
]; | |||
return { | |||
uis: [], | |||
root: '', | |||
init: function (root) { | |||
init: function (root, uiList = []) { | |||
if (root) | |||
this.root = root + '/'; | |||
startupUis.push(...uiList); | |||
events.on('onEnterGame', this.onEnterGame.bind(this)); | |||
events.on('onUiKeyDown', this.onUiKeyDown.bind(this)); | |||
events.on('onResize', this.onResize.bind(this)); | |||
@@ -21,49 +61,23 @@ define([ | |||
onEnterGame: function () { | |||
events.clearQueue(); | |||
[ | |||
'inventory', | |||
'equipment', | |||
'hud', | |||
'target', | |||
'menu', | |||
'spells', | |||
'messages', | |||
'online', | |||
'mainMenu', | |||
'context', | |||
'party', | |||
'help', | |||
'dialogue', | |||
'buffs', | |||
'tooltips', | |||
'tooltipInfo', | |||
'tooltipItem', | |||
'announcements', | |||
'quests', | |||
'events', | |||
'progressBar', | |||
'stash', | |||
'smithing', | |||
'talk', | |||
'trade', | |||
'overlay', | |||
'death', | |||
'leaderboard', | |||
'reputation', | |||
'mail', | |||
'wardrobe', | |||
'passives', | |||
'workbench', | |||
'middleHud', | |||
'options' | |||
].forEach(function (u) { | |||
this.build(u); | |||
startupUis.forEach(function (u) { | |||
if (u.path) | |||
this.buildModUi(u); | |||
else | |||
this.build(u); | |||
}, this); | |||
}, | |||
buildModUi: function (config) { | |||
const type = config.path.split('/').pop(); | |||
this.build(type, { | |||
path: config.path | |||
}); | |||
}, | |||
build: function (type, options) { | |||
//Don't make doubles? | |||
let className = 'ui' + type[0].toUpperCase() + type.substr(1); | |||
let el = $('.' + className); | |||
if (el.length > 0) | |||
@@ -73,7 +87,13 @@ define([ | |||
}, | |||
getTemplate: function (type, options) { | |||
require([this.root + 'ui/templates/' + type + '/' + type], this.onGetTemplate.bind(this, options)); | |||
let path = null; | |||
if (options && options.path) | |||
path = options.path + `\\${type}.js`; | |||
else | |||
path = this.root + 'ui/templates/' + type + '/' + type; | |||
require([path], this.onGetTemplate.bind(this, options)); | |||
}, | |||
onGetTemplate: function (options, template) { | |||
@@ -1,11 +1,13 @@ | |||
define([ | |||
'js/system/client', | |||
'js/system/events', | |||
'js/system/globals', | |||
'html!ui/templates/target/template', | |||
'css!ui/templates/target/styles' | |||
], function ( | |||
client, | |||
events, | |||
globals, | |||
template, | |||
styles | |||
) { | |||
@@ -47,7 +49,7 @@ define([ | |||
// target.player (only the logged-in player has a player component) | |||
if ((e.button !== 2) || (!target) || (!target.dialogue) || (target === window.player) || (target.prophecies)) { | |||
if (target.prophecies) { | |||
let inspectContext = [ | |||
const inspectContext = [ | |||
target.name, | |||
'----------', { | |||
text: 'inspect', | |||
@@ -55,13 +57,20 @@ define([ | |||
} | |||
]; | |||
globals.clientConfig.contextMenuActions.player.forEach(action => { | |||
inspectContext.push({ | |||
text: action.text, | |||
callback: this.onAction.bind(this, action, true) | |||
}); | |||
}); | |||
events.emit('onContextMenu', inspectContext, e.event); | |||
} | |||
return; | |||
} | |||
let talkContext = [ | |||
const talkContext = [ | |||
target.name, | |||
'----------', { | |||
text: 'talk', | |||
@@ -69,6 +78,13 @@ define([ | |||
} | |||
]; | |||
globals.clientConfig.contextMenuActions.npc.forEach(action => { | |||
talkContext.push({ | |||
text: action.text, | |||
callback: this.onAction.bind(this, action, false) | |||
}); | |||
}); | |||
events.emit('onContextMenu', talkContext, e.event); | |||
e.event.preventDefault(); | |||
@@ -79,6 +95,21 @@ define([ | |||
window.player.dialogue.talk(this.target); | |||
}, | |||
onAction: function (action, sendTargetServerId) { | |||
const { threadModule, cpn, method, data = {} } = action; | |||
if (method === 'performAction') | |||
data.data.playerId = this.target.id; | |||
else if (threadModule) | |||
data.targetId = sendTargetServerId ? this.target.serverId : this.target.id; | |||
client.request({ | |||
threadModule, | |||
cpn, | |||
method, | |||
data | |||
}); | |||
}, | |||
onInspect: function () { | |||
client.request({ | |||
cpn: 'player', | |||
@@ -100,7 +100,10 @@ define([ | |||
$('.modal').hide(); | |||
this.shown = true; | |||
this.el.show(); | |||
if (this.isFlex) | |||
this.el.css('display', 'flex'); | |||
else | |||
this.el.show(); | |||
if (this.onAfterShow) | |||
this.onAfterShow(); | |||
@@ -1,13 +1,22 @@ | |||
let events = require('../misc/events'); | |||
module.exports = { | |||
const config = { | |||
resourceList: [], | |||
uiList: [], | |||
contextMenuActions: { | |||
player: [], | |||
npc: [] | |||
} | |||
}; | |||
module.exports = { | |||
init: function () { | |||
events.emit('onBeforeGetResourceList', this.resourceList); | |||
events.emit('onBeforeGetResourceList', config.resourceList); | |||
events.emit('onBeforeGetUiList', config.uiList); | |||
events.emit('onBeforeGetContextMenuActions', config.contextMenuActions); | |||
}, | |||
getResourcesList: function (msg) { | |||
msg.callback(this.resourceList); | |||
getClientConfig: function (msg) { | |||
msg.callback(config); | |||
} | |||
}; |
@@ -8,7 +8,7 @@ module.exports = { | |||
// sqlite | |||
// rethink | |||
//eslint-disable-next-line no-process-env | |||
db: process.env.IWD_DB || 'sqlite', | |||
db: process.env.IWD_DB || 'rethink', | |||
//eslint-disable-next-line no-process-env | |||
dbHost: process.env.IWD_DB_HOST || 'localhost', | |||
//eslint-disable-next-line no-process-env | |||
@@ -15,6 +15,7 @@ let mapList = require('./config/maps/mapList'); | |||
let sheets = require('./security/sheets'); | |||
let fixes = require('./fixes/fixes'); | |||
let profanities = require('./misc/profanities'); | |||
const routerConfig = require('./security/routerConfig'); | |||
let startup = { | |||
init: function () { | |||
@@ -32,6 +33,7 @@ let startup = { | |||
}, | |||
onModsLoaded: function () { | |||
routerConfig.init(); | |||
classes.init(); | |||
spellsConfig.init(); | |||
spells.init(); | |||
@@ -5,6 +5,8 @@ module.exports = { | |||
actionQueue: [], | |||
eventListeners: [], | |||
addComponent: function (type, blueprint, isTransfer) { | |||
let cpn = this[type]; | |||
if (!cpn) { | |||
@@ -355,6 +357,21 @@ module.exports = { | |||
} | |||
}, | |||
onEvent: function (eventName, callback) { | |||
const entry = { | |||
eventName, | |||
callback | |||
}; | |||
this.eventListeners.push(entry); | |||
return this.offEvent.bind(this, entry); | |||
}, | |||
offEvent: function (entry) { | |||
this.eventListeners.spliceWhere(e => e === entry); | |||
}, | |||
fireEvent: function (event) { | |||
let args = [].slice.call(arguments, 1); | |||
@@ -373,6 +390,14 @@ module.exports = { | |||
callback.apply(cpn, args); | |||
} | |||
this.eventListeners.forEach(l => { | |||
const { eventName, callback } = l; | |||
if (eventName !== event) | |||
return; | |||
callback.apply(null, args); | |||
}); | |||
if (this.effects) | |||
this.effects.fireEvent(event, args); | |||
if (this.quests) | |||
@@ -14,6 +14,7 @@ module.exports = { | |||
this.players.push(p); | |||
}, | |||
onDisconnect: function (socket) { | |||
let player = this.players.find(p => p.socket.id === socket.id); | |||
@@ -52,6 +53,7 @@ module.exports = { | |||
this.players.spliceWhere(p => p.socket.id === socket.id); | |||
}, | |||
route: function (socket, msg) { | |||
let player = null; | |||
@@ -79,6 +81,17 @@ module.exports = { | |||
) | |||
return; | |||
if (msg.threadModule) { | |||
const source = this.players.find(p => p.socket.id === socket.id); | |||
if (!source) | |||
return; | |||
msg.data.sourceId = source.id; | |||
atlas.send(player.zone, msg); | |||
return; | |||
} | |||
let cpn = player[msg.cpn]; | |||
if (!cpn) | |||
return; | |||
@@ -87,6 +100,7 @@ module.exports = { | |||
if (cpn[method]) | |||
cpn[method](msg); | |||
}, | |||
unzone: function (msg) { | |||
let socket = msg.socket; | |||
let player = this.players.find(p => p.socket.id === socket.id); | |||
@@ -1,43 +1,28 @@ | |||
const { routerConfig: { allowed, secondaryAllowed, globalAllowed } } = require('./routerConfig'); | |||
module.exports = { | |||
allowedCpn: function (msg) { | |||
let allowed = { | |||
player: ['performAction', 'queueAction', 'move'], | |||
auth: ['login', 'register', 'play', 'getCharacterList', 'getCharacter', 'deleteCharacter', 'getSkinList', 'createCharacter', 'getCustomChannels'], | |||
social: ['chat', 'getInvite', 'acceptInvite', 'declineInvite', 'removeFromParty', 'leaveParty'] | |||
}; | |||
let valid = ((allowed[msg.cpn]) && (allowed[msg.cpn].indexOf(msg.method) > -1)); | |||
let valid = allowed[msg.cpn] && allowed[msg.cpn].includes(msg.method); | |||
if (!valid) | |||
return false; | |||
if (!msg.data.cpn) | |||
return true; | |||
let secondaryAllowed = { | |||
dialogue: ['talk'], | |||
gatherer: ['gather'], | |||
quests: ['complete'], | |||
inventory: ['combineStacks', 'splitStack', 'activateMtx', 'useItem', 'moveItem', 'enchantItem', 'getEnchantMaterials', 'learnAbility', 'unlearnAbility', 'dropItem', 'destroyItem', 'salvageItem', 'stashItem', 'mailItem', 'sortInventory'], | |||
equipment: ['equip', 'unequip', 'setQuickSlot', 'useQuickSlot', 'inspect'], | |||
stash: ['withdraw', 'open'], | |||
trade: ['buySell'], | |||
door: ['lock', 'unlock'], | |||
wardrobe: ['open', 'apply'], | |||
stats: ['respawn'], | |||
passives: ['tickNode', 'untickNode'], | |||
workbench: ['open', 'craft', 'getRecipe'] | |||
}; | |||
return ((secondaryAllowed[msg.data.cpn]) && (secondaryAllowed[msg.data.cpn].indexOf(msg.data.method) > -1)); | |||
const result = secondaryAllowed[msg.data.cpn] && secondaryAllowed[msg.data.cpn].includes(msg.data.method); | |||
return result; | |||
}, | |||
allowedGlobal: function (msg) { | |||
let allowed = { | |||
clientConfig: ['getResourcesList'], | |||
leaderboard: ['requestList'], | |||
cons: ['unzone'] | |||
}; | |||
const result = globalAllowed[msg.module] && globalAllowed[msg.module].includes(msg.method); | |||
return result; | |||
}, | |||
allowedGlobalCall: function (threadModule, method) { | |||
const result = globalAllowed[threadModule] && globalAllowed[threadModule].includes(method); | |||
return ((allowed[msg.module]) && (allowed[msg.module].indexOf(msg.method) > -1)); | |||
return result; | |||
} | |||
}; |
@@ -0,0 +1,36 @@ | |||
let events = require('../misc/events'); | |||
const routerConfig = { | |||
allowed: { | |||
player: ['performAction', 'queueAction', 'move'], | |||
auth: ['login', 'register', 'play', 'getCharacterList', 'getCharacter', 'deleteCharacter', 'getSkinList', 'createCharacter', 'getCustomChannels'], | |||
social: ['chat', 'getInvite', 'acceptInvite', 'declineInvite', 'removeFromParty', 'leaveParty'] | |||
}, | |||
secondaryAllowed: { | |||
dialogue: ['talk'], | |||
gatherer: ['gather'], | |||
quests: ['complete'], | |||
inventory: ['combineStacks', 'splitStack', 'activateMtx', 'useItem', 'moveItem', 'enchantItem', 'getEnchantMaterials', 'learnAbility', 'unlearnAbility', 'dropItem', 'destroyItem', 'salvageItem', 'stashItem', 'mailItem', 'sortInventory'], | |||
equipment: ['equip', 'unequip', 'setQuickSlot', 'useQuickSlot', 'inspect'], | |||
stash: ['withdraw', 'open'], | |||
trade: ['buySell'], | |||
door: ['lock', 'unlock'], | |||
wardrobe: ['open', 'apply'], | |||
stats: ['respawn'], | |||
passives: ['tickNode', 'untickNode'], | |||
workbench: ['open', 'craft', 'getRecipe'] | |||
}, | |||
globalAllowed: { | |||
clientConfig: ['getClientConfig'], | |||
leaderboard: ['requestList'], | |||
cons: ['unzone'] | |||
} | |||
}; | |||
module.exports = { | |||
routerConfig, | |||
init: function () { | |||
events.emit('onBeforeGetRouterConfig', routerConfig); | |||
} | |||
}; |
@@ -72,6 +72,11 @@ module.exports = { | |||
if (!router.allowedCpn(msg)) | |||
return; | |||
cons.route(socket, msg); | |||
} else if (msg.threadModule) { | |||
if (!router.allowedGlobalCall(msg.threadModule, msg.method)) | |||
return; | |||
cons.route(socket, msg); | |||
} else { | |||
if (!router.allowedGlobal(msg)) | |||
@@ -92,7 +97,18 @@ module.exports = { | |||
file = file.replace('/' + root + '/', ''); | |||
if (root === 'server' && (file.indexOf('mods') === -1 || file.indexOf('png') === -1)) | |||
const validRequest = ( | |||
root !== 'server' || | |||
( | |||
file.includes('mods/') && | |||
( | |||
file.includes('.png') || | |||
file.includes('/ui/') | |||
) | |||
) | |||
); | |||
if (!validRequest) | |||
return null; | |||
res.sendFile(file, { | |||
@@ -28,7 +28,7 @@ module.exports = { | |||
herbs.init(); | |||
map.init(args); | |||
let fakeInstance = { | |||
const fakeInstance = { | |||
objects: objects, | |||
syncer: syncer, | |||
physics: physics, | |||
@@ -91,6 +91,8 @@ process.on('message', m => { | |||
if (found) | |||
break; | |||
} | |||
} else if (m.method) | |||
} else if (m.threadModule) | |||
global[m.threadModule][m.method](m.data); | |||
else if (m.method) | |||
instancer[m.method](m.args); | |||
}); |