diff --git a/.gitignore b/.gitignore index dd41ccd3..3f7ed0db 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ node_modules -storage.db \ No newline at end of file +storage.db +*.sublime-project +*.sublime-workspace \ No newline at end of file diff --git a/src/client/images/characters.png b/src/client/images/characters.png index 33524599..a099f0be 100644 Binary files a/src/client/images/characters.png and b/src/client/images/characters.png differ diff --git a/src/client/images/items.pyxel b/src/client/images/items.pyxel index 1f478522..3ddfb66f 100644 Binary files a/src/client/images/items.pyxel and b/src/client/images/items.pyxel differ diff --git a/src/client/js/main.js b/src/client/js/main.js index 54091360..f2aa49b1 100644 --- a/src/client/js/main.js +++ b/src/client/js/main.js @@ -35,8 +35,23 @@ define([ hasFocus: true, init: function() { + client.init(this.onClientReady.bind(this)); + }, + + onClientReady: function() { + client.request({ + module: 'clientConfig', + method: 'getResourcesList', + callback: this.onGetResourceList.bind(this) + }); + }, + + onGetResourceList: function(list) { + resources.init(list); + events.on('onResourcesLoaded', this.start.bind(this)); }, + start: function() { window.onfocus = this.onFocus.bind(this, true); window.onblur = this.onFocus.bind(this, false); @@ -46,7 +61,6 @@ define([ }); objects.init(); - client.init(); renderer.init(); input.init(); diff --git a/src/client/js/renderer.js b/src/client/js/renderer.js index 025e3f0b..198b7ac3 100644 --- a/src/client/js/renderer.js +++ b/src/client/js/renderer.js @@ -97,7 +97,13 @@ define([ this.stage.addChild(layers[l]) }, this); - ['sprites', 'tiles', 'mobs', 'bosses', 'bigObjects', 'objects', 'characters', 'attacks', 'auras', 'walls', 'ui', 'animChar', 'animMob', 'animBoss'].forEach(function(t) { + var spriteNames = ['sprites', 'tiles', 'mobs', 'bosses', 'bigObjects', 'objects', 'characters', 'attacks', 'auras', 'walls', 'ui', 'animChar', 'animMob', 'animBoss']; + resources.spriteNames.forEach(function(s) { + if (s.indexOf('.png') > -1) + spriteNames.push(s); + }); + + spriteNames.forEach(function(t) { this.textures[t] = new pixi.BaseTexture(resources.sprites[t].image); this.textures[t].scaleMode = pixi.SCALE_MODES.NEAREST; }, this); diff --git a/src/client/js/resources.js b/src/client/js/resources.js index 168a310c..405c2c6f 100644 --- a/src/client/js/resources.js +++ b/src/client/js/resources.js @@ -28,13 +28,17 @@ define([ ], sprites: {}, ready: false, - init: function() { + init: function(list) { + list.forEach(function(l) { + this.spriteNames.push(l); + }, this); + this.spriteNames.forEach(function(s) { var sprite = { image: (new Image()), ready: false }; - sprite.image.src = 'images/' + s + '.png'; + sprite.image.src = s.indexOf('png') > -1 ? s : 'images/' + s + '.png'; sprite.image.onload = this.onSprite.bind(this, sprite); this.sprites[s] = sprite; @@ -59,7 +63,5 @@ define([ } }; - resources.init(); - return resources; }); \ No newline at end of file diff --git a/src/client/js/system/client.js b/src/client/js/system/client.js index 72df6ff6..bc08fc1f 100644 --- a/src/client/js/system/client.js +++ b/src/client/js/system/client.js @@ -8,7 +8,7 @@ define([ var client = { doneConnect: false, - init: function() { + init: function(onReady) { var tType = 'websocket'; if (window.location.href.indexOf('polling') > -1) tType = 'polling'; @@ -17,17 +17,20 @@ define([ transports: [ tType ] }); - this.socket.on('connect', this.onConnected.bind(this)); + this.socket.on('connect', this.onConnected.bind(this, onReady)); this.socket.on('handshake', this.onHandshake.bind(this)); this.socket.on('event', this.onEvent.bind(this)); this.socket.on('events', this.onEvents.bind(this)); this.socket.on('dc', this.onDisconnect.bind(this)); }, - onConnected: function() { + onConnected: function(onReady) { if (this.doneConnect) this.onDisconnect(); else this.doneConnect = true; + + if (onReady) + onReady(); }, onDisconnect: function() { window.location = window.location; diff --git a/src/client/ui/templates/characters/characters.js b/src/client/ui/templates/characters/characters.js index 99fa970b..28ddeae3 100644 --- a/src/client/ui/templates/characters/characters.js +++ b/src/client/ui/templates/characters/characters.js @@ -135,8 +135,10 @@ define([ spirteX = -(spirteX * 32); spriteY = -(spriteY * 32); + var spritesheet = result.previewSpritesheet || '../../../images/charas.png'; + this.find('.sprite') - .css('background', 'url("../../../images/charas.png") ' + spirteX + 'px ' + spriteY + 'px') + .css('background', 'url("' + spritesheet + '") ' + spirteX + 'px ' + spriteY + 'px') .show(); this.find('.name').html(name); diff --git a/src/client/ui/templates/createCharacter/createCharacter.js b/src/client/ui/templates/createCharacter/createCharacter.js index 3328bf69..556d9714 100644 --- a/src/client/ui/templates/createCharacter/createCharacter.js +++ b/src/client/ui/templates/createCharacter/createCharacter.js @@ -15,12 +15,7 @@ define([ tpl: template, centered: true, - classSprites: { - warrior: [1, 1], - wizard: [2, 0], - thief: [6, 0], - cleric: [4, 0] - }, + classSprites: null, class: 'wizard', costume: 0, @@ -172,13 +167,15 @@ define([ }, setSprite: function() { - var classSprite = this.classSprites[this.class]; - var costume = classSprite[this.costume].split(','); + var classSprite = this.classSprites[this.class][this.costume]; + var costume = classSprite.sprite.split(','); var spirteX = -costume[0] * 32; var spriteY = -costume[1] * 32; + var spritesheet = classSprite.spritesheet || '../../../images/charas.png'; + this.find('.sprite') - .css('background', 'url("../../../images/charas.png") ' + spirteX + 'px ' + spriteY + 'px'); + .css('background', 'url("' + spritesheet + '") ' + spirteX + 'px ' + spriteY + 'px'); } }; }); \ No newline at end of file diff --git a/src/client/ui/templates/equipment/equipment.js b/src/client/ui/templates/equipment/equipment.js index 40b38322..2cb18346 100644 --- a/src/client/ui/templates/equipment/equipment.js +++ b/src/client/ui/templates/equipment/equipment.js @@ -113,12 +113,14 @@ define([ slot = 'rune-' + spellId; } + var spritesheet = item.spritesheet || '../../../images/items.png'; + var elSlot = this.find('[slot="' + slot + '"]'); elSlot .data('item', item) .removeClass('empty') .find('.icon') - .css('background', 'url(../../../images/items.png) ' + imgX + 'px ' + imgY + 'px') + .css('background', 'url("' + spritesheet + '") ' + imgX + 'px ' + imgY + 'px') .off() .on('mousemove', this.onHoverItem.bind(this, elSlot, item, null)) .on('mouseleave', this.onHoverItem.bind(this, null, null)) @@ -159,7 +161,7 @@ define([ .forEach(function(item) { var sprite = item.sprite || [7, 0]; - var spriteSheet = item.empty ? 'uiIcons' : 'items'; + var spriteSheet = item.empty ? '../../../images/uiIcons.png' : item.spritesheet || '../../../images/items.png'; var imgX = -sprite[0] * 64; var imgY = -sprite[1] * 64; @@ -168,7 +170,7 @@ define([ el .find('.icon') - .css('background', 'url(../../../images/' + spriteSheet + '.png) ' + imgX + 'px ' + imgY + 'px') + .css('background', 'url("' + spriteSheet + '") ' + imgX + 'px ' + imgY + 'px') .on('mousemove', this.onHoverItem.bind(this, el, item, null)) .on('mouseleave', this.onHoverItem.bind(this, null, null)) .on('click', this.equipItem.bind(this, item)); diff --git a/src/client/ui/templates/inventory/inventory.js b/src/client/ui/templates/inventory/inventory.js index b16cc343..66ed9e8a 100644 --- a/src/client/ui/templates/inventory/inventory.js +++ b/src/client/ui/templates/inventory/inventory.js @@ -119,7 +119,7 @@ define([ var itemEl = $(tplItem) .appendTo(container); - var spritesheet = 'items'; + var spritesheet = item.spritesheet || 'items'; if (item.material) spritesheet = 'materials'; else if (item.quest) diff --git a/src/client/ui/templates/smithing/smithing.js b/src/client/ui/templates/smithing/smithing.js index 1b135b36..e2994310 100644 --- a/src/client/ui/templates/smithing/smithing.js +++ b/src/client/ui/templates/smithing/smithing.js @@ -220,7 +220,7 @@ define([ var imgX = -item.sprite[0] * 64; var imgY = -item.sprite[1] * 64; - var spritesheet = 'items'; + var spritesheet = item.spritesheet || 'items'; if (item.material) spritesheet = 'materials'; else if (item.quest) diff --git a/src/client/ui/templates/spells/spells.js b/src/client/ui/templates/spells/spells.js index 5abd6fb7..5bff7b83 100644 --- a/src/client/ui/templates/spells/spells.js +++ b/src/client/ui/templates/spells/spells.js @@ -43,9 +43,10 @@ define([ .on('mouseover', this.onShowTooltip.bind(this, el, spells[i])) .on('mouseleave', this.onHideTooltip.bind(this, el)); + var spritesheet = spells[i].spritesheet || '../../../images/abilityIcons.png'; el .find('.icon').css({ - 'background': 'url("../../../images/abilityIcons.png") ' + x + 'px ' + y + 'px' + 'background': 'url("' + spritesheet + '") ' + x + 'px ' + y + 'px' }) .next().html(i + 1); diff --git a/src/client/ui/templates/trade/trade.js b/src/client/ui/templates/trade/trade.js index cb786760..3aebcea8 100644 --- a/src/client/ui/templates/trade/trade.js +++ b/src/client/ui/templates/trade/trade.js @@ -62,7 +62,7 @@ define([ var size = 64; var offset = 0; - var spritesheet = 'items'; + var spritesheet = item.spritesheet || 'items'; if (item.material) spritesheet = 'materials'; else if (item.quest) diff --git a/src/server/components/auth.js b/src/server/components/auth.js index 7df5c54e..83a20e90 100644 --- a/src/server/components/auth.js +++ b/src/server/components/auth.js @@ -115,8 +115,8 @@ define([ var result = characters .map(c => ({ - name: c, - level: leaderboard.getLevel(c) + name: c.name ? c.name : c, + level: leaderboard.getLevel(c.name ? c.name : c) })); data.callback(result); @@ -300,14 +300,8 @@ define([ this.obj.class = data.class; this.obj.costume = data.costume; - var tiles = { - wizard: [2, 3], - cleric: [4, 5], - thief: [6, 7], - warrior: [9, 10] - }; - - this.obj.cell = tiles[data.class][data.costume]; + this.obj.cell = skins.getCell(this.obj.class, this.obj.costume); + this.obj.previewSpritesheet = skins.getSpritesheet(this.obj.class); var simple = this.obj.getSimple(true); simple.components.push({ @@ -360,10 +354,16 @@ define([ }, onDeleteCharacter: function(msg, result) { this.characterList.spliceWhere(c => c == msg.data.name); + var characterList = this.characterList + .map(c => ({ + name: c.name ? c.name : c, + level: leaderboard.getLevel(c.name ? c.name : c) + })); + io.set({ ent: this.username, field: 'characterList', - value: JSON.stringify(this.characterList), + value: JSON.stringify(characterList), callback: this.onRemoveFromList.bind(this, msg) }); diff --git a/src/server/components/inventory.js b/src/server/components/inventory.js index 02217d1e..418c7794 100644 --- a/src/server/components/inventory.js +++ b/src/server/components/inventory.js @@ -11,7 +11,6 @@ define([ objects, classes ) { - return { type: 'inventory', diff --git a/src/server/components/player.js b/src/server/components/player.js index efe75a97..490265c2 100644 --- a/src/server/components/player.js +++ b/src/server/components/player.js @@ -26,9 +26,10 @@ define([ spawn: function(character) { var obj = this.obj; extend(true, obj, { - sheetName: 'characters', + sheetName: classes.getSpritesheet(character.class), layerName: 'mobs', cell: character.cell, + previewSpritesheet: character.previewSpritesheet, name: character.name, class: character.class, zoneName: character.zoneName || 'tutorial-cove', diff --git a/src/server/components/spellbook.js b/src/server/components/spellbook.js index 73095a31..e7e45892 100644 --- a/src/server/components/spellbook.js +++ b/src/server/components/spellbook.js @@ -2,12 +2,14 @@ define([ './../config/spells/spellTemplate', './../config/animations', './../config/spells', - './../config/spellsConfig' + './../config/spellsConfig', + 'misc/events' ], function( spellTemplate, animations, playerSpells, - playerSpellsConfig + playerSpellsConfig, + events ) { return { type: 'spellbook', @@ -82,9 +84,15 @@ define([ var type = options.type[0].toUpperCase() + options.type.substr(1); - var typeTemplate = require('./config/spells/spell' + type); + var typeTemplate = { + type: type, + template: null + }; + events.emit('onBeforeGetSpellTemplate', typeTemplate); + if (!typeTemplate.template) + typeTemplate.template = require('./config/spells/spell' + type); - var builtSpell = extend(true, {}, spellTemplate, typeTemplate, options); + var builtSpell = extend(true, {}, spellTemplate, typeTemplate.template, options); builtSpell.obj = this.obj; builtSpell.baseDamage = builtSpell.damage; builtSpell.damage += (options.damageAdd || 0); diff --git a/src/server/config/classes.js b/src/server/config/classes.js index ac68917b..c46080aa 100644 --- a/src/server/config/classes.js +++ b/src/server/config/classes.js @@ -1,9 +1,9 @@ define([ - + 'misc/events' ], function( - + events ) { - return { + var classes = { spells: { wizard: ['ice spear'], cleric: ['healing circle'], @@ -41,6 +41,13 @@ define([ cleric: 'Mace', thief: 'Dagger', warrior: 'Axe' + }, + + getSpritesheet: function(className) { + return this.stats[className].spritesheet || 'characters'; } }; + + events.emit('onBeforeGetClasses', classes); + return classes; }); \ No newline at end of file diff --git a/src/server/config/clientConfig.js b/src/server/config/clientConfig.js new file mode 100644 index 00000000..5625e440 --- /dev/null +++ b/src/server/config/clientConfig.js @@ -0,0 +1,17 @@ +define([ + 'misc/events' +], function( + events +) { + return { + resourceList: [], + + init: function() { + events.emit('onBeforeGetResourceList', this.resourceList); + }, + + getResourcesList: function(msg) { + msg.callback(this.resourceList); + } + }; +}); \ No newline at end of file diff --git a/src/server/config/skins.js b/src/server/config/skins.js index 888f6a16..9b218218 100644 --- a/src/server/config/skins.js +++ b/src/server/config/skins.js @@ -1,7 +1,7 @@ define([ - + 'misc/events' ], function( - + events ) { var config = { 'wizard 1': { @@ -60,6 +60,8 @@ define([ } }; + events.emit('onBeforeGetSkins', config); + return { getBlueprint: function(skinId) { return config[skinId]; @@ -79,10 +81,35 @@ define([ if (!result[l.class]) result[l.class] = []; - result[l.class].push(l.sprite[0] + ',' + l.sprite[1]); + result[l.class].push({ + sprite: l.sprite[0] + ',' + l.sprite[1], + spritesheet: l.spritesheet + }); }); return result; + }, + + getCell: function(className, costume) { + var res = Object.keys(config) + .filter(function(s) { + return (config[s].class == className); + }) + .map(function(s) { + return config[s]; + })[costume]; + + return (res.sprite[1] * 8) + res.sprite[0]; + }, + + getSpritesheet: function(className) { + return Object.keys(config) + .filter(function(s) { + return (config[s].class == className); + }) + .map(function(s) { + return config[s]; + })[0].spritesheet; } }; }); \ No newline at end of file diff --git a/src/server/config/spells.js b/src/server/config/spells.js index 762add35..01baa07c 100644 --- a/src/server/config/spells.js +++ b/src/server/config/spells.js @@ -1,9 +1,9 @@ define([ - + 'misc/events' ], function( - + events ) { - return [{ + var spells = [{ name: 'Magic Missile', description: 'Launches an orb of unfocussed energy at your target.', type: 'projectile', @@ -382,4 +382,7 @@ define([ chance: 0.02 } }]; + + events.emit('onBeforeGetSpellsInfo', spells); + return spells; }); \ No newline at end of file diff --git a/src/server/config/spellsConfig.js b/src/server/config/spellsConfig.js index cb09914f..69092cc5 100644 --- a/src/server/config/spellsConfig.js +++ b/src/server/config/spellsConfig.js @@ -1,9 +1,9 @@ define([ - + 'misc/events' ], function( - + events ) { - return { + var spells = { 'magic missile': { statType: 'int', statMult: 0.216, @@ -172,4 +172,7 @@ define([ } } }; + + events.emit('onBeforeGetSpellsConfig', spells); + return spells; }); \ No newline at end of file diff --git a/src/server/globals.js b/src/server/globals.js index 93ec4a85..3713eed8 100644 --- a/src/server/globals.js +++ b/src/server/globals.js @@ -4,14 +4,16 @@ define([ 'misc/helpers', 'items/lootRoller', 'world/atlas', - 'leaderboard/leaderboard' + 'leaderboard/leaderboard', + 'config/clientConfig' ], function( extend, cons, helpers, lootRoller, atlas, - leaderboard + leaderboard, + clientConfig ) { return { init: function() { @@ -21,6 +23,9 @@ define([ global.lootRoller = lootRoller; global.atlas = atlas; global.leaderboard = leaderboard; + global.clientConfig = clientConfig; + + clientConfig.init(); } }; }); \ No newline at end of file diff --git a/src/server/items/config/types.js b/src/server/items/config/types.js index 450fca0c..4b5715f6 100644 --- a/src/server/items/config/types.js +++ b/src/server/items/config/types.js @@ -1,9 +1,9 @@ define([ - + 'misc/events' ], function( - + events ) { - return { + var types = { head: { 'Helmet': { sprite: [0, 0], @@ -191,4 +191,7 @@ define([ } } } + + events.emit('onBeforeGetItemTypes', types); + return types; }); \ No newline at end of file diff --git a/src/server/items/generators/types.js b/src/server/items/generators/types.js index ba49e4c5..b251c4a8 100644 --- a/src/server/items/generators/types.js +++ b/src/server/items/generators/types.js @@ -15,6 +15,8 @@ define([ item.type = type; item.sprite = typeBlueprint.sprite; + if (typeBlueprint.spritesheet) + item.spritesheet = typeBlueprint.spritesheet; if (typeBlueprint.spellName) blueprint.spellName = typeBlueprint.spellName; diff --git a/src/server/misc/events.js b/src/server/misc/events.js new file mode 100644 index 00000000..edda6923 --- /dev/null +++ b/src/server/misc/events.js @@ -0,0 +1,62 @@ +define([ + +], function( + +) { + return { + events: {}, + queue: [], + on: function(event, callback) { + var list = this.events[event] || (this.events[event] = []); + list.push(callback); + + for (var i = 0; i < this.queue.length; i++) { + var q = this.queue[i]; + if (q.event != event) + continue; + + this.queue.splice(i, 1); + i--; + + q.args.splice(0, 0, event); + + this.emit.apply(this, q.args); + } + + return callback; + }, + off: function(event, callback) { + var list = this.events[event] || []; + var lLen = list.length; + for (var i = 0; i < lLen; i++) { + if (list[i] == callback) { + list.splice(i, 1); + i--; + lLen--; + } + } + + if (lLen == 0) + delete this.events[event]; + }, + emit: function(event) { + var args = [].slice.call(arguments, 1); + + var list = this.events[event]; + if (!list) { + this.queue.push({ + event: event, + args: args + }); + + return; + } + + var len = list.length + for (var i = 0; i < len; i++) { + var l = list[i]; + l.apply(null, args); + } + } + }; +}); \ No newline at end of file diff --git a/src/server/misc/mods.js b/src/server/misc/mods.js new file mode 100644 index 00000000..7ca54fbb --- /dev/null +++ b/src/server/misc/mods.js @@ -0,0 +1,14 @@ +define([ + 'mods/modList' +], function( + modList +) { + return { + init: function() { + modList.forEach(function(m) { + var mod = require('mods/' + m + '/index'); + mod.init(); + }, this); + } + }; +}); \ No newline at end of file diff --git a/src/server/mods/modList.js b/src/server/mods/modList.js new file mode 100644 index 00000000..47cce6b9 --- /dev/null +++ b/src/server/mods/modList.js @@ -0,0 +1,9 @@ +define([ + +], function( + +) { + return [ + + ]; +}); \ No newline at end of file diff --git a/src/server/server.js b/src/server/server.js index ed2f7037..12b0e561 100644 --- a/src/server/server.js +++ b/src/server/server.js @@ -10,7 +10,10 @@ define([ global.io = require('socket.io')(server); app.use(function(req, res, next) { - req.url = '/client/' + req.url; + if (req.url.indexOf('/server') != 0) + req.url = '/client/' + req.url; + else + req.url.substr(7); next(); }); diff --git a/src/server/startup.js b/src/server/startup.js index 0f937ee0..35308852 100644 --- a/src/server/startup.js +++ b/src/server/startup.js @@ -4,14 +4,16 @@ define([ 'world/atlas', 'components/components', 'leaderboard/leaderboard', - 'security/io' + 'security/io', + 'misc/mods' ], function( globals, server, atlas, components, leaderboard, - io + io, + mods ) { return { init: function() { @@ -30,6 +32,7 @@ define([ server.init(this.onServerReady.bind(this)); }, onServerReady: function() { + mods.init(); atlas.init(); leaderboard.init(); } diff --git a/src/server/world/worker.js b/src/server/world/worker.js index 1616887e..acf56164 100644 --- a/src/server/world/worker.js +++ b/src/server/world/worker.js @@ -9,9 +9,9 @@ global.io = true; var instancer = null; requirejs([ - 'extend', 'misc/helpers', 'components/components', 'world/instancer', 'security/io' + 'extend', 'misc/helpers', 'components/components', 'world/instancer', 'security/io', 'misc/mods' ], function( - extend, helpers, components, _instancer, io + extend, helpers, components, _instancer, io, mods ) { var onDbReady = function() { global.extend = extend; @@ -26,6 +26,8 @@ requirejs([ }); }); + mods.init(); + setInterval(function() { global.gc(); }, 60000);