@@ -8,6 +8,7 @@ audit: | |||||
stage: test | stage: test | ||||
script: | script: | ||||
- cd src/server | - cd src/server | ||||
- npm install | |||||
- npm audit | - npm audit | ||||
allow_failure: true | allow_failure: true | ||||
only: | only: | ||||
@@ -17,9 +18,10 @@ audit: | |||||
lint-server: | lint-server: | ||||
stage: test | stage: test | ||||
script: | script: | ||||
- npm install eslint@7.32.0 eslint-plugin-prettier prettier babel-eslint eslint-plugin-requirejs | |||||
- cd src/server | |||||
- ../../node_modules/.bin/eslint . | |||||
- cd src | |||||
- npm install | |||||
- cd server | |||||
- ../node_modules/.bin/eslint . | |||||
only: | only: | ||||
- merge_requests | - merge_requests | ||||
- master | - master | ||||
@@ -27,9 +29,10 @@ lint-server: | |||||
lint-client: | lint-client: | ||||
stage: test | stage: test | ||||
script: | script: | ||||
- npm install eslint@7.32.0 eslint-plugin-prettier prettier babel-eslint eslint-plugin-requirejs | |||||
- cd src/client | |||||
- ../../node_modules/.bin/eslint . | |||||
- cd src | |||||
- npm install | |||||
- cd client | |||||
- ../node_modules/.bin/eslint . | |||||
only: | only: | ||||
- merge_requests | - merge_requests | ||||
- master | - master | ||||
@@ -1,3 +0,0 @@ | |||||
/client/plugins/* | |||||
node_modules/* | |||||
*.json |
@@ -220,7 +220,7 @@ | |||||
"no-throw-literal": 2, | "no-throw-literal": 2, | ||||
"no-undef": 1, | "no-undef": 1, | ||||
"no-undef-init": 2, | "no-undef-init": 2, | ||||
"no-underscore-dangle": 1, | |||||
"no-underscore-dangle": 0, | |||||
"no-unneeded-ternary": 2, | "no-unneeded-ternary": 2, | ||||
"no-unreachable": 1, | "no-unreachable": 1, | ||||
"no-unused-expressions": 2, | "no-unused-expressions": 2, | ||||
@@ -11,7 +11,6 @@ define([ | |||||
'js/sound/sound', | 'js/sound/sound', | ||||
'js/system/globals', | 'js/system/globals', | ||||
'js/components/components', | 'js/components/components', | ||||
'ui/templates/online/online', | |||||
'ui/templates/tooltips/tooltips' | 'ui/templates/tooltips/tooltips' | ||||
], function ( | ], function ( | ||||
client, | client, | ||||
@@ -26,10 +26,7 @@ define([ | |||||
return callback; | return callback; | ||||
}, | }, | ||||
clearQueue: function () { | clearQueue: function () { | ||||
//Hack to allow the player list to persist | |||||
this.queue.spliceWhere(function (q) { | |||||
return ((q.event !== 'onGetConnectedPlayer') && (q.event !== 'onGetDisconnectedPlayer')); | |||||
}); | |||||
this.queue.length = 0; | |||||
}, | }, | ||||
off: function (eventName, callback) { | off: function (eventName, callback) { | ||||
let list = this.events[eventName] || []; | let list = this.events[eventName] || []; | ||||
@@ -2,12 +2,7 @@ | |||||
"name": "isleward_client", | "name": "isleward_client", | ||||
"version": "0.12.0", | "version": "0.12.0", | ||||
"description": "isleward", | "description": "isleward", | ||||
"dependencies": { | |||||
}, | |||||
"devDependencies": { | "devDependencies": { | ||||
"eslint": "^7.32.0", | |||||
"babel-eslint": "^10.1.0", | |||||
"eslint-plugin-prettier": "^3.4.0", | |||||
"eslint-plugin-requirejs": "^4.0.1" | |||||
} | } | ||||
} | } |
@@ -97,7 +97,7 @@ define([ | |||||
else | else | ||||
path = this.root + 'ui/templates/' + type + '/' + type; | path = this.root + 'ui/templates/' + type + '/' + type; | ||||
} | } | ||||
require([path], this.onGetTemplate.bind(this, options, type)); | require([path], this.onGetTemplate.bind(this, options, type)); | ||||
}, | }, | ||||
@@ -1,177 +0,0 @@ | |||||
define([ | |||||
'js/system/events', | |||||
'js/system/client', | |||||
'js/system/globals', | |||||
'html!ui/templates/online/template', | |||||
'css!ui/templates/online/styles', | |||||
'html!ui/templates/online/templateListItem' | |||||
], function ( | |||||
events, | |||||
client, | |||||
globals, | |||||
template, | |||||
styles, | |||||
templateListItem | |||||
) { | |||||
return { | |||||
tpl: template, | |||||
centered: true, | |||||
onlineList: [], | |||||
modal: true, | |||||
hasClose: true, | |||||
actions: [], | |||||
postRender: function () { | |||||
globals.onlineList = this.onlineList; | |||||
this.onEvent('onGetConnectedPlayer', this.onGetConnectedPlayer.bind(this)); | |||||
this.onEvent('onGetDisconnectedPlayer', this.onGetDisconnectedPlayer.bind(this)); | |||||
this.onEvent('onGetSocialActions', this.onGetSocialActions.bind(this)); | |||||
this.onEvent('onKeyDown', this.onKeyDown.bind(this)); | |||||
this.onEvent('onShowOnline', this.toggle.bind(this)); | |||||
}, | |||||
onGetSocialActions: function (actions) { | |||||
this.actions = actions; | |||||
}, | |||||
onKeyDown: function (key) { | |||||
if (key === 'o') | |||||
this.toggle(); | |||||
}, | |||||
onAfterShow: function () { | |||||
this.build(); | |||||
}, | |||||
onGetConnectedPlayer: function (list) { | |||||
if (!list.length) | |||||
list = [list]; | |||||
let onlineList = this.onlineList; | |||||
list.forEach(function (l) { | |||||
let exists = onlineList.find(function (o) { | |||||
return (o.name === l.name); | |||||
}); | |||||
if (exists) | |||||
$.extend(true, exists, l); | |||||
else | |||||
onlineList.push(l); | |||||
}); | |||||
onlineList | |||||
.sort(function (a, b) { | |||||
if (a.level === b.level) { | |||||
if (a.name > b.name) | |||||
return 1; | |||||
return -1; | |||||
} return b.level - a.level; | |||||
}); | |||||
if (this.shown) | |||||
this.build(); | |||||
}, | |||||
onGetDisconnectedPlayer: function (playerName) { | |||||
let onlineList = this.onlineList; | |||||
onlineList.spliceWhere(function (o) { | |||||
return (o.name === playerName); | |||||
}); | |||||
if (this.shown) | |||||
this.build(); | |||||
}, | |||||
build: function () { | |||||
let headingText = this.el.find('.heading-text'); | |||||
let playerCount = this.onlineList.length; | |||||
headingText.html(`online players (${playerCount})`); | |||||
let container = this.el.find('.list'); | |||||
container | |||||
.children(':not(.heading)') | |||||
.remove(); | |||||
this.onlineList.forEach(function (l) { | |||||
let html = templateListItem | |||||
.replace('$NAME$', l.name) | |||||
.replace('$LEVEL$', l.level) | |||||
.replace('$CLASS$', l.class); | |||||
let el = $(html) | |||||
.appendTo(container) | |||||
.on('contextmenu', this.showContext.bind(this, l)); | |||||
if (isMobile) | |||||
el.on('mousedown', this.showContext.bind(this, l)); | |||||
}, this); | |||||
}, | |||||
showContext: function (char, e) { | |||||
if (char.name !== window.player.name) { | |||||
const extraActions = this.actions.map(({ command, text }) => { | |||||
return { | |||||
text, | |||||
callback: this.performAction.bind(this, command, char.name) | |||||
}; | |||||
}); | |||||
const isBlocked = window.player.social.isPlayerBlocked(char.name); | |||||
const actions = [{ | |||||
text: 'invite to party', | |||||
callback: this.invite.bind(this, char.id) | |||||
}, { | |||||
text: 'whisper', | |||||
callback: events.emit.bind(events, 'onDoWhisper', char.name) | |||||
}, { | |||||
text: isBlocked ? 'unblock' : 'block', | |||||
callback: this.block.bind(this, char.name) | |||||
}, ...extraActions]; | |||||
events.emit('onBeforeOnlineListContext', char.id, actions); | |||||
events.emit('onContextMenu', actions, e); | |||||
} | |||||
e.preventDefault(); | |||||
return false; | |||||
}, | |||||
performAction: function (command, charName) { | |||||
client.request({ | |||||
cpn: 'social', | |||||
method: 'chat', | |||||
data: { | |||||
message: `/${command} ${charName}` | |||||
} | |||||
}); | |||||
}, | |||||
block: function (charName) { | |||||
const isBlocked = window.player.social.isPlayerBlocked(charName); | |||||
let method = isBlocked ? 'unblock' : 'block'; | |||||
this.performAction(method, charName); | |||||
}, | |||||
invite: function (charId) { | |||||
this.hide(); | |||||
client.request({ | |||||
cpn: 'social', | |||||
method: 'getInvite', | |||||
data: { | |||||
targetId: charId | |||||
} | |||||
}); | |||||
} | |||||
}; | |||||
}); |
@@ -1,100 +0,0 @@ | |||||
@import "../../../css/colors.less"; | |||||
.uiOnline { | |||||
display: none; | |||||
background-color: @blackB; | |||||
border: 5px solid @blackB; | |||||
text-align: center; | |||||
width: 450px; | |||||
height: 396px; | |||||
> .heading { | |||||
color: @blueA; | |||||
width: 100%; | |||||
height: 36px; | |||||
background-color: @blackB; | |||||
.heading-text { | |||||
padding-top: 8px; | |||||
margin: auto; | |||||
} | |||||
} | |||||
.bottom { | |||||
height: calc(100% - 36px); | |||||
background-color: @blackC; | |||||
padding: 8px; | |||||
.list { | |||||
width: 100%; | |||||
height: 100%; | |||||
overflow-y: auto; | |||||
background-color: @blackC; | |||||
display: flex; | |||||
flex-direction: column; | |||||
.heading { | |||||
height: 24px; | |||||
color: @white; | |||||
> div { | |||||
float: left; | |||||
padding: 4px; | |||||
height: 24px; | |||||
&:nth-child(1) { | |||||
width: 10%; | |||||
} | |||||
&:nth-child(2) { | |||||
width: 55%; | |||||
} | |||||
&:nth-child(3) { | |||||
width: 35%; | |||||
} | |||||
} | |||||
} | |||||
.onlineUser { | |||||
color: @grayC; | |||||
height: 24px; | |||||
cursor: pointer; | |||||
> div { | |||||
float: left; | |||||
padding: 4px; | |||||
height: 24px; | |||||
&:nth-child(1) { | |||||
width: 10%; | |||||
} | |||||
&:nth-child(2) { | |||||
width: 55%; | |||||
} | |||||
&:nth-child(3) { | |||||
width: 35%; | |||||
} | |||||
} | |||||
&:hover { | |||||
background-color: @blackB; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
.mobile .uiOnline { | |||||
z-index: 2; | |||||
} |
@@ -1,14 +0,0 @@ | |||||
<div class="uiOnline hasBorderShadow"> | |||||
<div class="heading"> | |||||
<div class="heading-text">online players</div> | |||||
</div> | |||||
<div class="bottom"> | |||||
<div class="list"> | |||||
<div class="heading"> | |||||
<div class="col">level</div> | |||||
<div class="col">name</div> | |||||
<div class="col">spirit</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> |
@@ -1,5 +0,0 @@ | |||||
<div class="onlineUser"> | |||||
<div class="level">$LEVEL$</div> | |||||
<div class="name">$NAME$</div> | |||||
<div class>($CLASS$)</div> | |||||
</div> |
@@ -30,7 +30,7 @@ define([ | |||||
this.onEvent('onGetParty', this.onGetParty.bind(this)); | this.onEvent('onGetParty', this.onGetParty.bind(this)); | ||||
this.onEvent('onPartyDisband', this.onPartyDisband.bind(this)); | this.onEvent('onPartyDisband', this.onPartyDisband.bind(this)); | ||||
this.onEvent('onGetConnectedPlayer', this.onGetConnectedPlayer.bind(this)); | |||||
this.onEvent('globalObjectListUpdated', this.globalObjectListUpdated.bind(this)); | |||||
this.onEvent('onGetPartyStats', this.onGetPartyStats.bind(this)); | this.onEvent('onGetPartyStats', this.onGetPartyStats.bind(this)); | ||||
@@ -38,46 +38,34 @@ define([ | |||||
this.onTogglePartyView(config.partyView); | this.onTogglePartyView(config.partyView); | ||||
}, | }, | ||||
onGetConnectedPlayer: function (msg) { | |||||
globalObjectListUpdated: function ({ list }) { | |||||
if (!window.player) | if (!window.player) | ||||
return; | return; | ||||
const { party } = this; | const { party } = this; | ||||
const { player: { serverId: playerId, zoneId: playerZone } } = window; | |||||
const { player: { serverId: playerId } } = window; | |||||
const player = list.find(l => l.id === playerId); | |||||
const { zoneId: playerZone } = player; | |||||
if (!party) | if (!party) | ||||
return; | return; | ||||
if (!(msg instanceof Array)) | |||||
msg = [msg]; | |||||
msg.forEach(m => { | |||||
const { id: mId, zoneId: mZone } = m; | |||||
list.forEach(l => { | |||||
const { id: mId, zoneId: mZone, level: mLevel } = l; | |||||
if (!party.includes(m.id)) | |||||
if (!party.includes(mId)) | |||||
return; | return; | ||||
if (mId !== playerId) { | if (mId !== playerId) { | ||||
const el = this.find('.member[memberId="' + m.id + '"]'); | |||||
const el = this.find('.member[memberId="' + mId + '"]'); | |||||
el.removeClass('differentZone'); | el.removeClass('differentZone'); | ||||
if (m.zoneId !== playerZone) | |||||
if (mZone !== playerZone) | |||||
el.addClass('differentZone'); | el.addClass('differentZone'); | ||||
el.find('.txtLevel').html('level: ' + m.level); | |||||
return; | |||||
el.find('.txtLevel').html('level: ' + mLevel); | |||||
} | } | ||||
party.forEach(p => { | |||||
const mObj = globals.onlineList.find(o => o.id === p); | |||||
const el = this.find('.member[memberId="' + p + '"]'); | |||||
el.removeClass('differentZone'); | |||||
if (mObj.zoneId !== mZone) | |||||
el.addClass('differentZone'); | |||||
}); | |||||
}); | }); | ||||
}, | }, | ||||
@@ -0,0 +1,14 @@ | |||||
{ | |||||
"name": "isleward", | |||||
"version": "0.12.0", | |||||
"description": "isleward", | |||||
"dependencies": { | |||||
}, | |||||
"devDependencies": { | |||||
"babel-eslint": "^10.1.0", | |||||
"eslint": "7.32.0", | |||||
"eslint-plugin-prettier": "4.0.0", | |||||
"eslint-plugin-requirejs": "^4.0.1" | |||||
} | |||||
} |
@@ -1,2 +1,2 @@ | |||||
node_modules/* | node_modules/* | ||||
config/passiveTree.js | |||||
config/passiveTree.js |
@@ -306,7 +306,13 @@ | |||||
"overrides": [ | "overrides": [ | ||||
{ | { | ||||
"files": [ | "files": [ | ||||
"**/clientComponents/**/*.js" | |||||
"clientComponents/**/*" | |||||
], | |||||
"extends": "../client/.eslintrc" | |||||
}, | |||||
{ | |||||
"files": [ | |||||
"mods/**/ui/**/*" | |||||
], | ], | ||||
"extends": "../client/.eslintrc" | "extends": "../client/.eslintrc" | ||||
} | } | ||||
@@ -107,35 +107,13 @@ module.exports = { | |||||
atlas.addObject(this.obj, true); | atlas.addObject(this.obj, true); | ||||
cons.emit('events', { | |||||
onGetMessages: [{ | |||||
messages: [{ | |||||
class: 'color-blueB', | |||||
message: this.obj.name + ' has come online' | |||||
}] | |||||
}], | |||||
onGetConnectedPlayer: [cons.getCharacterList()] | |||||
eventEmitter.emit('playerObjAdded', { | |||||
obj | |||||
}); | }); | ||||
cb(); | cb(); | ||||
}, | }, | ||||
broadcastSelf: function () { | |||||
let obj = this.obj; | |||||
let self = { | |||||
id: obj.id, | |||||
zoneId: obj.zoneId, | |||||
name: obj.name, | |||||
level: obj.level, | |||||
class: obj.class | |||||
}; | |||||
cons.emit('events', { | |||||
onGetConnectedPlayer: [self] | |||||
}); | |||||
}, | |||||
hasSeen: function (id) { | hasSeen: function (id) { | ||||
return (this.seen.indexOf(id) > -1); | return (this.seen.indexOf(id) > -1); | ||||
}, | }, | ||||
@@ -1,3 +1,5 @@ | |||||
const eventEmitter = require('../misc/events'); | |||||
let objBase = require('./objBase'); | let objBase = require('./objBase'); | ||||
module.exports = { | module.exports = { | ||||
@@ -305,8 +307,11 @@ module.exports = { | |||||
class: 'color-blueB', | class: 'color-blueB', | ||||
message: player.name + ' has reached level ' + obj.level | message: player.name + ' has reached level ' + obj.level | ||||
}] | }] | ||||
}], | |||||
onGetConnectedPlayer: [cons.getCharacterList()] | |||||
}] | |||||
}); | |||||
eventEmitter.emit('playerObjChanged', { | |||||
obj: player | |||||
}); | }); | ||||
} | } | ||||
}, | }, | ||||
@@ -15,10 +15,6 @@ | |||||
"universal-analytics": "^0.5.1" | "universal-analytics": "^0.5.1" | ||||
}, | }, | ||||
"devDependencies": { | "devDependencies": { | ||||
"babel-eslint": "^10.1.0", | |||||
"eslint": "^7.32.0", | |||||
"eslint-plugin-prettier": "^4.0.0", | |||||
"eslint-plugin-requirejs": "^4.0.1", | |||||
"sqlite3": "^5.0.3" | "sqlite3": "^5.0.3" | ||||
} | } | ||||
} | } |
@@ -1,5 +1,6 @@ | |||||
//External Modules | //External Modules | ||||
const objects = require('../objects/objects'); | const objects = require('../objects/objects'); | ||||
const eventEmitter = require('../misc/events'); | |||||
//Helpers | //Helpers | ||||
const { route, routeGlobal } = require('./connections/route'); | const { route, routeGlobal } = require('./connections/route'); | ||||
@@ -56,14 +57,8 @@ module.exports = { | |||||
} | } | ||||
if (player.name) { | if (player.name) { | ||||
this.emit('events', { | |||||
onGetMessages: [{ | |||||
messages: [{ | |||||
class: 'color-blueB', | |||||
message: player.name + ' has gone offline' | |||||
}] | |||||
}], | |||||
onGetDisconnectedPlayer: [player.name] | |||||
eventEmitter.emit('playerObjRemoved', { | |||||
id: player.id | |||||
}); | }); | ||||
if (player.has('id')) | if (player.has('id')) | ||||
@@ -107,14 +102,8 @@ module.exports = { | |||||
} | } | ||||
}); | }); | ||||
this.emit('events', { | |||||
onGetMessages: [{ | |||||
messages: [{ | |||||
class: 'color-blueB', | |||||
message: player.name + ' has gone offline' | |||||
}] | |||||
}], | |||||
onGetDisconnectedPlayer: [player.name] | |||||
eventEmitter.emit('playerObjRemoved', { | |||||
id: player.id | |||||
}); | }); | ||||
//If we don't do this, the atlas will try to remove it from the thread | //If we don't do this, the atlas will try to remove it from the thread | ||||
@@ -9,7 +9,6 @@ const appRoot = (req, res) => { | |||||
const appFile = (req, res) => { | const appFile = (req, res) => { | ||||
let root = req.url.split('/')[1]; | let root = req.url.split('/')[1]; | ||||
let file = req.params[0]; | let file = req.params[0]; | ||||
file = file.replace('/' + root + '/', ''); | file = file.replace('/' + root + '/', ''); | ||||
const validRequest = ( | const validRequest = ( | ||||
@@ -46,7 +46,9 @@ module.exports = { | |||||
serverObj.zoneId = thread.id; | serverObj.zoneId = thread.id; | ||||
serverObj.zoneName = thread.name; | serverObj.zoneName = thread.name; | ||||
serverObj.player.broadcastSelf(); | |||||
events.emit('playerObjChanged', { | |||||
obj | |||||
}); | |||||
const simpleObj = obj.getSimple ? obj.getSimple(true, true) : obj; | const simpleObj = obj.getSimple ? obj.getSimple(true, true) : obj; | ||||