From f6fe6c2f32e0d2fcf36034e10113a83cf63dfb87 Mon Sep 17 00:00:00 2001 From: Shaun Date: Sat, 21 Oct 2023 13:42:49 +0200 Subject: [PATCH 01/20] bug #2003: When updating player.level in the main thread, we now also update the stats component --- src/server/objects/objects.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/server/objects/objects.js b/src/server/objects/objects.js index 24b61e48..1b63c497 100644 --- a/src/server/objects/objects.js +++ b/src/server/objects/objects.js @@ -301,6 +301,8 @@ module.exports = { if (obj.level) { await leaderboard.setLevel(player.name, obj.level); + player.components.find(c => c.type === 'stats').values.level = obj.level; + cons.emit('events', { onGetMessages: [{ messages: [{ From 740a214362f960f5e1e9af502fbfb3fed51f80fb Mon Sep 17 00:00:00 2001 From: Shaun Date: Sun, 22 Oct 2023 11:42:48 +0200 Subject: [PATCH 02/20] bug #2004: no longer emitting players before they are added to map threads --- .../templates/announcements/announcements.js | 2 +- src/server/components/player.js | 4 --- src/server/config/clientConfig.js | 4 +-- src/server/world/atlas.js | 28 ++++++++++++++++--- src/server/world/threadManager.js | 21 ++++++++++++-- 5 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/client/ui/templates/announcements/announcements.js b/src/client/ui/templates/announcements/announcements.js index a239d981..1e45bcf7 100644 --- a/src/client/ui/templates/announcements/announcements.js +++ b/src/client/ui/templates/announcements/announcements.js @@ -43,7 +43,7 @@ define([ el.css('margin-top', e.top); this.message = { - ttl: this.maxTtl, + ttl: e.ttl ?? this.maxTtl, el: el }; }, diff --git a/src/server/components/player.js b/src/server/components/player.js index acb3c647..ed43cbc5 100644 --- a/src/server/components/player.js +++ b/src/server/components/player.js @@ -107,10 +107,6 @@ module.exports = { atlas.addObject(this.obj, true); - eventEmitter.emit('playerObjAdded', { - obj - }); - cb(); }, diff --git a/src/server/config/clientConfig.js b/src/server/config/clientConfig.js index fa30a273..7c6a61d3 100644 --- a/src/server/config/clientConfig.js +++ b/src/server/config/clientConfig.js @@ -159,7 +159,8 @@ const config = { ] }, uiLoginList: [ - 'login' + 'login', + 'announcements' ], uiList: [ 'inventory', @@ -179,7 +180,6 @@ const config = { 'tooltips', 'tooltipInfo', 'tooltipItem', - 'announcements', 'quests', 'events', 'progressBar', diff --git a/src/server/world/atlas.js b/src/server/world/atlas.js index 29dc30c3..cad2e583 100644 --- a/src/server/world/atlas.js +++ b/src/server/world/atlas.js @@ -2,7 +2,8 @@ const objects = require('../objects/objects'); const events = require('../misc/events'); const { - getThread, killThread, sendMessageToThread, getThreadFromId, returnWhenThreadsIdle, gePlayerCountInThread + getThread, killThread, sendMessageToThread, getThreadFromId, doesThreadExist, + returnWhenThreadsIdle, getPlayerCountInThread, killThreadIfEmpty } = require('./threadManager'); const { registerCallback, removeCallback } = require('./atlas/registerCallback'); @@ -40,10 +41,29 @@ module.exports = { zoneId = partyLeader.zoneId; } - const { thread, resetObjPosition } = await getThread({ + const eGetThread = { zoneName, zoneId - }); + }; + + if (!doesThreadExist(eGetThread)) { + serverObj.socket.emit('event', { + event: 'onGetAnnouncement', + data: { + msg: 'Generating a new map, please wait as this may take a few moments..', + ttl: 5000 + } + }); + } + + const { thread, resetObjPosition } = await getThread(eGetThread); + + //Perhaps the player disconnected while waiting for the thread to spawn + if (!obj.socket.connected) { + await killThreadIfEmpty(thread); + + return; + } if (resetObjPosition) { delete obj.x; @@ -108,7 +128,7 @@ module.exports = { return; } - if (thread.instanced && (await gePlayerCountInThread(thread)) === 1) { + if (thread.instanced && (await getPlayerCountInThread(thread)) === 1) { this.removeObjectFromInstancedZone(thread, playerId, callback); return; diff --git a/src/server/world/threadManager.js b/src/server/world/threadManager.js index 707f64bb..9ad4e56e 100644 --- a/src/server/world/threadManager.js +++ b/src/server/world/threadManager.js @@ -20,7 +20,7 @@ const getThreadFromId = threadId => { return threads.find(t => t.id === threadId); }; -const gePlayerCountInThread = async thread => { +const getPlayerCountInThread = async thread => { const { playerCount } = await new Promise(res => { const cb = registerCallback(res); @@ -94,7 +94,7 @@ const messageHandlers = { rezone: async function (thread, message) { const { args: { obj, newZone, keepPos = true } } = message; - if (thread.instanced && (await gePlayerCountInThread(thread)) === 0) { + if (thread.instanced && (await getPlayerCountInThread(thread)) === 0) { thread.worker.kill(); threads.spliceWhere(t => t === thread); } @@ -173,6 +173,12 @@ const spawnThread = async ({ name, path, instanced }) => { return promise; }; +const doesThreadExist = ({ zoneName, zoneId }) => { + const exists = threads.some(t => t.id === zoneId && t.name === zoneName); + + return exists; +}; + const getThread = async ({ zoneName, zoneId }) => { const result = { resetObjPosition: false, @@ -208,6 +214,13 @@ const killThread = thread => { threads.spliceWhere(t => t === thread); }; +const killThreadIfEmpty = async thread => { + const playerCount = await getPlayerCountInThread(thread); + + if (playerCount === 0) + killThread(thread); +}; + const spawnMapThreads = async () => { const promises = mapList .filter(m => !m.disabled && !m.instanced) @@ -255,9 +268,11 @@ module.exports = { getThread, killThread, getThreadFromId, + doesThreadExist, spawnMapThreads, messageAllThreads, + killThreadIfEmpty, sendMessageToThread, returnWhenThreadsIdle, - gePlayerCountInThread + getPlayerCountInThread }; From 4fc6ccb1c904ec3977d7376a59af118efd25e9a7 Mon Sep 17 00:00:00 2001 From: Shaun Date: Sun, 22 Oct 2023 11:48:38 +0200 Subject: [PATCH 03/20] bug: fixed a crash --- src/server/world/atlas.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/world/atlas.js b/src/server/world/atlas.js index cad2e583..476be5b6 100644 --- a/src/server/world/atlas.js +++ b/src/server/world/atlas.js @@ -59,7 +59,7 @@ module.exports = { const { thread, resetObjPosition } = await getThread(eGetThread); //Perhaps the player disconnected while waiting for the thread to spawn - if (!obj.socket.connected) { + if (!serverObj.socket.connected) { await killThreadIfEmpty(thread); return; From b453ee373e5ece455f84870734192ffb3e86dcdd Mon Sep 17 00:00:00 2001 From: Shaun Date: Sun, 22 Oct 2023 12:01:58 +0200 Subject: [PATCH 04/20] bug #2004: Fixed the thread finder check and announcement duration --- src/server/config/serverConfig.js | 2 +- src/server/mods/checkModRepos.js | 79 +++++++++++++++++++++++++++++++ src/server/world/atlas.js | 2 +- src/server/world/threadManager.js | 15 +++++- 4 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 src/server/mods/checkModRepos.js diff --git a/src/server/config/serverConfig.js b/src/server/config/serverConfig.js index ae549066..f8e99b51 100644 --- a/src/server/config/serverConfig.js +++ b/src/server/config/serverConfig.js @@ -10,7 +10,7 @@ module.exports = { //Options: // sqlite // rethink - db: process.env.IWD_DB || 'sqlite', + db: process.env.IWD_DB || 'rethink', dbHost: process.env.IWD_DB_HOST || 'localhost', dbPort: process.env.IWD_DB_PORT || 28015, dbName: process.env.IWD_DB_NAME || 'live', diff --git a/src/server/mods/checkModRepos.js b/src/server/mods/checkModRepos.js new file mode 100644 index 00000000..1e0e012e --- /dev/null +++ b/src/server/mods/checkModRepos.js @@ -0,0 +1,79 @@ +const fs = require('fs'); +const { execSync } = require('child_process'); +const path = require('path'); + +function getSubdirectories (directoryPath) { + return fs.readdirSync(directoryPath, { withFileTypes: true }) + .filter(dirent => dirent.isDirectory()) + .map(dirent => dirent.name); +} + +function isGitRepository (directoryPath) { + const gitFolderPath = path.join(directoryPath, '.git'); + return fs.existsSync(gitFolderPath) && fs.statSync(gitFolderPath).isDirectory(); +} + +function doesReleaseBranchExist (directoryPath) { + try { + const branches = execSync('git branch -r', { cwd: directoryPath, encoding: 'utf-8' }); + return branches.includes('origin/release'); + } catch (error) { + return false; + } +} + +function getCommitsInRange (directoryPath, range) { + const command = `git log --pretty=format:"%s" --abbrev-commit ${range}`; + try { + const result = execSync(command, { cwd: directoryPath, encoding: 'utf-8' }); + return result.trim().split('\n'); + } catch (error) { + return []; + } +} + +function getCommitCountBehind (directoryPath) { + if (doesReleaseBranchExist(directoryPath)) { + execSync('git fetch origin release', { cwd: directoryPath, encoding: 'utf-8' }); + + const command = 'origin/release..origin/master'; + const commitMessages = getCommitsInRange(directoryPath, command); + const commitCount = commitMessages.length; + + if (commitMessages.length === 1 && commitMessages[0] === '') + return { count: 0, messages: [] }; + + return { count: commitCount, messages: commitMessages }; + } + return { count: 0, messages: [] }; +} + +const greenColor = '\x1b[32m'; +const grayColor = '\x1b[90m'; +const resetColor = '\x1b[0m'; + +function displayCommitCountBehind (directoryPath) { + if (isGitRepository(directoryPath)) { + const { count, messages } = getCommitCountBehind(directoryPath); + if (count > 0) { + console.log(`${greenColor}${path.basename(directoryPath)}: ${count} commit(s)`); + messages.forEach((message, index) => { + console.log(`${grayColor}${index + 1}. ${message}`); + }); + console.log('\n'); + } + } +} + +function processSubdirectories (subdirectories) { + subdirectories.forEach(subdirectory => { + const fullPath = path.join(process.cwd(), subdirectory); + if (isGitRepository(fullPath)) + displayCommitCountBehind(fullPath); + }); +} + +console.log('\n'); +const subdirectories = getSubdirectories(process.cwd()); +processSubdirectories(subdirectories); +console.log(resetColor); diff --git a/src/server/world/atlas.js b/src/server/world/atlas.js index 476be5b6..7911c030 100644 --- a/src/server/world/atlas.js +++ b/src/server/world/atlas.js @@ -51,7 +51,7 @@ module.exports = { event: 'onGetAnnouncement', data: { msg: 'Generating a new map, please wait as this may take a few moments..', - ttl: 5000 + ttl: 500 } }); } diff --git a/src/server/world/threadManager.js b/src/server/world/threadManager.js index 9ad4e56e..170f3d24 100644 --- a/src/server/world/threadManager.js +++ b/src/server/world/threadManager.js @@ -174,9 +174,22 @@ const spawnThread = async ({ name, path, instanced }) => { }; const doesThreadExist = ({ zoneName, zoneId }) => { + let map = mapList.find(m => m.name === zoneName); + + if (!map) + map = mapList.find(m => m.name === clientConfig.config.defaultZone); + const exists = threads.some(t => t.id === zoneId && t.name === zoneName); - return exists; + if (exists) + return true; + + if (map.instanced) + return false; + + const thread = getThreadFromName(map.name); + + return !!thread; }; const getThread = async ({ zoneName, zoneId }) => { From a4a59e2a0ee53c3ed8f1909a9c42ea181eed0b9f Mon Sep 17 00:00:00 2001 From: Big Bad Waffle Date: Sun, 22 Oct 2023 10:03:18 +0000 Subject: [PATCH 05/20] Revert "bug #2004: Fixed the thread finder check and announcement duration" This reverts commit b453ee373e5ece455f84870734192ffb3e86dcdd --- src/server/config/serverConfig.js | 2 +- src/server/mods/checkModRepos.js | 79 ------------------------------- src/server/world/atlas.js | 2 +- src/server/world/threadManager.js | 15 +----- 4 files changed, 3 insertions(+), 95 deletions(-) delete mode 100644 src/server/mods/checkModRepos.js diff --git a/src/server/config/serverConfig.js b/src/server/config/serverConfig.js index f8e99b51..ae549066 100644 --- a/src/server/config/serverConfig.js +++ b/src/server/config/serverConfig.js @@ -10,7 +10,7 @@ module.exports = { //Options: // sqlite // rethink - db: process.env.IWD_DB || 'rethink', + db: process.env.IWD_DB || 'sqlite', dbHost: process.env.IWD_DB_HOST || 'localhost', dbPort: process.env.IWD_DB_PORT || 28015, dbName: process.env.IWD_DB_NAME || 'live', diff --git a/src/server/mods/checkModRepos.js b/src/server/mods/checkModRepos.js deleted file mode 100644 index 1e0e012e..00000000 --- a/src/server/mods/checkModRepos.js +++ /dev/null @@ -1,79 +0,0 @@ -const fs = require('fs'); -const { execSync } = require('child_process'); -const path = require('path'); - -function getSubdirectories (directoryPath) { - return fs.readdirSync(directoryPath, { withFileTypes: true }) - .filter(dirent => dirent.isDirectory()) - .map(dirent => dirent.name); -} - -function isGitRepository (directoryPath) { - const gitFolderPath = path.join(directoryPath, '.git'); - return fs.existsSync(gitFolderPath) && fs.statSync(gitFolderPath).isDirectory(); -} - -function doesReleaseBranchExist (directoryPath) { - try { - const branches = execSync('git branch -r', { cwd: directoryPath, encoding: 'utf-8' }); - return branches.includes('origin/release'); - } catch (error) { - return false; - } -} - -function getCommitsInRange (directoryPath, range) { - const command = `git log --pretty=format:"%s" --abbrev-commit ${range}`; - try { - const result = execSync(command, { cwd: directoryPath, encoding: 'utf-8' }); - return result.trim().split('\n'); - } catch (error) { - return []; - } -} - -function getCommitCountBehind (directoryPath) { - if (doesReleaseBranchExist(directoryPath)) { - execSync('git fetch origin release', { cwd: directoryPath, encoding: 'utf-8' }); - - const command = 'origin/release..origin/master'; - const commitMessages = getCommitsInRange(directoryPath, command); - const commitCount = commitMessages.length; - - if (commitMessages.length === 1 && commitMessages[0] === '') - return { count: 0, messages: [] }; - - return { count: commitCount, messages: commitMessages }; - } - return { count: 0, messages: [] }; -} - -const greenColor = '\x1b[32m'; -const grayColor = '\x1b[90m'; -const resetColor = '\x1b[0m'; - -function displayCommitCountBehind (directoryPath) { - if (isGitRepository(directoryPath)) { - const { count, messages } = getCommitCountBehind(directoryPath); - if (count > 0) { - console.log(`${greenColor}${path.basename(directoryPath)}: ${count} commit(s)`); - messages.forEach((message, index) => { - console.log(`${grayColor}${index + 1}. ${message}`); - }); - console.log('\n'); - } - } -} - -function processSubdirectories (subdirectories) { - subdirectories.forEach(subdirectory => { - const fullPath = path.join(process.cwd(), subdirectory); - if (isGitRepository(fullPath)) - displayCommitCountBehind(fullPath); - }); -} - -console.log('\n'); -const subdirectories = getSubdirectories(process.cwd()); -processSubdirectories(subdirectories); -console.log(resetColor); diff --git a/src/server/world/atlas.js b/src/server/world/atlas.js index 7911c030..476be5b6 100644 --- a/src/server/world/atlas.js +++ b/src/server/world/atlas.js @@ -51,7 +51,7 @@ module.exports = { event: 'onGetAnnouncement', data: { msg: 'Generating a new map, please wait as this may take a few moments..', - ttl: 500 + ttl: 5000 } }); } diff --git a/src/server/world/threadManager.js b/src/server/world/threadManager.js index 170f3d24..9ad4e56e 100644 --- a/src/server/world/threadManager.js +++ b/src/server/world/threadManager.js @@ -174,22 +174,9 @@ const spawnThread = async ({ name, path, instanced }) => { }; const doesThreadExist = ({ zoneName, zoneId }) => { - let map = mapList.find(m => m.name === zoneName); - - if (!map) - map = mapList.find(m => m.name === clientConfig.config.defaultZone); - const exists = threads.some(t => t.id === zoneId && t.name === zoneName); - if (exists) - return true; - - if (map.instanced) - return false; - - const thread = getThreadFromName(map.name); - - return !!thread; + return exists; }; const getThread = async ({ zoneName, zoneId }) => { From 721ecfe54b6b3186b02b17b126567e2bfe45f441 Mon Sep 17 00:00:00 2001 From: Shaun Date: Sun, 22 Oct 2023 12:04:25 +0200 Subject: [PATCH 06/20] bug #2004: Fixed the thread finder check and announcement duration --- src/server/world/atlas.js | 2 +- src/server/world/threadManager.js | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/server/world/atlas.js b/src/server/world/atlas.js index 476be5b6..7911c030 100644 --- a/src/server/world/atlas.js +++ b/src/server/world/atlas.js @@ -51,7 +51,7 @@ module.exports = { event: 'onGetAnnouncement', data: { msg: 'Generating a new map, please wait as this may take a few moments..', - ttl: 5000 + ttl: 500 } }); } diff --git a/src/server/world/threadManager.js b/src/server/world/threadManager.js index 9ad4e56e..170f3d24 100644 --- a/src/server/world/threadManager.js +++ b/src/server/world/threadManager.js @@ -174,9 +174,22 @@ const spawnThread = async ({ name, path, instanced }) => { }; const doesThreadExist = ({ zoneName, zoneId }) => { + let map = mapList.find(m => m.name === zoneName); + + if (!map) + map = mapList.find(m => m.name === clientConfig.config.defaultZone); + const exists = threads.some(t => t.id === zoneId && t.name === zoneName); - return exists; + if (exists) + return true; + + if (map.instanced) + return false; + + const thread = getThreadFromName(map.name); + + return !!thread; }; const getThread = async ({ zoneName, zoneId }) => { From 286ff80b95b3934aaa687e091c620a6dd298fb6d Mon Sep 17 00:00:00 2001 From: Shaun Date: Sat, 18 Nov 2023 10:59:09 +0200 Subject: [PATCH 07/20] bug #2005: fixed an issue causing the announcements UI to be gone after exiting to character select --- src/server/config/clientConfig.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/server/config/clientConfig.js b/src/server/config/clientConfig.js index 7c6a61d3..21a9f586 100644 --- a/src/server/config/clientConfig.js +++ b/src/server/config/clientConfig.js @@ -194,7 +194,8 @@ const config = { 'passives', 'workbench', 'middleHud', - 'options' + 'options', + 'announcements' ], contextMenuActions: { player: [], From 82a5d90a60b01aeff6eb0675ae85fa7ad9479dff Mon Sep 17 00:00:00 2001 From: Shaun Date: Wed, 27 Dec 2023 13:29:06 +0200 Subject: [PATCH 08/20] modding #2009: new event afterGetEventList --- src/server/events/events.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/server/events/events.js b/src/server/events/events.js index fa1ac9ee..81dee05b 100644 --- a/src/server/events/events.js +++ b/src/server/events/events.js @@ -49,6 +49,10 @@ module.exports = { if (!e.disabled) this.configs.push(extend({}, e)); }, this); + + this.instance.eventEmitter.emit('afterGetEventList', { + eventConfigs: this.configs + }); }, getEvent: function (name) { From dc8b129f733f555f2a6d9fd293c3d4f91ad697f7 Mon Sep 17 00:00:00 2001 From: Shaun Date: Fri, 29 Dec 2023 17:45:17 +0200 Subject: [PATCH 09/20] modding #2010: Added two new events and fixed a ciruclar reference warning --- .../templates/createCharacter/createCharacter.js | 16 ++++++++++------ src/server/components/auth.js | 9 ++++++++- src/server/world/threadManager.js | 3 +-- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/client/ui/templates/createCharacter/createCharacter.js b/src/client/ui/templates/createCharacter/createCharacter.js index f91d6e64..8116e723 100644 --- a/src/client/ui/templates/createCharacter/createCharacter.js +++ b/src/client/ui/templates/createCharacter/createCharacter.js @@ -132,15 +132,19 @@ define([ create: function () { this.el.addClass('disabled'); + const eCreateCharacter = { + name: this.find('.txtName').val(), + class: this.class, + skinId: this.skinId, + prophecies: this.prophecies + }; + + events.emit('beforeCreateCharacter', eCreateCharacter); + client.request({ cpn: 'auth', method: 'createCharacter', - data: { - name: this.find('.txtName').val(), - class: this.class, - skinId: this.skinId, - prophecies: this.prophecies - }, + data: eCreateCharacter, callback: this.onCreate.bind(this) }); }, diff --git a/src/server/components/auth.js b/src/server/components/auth.js index 27037b37..a48f462e 100644 --- a/src/server/components/auth.js +++ b/src/server/components/auth.js @@ -500,10 +500,17 @@ module.exports = { customChannels: this.customChannels }); + const eBeforeSaveCharacter = { + obj: simple, + config: data + }; + + eventEmitter.emit('beforeSaveCharacter', eBeforeSaveCharacter); + await io.setAsync({ key: name, table: 'character', - value: simple, + value: eBeforeSaveCharacter.obj, serialize: true }); diff --git a/src/server/world/threadManager.js b/src/server/world/threadManager.js index 170f3d24..0b4eb923 100644 --- a/src/server/world/threadManager.js +++ b/src/server/world/threadManager.js @@ -3,7 +3,6 @@ const childProcess = require('child_process'); //Imports const objects = require('../objects/objects'); -const connections = require('../security/connections'); const { mapList } = require('./mapManager'); const { registerCallback } = require('./atlas/registerCallback'); @@ -76,7 +75,7 @@ const messageHandlers = { }, callDifferentThread: function (thread, message) { - let obj = connections.players.find(p => (p.name === message.playerName)); + let obj = cons.players.find(p => (p.name === message.playerName)); if (!obj) return; From c8a500c9fecc92f5022702a634e14df42fe85d9b Mon Sep 17 00:00:00 2001 From: Shaun Date: Sat, 30 Dec 2023 09:41:14 +0200 Subject: [PATCH 10/20] bug #2011: fixed a crash in ioRethink.logError and added debugging --- src/server/components/auth.js | 25 ++++++++++++++ src/server/db/ioRethink.js | 56 +++++++++++++++++++++++++------ src/server/objects/objects.js | 9 +---- src/server/world/threadManager.js | 15 +++++++++ 4 files changed, 86 insertions(+), 19 deletions(-) diff --git a/src/server/components/auth.js b/src/server/components/auth.js index a48f462e..a6e56267 100644 --- a/src/server/components/auth.js +++ b/src/server/components/auth.js @@ -425,6 +425,7 @@ module.exports = { msg.callback(); }, + /* eslint-disable-next-line max-lines-per-function */ createCharacter: async function (msg) { let data = msg.data; let name = data.name; @@ -458,8 +459,14 @@ module.exports = { return; } + console.log('Starting new character create for', name); + const t1 = +new Date(); + const releaseCreateLock = await getCreateLock(); + const t2 = +new Date(); + console.log('Took', t2 - t1, 'ms to get a create lock'); + let exists = await io.getAsync({ key: name, ignoreCase: true, @@ -467,6 +474,9 @@ module.exports = { noDefault: true }); + const t3 = +new Date(); + console.log('Took', t3 - t2, 'ms to check if the character exists'); + if (exists) { releaseCreateLock(); msg.callback(messages.login.charExists); @@ -488,7 +498,13 @@ module.exports = { let simple = this.obj.getSimple(true); + const t4 = +new Date(); + console.log('Took', t4 - t3, 'ms to build the simpleObj'); + await this.verifySkin(simple); + + const t5 = +new Date(); + console.log('Took', t5 - t4, 'ms to verify the skin'); let prophecies = (data.prophecies || []).filter(p => p); @@ -507,6 +523,9 @@ module.exports = { eventEmitter.emit('beforeSaveCharacter', eBeforeSaveCharacter); + const t6 = +new Date(); + console.log('Took', t6 - t5, 'ms to run beforeSaveCharacter'); + await io.setAsync({ key: name, table: 'character', @@ -516,6 +535,9 @@ module.exports = { this.characters[name] = simple; this.characterList.push(name); + + const t7 = +new Date(); + console.log('Took', t7 - t6, 'ms to save the character'); await io.setAsync({ key: this.username, @@ -524,6 +546,9 @@ module.exports = { serialize: true }); + const t8 = +new Date(); + console.log('Took', t8 - t7, 'ms to save the character list'); + releaseCreateLock(); this.initTracker(); diff --git a/src/server/db/ioRethink.js b/src/server/db/ioRethink.js index 244faf6e..ae984543 100644 --- a/src/server/db/ioRethink.js +++ b/src/server/db/ioRethink.js @@ -137,7 +137,16 @@ module.exports = { }) .run(); } catch (e) { - this.logError(e, table, id); + this.logError({ + sourceModule: 'ioRethink', + sourceMethod: 'setAsync', + error: e, + info: { + table, + key: id, + value: JSON.stringify(value) + } + }); } }, @@ -151,7 +160,15 @@ module.exports = { .insert(value, { conflict }) .run(); } catch (e) { - this.logError(e, table, JSON.stringify(value)); + this.logError({ + sourceModule: 'ioRethink', + sourceMethod: 'setFlat', + error: e, + info: { + table, + value: JSON.stringify(value) + } + }); } }, @@ -193,7 +210,17 @@ module.exports = { }) .run(); } catch (e) { - this.logError(e, table, key); + this.logError({ + sourceModule: 'ioRethink', + sourceMethod: 'append', + error: e, + info: { + table, + key, + field, + value: JSON.stringify(value) + } + }); } }, @@ -208,19 +235,26 @@ module.exports = { return !!res; }, - logError: async function (error, table, key) { + logError: async function ({ sourceModule, sourceMethod, error, info }) { try { - const errorValue = `${error.toString()} | ${error.stack.toString()} | ${table} | ${key}`; - await this.setAsync({ - key: new Date(), table: 'error', - value: errorValue + value: { + date: new Date(), + sourceModule, + sourceMethod, + error: error.toString(), + stack: error.stack.toString(), + info + } }); } catch (e) {} - process.send({ - event: 'onCrashed' - }); + if (process.send) { + process.send({ + event: 'onCrashed' + }); + } else + process.exit(); } }; diff --git a/src/server/objects/objects.js b/src/server/objects/objects.js index 1b63c497..7ca993e2 100644 --- a/src/server/objects/objects.js +++ b/src/server/objects/objects.js @@ -253,15 +253,8 @@ module.exports = { if (!storeEntry) { const playerObj = objects.find(o => o.id === toId); - if (!playerObj || playerObj.zoneName !== sourceZone) { - io.setAsync({ - key: new Date(), - table: 'error', - value: `ignoring ${e}` - }); - + if (!playerObj || playerObj.zoneName !== sourceZone) continue; - } store[toId] = { obj: playerObj, diff --git a/src/server/world/threadManager.js b/src/server/world/threadManager.js index 0b4eb923..711330b9 100644 --- a/src/server/world/threadManager.js +++ b/src/server/world/threadManager.js @@ -213,6 +213,21 @@ const getThread = async ({ zoneName, zoneId }) => { thread = getThreadFromName(map.name); } + if (!thread) { + io.logError({ + sourceModule: 'threadManager', + sourceMethod: 'getThread', + error: 'No thread found', + info: { + requestedZoneName: zoneName, + requestedZoneId: zoneId, + useMapName: map.name + } + }); + + process.exit(); + } + if (!thread.isReady) await thread.promise; From 4ec2d17a845381a1af4b996809b4fd7fd7dbbf72 Mon Sep 17 00:00:00 2001 From: Shaun Date: Sat, 30 Dec 2023 10:40:25 +0200 Subject: [PATCH 11/20] optimize #2011: Added indices to the login and character tables for assisting in case insensitive checks --- src/server/components/auth.js | 25 ------------------------- src/server/db/ioRethink.js | 15 ++++++++++++++- 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/src/server/components/auth.js b/src/server/components/auth.js index a6e56267..a48f462e 100644 --- a/src/server/components/auth.js +++ b/src/server/components/auth.js @@ -425,7 +425,6 @@ module.exports = { msg.callback(); }, - /* eslint-disable-next-line max-lines-per-function */ createCharacter: async function (msg) { let data = msg.data; let name = data.name; @@ -459,14 +458,8 @@ module.exports = { return; } - console.log('Starting new character create for', name); - const t1 = +new Date(); - const releaseCreateLock = await getCreateLock(); - const t2 = +new Date(); - console.log('Took', t2 - t1, 'ms to get a create lock'); - let exists = await io.getAsync({ key: name, ignoreCase: true, @@ -474,9 +467,6 @@ module.exports = { noDefault: true }); - const t3 = +new Date(); - console.log('Took', t3 - t2, 'ms to check if the character exists'); - if (exists) { releaseCreateLock(); msg.callback(messages.login.charExists); @@ -498,13 +488,7 @@ module.exports = { let simple = this.obj.getSimple(true); - const t4 = +new Date(); - console.log('Took', t4 - t3, 'ms to build the simpleObj'); - await this.verifySkin(simple); - - const t5 = +new Date(); - console.log('Took', t5 - t4, 'ms to verify the skin'); let prophecies = (data.prophecies || []).filter(p => p); @@ -523,9 +507,6 @@ module.exports = { eventEmitter.emit('beforeSaveCharacter', eBeforeSaveCharacter); - const t6 = +new Date(); - console.log('Took', t6 - t5, 'ms to run beforeSaveCharacter'); - await io.setAsync({ key: name, table: 'character', @@ -535,9 +516,6 @@ module.exports = { this.characters[name] = simple; this.characterList.push(name); - - const t7 = +new Date(); - console.log('Took', t7 - t6, 'ms to save the character'); await io.setAsync({ key: this.username, @@ -546,9 +524,6 @@ module.exports = { serialize: true }); - const t8 = +new Date(); - console.log('Took', t8 - t7, 'ms to save the character list'); - releaseCreateLock(); this.initTracker(); diff --git a/src/server/db/ioRethink.js b/src/server/db/ioRethink.js index ae984543..e01fdc51 100644 --- a/src/server/db/ioRethink.js +++ b/src/server/db/ioRethink.js @@ -33,6 +33,19 @@ module.exports = { _.log(e); } } + + //Create indices used for case-insensitive checks + if (!(await r.table('login').indexList()).includes('idLowerCase')) { + await r.table('login').indexCreate('idLowerCase', r.row('id').downcase()); + + _.log('Created index: idLowerCase on table: login'); + } + + if (!(await r.table('character').indexList()).includes('idLowerCase')) { + await r.table('character').indexCreate('idLowerCase', r.row('id').downcase()); + + _.log('Created index: idLowerCase on table: character'); + } }, createTable: async function (tableName) { @@ -46,7 +59,7 @@ module.exports = { getAsyncIgnoreCase: async function (table, key) { const res = await r.table(table) - .filter(doc => doc('id').match(`(?i)^${key}$`)) + .getAll(key.toLowerCase(), { index: 'idLowerCase' }) .run(); return res[0]; From 6bf5da5569f58ca4f3b2a17bd96c9d9eb4d0d566 Mon Sep 17 00:00:00 2001 From: Shaun Date: Mon, 1 Jan 2024 08:49:51 +0200 Subject: [PATCH 12/20] modding #2012: Added the beforeSpawnResource that allows spawned resources' positions to be set by mods --- src/server/world/resourceSpawner.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/server/world/resourceSpawner.js b/src/server/world/resourceSpawner.js index 28ae1e4c..9ea5890d 100644 --- a/src/server/world/resourceSpawner.js +++ b/src/server/world/resourceSpawner.js @@ -1,4 +1,5 @@ let herbs = require('../config/herbs'); +const eventEmitter = require('../misc/events'); const defaultGatherChance = { herb: 100, @@ -122,8 +123,20 @@ module.exports = { }, spawn: function (node) { - let blueprint = node.blueprint; - let position = this.getRandomSpawnPosition(node, blueprint); + const blueprint = node.blueprint; + + const eBeforeSpawnResource = { + node, + position: undefined, + allowRandomPosition: true + }; + eventEmitter.emit('beforeSpawnResource', eBeforeSpawnResource); + + if (eBeforeSpawnResource.allowRandomPosition && !eBeforeSpawnResource.position) + eBeforeSpawnResource.position = this.getRandomSpawnPosition(node, blueprint); + + const { position } = eBeforeSpawnResource; + if (!position) return false; From 36248f84ea142db4910df6541b7c7cdada224f36 Mon Sep 17 00:00:00 2001 From: Shaun Date: Mon, 1 Jan 2024 08:51:49 +0200 Subject: [PATCH 13/20] Added clientConfig.getTileIndexInAtlasSync for use by mods when we know that the sprite atlas has already fully loaded --- src/server/config/clientConfig.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/server/config/clientConfig.js b/src/server/config/clientConfig.js index 21a9f586..dac9d71c 100644 --- a/src/server/config/clientConfig.js +++ b/src/server/config/clientConfig.js @@ -283,6 +283,26 @@ module.exports = { return result; }, + getTileIndexInAtlasSync: function (spriteSheet, tileIndexInSource) { + const { atlasTextures, atlasTextureDimensions } = config; + + const indexOfSheet = atlasTextures.indexOf(spriteSheet); + + let tileCountBeforeSheet = 0; + + for (let i = 0; i < indexOfSheet; i++) { + const sheet = atlasTextures[i]; + const { width, height } = atlasTextureDimensions[sheet]; + + tileCountBeforeSheet += ((width / 8) * (height / 8)); + } + + //Tile index 0 is 'no tile' in map files so we need to increment by 1 + const result = tileCountBeforeSheet + tileIndexInSource + 1; + + return result; + }, + //Used to send to clients getClientConfig: function (msg) { msg.callback(config); From 6f8e57621f4e84a442e15ea8faea651507d89f1a Mon Sep 17 00:00:00 2001 From: Shaun Date: Wed, 3 Jan 2024 11:30:49 +0200 Subject: [PATCH 14/20] removed unused code in ui/stash and allowed dialogue methods to be async --- src/client/ui/templates/stash/stash.js | 12 ------------ src/server/components/dialogue.js | 14 ++++++++------ 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/client/ui/templates/stash/stash.js b/src/client/ui/templates/stash/stash.js index 3265b01e..7b60bb62 100644 --- a/src/client/ui/templates/stash/stash.js +++ b/src/client/ui/templates/stash/stash.js @@ -112,18 +112,6 @@ define([ events.emit('onShowItemTooltip', item, ttPos, true); }, - onClick: function (el, item) { - client.request({ - cpn: 'player', - method: 'performAction', - data: { - cpn: 'equipment', - method: 'equip', - data: item.id - } - }); - }, - onGetStashItems: function (items) { this.items = items; diff --git a/src/server/components/dialogue.js b/src/server/components/dialogue.js index 5deb2cf1..b1d16b7e 100644 --- a/src/server/components/dialogue.js +++ b/src/server/components/dialogue.js @@ -15,7 +15,7 @@ module.exports = { this.trigger.destroyed = true; }, - talk: function (msg) { + talk: async function (msg) { if (!msg) return false; @@ -41,7 +41,7 @@ module.exports = { if ((target.trade) && (target.trade.faction)) this.obj.reputation.discoverFaction(target.trade.faction.id); - let state = target.dialogue.getState(this.obj, msg.state); + let state = await target.dialogue.getState(this.obj, msg.state); if (!state) { this.obj.syncer.set(true, 'dialogue', 'state', null); return false; @@ -54,7 +54,8 @@ module.exports = { this.obj.syncer.set(true, 'dialogue', 'state', null); }, - getState: function (sourceObj, state = 1) { + /* eslint-disable-next-line max-lines-per-function */ + getState: async function (sourceObj, state = 1) { let result = null; if ((state + '').indexOf('.') > -1) { let config = this.states[(state + '').split('.')[0]]; @@ -93,8 +94,9 @@ module.exports = { if (stateConfig.goto) { if (result) - return this.getState(sourceObj, stateConfig.goto.success); - return this.getState(sourceObj, stateConfig.goto.failure); + return await this.getState(sourceObj, stateConfig.goto.success); + + return await this.getState(sourceObj, stateConfig.goto.failure); } if (result) { useMsg = extend([], useMsg); @@ -102,7 +104,7 @@ module.exports = { } else return null; } else if (stateConfig.method) { - let methodResult = stateConfig.method.call(this.obj, sourceObj); + let methodResult = await stateConfig.method.call(this.obj, sourceObj); if (methodResult) { useMsg = extend([], useMsg); useMsg[0].msg = methodResult; From 6c38100f6948503b371ca2a5d47b94a22b75ab09 Mon Sep 17 00:00:00 2001 From: Shaun Date: Sun, 14 Jan 2024 09:29:54 +0200 Subject: [PATCH 15/20] work --- src/client/ui/templates/inventory/inventory.js | 10 +++++++++- src/server/db/ioRethink.js | 10 ++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/client/ui/templates/inventory/inventory.js b/src/client/ui/templates/inventory/inventory.js index 912459a1..c1811887 100644 --- a/src/client/ui/templates/inventory/inventory.js +++ b/src/client/ui/templates/inventory/inventory.js @@ -358,8 +358,16 @@ define([ if (isMobile) this.hideTooltip(null, this.hoverItem); + const eBeforeShowItemContextMenu = { + sourceUi: 'inventory', + item: this.hoverItem, + ctxConfig + }; + + events.emit('beforeShowItemContextMenu', eBeforeShowItemContextMenu); + if (ctxConfig.length > 0) - events.emit('onContextMenu', ctxConfig, e); + events.emit('onContextMenu', eBeforeShowItemContextMenu.ctxConfig, e); e.preventDefault(); return false; diff --git a/src/server/db/ioRethink.js b/src/server/db/ioRethink.js index e01fdc51..35c4130a 100644 --- a/src/server/db/ioRethink.js +++ b/src/server/db/ioRethink.js @@ -195,6 +195,16 @@ module.exports = { .run(); }, + deleteFilterAsync: async function ({ + table, + filter + }) { + await r.table(table) + .filter(filter) + .delete() + .run(); + }, + subscribe: function (table) { return r.table(table) .changes() From 4ea4a03ddf0f7ed1f924d2d31b96dc65045830f5 Mon Sep 17 00:00:00 2001 From: Big Bad Waffle Date: Sun, 14 Jan 2024 07:32:03 +0000 Subject: [PATCH 16/20] Resolve "Crews" --- src/client/ui/templates/inventory/inventory.js | 10 +++++++++- src/client/ui/templates/stash/stash.js | 12 ------------ src/server/components/dialogue.js | 14 ++++++++------ src/server/db/ioRethink.js | 10 ++++++++++ 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/client/ui/templates/inventory/inventory.js b/src/client/ui/templates/inventory/inventory.js index 912459a1..c1811887 100644 --- a/src/client/ui/templates/inventory/inventory.js +++ b/src/client/ui/templates/inventory/inventory.js @@ -358,8 +358,16 @@ define([ if (isMobile) this.hideTooltip(null, this.hoverItem); + const eBeforeShowItemContextMenu = { + sourceUi: 'inventory', + item: this.hoverItem, + ctxConfig + }; + + events.emit('beforeShowItemContextMenu', eBeforeShowItemContextMenu); + if (ctxConfig.length > 0) - events.emit('onContextMenu', ctxConfig, e); + events.emit('onContextMenu', eBeforeShowItemContextMenu.ctxConfig, e); e.preventDefault(); return false; diff --git a/src/client/ui/templates/stash/stash.js b/src/client/ui/templates/stash/stash.js index 3265b01e..7b60bb62 100644 --- a/src/client/ui/templates/stash/stash.js +++ b/src/client/ui/templates/stash/stash.js @@ -112,18 +112,6 @@ define([ events.emit('onShowItemTooltip', item, ttPos, true); }, - onClick: function (el, item) { - client.request({ - cpn: 'player', - method: 'performAction', - data: { - cpn: 'equipment', - method: 'equip', - data: item.id - } - }); - }, - onGetStashItems: function (items) { this.items = items; diff --git a/src/server/components/dialogue.js b/src/server/components/dialogue.js index 5deb2cf1..b1d16b7e 100644 --- a/src/server/components/dialogue.js +++ b/src/server/components/dialogue.js @@ -15,7 +15,7 @@ module.exports = { this.trigger.destroyed = true; }, - talk: function (msg) { + talk: async function (msg) { if (!msg) return false; @@ -41,7 +41,7 @@ module.exports = { if ((target.trade) && (target.trade.faction)) this.obj.reputation.discoverFaction(target.trade.faction.id); - let state = target.dialogue.getState(this.obj, msg.state); + let state = await target.dialogue.getState(this.obj, msg.state); if (!state) { this.obj.syncer.set(true, 'dialogue', 'state', null); return false; @@ -54,7 +54,8 @@ module.exports = { this.obj.syncer.set(true, 'dialogue', 'state', null); }, - getState: function (sourceObj, state = 1) { + /* eslint-disable-next-line max-lines-per-function */ + getState: async function (sourceObj, state = 1) { let result = null; if ((state + '').indexOf('.') > -1) { let config = this.states[(state + '').split('.')[0]]; @@ -93,8 +94,9 @@ module.exports = { if (stateConfig.goto) { if (result) - return this.getState(sourceObj, stateConfig.goto.success); - return this.getState(sourceObj, stateConfig.goto.failure); + return await this.getState(sourceObj, stateConfig.goto.success); + + return await this.getState(sourceObj, stateConfig.goto.failure); } if (result) { useMsg = extend([], useMsg); @@ -102,7 +104,7 @@ module.exports = { } else return null; } else if (stateConfig.method) { - let methodResult = stateConfig.method.call(this.obj, sourceObj); + let methodResult = await stateConfig.method.call(this.obj, sourceObj); if (methodResult) { useMsg = extend([], useMsg); useMsg[0].msg = methodResult; diff --git a/src/server/db/ioRethink.js b/src/server/db/ioRethink.js index e01fdc51..35c4130a 100644 --- a/src/server/db/ioRethink.js +++ b/src/server/db/ioRethink.js @@ -195,6 +195,16 @@ module.exports = { .run(); }, + deleteFilterAsync: async function ({ + table, + filter + }) { + await r.table(table) + .filter(filter) + .delete() + .run(); + }, + subscribe: function (table) { return r.table(table) .changes() From e69f4d8cae2096e91d20c8cd1797073ac2545773 Mon Sep 17 00:00:00 2001 From: Shaun Date: Sat, 27 Jan 2024 12:21:35 +0200 Subject: [PATCH 17/20] Showing db error messages in the console --- src/server/db/ioRethink.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/server/db/ioRethink.js b/src/server/db/ioRethink.js index 35c4130a..b10dee92 100644 --- a/src/server/db/ioRethink.js +++ b/src/server/db/ioRethink.js @@ -150,7 +150,7 @@ module.exports = { }) .run(); } catch (e) { - this.logError({ + await this.logError({ sourceModule: 'ioRethink', sourceMethod: 'setAsync', error: e, @@ -173,7 +173,7 @@ module.exports = { .insert(value, { conflict }) .run(); } catch (e) { - this.logError({ + await this.logError({ sourceModule: 'ioRethink', sourceMethod: 'setFlat', error: e, @@ -233,7 +233,7 @@ module.exports = { }) .run(); } catch (e) { - this.logError({ + await this.logError({ sourceModule: 'ioRethink', sourceMethod: 'append', error: e, @@ -279,5 +279,7 @@ module.exports = { }); } else process.exit(); + + throw new Error('Forcing crash'); } }; From a314308a0f4b1f6381884f630768555375b02b55 Mon Sep 17 00:00:00 2001 From: Shaun Date: Sat, 27 Jan 2024 15:52:19 +0200 Subject: [PATCH 18/20] modding #2014: new server event 'beforeDeleteCharacter' --- .../ui/templates/characters/characters.js | 30 +++++++++++++------ src/server/components/auth.js | 23 +++++++++++++- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/src/client/ui/templates/characters/characters.js b/src/client/ui/templates/characters/characters.js index cb236b13..c1fe5ce3 100644 --- a/src/client/ui/templates/characters/characters.js +++ b/src/client/ui/templates/characters/characters.js @@ -222,7 +222,7 @@ define([ this.find('.message').html(msg); }, - onDeleteClick: function () { + onDeleteClick: async function () { if (!this.selected) return; @@ -242,22 +242,34 @@ define([ this.el.addClass('disabled'); - client.request({ - cpn: 'auth', - method: 'deleteCharacter', - data: { - name: this.selected - }, - callback: this.onGetCharacters.bind(this) + const result = await new Promise(res => { + client.request({ + cpn: 'auth', + method: 'deleteCharacter', + data: { + name: this.selected + }, + callback: res + }); }); + + if (!result.success) { + this.setMessage(result.msg); + this.el.removeClass('disabled'); + + return; + } + + this.onGetCharacters(result.characterList); }, onDeleteReset: function () { - this.setMessage(''); this.deleteCount = 0; this.find('.btnDelete') .removeClass('deleting') .html('delete'); + + setTimeout(this.setMessage.bind(this, ''), 5000); } }; }); diff --git a/src/server/components/auth.js b/src/server/components/auth.js index a48f462e..62fb29cb 100644 --- a/src/server/components/auth.js +++ b/src/server/components/auth.js @@ -547,6 +547,24 @@ module.exports = { return; } + const msgBeforeDeleteCharacter = { + obj: this, + name: data.name, + success: true, + msg: null + }; + + await eventEmitter.emit('beforeDeleteCharacter', msgBeforeDeleteCharacter); + + if (!msgBeforeDeleteCharacter.success) { + msg.callback({ + success: false, + msg: msgBeforeDeleteCharacter.msg + }); + + return; + } + await io.deleteAsync({ key: data.name, table: 'character' @@ -576,7 +594,10 @@ module.exports = { level: leaderboard.getLevel(c.name ? c.name : c) })); - msg.callback(result); + msg.callback({ + success: true, + characterList: result + }); }, permadie: function () { From e61cd864e68ab7402c4cbd700d6b2dc5abcd68dd Mon Sep 17 00:00:00 2001 From: Shaun Date: Sat, 27 Jan 2024 15:53:25 +0200 Subject: [PATCH 19/20] bug #2015: the context menu no longer extends over the window boundary --- src/client/ui/templates/context/context.js | 2 ++ src/client/ui/templates/context/styles.less | 1 + 2 files changed, 3 insertions(+) diff --git a/src/client/ui/templates/context/context.js b/src/client/ui/templates/context/context.js index 530c6dda..083647a4 100644 --- a/src/client/ui/templates/context/context.js +++ b/src/client/ui/templates/context/context.js @@ -68,6 +68,8 @@ define([ pos.top = e.detail.clientY; } + pos['max-height'] = window.innerHeight - pos.top - 10; + this.el .css(pos) .show(); diff --git a/src/client/ui/templates/context/styles.less b/src/client/ui/templates/context/styles.less index 2bb0f4ad..dd040b6d 100644 --- a/src/client/ui/templates/context/styles.less +++ b/src/client/ui/templates/context/styles.less @@ -11,6 +11,7 @@ color: @white; text-align: center; line-height: 15px; + overflow-y: auto; .list { width: 100%; From e1977421190192ac904f7e4fdacf1e71a71b16a3 Mon Sep 17 00:00:00 2001 From: Shaun Date: Sat, 10 Feb 2024 10:22:20 +0200 Subject: [PATCH 20/20] chore: bumped version to 0.14.0 --- src/client/package.json | 2 +- src/client/ui/templates/login/template.html | 4 ++-- src/package.json | 2 +- src/server/config/serverConfig.js | 2 +- src/server/package.json | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/client/package.json b/src/client/package.json index f33e7a33..69602d68 100644 --- a/src/client/package.json +++ b/src/client/package.json @@ -1,6 +1,6 @@ { "name": "isleward_client", - "version": "0.13.0", + "version": "0.14.0", "description": "isleward", "devDependencies": { diff --git a/src/client/ui/templates/login/template.html b/src/client/ui/templates/login/template.html index 8635ed1e..35b2d960 100644 --- a/src/client/ui/templates/login/template.html +++ b/src/client/ui/templates/login/template.html @@ -11,11 +11,11 @@
-
[ Latest Release Notes ]
+
[ Latest Release Notes ]
Pledge on Patreon
Donate on Paypal
Access the Wiki
-
v0.13.0
+
v0.14.0
diff --git a/src/package.json b/src/package.json index 16b7c980..3cf80368 100644 --- a/src/package.json +++ b/src/package.json @@ -1,6 +1,6 @@ { "name": "isleward", - "version": "0.13.0", + "version": "0.14.0", "description": "isleward", "dependencies": { diff --git a/src/server/config/serverConfig.js b/src/server/config/serverConfig.js index ae549066..8c890be5 100644 --- a/src/server/config/serverConfig.js +++ b/src/server/config/serverConfig.js @@ -1,7 +1,7 @@ /* eslint-disable no-process-env */ module.exports = { - version: '0.13.0', + version: '0.14.0', port: 4000, startupMessage: 'Server: ready', diff --git a/src/server/package.json b/src/server/package.json index 1949ddbc..ee01a6e2 100644 --- a/src/server/package.json +++ b/src/server/package.json @@ -1,6 +1,6 @@ { "name": "isleward_server", - "version": "0.13.0", + "version": "0.14.0", "description": "isleward", "dependencies": { "axios": "^0.22.0",