From 26941c60b246333733d1ef316636b819783bfbcf Mon Sep 17 00:00:00 2001 From: Metritutus <324345+Metritutus@users.noreply.github.com> Date: Sun, 22 Sep 2024 22:21:41 +0100 Subject: [PATCH] # Client updates: * Updated 128x128_star_black_hole.svg and 128x128_star_scannable_binary.svg to be styled using a CSS class so that their styles can be overridden. * Added 128x128_star_pulsar.svg. * Added SvgWrapper component to allow SVG files to be rendered directly to the DOM (and thus be affected by CSS classes in the DOM) instead of loading them in their own shadow DOMs. * Added StarIcon component for displaying star icons in the UI consistently. * Added SortInfo class. * Added GridHelper class. * Updated tables: - Consolidated sorting functionality and added the capability for tables to be sorted by multiple values, eg sort by specialist name and then by star name. - Added capability to be able to sort by more columns, eg specialists and players. - Fixed some tables sorting by ship count when clicking on the Name header instead of the Name. - Added various tooltips. - Tables now respond to time machine ot tick changes. - Split resources are now shown as separate, sportable columns. - Infrastructure values now have proper columns. - Added Warp Gate column to Stars table. - Fixed player icon shape always being a circle on some tables. - Updated Technology table to show colours indicating whether the current player's technology is the best or worst, matching how it behaves on the player modal Technology section. - Fixed Empires table not having colours for Economy, Industry and Science values. - Added Star Types table. * Updated MainMenu component to also load player roles when mounted. * Updated reloadGameCheck() in Game component: - to emit a new onGameTick event when the game ticks. - to play a sound and show a toast message when a new tick occurs, even if the player is viewing a historic tick. * Updated TickSelector component: - to move to the latest tick when a new tick occurs, if the player was previously viewing the latest tick. - to have a minimum tick matching the minimum tick stored in the time machine (ie if it doesn't exist in the time machine, it won't be selectable). * Renamed calculateTicksToNextShip() method in gameHelper to calculateTicksToBonusShip(), and updated its functionality to calculate the number of ticks to the bonus ship (which will just be the next ship if the star is producing less than 1 ship per tick). * Updated StarDetail component to show ticks to bonus ship instead of next ship if the star is producing more than 1 ship per tick. * Fixed client-side only issue where science infrastructure upgrades did not reflecting whether or not a Research Station existed until the page was refreshed. # Server updates: * Added getHistoryMinimumTick() method to HistoryService. * Updated Repository class: - Added types. - Fixed returning awaited promise results from Promise methods. - Added missing await to countAll() method. * Updated getUserCount() method in UserService to fix missing await in async method. * Added timeMachineMinimumTick property to Game interface. * Added ownerByPlayer property to MapObject interface. * Updated GameGalaxyService: - Updated getGalaxy() method to set new timeMachineMinimumTick property. - Updated _setStarInfoBasic(), _setStarInfoDetailed() and _setCarrierInfoDetailed() methods to set new ownerByPlayer property. --- client/package-lock.json | 9 + client/package.json | 1 + .../map-objects/128x128_star_black_hole.svg | 11 +- .../128x128_star_scannable_binary.svg | 21 ++- .../src/assets/stars/128x128_star_pulsar.svg | 15 ++ client/src/main.js | 4 +- client/src/services/data/sortInfo.js | 40 +++++ client/src/services/gameHelper.js | 11 +- client/src/services/gridHelper.js | 61 +++++++ client/src/store.js | 12 +- client/src/views/MainMenu.vue | 5 +- client/src/views/components/SvgWrapper.vue | 53 ++++++ client/src/views/game/Game.vue | 11 +- .../game/components/galaxy/CapitalRow.vue | 18 +- .../game/components/galaxy/CapitalsTable.vue | 130 +++++--------- .../game/components/galaxy/CarrierRow.vue | 9 +- .../game/components/galaxy/CarriersTable.vue | 111 +++++------- .../game/components/galaxy/EmpireRow.vue | 6 +- .../game/components/galaxy/EmpiresTable.vue | 122 ++++++------- .../views/game/components/galaxy/Galaxy.vue | 9 + .../components/galaxy/NaturalResourcesRow.vue | 16 +- .../galaxy/NaturalResourcesTable.vue | 134 ++++++-------- .../views/game/components/galaxy/ShipRow.vue | 10 +- .../game/components/galaxy/ShipsTable.vue | 128 +++++++------ .../views/game/components/galaxy/StarRow.vue | 12 +- .../game/components/galaxy/StarTypesRow.vue | 62 +++++++ .../game/components/galaxy/StarTypesTable.vue | 150 ++++++++++++++++ .../game/components/galaxy/StarsTable.vue | 158 ++++++---------- .../game/components/galaxy/TechnologyRow.vue | 45 +++-- .../components/galaxy/TechnologyTable.vue | 169 ++++++++---------- .../game/components/menu/TickSelector.vue | 14 +- ...BulkInfrastructureUpgradeScheduleTable.vue | 66 ++----- .../BulkInfrastructureUpgradeStarTable.vue | 117 +++++------- .../BulkInfrastructureUpgradeStarTableRow.vue | 6 +- .../views/game/components/star/StarDetail.vue | 67 ++++--- .../views/game/components/star/StarIcon.vue | 115 ++++++++++++ .../game/components/star/StarResources.vue | 65 +++++-- server/db/models/Game.ts | 4 +- server/package-lock.json | 2 +- server/package.json | 2 +- server/services/carrier.ts | 2 + server/services/gameCreate.ts | 1 + server/services/gameGalaxy.ts | 12 ++ server/services/history.ts | 5 + server/services/repository.ts | 44 +++-- server/services/star.ts | 7 +- server/services/types/Game.ts | 1 + server/services/types/Map.ts | 2 + server/services/user.ts | 2 +- 49 files changed, 1247 insertions(+), 830 deletions(-) create mode 100644 client/src/assets/stars/128x128_star_pulsar.svg create mode 100644 client/src/services/data/sortInfo.js create mode 100644 client/src/services/gridHelper.js create mode 100644 client/src/views/components/SvgWrapper.vue create mode 100644 client/src/views/game/components/galaxy/StarTypesRow.vue create mode 100644 client/src/views/game/components/galaxy/StarTypesTable.vue create mode 100644 client/src/views/game/components/star/StarIcon.vue diff --git a/client/package-lock.json b/client/package-lock.json index 91263aff2..db8888d8b 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -25,6 +25,7 @@ "voronoi": "^1.0.0", "vue": "^2.6.12", "vue-chartjs": "^3.5.1", + "vue-fragment": "^1.6.0", "vue-recaptcha": "^1.3.0", "vue-router": "^3.5.1", "vue-socket.io": "^3.0.10", @@ -14497,6 +14498,14 @@ "chart.js": ">= 2.5" } }, + "node_modules/vue-fragment": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/vue-fragment/-/vue-fragment-1.6.0.tgz", + "integrity": "sha512-a5T8ZZZK/EQzgVShEl374HbobUJ0a7v12BzOzS6Z/wd/5EE/5SffcyHC+7bf9hP3L7Yc0hhY/GhMdwFQ25O/8A==", + "peerDependencies": { + "vue": "^2.5.16" + } + }, "node_modules/vue-hot-reload-api": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", diff --git a/client/package.json b/client/package.json index 33217cfc9..be7172fae 100644 --- a/client/package.json +++ b/client/package.json @@ -25,6 +25,7 @@ "voronoi": "^1.0.0", "vue": "^2.6.12", "vue-chartjs": "^3.5.1", + "vue-fragment": "^1.6.0", "vue-recaptcha": "^1.3.0", "vue-router": "^3.5.1", "vue-socket.io": "^3.0.10", diff --git a/client/src/assets/map-objects/128x128_star_black_hole.svg b/client/src/assets/map-objects/128x128_star_black_hole.svg index e45f43f9e..409e4dcb6 100644 --- a/client/src/assets/map-objects/128x128_star_black_hole.svg +++ b/client/src/assets/map-objects/128x128_star_black_hole.svg @@ -1,4 +1,11 @@ - + - + + \ No newline at end of file diff --git a/client/src/assets/map-objects/128x128_star_scannable_binary.svg b/client/src/assets/map-objects/128x128_star_scannable_binary.svg index e799c018e..d7ac133fc 100644 --- a/client/src/assets/map-objects/128x128_star_scannable_binary.svg +++ b/client/src/assets/map-objects/128x128_star_scannable_binary.svg @@ -1,9 +1,24 @@ - + + - - + + \ No newline at end of file diff --git a/client/src/assets/stars/128x128_star_pulsar.svg b/client/src/assets/stars/128x128_star_pulsar.svg new file mode 100644 index 000000000..b16fa087e --- /dev/null +++ b/client/src/assets/stars/128x128_star_pulsar.svg @@ -0,0 +1,15 @@ + + + + + + + + + \ No newline at end of file diff --git a/client/src/main.js b/client/src/main.js index f14bbc4a1..3f6af087c 100644 --- a/client/src/main.js +++ b/client/src/main.js @@ -4,7 +4,7 @@ import Toasted from 'vue-toasted' import App from './App.vue' import router from './router' import store from './store' - +import { Plugin as FragmentPlugin } from 'vue-fragment' import $ from 'jquery' import 'pixi.js-legacy' import 'pixi-viewport' @@ -80,6 +80,8 @@ Vue.directive('tooltip', function(el, binding) { }) }) +Vue.use(FragmentPlugin); + new Vue({ router, store, diff --git a/client/src/services/data/sortInfo.js b/client/src/services/data/sortInfo.js new file mode 100644 index 000000000..e0ffc40f8 --- /dev/null +++ b/client/src/services/data/sortInfo.js @@ -0,0 +1,40 @@ +export default class SortInfo { + propertyPaths; + sortAscending; + + constructor(propertyPaths, sortAscending) { + this.propertyPaths = propertyPaths ?? null; + this.sortAscending = sortAscending ?? true; + } + + swapSort(propertyPaths) { + // If sorting by a new column, reset the sort. + if (JSON.stringify(this.propertyPaths) !== JSON.stringify(propertyPaths)) { + this.propertyPaths = !Array.isArray(propertyPaths[0]) ? [propertyPaths] : propertyPaths; + this.sortAscending = true + } else { + // Otherwise if we are sorting by the same column, flip the sort direction. + this.sortAscending = !this.sortAscending + } + } + + static fromJSON(jsonSortInfo, defaultSortInfo) { + let parsedSortInfo = null; + + try { + parsedSortInfo = jsonSortInfo != undefined ? JSON.parse(jsonSortInfo) : null; + } + catch (e) { + console.warn(`SortInfo.fromJSON failed to parse the following JSON: ${jsonSortInfo}`); + console.warn(e); + } + + // Fall back to defaults if we have them! + if (parsedSortInfo?.propertyPaths != null && parsedSortInfo?.sortAscending != null) { + return new SortInfo(parsedSortInfo?.propertyPaths, parsedSortInfo?.sortAscending); + } + else { + return new SortInfo(defaultSortInfo?.propertyPaths, defaultSortInfo?.sortAscending); + } + } +} diff --git a/client/src/services/gameHelper.js b/client/src/services/gameHelper.js index 258385ea0..ff49e5c90 100644 --- a/client/src/services/gameHelper.js +++ b/client/src/services/gameHelper.js @@ -1072,7 +1072,7 @@ class GameHelper { userPlayer.stats.totalIndustry++ break; case 'science': - userPlayer.stats.totalScience += game.constants.research.sciencePointMultiplier + userPlayer.stats.totalScience += game.constants.research.sciencePointMultiplier * (star.specialistId === 11 ? 2 : 1); // Research Station break; } @@ -1256,18 +1256,19 @@ class GameHelper { return game.galaxy.teams.find(t => t._id === teamId); } - calculateTicksToNextShip(shipsActual, manufacturing) { + calculateTicksToBonusShip(shipsActual, manufacturing) { if (manufacturing <= 0) { return null } - const next = Math.floor(shipsActual + 1); - let current = shipsActual; + const next = 1; + const partialManufacturing = manufacturing - Math.floor(manufacturing); + let current = shipsActual - Math.floor(shipsActual); let count = 0; while (current < next) { count++; - current += manufacturing; + current += partialManufacturing; } return count; diff --git a/client/src/services/gridHelper.js b/client/src/services/gridHelper.js new file mode 100644 index 000000000..051c01615 --- /dev/null +++ b/client/src/services/gridHelper.js @@ -0,0 +1,61 @@ +class GridHelper { + getNestedObject(nestedObj, pathArr) { + if (!Array.isArray(pathArr)) { + pathArr = pathArr.split(',') + } + + return pathArr.reduce((obj, key) => + (obj && obj[key] !== undefined) ? obj[key] : null, nestedObj) + } + + dynamicSort(data, sortInfo) { + if (sortInfo?.propertyPaths != null) { + data = data.sort((a, b) => this.dynamicCompare(a, b, sortInfo)); + } + + return data; + } + + dynamicCompare(a, b, sortInfo) { + let result = 0; + + for (let propertyPath of sortInfo.propertyPaths) { + let bo = this.getNestedObject(b, propertyPath); + let ao = this.getNestedObject(a, propertyPath); + + result = this.compare(ao, bo); + + if (result !== 0) { + break; + } + } + + return sortInfo.sortAscending ? result : -result; + } + + compare(a, b) { + if (a === b) { + return 0; + } + // Sort null values after everything else + else if (a === null) { + return 1; + } + else if (b === null) { + return -1; + } + else { + + let result = a < b ? -1 : 1; + + // Invert booleans - we want true values to come first. + if (typeof a === 'boolean' && typeof b === 'boolean') { + result = -result; + } + + return result; + } + } +} + +export default new GridHelper() diff --git a/client/src/store.js b/client/src/store.js index 4375d08c8..c3fe1df5e 100644 --- a/client/src/store.js +++ b/client/src/store.js @@ -267,10 +267,16 @@ export default new Vuex.Store({ }, gameStarBulkUpgraded (state, data) { - let player = GameHelper.getUserPlayer(state.game) + let player = GameHelper.getUserPlayer(state.game); + + let newScience = 0; data.stars.forEach(s => { - let star = GameHelper.getStarById(state.game, s.starId) + let star = GameHelper.getStarById(state.game, s.starId); + + if (data.infrastructureType === 'science') { + newScience += s.infrastructure * (star.specialistId === 11 ? 2 : 1); // Research Station + } star.infrastructure[data.infrastructureType] = s.infrastructure @@ -307,7 +313,7 @@ export default new Vuex.Store({ player.stats.totalIndustry += data.upgraded break; case 'science': - player.stats.totalScience += (data.upgraded * state.game.constants.research.sciencePointMultiplier) + player.stats.totalScience += (newScience * state.game.constants.research.sciencePointMultiplier) break; } }, diff --git a/client/src/views/MainMenu.vue b/client/src/views/MainMenu.vue index 511ff4af4..d7ccc78d1 100644 --- a/client/src/views/MainMenu.vue +++ b/client/src/views/MainMenu.vue @@ -154,7 +154,7 @@ export default { } }, mounted () { - this.loadAchievements() + this.loadData() }, methods: { async logout () { @@ -172,13 +172,14 @@ export default { router.push({ name: 'home' }) }, - async loadAchievements () { + async loadData () { try { let response = await userService.getMyUserInfo() this.user = response.data this.achievements = response.data.achievements + this.$store.commit('setRoles', response.data.roles) this.$store.commit('setUserCredits', response.data.credits) this.$store.commit('setUserIsEstablishedPlayer', response.data.isEstablishedPlayer) } catch (err) { diff --git a/client/src/views/components/SvgWrapper.vue b/client/src/views/components/SvgWrapper.vue new file mode 100644 index 000000000..4cb6cd95d --- /dev/null +++ b/client/src/views/components/SvgWrapper.vue @@ -0,0 +1,53 @@ + + + + + diff --git a/client/src/views/game/Game.vue b/client/src/views/game/Game.vue index e1e74bc3c..e4b1549d7 100644 --- a/client/src/views/game/Game.vue +++ b/client/src/views/game/Game.vue @@ -41,6 +41,7 @@ import moment from 'moment' import gameHelper from '../../services/gameHelper' import authService from '../../services/api/auth' import ColourOverrideDialog from "./components/player/ColourOverrideDialog.vue"; +import eventBus from '../../eventBus' export default { components: { @@ -394,12 +395,14 @@ export default { this.$store.commit('setTick', response.data.state.tick) this.$store.commit('setProductionTick', response.data.state.productionTick) } else { - await this.reloadGame() + await this.reloadGame(); + } - this.$toasted.show(`The game has ticked. Cycle ${response.data.state.productionTick}, Tick ${response.data.state.tick}.`, { type: 'success' }) + eventBus.$emit('onGameTick'); + + this.$toasted.show(`The game has ticked. Cycle ${response.data.state.productionTick}, Tick ${response.data.state.tick}.`, { type: 'success' }); - AudioService.download() - } + AudioService.download(); } } } catch (e) { diff --git a/client/src/views/game/components/galaxy/CapitalRow.vue b/client/src/views/game/components/galaxy/CapitalRow.vue index c7a480161..c5be62dfc 100644 --- a/client/src/views/game/components/galaxy/CapitalRow.vue +++ b/client/src/views/game/components/galaxy/CapitalRow.vue @@ -1,24 +1,29 @@ + + {{star.name}} {{star.infrastructure.economy}} + + {{star.infrastructure.industry}} + + {{star.infrastructure.science}} - + diff --git a/client/src/views/game/components/galaxy/CapitalsTable.vue b/client/src/views/game/components/galaxy/CapitalsTable.vue index 8123d23c9..d3a529fe5 100644 --- a/client/src/views/game/components/galaxy/CapitalsTable.vue +++ b/client/src/views/game/components/galaxy/CapitalsTable.vue @@ -2,7 +2,7 @@
- @@ -17,135 +17,99 @@ - - + + - - + + + -
NameName - - - - - + + + + + + + +
-

No stars to display.

+

No stars to display.

diff --git a/client/src/views/game/components/galaxy/CarriersTable.vue b/client/src/views/game/components/galaxy/CarriersTable.vue index d1b84e17e..107b808de 100644 --- a/client/src/views/game/components/galaxy/CarriersTable.vue +++ b/client/src/views/game/components/galaxy/CarriersTable.vue @@ -2,7 +2,7 @@
- @@ -17,117 +17,96 @@ - + - - - + + + - - + + - +
Name + + ETATotalETATotal
-

No carriers to display.

+

No carriers to display.

diff --git a/client/src/views/game/components/galaxy/NaturalResourcesTable.vue b/client/src/views/game/components/galaxy/NaturalResourcesTable.vue index 6b5300efb..f118ef26f 100644 --- a/client/src/views/game/components/galaxy/NaturalResourcesTable.vue +++ b/client/src/views/game/components/galaxy/NaturalResourcesTable.vue @@ -2,7 +2,7 @@
- @@ -17,135 +17,103 @@ - - + + - - + + + - + + + + - +
NameName - + + + + + - ResourcesResources E I S
-

No stars to display.

+

No stars to display.

diff --git a/client/src/views/game/components/galaxy/ShipsTable.vue b/client/src/views/game/components/galaxy/ShipsTable.vue index 38353c7d0..79da5a089 100644 --- a/client/src/views/game/components/galaxy/ShipsTable.vue +++ b/client/src/views/game/components/galaxy/ShipsTable.vue @@ -2,7 +2,7 @@
- @@ -17,16 +17,26 @@ - - + + - - - + + + - @@ -34,63 +44,71 @@ -

No ships to display.

+

No ships to display.

+ + diff --git a/client/src/views/game/components/galaxy/StarTypesTable.vue b/client/src/views/game/components/galaxy/StarTypesTable.vue new file mode 100644 index 000000000..5d1decb50 --- /dev/null +++ b/client/src/views/game/components/galaxy/StarTypesTable.vue @@ -0,0 +1,150 @@ + + + + + diff --git a/client/src/views/game/components/galaxy/StarsTable.vue b/client/src/views/game/components/galaxy/StarsTable.vue index 863b79015..2dae5b501 100644 --- a/client/src/views/game/components/galaxy/StarsTable.vue +++ b/client/src/views/game/components/galaxy/StarsTable.vue @@ -2,7 +2,7 @@
- @@ -10,7 +10,7 @@
-
+
Name + + + Name + + T + + + + +
- - + + - - + + - - - - + + + + + - +
NameName - - - - - + + + + + + $E$I$S + + + + $E$I$S
-

No stars to display.

+

No stars to display.

+ + diff --git a/client/src/views/game/components/star/StarResources.vue b/client/src/views/game/components/star/StarResources.vue index 52aa8f244..c83afa1cb 100644 --- a/client/src/views/game/components/star/StarResources.vue +++ b/client/src/views/game/components/star/StarResources.vue @@ -1,31 +1,66 @@