Adapt system and planet managers to use common managers

This commit is contained in:
Aelita4 2024-11-14 14:43:34 +01:00
parent d0993a427f
commit 40499415be
Signed by: Aelita4
GPG Key ID: E44490C2025906C1
29 changed files with 606 additions and 302 deletions

View File

@ -3,7 +3,7 @@ import { ObjectId } from 'mongodb';
import { getHighestWeightedLanguage, getLocales, getName } from '../lib/utils/langDriver'; import { getHighestWeightedLanguage, getLocales, getName } from '../lib/utils/langDriver';
import { getAllResources } from '../lib/db/resources'; import { getAllResources } from '../lib/db/resources';
import locationManager from '../lib/classes/managers/LocationManager'; import locationManager from '../lib/classes/managers/LocationManager';
import { Resource } from '../lib/classes/managers/ResourceManager'; import { Resource } from '../lib/classes/managers/abstract/ResourceManager';
const resourceTypes = await getAllResources(); const resourceTypes = await getAllResources();
@ -46,7 +46,7 @@ for(const key of planet.resources.resources) {
</div> </div>
<div class="resourcebar-item-tooltip"> <div class="resourcebar-item-tooltip">
<div class="resourcebar-item-tooltip-name">{getName(lang, 'general', 'avaliable')} - <span class="resourcebar-item-tooltip-avaliable">{Math.floor(res.amount).toString()}</span></div> <div class="resourcebar-item-tooltip-name">{getName(lang, 'general', 'avaliable')} - <span class="resourcebar-item-tooltip-avaliable">{Math.floor(res.amount).toString()}</span></div>
<div class="resourcebar-item-tooltip-name">{getName(lang, 'general', 'production')} - <span class="resourcebar-item-tooltip-production">{res.perHourMiningRate.toString()}</span></div> <div class="resourcebar-item-tooltip-name">{getName(lang, 'general', 'production')} - <span class="resourcebar-item-tooltip-production">{res.perHourMiningRate?.toString() ?? "0"}</span></div>
<div class="resourcebar-item-tooltip-name">{getName(lang, 'general', 'capacity')} - <span class="resourcebar-item-tooltip-capacity">{'21372137'}</span></div> <div class="resourcebar-item-tooltip-name">{getName(lang, 'general', 'capacity')} - <span class="resourcebar-item-tooltip-capacity">{'21372137'}</span></div>
</div> </div>
</div> </div>

View File

@ -49,7 +49,7 @@ export default class Building {
} }
// research // research
const playerResearch = this.manager.planet.manager.owner.research; const playerResearch = this.manager.planet.system.data.ownedBy.research;
let playerResearchCanBuild = { canBuild: true, missing: "" }; let playerResearchCanBuild = { canBuild: true, missing: "" };
for(const researchReq of this.data.requirements.research) { for(const researchReq of this.data.requirements.research) {
if((playerResearch.research.find((research) => research.id === researchReq.id)?.level ?? 0) < researchReq.level) { if((playerResearch.research.find((research) => research.id === researchReq.id)?.level ?? 0) < researchReq.level) {

View File

@ -1,5 +1,6 @@
import DBShip from "../../types/db/DBShip"; import DBShip from "../../types/db/DBShip";
import ShipManager from "./managers/ShipManager"; import SystemManager from "./managers/SystemManager";
import ShipManager from "./managers/abstract/ShipManager";
export default class Ship { export default class Ship {
manager: ShipManager; manager: ShipManager;
@ -13,7 +14,7 @@ export default class Ship {
} }
async checkRequiredResources(): Promise<boolean> { async checkRequiredResources(): Promise<boolean> {
const resources = await this.manager.planet.resources.calculateCurrentAvailableResources(); const resources = await this.manager.manager.resources.calculateCurrentAvailableResources();
const requirements = this.data.requirements.resources; const requirements = this.data.requirements.resources;
@ -33,21 +34,36 @@ export default class Ship {
} }
async checkRequirements(): Promise<{ canBuild: boolean, error: string }> { async checkRequirements(): Promise<{ canBuild: boolean, error: string }> {
const playerBuildings = this.manager.planet.buildings.buildings; if(!(this.manager.manager instanceof SystemManager)) {
let playerBuildingsCanBuild = { canBuild: true, missing: "" }; const playerBuildings = this.manager.manager.buildings.buildings;
this.data.requirements.buildings.forEach((buildingReq: any) => { let playerBuildingsCanBuild = { canBuild: true, missing: "" };
if((playerBuildings.filter((building) => building.data.id === buildingReq.id)[0]?.level ?? 0) < buildingReq.level) { this.data.requirements.buildings.forEach((buildingReq: any) => {
playerBuildingsCanBuild = { canBuild: false, missing: `${buildingReq.id} level ${buildingReq.level} required, found ${playerBuildings.filter((building) => building.data.id === buildingReq.id)[0]?.level ?? 0}` }; if((playerBuildings.filter((building) => building.data.id === buildingReq.id)[0]?.level ?? 0) < buildingReq.level) {
return; playerBuildingsCanBuild = { canBuild: false, missing: `${buildingReq.id} level ${buildingReq.level} required, found ${playerBuildings.filter((building) => building.data.id === buildingReq.id)[0]?.level ?? 0}` };
return;
}
});
if(!playerBuildingsCanBuild.canBuild) return {
canBuild: false,
error: playerBuildingsCanBuild.missing
} }
}); } /*else { //TODO: check for structures requirements
if(!playerBuildingsCanBuild.canBuild) return { const structures = this.manager.manager.structures.structures;
canBuild: false, let playerStructuresCanBuild = { canBuild: true, missing: "" };
error: playerBuildingsCanBuild.missing this.data.requirements.structures.forEach((buildingReq: any) => {
} if((structures.filter((building) => building.data.id === buildingReq.id)[0]?.level ?? 0) < buildingReq.level) {
playerStructuresCanBuild = { canBuild: false, missing: `${buildingReq.id} level ${buildingReq.level} required, found ${structures.filter((structure) => structure.data.id === buildingReq.id)[0]?.level ?? 0}` };
return;
}
});
if(!playerStructuresCanBuild.canBuild) return {
canBuild: false,
error: playerStructuresCanBuild.missing
}
}*/
// research // research
const playerResearch = this.manager.planet.manager.owner.research; const playerResearch = this.manager.manager instanceof SystemManager ? this.manager.manager.data.ownedBy.research : this.manager.manager.system.data.ownedBy.research;
let playerResearchCanBuild = { canBuild: true, missing: "" }; let playerResearchCanBuild = { canBuild: true, missing: "" };
for(const researchReq of this.data.requirements.research) { for(const researchReq of this.data.requirements.research) {
if(playerResearch.research.find((research) => research.id === researchReq.id)?.level ?? 0 < researchReq.level) { if(playerResearch.research.find((research) => research.id === researchReq.id)?.level ?? 0 < researchReq.level) {

View File

@ -12,59 +12,59 @@ export default class Structure {
this.level = level; this.level = level;
} }
// async checkRequiredResources(level: number): Promise<boolean> { async checkRequiredResources(level: number): Promise<boolean> {
// const resources = await this.manager.planet.resources.calculateCurrentAvailableResources(); const resources = await this.manager.system.resources.calculateCurrentAvailableResources();
// const requirements = this.data.requirements.resources; const requirements = this.data.requirements.resources;
// let canBuild = true; let canBuild = true;
// for(let res of requirements) { for(let res of requirements) {
// const resource = resources.find(r => r.id === res.id); const resource = resources.find(r => r.id === res.id);
// if(!resource) return false; if(!resource) return false;
// const required = Math.pow(this.data.multiplier, level) * res.amount; const required = Math.pow(this.data.multiplier, level) * res.amount;
// if(resource.amount < required) { if(resource.amount < required) {
// canBuild = false; canBuild = false;
// break; break;
// } }
// } }
// return canBuild; return canBuild;
// } }
// async checkRequirements(): Promise<{ canBuild: boolean, error: string }> { async checkRequirements(): Promise<{ canBuild: boolean, error: string }> {
// const playerBuildings = this.manager.buildings; const playerStructures = this.manager.structures;
// let playerBuildingsCanBuild = { canBuild: true, missing: "" }; let playerStructuresCanBuild = { canBuild: true, missing: "" };
// this.data.requirements.buildings.forEach((buildingReq: any) => { this.data.requirements.structures.forEach((structureReq: any) => {
// if(playerBuildings.filter((building) => building.data.id === buildingReq.id)[0]?.level ?? 0 < buildingReq.level) { if(playerStructures.filter((structure) => structure.data.id === structureReq.id)[0]?.level ?? 0 < structureReq.level) {
// playerBuildingsCanBuild = { canBuild: false, missing: `${buildingReq.id} level ${buildingReq.level} required, found ${playerBuildings.filter((building) => building.data.id === buildingReq.id)[0]?.level ?? 0}` }; playerStructuresCanBuild = { canBuild: false, missing: `${structureReq.id} level ${structureReq.level} required, found ${playerStructures.filter((structure) => structure.data.id === structureReq.id)[0]?.level ?? 0}` };
// return; return;
// } }
// }); });
// if(!playerBuildingsCanBuild.canBuild) return { if(!playerStructuresCanBuild.canBuild) return {
// canBuild: false, canBuild: false,
// error: playerBuildingsCanBuild.missing error: playerStructuresCanBuild.missing
// } }
// // research // research
// const playerResearch = this.manager.planet.manager.owner.research; const playerResearch = this.manager.system.data.ownedBy.research;
// let playerResearchCanBuild = { canBuild: true, missing: "" }; let playerResearchCanBuild = { canBuild: true, missing: "" };
// for(const researchReq of this.data.requirements.research) { for(const researchReq of this.data.requirements.research) {
// if((playerResearch.research.find((research) => research.id === researchReq.id)?.level ?? 0) < researchReq.level) { if((playerResearch.research.find((research) => research.id === researchReq.id)?.level ?? 0) < researchReq.level) {
// playerResearchCanBuild = { canBuild: false, missing: `${researchReq.id} level ${researchReq.level} required, found ${playerResearch.research.find((research) => research.id === researchReq.id)?.level ?? 0}` }; playerResearchCanBuild = { canBuild: false, missing: `${researchReq.id} level ${researchReq.level} required, found ${playerResearch.research.find((research) => research.id === researchReq.id)?.level ?? 0}` };
// } }
// }; };
// if(!playerResearchCanBuild.canBuild) return { if(!playerResearchCanBuild.canBuild) return {
// canBuild: false, canBuild: false,
// error: playerResearchCanBuild.missing error: playerResearchCanBuild.missing
// } }
// return { return {
// canBuild: true, canBuild: true,
// error: "" error: ""
// } }
// } }
} }

View File

@ -3,11 +3,12 @@ import MissionType from "../../../types/MissionType";
import DBFleet from "../../../types/db/DBFleet"; import DBFleet from "../../../types/db/DBFleet";
import { updateFleet } from "../../db/fleet"; import { updateFleet } from "../../db/fleet";
import { Planet } from "./PlanetManager"; import { Planet } from "./PlanetManager";
import SystemManager, { System } from "./SystemManager";
export type Fleet = { export type Fleet = {
id: ObjectId, id: ObjectId,
source: Planet, source: Planet | SystemManager,
destination: Planet, destination: Planet | SystemManager,
departureTime: Date, departureTime: Date,
arrivalTime: Date, arrivalTime: Date,
returning: boolean, returning: boolean,
@ -19,7 +20,7 @@ export type Fleet = {
export default class FleetManager { export default class FleetManager {
data: Fleet; data: Fleet;
constructor(id: ObjectId, source: Planet, destination: Planet, departureTime: Date, arrivalTime: Date, returning: boolean, mission: MissionType, ships: Array<{ id: string, amount: number }>, cargo: Array<{ id: string, amount: number }>) { constructor(id: ObjectId, source: Planet | SystemManager, destination: Planet | SystemManager, departureTime: Date, arrivalTime: Date, returning: boolean, mission: MissionType, ships: Array<{ id: string, amount: number }>, cargo: Array<{ id: string, amount: number }>) {
this.data = { this.data = {
id, id,
source, source,
@ -33,6 +34,32 @@ export default class FleetManager {
} }
} }
isSourcePlanet(): this is { data: { source: Planet } } {
return 'resources' in this.data.source;
}
isSourceSystem(): this is { data: { source: SystemManager } } {
return 'structures' in this.data.source;
}
isDestinationPlanet(): this is { data: { destination: Planet } } {
return 'resources' in this.data.destination;
}
isDestinationSystem(): this is { data: { destination: SystemManager } } {
return 'structures' in this.data.destination;
}
getSourceOwner() {
if(this.isSourcePlanet()) return this.data.source.system.data.ownedBy;
if(this.isSourceSystem()) return this.data.source.data.ownedBy;
}
getDestinationOwner() {
if(this.isDestinationPlanet()) return this.data.destination.system.data.ownedBy;
if(this.isDestinationSystem()) return this.data.destination.data.ownedBy;
}
async checkStatus(): Promise<{ finished: boolean, fleet: Fleet }> { async checkStatus(): Promise<{ finished: boolean, fleet: Fleet }> {
if(this.data.arrivalTime.getTime() < Date.now()) { if(this.data.arrivalTime.getTime() < Date.now()) {
const finished = await this.finish(); const finished = await this.finish();
@ -82,10 +109,13 @@ export default class FleetManager {
} }
async sync() { async sync() {
const source = this.data.source instanceof SystemManager ? this.data.source.data._id : this.data.source._id;
const destination = this.data.destination instanceof SystemManager ? this.data.destination.data._id : this.data.destination._id;
const data: DBFleet = { const data: DBFleet = {
_id: this.data.id, _id: this.data.id,
source: this.data.source._id, source,
destination: this.data.destination._id, destination,
departureTime: this.data.departureTime, departureTime: this.data.departureTime,
arrivalTime: this.data.arrivalTime, arrivalTime: this.data.arrivalTime,
returning: this.data.returning, returning: this.data.returning,

View File

@ -1,13 +1,13 @@
import { ObjectId } from "mongodb"; import { ObjectId } from "mongodb";
import PlanetManager, { Planet } from "./PlanetManager"; import { getAllFleet } from "../../db/fleet";
import { getAllGalaxies } from "../../db/galaxies"; import { getAllGalaxies } from "../../db/galaxies";
import { getSectorById } from "../../db/sectors"; import { getSectorById } from "../../db/sectors";
import { getSystemById } from "../../db/systems"; import { getSystemById } from "../../db/systems";
import { getAllUsers } from "../../db/users"; import { getAllUsers } from "../../db/users";
import User from "../User"; import User from "../User";
import StructureManager from "./StructureManager";
import FleetManager from "./FleetManager"; import FleetManager from "./FleetManager";
import { getAllFleet } from "../../db/fleet"; import { Planet } from "./PlanetManager";
import SystemManager, { System } from "./SystemManager";
export type Galaxy = { export type Galaxy = {
_id: ObjectId, _id: ObjectId,
@ -24,16 +24,7 @@ export type Sector = {
galaxy: Galaxy, galaxy: Galaxy,
name: string, name: string,
expedition: null, expedition: null,
systems: Array<System> systems: Array<SystemManager>
}
export type System = {
_id: ObjectId,
sector: Sector,
name: string,
ownedBy: User,
structures: StructureManager,
planets: PlanetManager
} }
class LocationManager { class LocationManager {
@ -99,14 +90,16 @@ class LocationManager {
ownedBy: user, ownedBy: user,
//@ts-ignore //@ts-ignore
structures: null, structures: null,
planets: new PlanetManager(user) //@ts-ignore
resources: null,
//@ts-ignore
ships: null,
planets: []
}; };
systemObject.structures = await new StructureManager(systemObject).init(systemData.structures); const s = await new SystemManager(systemObject).fillData(systemData);
await systemObject.planets.fillData(systemObject, systemData.planets); sectorObject.systems.push(s);
sectorObject.systems.push(systemObject);
}; };
console.log(`Loaded ${sectorObject.systems.length} systems from sector ${sectorObject.name}`); console.log(`Loaded ${sectorObject.systems.length} systems from sector ${sectorObject.name}`);
@ -126,7 +119,7 @@ class LocationManager {
const userDB = users.find(u => u._id.equals(user.id)); const userDB = users.find(u => u._id.equals(user.id));
const mainPlanet = this.getPlanet(userDB?.mainPlanet as ObjectId); const mainPlanet = this.getPlanet(userDB?.mainPlanet as ObjectId);
if(!mainPlanet) throw new Error("Main planet not found"); if(!mainPlanet) throw new Error(`Main planet not found for user ${user.username} (${user.id})`);
user.mainPlanet = mainPlanet; user.mainPlanet = mainPlanet;
}; };
@ -134,9 +127,9 @@ class LocationManager {
const fleets = await getAllFleet(); const fleets = await getAllFleet();
for(const fleet of fleets) { for(const fleet of fleets) {
if(fleet.arrivalTime > currentTime) { if(fleet.arrivalTime > currentTime) {
const source = this.getPlanet(fleet.source); const source = this.getPlanet(fleet.source) || this.getSystem(fleet.source);
const destination = this.getPlanet(fleet.destination); const destination = this.getPlanet(fleet.destination) || this.getSystem(fleet.destination);
if(source && destination) this.fleet.push(new FleetManager( if(source && destination) this.fleet.push(new FleetManager(
fleet._id, fleet._id,
source, source,
@ -156,6 +149,30 @@ class LocationManager {
return this; return this;
} }
findId(id: ObjectId) {
let found: SystemManager | Planet | null = null;
for(const galaxy of this.galaxies) {
for(const sector of galaxy.sectors) {
for(const system of sector.systems) {
if(system.data._id.equals(id)) {
found = system;
break;
}
for(const planet of system.planets) {
if(planet._id.equals(id)) {
found = planet;
break;
}
}
}
}
}
return found;
}
getGalaxy(_id: ObjectId) { getGalaxy(_id: ObjectId) {
return this.galaxies.find(galaxy => galaxy._id.equals(_id)); return this.galaxies.find(galaxy => galaxy._id.equals(_id));
} }
@ -169,20 +186,20 @@ class LocationManager {
} }
getSystem(_id: ObjectId) { getSystem(_id: ObjectId) {
let foundSystem: System | undefined; let foundSystem: SystemManager | undefined;
this.galaxies.find(galaxy => galaxy.sectors.find(sector => sector.systems.find(system => { this.galaxies.find(galaxy => galaxy.sectors.find(sector => sector.systems.find(system => {
if(system._id.equals(_id)) foundSystem = system if(system.data._id.equals(_id)) foundSystem = system
}))); })));
return foundSystem return foundSystem
} }
getSystemsOwnedBy(id: ObjectId) { getSystemsOwnedBy(id: ObjectId) {
const systems: System[] = []; const systems: SystemManager[] = [];
for(const galaxy of this.galaxies) { for(const galaxy of this.galaxies) {
for(const sector of galaxy.sectors) { for(const sector of galaxy.sectors) {
for(const system of sector.systems) { for(const system of sector.systems) {
if(system.ownedBy.id.equals(id)) systems.push(system); if(system.data.ownedBy.id.equals(id)) systems.push(system);
} }
} }
} }
@ -196,7 +213,7 @@ class LocationManager {
for(const galaxy of this.galaxies) { for(const galaxy of this.galaxies) {
for(const sector of galaxy.sectors) { for(const sector of galaxy.sectors) {
for(const system of sector.systems) { for(const system of sector.systems) {
foundPlanet = system.planets.getPlanetById(_id); foundPlanet = system.planets.find(planet => planet._id.equals(_id));
if(foundPlanet) break; if(foundPlanet) break;
} }
if(foundPlanet) break; if(foundPlanet) break;
@ -222,7 +239,17 @@ class LocationManager {
async getAllFleetByUserId(userId: string) { async getAllFleetByUserId(userId: string) {
await this.updateFleet(); await this.updateFleet();
return userId === '' ? [] : this.fleet.filter(fleet => fleet.data.source.manager.owner.id.equals(userId) || fleet.data.destination.manager.owner.id.equals(userId)); return userId === '' ? [] : this.fleet.filter(fleet => {
let found = false;
if(fleet.data.source instanceof SystemManager) found = fleet.data.source.data.ownedBy.id.equals(userId);
else found = fleet.data.source.system.data.ownedBy.id.equals(userId);
if(fleet.data.destination instanceof SystemManager) found = fleet.data.destination.data.ownedBy.id.equals(userId);
else found = fleet.data.destination.system.data.ownedBy.id.equals(userId);
return found;
});
} }
addFleet(fleet: FleetManager) { addFleet(fleet: FleetManager) {

View File

@ -1,57 +1,15 @@
import { ObjectId } from "mongodb"; import { ObjectId } from "mongodb";
import BuildingManager from "./BuildingManager"; import BuildingManager from "./BuildingManager";
import { getPlanetById } from "../../db/planets"; import PlanetResourceManager from "./PlanetResourceManager";
import ResourceManager from "./ResourceManager"; import ShipManager from "./PlanetShipManager";
import User from "../User"; import SystemManager from "./SystemManager";
import ShipManager from "./ShipManager";
import { System } from "./LocationManager";
export type Planet = { export type Planet = {
_id: ObjectId; _id: ObjectId;
manager: PlanetManager; system: SystemManager;
name: string; name: string;
fields: number; fields: number;
resources: ResourceManager; resources: PlanetResourceManager;
buildings: BuildingManager; buildings: BuildingManager;
ships: ShipManager; ships: ShipManager;
}
export default class PlanetManager {
planets: Array<Planet> = [];
owner: User;
system!: System;
constructor(user: User) {
this.owner = user;
}
async fillData(system: System, planets: ObjectId[]) {
this.system = system;
await Promise.all(planets.map(async planetId => {
const planet = await getPlanetById(planetId);
const planetObject: Planet = {
_id: planet._id,
manager: this,
name: planet.name,
fields: planet.fields,
//@ts-ignore
resources: null,
//@ts-ignore
buildings: null,
//@ts-ignore
ships: null
}
planetObject.resources = await new ResourceManager(planetObject).init(planet.resources);
planetObject.buildings = await new BuildingManager(planetObject).init(planet.buildings);
planetObject.ships = await new ShipManager(planetObject).init(planet.ships);
this.planets.push(planetObject);
}));
}
getPlanetById(id: ObjectId) {
return this.planets.find(planet => planet._id.equals(id));
}
} }

View File

@ -1,22 +1,13 @@
import DBResource from "../../../types/db/DBResource";
import { updatePlanetResources } from "../../db/planets"; import { updatePlanetResources } from "../../db/planets";
import { getAllResources } from "../../db/resources"; import { getAllResources } from "../../db/resources";
import { Planet } from "./PlanetManager"; import { Planet } from "./PlanetManager";
import ResourceManager from "./abstract/ResourceManager";
export type Resource = { export default class PlanetResourceManager extends ResourceManager {
id: string,
amount: number,
lastUpdated: Date,
perHourMiningRate: number,
data: DBResource
}
export default class ResourceManager {
resources: Array<Resource> = [];
resourcesDB: DBResource[] = [];
planet: Planet; planet: Planet;
constructor(planet: Planet) { constructor(planet: Planet) {
super();
this.planet = planet; this.planet = planet;
} }
@ -100,73 +91,6 @@ export default class ResourceManager {
return this; return this;
} }
getResourceById(resId: string) {
return this.resources.find(res => res.id === resId);
}
async calculateCurrentAvailableResources() {
this.resources.forEach(res => {
const timeDiff = Math.abs((new Date()).getTime() - res.lastUpdated.getTime());
const hours = timeDiff / (1000 * 60 * 60);
const amountToAdd = hours * res.perHourMiningRate;
res.amount += amountToAdd;
res.lastUpdated = new Date();
});
await updatePlanetResources(this.planet._id, this.resources);
return this.resources;
}
async getDifference(resources: { id: string, amount: number }[]): Promise<Array<Resource>> {
const currentResources = await this.calculateCurrentAvailableResources();
const difference: Resource[] = [];
currentResources.forEach(res => {
const currentRes = resources.find(r => r.id === res.id);
if(currentRes) difference.push({
id: res.id,
amount: res.amount - currentRes.amount,
lastUpdated: res.lastUpdated,
perHourMiningRate: res.perHourMiningRate,
data: res.data
});
else difference.push(res);
});
return difference;
}
add(resources: Resource[]) {
for(const res of resources) {
const resource = this.resources.find(r => r.id === res.id);
if(resource) resource.amount += res.amount;
else this.resources.push(res);
}
}
async updateAmount(resources: { id: string, amount: number }[]) {
await this.calculateCurrentAvailableResources();
for(const res of resources) {
const resource = this.resources.find(r => r.id === res.id);
if(resource) resource.amount += res.amount;
}
}
setAmount(resources: { id: string, amount: number }[]) {
for(const res of resources) {
const resource = this.resources.find(r => r.id === res.id);
if(resource) resource.amount = res.amount;
else this.resources.push({
id: res.id,
amount: res.amount,
lastUpdated: new Date(),
perHourMiningRate: 0,
data: this.resourcesDB.find(r => r.id === res.id)
});
}
}
async sync() { async sync() {
await updatePlanetResources(this.planet._id, this.resources.map(res => { await updatePlanetResources(this.planet._id, this.resources.map(res => {
return { return {

View File

@ -0,0 +1,17 @@
import { updatePlanetShips } from "../../db/planets";
import { Planet } from "./PlanetManager";
import ShipManager from "./abstract/ShipManager";
export default class PlanetShipManager extends ShipManager {
constructor(planet: Planet) {
super(planet);
}
get manager() {
return this._manager as Planet;
}
async sync() {
await updatePlanetShips(this.manager._id, this.ships.map(ship => { return { id: ship.data.id, amount: ship.amount } }));
}
}

View File

@ -1,17 +1,15 @@
import { updatePlanetBuildings } from '../../db/planets';
import Building from '../Building';
import DBStructure from '../../../types/db/DBStructure'; import DBStructure from '../../../types/db/DBStructure';
import { System } from './LocationManager';
import { getAllStructures } from '../../db/structures'; import { getAllStructures } from '../../db/structures';
import Structure from '../Structure';
import { updateSystemStructures } from '../../db/systems'; import { updateSystemStructures } from '../../db/systems';
import Structure from '../Structure';
import SystemManager from './SystemManager';
export default class StructureManager { export default class StructureManager {
structures: Array<Structure> = []; structures: Array<Structure> = [];
structuresDB: Array<DBStructure> = [] structuresDB: Array<DBStructure> = []
system: System; system: SystemManager;
constructor(system: System) { constructor(system: SystemManager) {
this.system = system; this.system = system;
} }
@ -45,6 +43,6 @@ export default class StructureManager {
} }
async sync() { async sync() {
await updateSystemStructures(this.system._id, this.structures.map(structure => { return { id: structure.data.id, level: structure.level } })); await updateSystemStructures(this.system.data._id, this.structures.map(structure => { return { id: structure.data.id, level: structure.level } }));
} }
} }

View File

@ -0,0 +1,73 @@
import { ObjectId } from "mongodb";
import DBSystem from "../../../types/db/DBSystem";
import { getPlanetById } from "../../db/planets";
import User from "../User";
import BuildingManager from "./BuildingManager";
import { Sector } from "./LocationManager";
import { Planet } from "./PlanetManager";
import PlanetResourceManager from "./PlanetResourceManager";
import PlanetShipManager from "./PlanetShipManager";
import StructureManager from "./StructureManager";
import SystemResourceManager from "./SystemResourceManager";
import SystemShipManager from "./SystemShipManager";
export type System = {
_id: ObjectId,
sector: Sector,
name: string,
ownedBy: User,
structures: StructureManager,
resources: SystemResourceManager,
ships: SystemShipManager,
planets: Planet[];
}
export default class SystemManager {
planets: Planet[] = [];
structures: StructureManager;
resources: SystemResourceManager;
ships: SystemShipManager;
data: System;
constructor(data: System) {
this.data = data;
this.structures = new StructureManager(this);
this.resources = new SystemResourceManager(this);
this.ships = new SystemShipManager(this);
}
async fillData(systemData: DBSystem) {
await this.structures.init(systemData.structures);
await this.resources.init(systemData.resources);
await this.ships.init(systemData.ships);
await Promise.all(systemData.planets.map(async planetId => {
const planet = await getPlanetById(planetId);
const planetObject: Planet = {
_id: planet._id,
system: this,
name: planet.name,
fields: planet.fields,
//@ts-ignore
resources: null,
//@ts-ignore
buildings: null,
//@ts-ignore
ships: null
}
planetObject.resources = await new PlanetResourceManager(planetObject).init(planet.resources);
planetObject.buildings = await new BuildingManager(planetObject).init(planet.buildings);
planetObject.ships = await new PlanetShipManager(planetObject).init(planet.ships);
this.planets.push(planetObject);
}));
return this;
}
addPlanet(planet: Planet) {
this.planets.push(planet);
}
}

View File

@ -0,0 +1,88 @@
import { getAllResources } from "../../db/resources";
import { updateSystemResources } from "../../db/systems";
import SystemManager from "./SystemManager";
import ResourceManager from "./abstract/ResourceManager";
export default class SystemResourceManager extends ResourceManager {
system: SystemManager;
constructor(system: SystemManager) {
super();
this.system = system;
}
async init(resourceData?: { id: string, amount: number }[]) {
const resources = await getAllResources();
this.resourcesDB = resources;
if(!resourceData || resourceData.length === 0) {
resourceData = [
{
id: "coal",
amount: 11
},
{
id: "iron",
amount: 22
},
{
id: "gold",
amount: 33
},
{
id: "water",
amount: 44
},
{
id: "sulfuric-acid",
amount: 55
},
{
id: "liquid-nitrogen",
amount: 66
},
{
id: "hydrogen",
amount: 77
},
{
id: "oxygen",
amount: 88
},
{
id: "helium-3",
amount: 99
}
];
await updateSystemResources(this.system.data._id, this.resources);
}
resourceData.forEach(resource => {
const resFromDB = resources.find(res => res.id === resource.id);
if(resFromDB) this.resources.push({
id: resource.id,
amount: resource.amount,
lastUpdated: null,
perHourMiningRate: null,
data: resFromDB
})
});
return this;
}
async sync() {
await updateSystemResources(this.system.data._id, this.resources.map(res => {
return {
id: res.id,
amount: res.amount,
lastUpdated: res.lastUpdated,
perHourMiningRate: res.perHourMiningRate
}
}));
}
}

View File

@ -0,0 +1,17 @@
import { updateSystemShips } from "../../db/systems";
import SystemManager from "./SystemManager";
import ShipManager from "./abstract/ShipManager";
export default class SystemShipManager extends ShipManager {
constructor(system: SystemManager) {
super(system);
}
get manager() {
return this._manager as SystemManager;
}
async sync() {
await updateSystemShips(this.manager.data._id, this.ships.map(ship => { return { id: ship.data.id, amount: ship.amount } }));
}
}

View File

@ -0,0 +1,92 @@
import DBResource from "../../../../types/db/DBResource";
export type Resource = {
id: string,
amount: number,
lastUpdated: Date | null,
perHourMiningRate: number | null,
data: DBResource
}
export default abstract class ResourceManager {
resources: Resource[] = [];
resourcesDB: DBResource[] = [];
abstract sync(): Promise<void>;
getResourceById(resId: string) {
return this.resources.find(res => res.id === resId);
}
async calculateCurrentAvailableResources() {
for(const res of this.resources) {
if(!res.lastUpdated || !res.perHourMiningRate) continue;
const timeDiff = Math.abs((new Date()).getTime() - res.lastUpdated.getTime());
const hours = timeDiff / (1000 * 60 * 60);
const amountToAdd = hours * res.perHourMiningRate;
res.amount += amountToAdd;
res.lastUpdated = new Date();
};
await this.sync();
return this.resources;
}
async getDifference(resources: { id: string, amount: number }[]): Promise<Array<Resource>> {
const currentResources = await this.calculateCurrentAvailableResources();
const difference: Resource[] = [];
currentResources.forEach(res => {
const currentRes = resources.find(r => r.id === res.id);
if(currentRes) difference.push({
id: res.id,
amount: res.amount - currentRes.amount,
lastUpdated: res.lastUpdated,
perHourMiningRate: res.perHourMiningRate,
data: res.data
});
else difference.push(res);
});
return difference;
}
add(resources: Resource[]) {
for(const res of resources) {
const resource = this.resources.find(r => r.id === res.id);
if(resource) resource.amount += res.amount;
else this.resources.push(res);
}
}
async updateAmount(resources: { id: string, amount: number }[]) {
await this.calculateCurrentAvailableResources();
for(const res of resources) {
const resource = this.resources.find(r => r.id === res.id);
if(resource) resource.amount += res.amount;
else this.resources.push({
id: res.id,
amount: res.amount,
lastUpdated: new Date(),
perHourMiningRate: 0,
data: this.resourcesDB.find(r => r.id === res.id) as DBResource
});
}
}
setAmount(resources: { id: string, amount: number }[]) {
for(const res of resources) {
const resource = this.resources.find(r => r.id === res.id);
if(resource) resource.amount = res.amount;
else this.resources.push({
id: res.id,
amount: res.amount,
lastUpdated: new Date(),
perHourMiningRate: 0,
data: this.resourcesDB.find(r => r.id === res.id) as DBResource
});
}
}
}

View File

@ -1,17 +1,21 @@
import { Planet } from './PlanetManager'; import { Planet } from '../PlanetManager';
import { updatePlanetBuildings, updatePlanetShips } from '../../db/planets'; import DBShip from '../../../../types/db/DBShip';
import DBShip from '../../../types/db/DBShip'; import { getAllShips } from '../../../db/ships';
import { getAllShips } from '../../db/ships'; import Ship from '../../Ship';
import Ship from '../Ship'; import SystemManager from '../SystemManager';
export default class ShipManager { export default abstract class ShipManager {
ships: Array<Ship> = []; ships: Array<Ship> = [];
shipsDB: Array<DBShip> = [] shipsDB: Array<DBShip> = [];
planet: Planet; protected _manager: Planet | SystemManager;
constructor(planet: Planet) { constructor(manager: Planet | SystemManager) {
this.planet = planet; this._manager = manager;
} }
abstract sync(): Promise<void>;
abstract get manager(): Planet | SystemManager;
async init(shipData: { id: string, amount: number }[]) { async init(shipData: { id: string, amount: number }[]) {
this.shipsDB = await getAllShips(); this.shipsDB = await getAllShips();
@ -56,8 +60,4 @@ export default class ShipManager {
if(findShip.amount <= 0) this.ships.splice(this.ships.indexOf(findShip), 1); if(findShip.amount <= 0) this.ships.splice(this.ships.indexOf(findShip), 1);
} }
} }
async sync() {
await updatePlanetShips(this.planet._id, this.ships.map(ship => { return { id: ship.data.id, amount: ship.amount } }));
}
} }

View File

@ -24,4 +24,22 @@ export const updateSystemStructures = async (systemId: ObjectId, structures: Arr
structures structures
} }
}); });
}
export const updateSystemResources = async (systemId: ObjectId, resources: Array<any>) => {
const systems = await Systems();
await systems.updateOne({ _id: systemId }, {
$set: {
resources
}
});
}
export const updateSystemShips = async (systemId: ObjectId, ships: Array<any>) => {
const systems = await Systems();
await systems.updateOne({ _id: systemId }, {
$set: {
ships
}
});
} }

View File

@ -94,7 +94,7 @@ export const POST: APIRoute = async({ request }) => {
} }
}); });
userPlanet.resources.update(resourcesAfter); userPlanet.resources.updateAmount(resourcesAfter.map(res => { return { id: res.id, amount: res.amount } }));
userPlanet.buildings.addBuilding(building); userPlanet.buildings.addBuilding(building);
await userPlanet.buildings.sync(); await userPlanet.buildings.sync();

View File

@ -9,6 +9,7 @@ import { Planet } from "../../../lib/classes/managers/PlanetManager";
import MissionType from "../../../types/MissionType"; import MissionType from "../../../types/MissionType";
import { getAllResources } from "../../../lib/db/resources"; import { getAllResources } from "../../../lib/db/resources";
import FleetManager from "../../../lib/classes/managers/FleetManager"; import FleetManager from "../../../lib/classes/managers/FleetManager";
import SystemManager from "../../../lib/classes/managers/SystemManager";
export const POST: APIRoute = async({ request }) => { export const POST: APIRoute = async({ request }) => {
const response = await validateAccessToken(request); const response = await validateAccessToken(request);
@ -47,14 +48,14 @@ export const POST: APIRoute = async({ request }) => {
) )
} }
const checkSource = checkPlanetId(body.source, 'source'); const checkSource = checkPlanetOrSystemId(body.source, 'source');
if(typeof checkSource.error !== "undefined") return new Response(JSON.stringify(checkSource), { status: checkSource.code }); if(typeof checkSource.error !== "undefined") return new Response(JSON.stringify(checkSource), { status: checkSource.code });
const checkDestination = checkPlanetId(body.destination, 'destination'); const checkDestination = checkPlanetOrSystemId(body.destination, 'destination');
if(typeof checkDestination.error !== "undefined") return new Response(JSON.stringify(checkDestination), { status: checkDestination.code }); if(typeof checkDestination.error !== "undefined") return new Response(JSON.stringify(checkDestination), { status: checkDestination.code });
const source = checkSource.planet; const source = checkSource.planetOrSystem;
const destination = checkDestination.planet; const destination = checkDestination.planetOrSystem;
const shipsDB = await getAllShips(); const shipsDB = await getAllShips();
@ -112,7 +113,7 @@ export const POST: APIRoute = async({ request }) => {
) )
} }
function checkPlanetId(id: string, type: string) { function checkPlanetOrSystemId(id: string, type: string) {
if(typeof ObjectId === "undefined") return { if(typeof ObjectId === "undefined") return {
code: 400, code: 400,
message: "Bad Request", message: "Bad Request",
@ -130,22 +131,22 @@ function checkPlanetId(id: string, type: string) {
} }
} }
const planet = locationManager.getPlanet(idToCheck); const planetOrSystem = locationManager.findId(idToCheck);
if(!planet) return { if(!planetOrSystem) return {
code: 404, code: 404,
message: "Not Found", message: "Not Found",
error: `Non-existent planet provided in '${type}'` error: `Non-existent planet or system provided in '${type}'`
} }
return { return {
code: 200, code: 200,
message: "OK", message: "OK",
planet planetOrSystem
} }
} }
function checkShips(ships: Array<{ id: string, amount: number }>, shipsDB: Array<DBShip>, sourcePlanet: Planet) { function checkShips(ships: Array<{ id: string, amount: number }>, shipsDB: Array<DBShip>, source: Planet | SystemManager) {
if(typeof ships === "undefined") return { if(typeof ships === "undefined") return {
code: 400, code: 400,
message: "Bad Request", message: "Bad Request",
@ -177,7 +178,7 @@ function checkShips(ships: Array<{ id: string, amount: number }>, shipsDB: Array
error: "Ship amount for ID '" + ships[i].id + "' is not a non-negative integer at position " + i error: "Ship amount for ID '" + ships[i].id + "' is not a non-negative integer at position " + i
} }
if(ships[i].amount > (sourcePlanet.ships.getShipById(ships[i].id)?.amount ?? 0)) return { if(ships[i].amount > (source.ships.getShipById(ships[i].id)?.amount ?? 0)) return {
code: 400, code: 400,
message: "Bad Request", message: "Bad Request",
error: "Not enough ships on planet with ID '" + ships[i].id + "' at position " + i error: "Not enough ships on planet with ID '" + ships[i].id + "' at position " + i
@ -190,7 +191,7 @@ function checkShips(ships: Array<{ id: string, amount: number }>, shipsDB: Array
} }
} }
function checkCargo(cargo: Array<{ id: string, amount: number }>, ships: Array<{ id: string, amount: number }>, planet: Planet, missionType: MissionType) { function checkCargo(cargo: Array<{ id: string, amount: number }>, ships: Array<{ id: string, amount: number }>, source: Planet | SystemManager, missionType: MissionType) {
if(missionType === "TRANSPORT" && cargo.length === 0) return { if(missionType === "TRANSPORT" && cargo.length === 0) return {
code: 400, code: 400,
message: "Bad Request", message: "Bad Request",
@ -204,7 +205,7 @@ function checkCargo(cargo: Array<{ id: string, amount: number }>, ships: Array<{
error: "Missing resource ID at position " + i error: "Missing resource ID at position " + i
} }
if(!planet.resources.resourcesDB.find(resource => resource.id === cargo[i].id)) return { if(!source.resources.resourcesDB.find(resource => resource.id === cargo[i].id)) return {
code: 404, code: 404,
message: "Not Found", message: "Not Found",
error: "Non-existent resource ID '" + cargo[i].id + "' at position " + i error: "Non-existent resource ID '" + cargo[i].id + "' at position " + i
@ -222,23 +223,23 @@ function checkCargo(cargo: Array<{ id: string, amount: number }>, ships: Array<{
error: "Resource amount for ID '" + cargo[i].id + "' is not a non-negative integer at position " + i error: "Resource amount for ID '" + cargo[i].id + "' is not a non-negative integer at position " + i
} }
if(cargo[i].amount > (planet.resources.resources.find(res => res.id === cargo[i].id)?.amount ?? 0)) return { if(cargo[i].amount > (source.resources.resources.find(res => res.id === cargo[i].id)?.amount ?? 0)) return {
code: 400, code: 400,
message: "Bad Request", message: "Bad Request",
error: "Not enough resources on planet with ID '" + cargo[i].id + "' at position " + i error: "Not enough resources on planet or system with ID '" + cargo[i].id + "' at position " + i
} }
} }
const totalCargoAvailable = { const totalCargoAvailable = {
solid: ships.reduce((acc, ship) => acc + (planet.ships.shipsDB.find(s => s.id === ship.id)?.capacity.solid ?? 0) * ship.amount, 0), solid: ships.reduce((acc, ship) => acc + (source.ships.shipsDB.find(s => s.id === ship.id)?.capacity.solid ?? 0) * ship.amount, 0),
liquid: ships.reduce((acc, ship) => acc + (planet.ships.shipsDB.find(s => s.id === ship.id)?.capacity.liquid ?? 0) * ship.amount, 0), liquid: ships.reduce((acc, ship) => acc + (source.ships.shipsDB.find(s => s.id === ship.id)?.capacity.liquid ?? 0) * ship.amount, 0),
gas: ships.reduce((acc, ship) => acc + (planet.ships.shipsDB.find(s => s.id === ship.id)?.capacity.gas ?? 0) * ship.amount, 0) gas: ships.reduce((acc, ship) => acc + (source.ships.shipsDB.find(s => s.id === ship.id)?.capacity.gas ?? 0) * ship.amount, 0)
} }
const totalCargoUsed = { const totalCargoUsed = {
solid: cargo.reduce((acc, resource) => planet.resources.resourcesDB.find(res => res.id === resource.id)?.type === "solid" ? acc + resource.amount : acc, 0), solid: cargo.reduce((acc, resource) => source.resources.resourcesDB.find(res => res.id === resource.id)?.type === "solid" ? acc + resource.amount : acc, 0),
liquid: cargo.reduce((acc, resource) => planet.resources.resourcesDB.find(res => res.id === resource.id)?.type === "liquid" ? acc + resource.amount : acc, 0), liquid: cargo.reduce((acc, resource) => source.resources.resourcesDB.find(res => res.id === resource.id)?.type === "liquid" ? acc + resource.amount : acc, 0),
gas: cargo.reduce((acc, resource) => planet.resources.resourcesDB.find(res => res.id === resource.id)?.type === "gas" ? acc + resource.amount : acc, 0) gas: cargo.reduce((acc, resource) => source.resources.resourcesDB.find(res => res.id === resource.id)?.type === "gas" ? acc + resource.amount : acc, 0)
} }
if(totalCargoUsed.solid > totalCargoAvailable.solid) return { if(totalCargoUsed.solid > totalCargoAvailable.solid) return {

View File

@ -15,7 +15,7 @@ export const GET: APIRoute = async ({ request }) => {
response.push({ response.push({
planetId: planet._id, planetId: planet._id,
ownerId: playerPlanet.manager.owner.id, ownerId: playerPlanet.system.data.ownedBy.id,
name: planet.name, name: planet.name,
}) })
}); });

View File

@ -35,7 +35,7 @@ export const GET: APIRoute = async ({ params, request }) => {
}), { status: 500 } }), { status: 500 }
); );
if(!planet.manager.owner.id.equals(user._id)) return new Response( if(!planet.system.data.ownedBy.id.equals(user._id)) return new Response(
JSON.stringify({ JSON.stringify({
code: 403, code: 403,
message: "Forbidden" message: "Forbidden"

View File

@ -43,7 +43,7 @@ export const POST: APIRoute = async({ request }) => {
) )
} }
const user = userPlanet.manager.owner; const user = userPlanet.system.data.ownedBy;
if(!user.id.equals(userDB._id)) { if(!user.id.equals(userDB._id)) {
return new Response( return new Response(
@ -139,15 +139,15 @@ export const POST: APIRoute = async({ request }) => {
) )
} }
userPlanet.resources.update(newResources); userPlanet.resources.updateAmount(newResources.map(res => { return { id: res.id, amount: res.amount } }));
userPlanet.manager.owner.research.addResearch({ user.research.addResearch({
id: researchId, id: researchId,
level: level + 1, level: level + 1,
data: research data: research
}); });
await userPlanet.resources.sync(); await userPlanet.resources.sync();
await userPlanet.manager.owner.research.sync(); await user.research.sync();
return new Response( return new Response(
JSON.stringify({ JSON.stringify({

View File

@ -115,7 +115,7 @@ export const POST: APIRoute = async({ request }) => {
} }
}); });
userPlanet.resources.update(resourcesAfter); userPlanet.resources.updateAmount(resourcesAfter.map(res => { return { id: res.id, amount: res.amount } }));
userPlanet.ships.addShips(ship.data.id, amount); userPlanet.ships.addShips(ship.data.id, amount);
await userPlanet.ships.sync(); await userPlanet.ships.sync();

View File

@ -8,6 +8,7 @@ import locationManager from '../../lib/classes/managers/LocationManager';
import { getAllFleetByUser } from '../../lib/db/fleet'; import { getAllFleetByUser } from '../../lib/db/fleet';
import { getAllShips } from '../../lib/db/ships'; import { getAllShips } from '../../lib/db/ships';
import { ObjectId } from 'mongodb'; import { ObjectId } from 'mongodb';
import SystemManager from '../../lib/classes/managers/SystemManager';
const loggedToken = Astro.cookies.get('sessionToken')?.value ?? null; const loggedToken = Astro.cookies.get('sessionToken')?.value ?? null;
const username = Astro.cookies.get('username')?.value ?? ""; const username = Astro.cookies.get('username')?.value ?? "";
@ -44,10 +45,10 @@ if(Astro.request.method === "POST") {
}); });
} }
}); });
const fleetData = { const fleetData = {
source: planet._id, source: planet._id,
destination: new ObjectId(form.get('destination-planet')?.toString() ?? ""), destination: form.get('toSystem') ? form.get('destination-system')?.toString() : form.get('destination-planet')?.toString(),
mission: form.get('mission')?.toString() ?? "NULL", mission: form.get('mission')?.toString() ?? "NULL",
ships: ships.map(ship => { ships: ships.map(ship => {
const amount = parseInt(form.get(`ship-amount-${ship.id}`)?.toString() ?? "0"); const amount = parseInt(form.get(`ship-amount-${ship.id}`)?.toString() ?? "0");
@ -86,14 +87,20 @@ let friendly = 0;
let enemy = 0; let enemy = 0;
for(const system of userSystems) { for(const system of userSystems) {
for(const planet of system.planets.planets) { for(const planet of system.planets) {
for(const f of fleet) { for(const f of fleet) {
if(f.source.equals(planet._id)) own++; if(f.source.equals(planet._id) || f.source.equals(system.data._id)) own++;
else if(f.destination.equals(planet._id)) { else if(f.destination.equals(planet._id) || f.destination.equals(system.data._id)) {
if(f.mission === 'ATTACK') enemy++; if(f.mission === 'ATTACK') enemy++;
else { else {
const source = locationManager.getPlanet(f.source)?.manager.owner.id; const sourceObj = locationManager.findId(f.source);
const destination = locationManager.getPlanet(f.destination)?.manager.owner.id; const destinationObj = locationManager.findId(f.destination);
if(!sourceObj || !destinationObj) continue;
const source = sourceObj instanceof SystemManager ? sourceObj.data.ownedBy.id : sourceObj.system.data.ownedBy.id;
const destination = destinationObj instanceof SystemManager ? destinationObj.data.ownedBy.id : destinationObj.system.data.ownedBy.id;
if(!source?.equals(destination)) friendly++; if(!source?.equals(destination)) friendly++;
} }
} }
@ -111,9 +118,9 @@ const sectorsList = galaxies.map(galaxy => {
name: sector.name, name: sector.name,
systems: sector.systems.map(system => { systems: sector.systems.map(system => {
return { return {
_id: system._id, _id: system.data._id,
name: system.name, name: system.data.name,
planets: system.planets.planets.map(planet => { planets: system.planets.map(planet => {
return { return {
_id: planet._id, _id: planet._id,
name: planet.name name: planet.name
@ -137,9 +144,13 @@ const lang = await getLocales(Astro.cookies.get('language')?.value ?? await getH
<div class="fleet-status"> <div class="fleet-status">
<h2>Fleet status ({fleet.length} total | {own} own | {friendly} friendly | {enemy} enemy)</h2> <h2>Fleet status ({fleet.length} total | {own} own | {friendly} friendly | {enemy} enemy)</h2>
<ul> <ul>
{fleet.map(f => <li> {fleet.map(f => {
const source = locationManager.findId(f.source);
const destination = locationManager.findId(f.destination);
return (<li>
<div class="ship-cards"> <div class="ship-cards">
{locationManager.getPlanet(f.source)?.name ?? "?"} =&gt; {locationManager.getPlanet(f.destination)?.name ?? "?"} | {f.mission}{f.returning ? " (R)" : ""}<br /> <span style={`${source instanceof SystemManager && "color:red;"}`}>{(source instanceof SystemManager ? source.data.name : source?.name) ?? "?"}</span> =&gt; <span style={`${destination instanceof SystemManager && "color:red;"}`}>{(destination instanceof SystemManager ? destination.data.name : destination?.name) ?? "?"}</span> | {f.mission}{f.returning ? " (R)" : ""}<br />
Containing: {f.ships.map(s => { Containing: {f.ships.map(s => {
const ship = ships.find(ship => ship.id === s.id); const ship = ships.find(ship => ship.id === s.id);
return `${getName(lang, 'ships', s.id)} x${s.amount}`; return `${getName(lang, 'ships', s.id)} x${s.amount}`;
@ -148,7 +159,8 @@ const lang = await getLocales(Astro.cookies.get('language')?.value ?? await getH
Departured at: {f.departureTime.toISOString()} <br /> Departured at: {f.departureTime.toISOString()} <br />
Arrives: {f.arrivalTime.toISOString()} ({Math.floor((f.arrivalTime.getTime() - new Date().getTime()) / 1000)}) Arrives: {f.arrivalTime.toISOString()} ({Math.floor((f.arrivalTime.getTime() - new Date().getTime()) / 1000)})
</div> </div>
</li>)} </li>)
})}
</ul> </ul>
</div> </div>
</label> </label>
@ -168,6 +180,7 @@ const lang = await getLocales(Astro.cookies.get('language')?.value ?? await getH
<label for="attack"><input type="radio" name="mission" value="ATTACK" id="attack" required />Attack</label> <label for="attack"><input type="radio" name="mission" value="ATTACK" id="attack" required />Attack</label>
<label for="transport"><input type="radio" name="mission" value="TRANSPORT" id="transport" />Transport</label> <label for="transport"><input type="radio" name="mission" value="TRANSPORT" id="transport" />Transport</label>
<label for="transfer"><input type="radio" name="mission" value="TRANSFER" id="transfer" />Transfer</label> <label for="transfer"><input type="radio" name="mission" value="TRANSFER" id="transfer" />Transfer</label>
<label><input type="checkbox" name="toSystem" />Send to system</label>
<hr /> <hr />
<h2>Send to:</h2> <h2>Send to:</h2>
<div class="fleet-destination"> <div class="fleet-destination">
@ -340,7 +353,7 @@ const lang = await getLocales(Astro.cookies.get('language')?.value ?? await getH
transition-timing-function: ease; transition-timing-function: ease;
} }
input[type=checkbox] { #fleet-toggle {
position: absolute; position: absolute;
top: -9999px; top: -9999px;
left: -9999px; left: -9999px;
@ -353,7 +366,7 @@ const lang = await getLocales(Astro.cookies.get('language')?.value ?? await getH
cursor: pointer; cursor: pointer;
} }
input[type=checkbox]:checked ~ .fleet-status ul { #fleet-toggle:checked ~ .fleet-status ul {
opacity: 1; opacity: 1;
height: auto; height: auto;
max-height: 1000px; max-height: 1000px;
@ -414,8 +427,9 @@ const lang = await getLocales(Astro.cookies.get('language')?.value ?? await getH
const destinationSector = document.getElementById('destination-sector'); const destinationSector = document.getElementById('destination-sector');
const destinationSystem = document.getElementById('destination-system'); const destinationSystem = document.getElementById('destination-system');
const destinationPlanet = document.getElementById('destination-planet'); const destinationPlanet = document.getElementById('destination-planet');
const toSystemCheckbox = document.querySelector('input[name="toSystem"]');
if(!destinationGalaxy || !destinationSector || !destinationSystem || !destinationPlanet) { if(!destinationGalaxy || !destinationSector || !destinationSystem || !destinationPlanet || !toSystemCheckbox) {
console.error('Could not find destination elements'); console.error('Could not find destination elements');
return; return;
}; };
@ -508,6 +522,14 @@ const lang = await getLocales(Astro.cookies.get('language')?.value ?? await getH
destinationGalaxy.dispatchEvent(new Event('change')); destinationGalaxy.dispatchEvent(new Event('change'));
toSystemCheckbox.addEventListener('change', () => {
if(toSystemCheckbox.checked) {
destinationPlanet.disabled = true;
} else {
destinationPlanet.disabled = false;
}
});
const addNew = document.getElementById('cargo-add-new'); const addNew = document.getElementById('cargo-add-new');
addNew.addEventListener('click', () => { addNew.addEventListener('click', () => {

View File

@ -26,7 +26,7 @@ if(currentPlanet === undefined) {
<NavBar loggedIn="true" active="overview" /> <NavBar loggedIn="true" active="overview" />
<ResourceBar /> <ResourceBar />
<h1>{currentPlanet.name} in {currentPlanet.manager.system.name}</h1> <h1>{currentPlanet.name} in {currentPlanet.system.data.name}</h1>
</Layout> </Layout>
<style> <style>

View File

@ -41,15 +41,18 @@ if(Astro.request.method === "POST") {
<NavBar loggedIn="true" active="systemManager" /> <NavBar loggedIn="true" active="systemManager" />
<ResourceBar /> <ResourceBar />
<h1>Selected system: {currentSystem.name} in {currentSystem.sector.name} in {currentSystem.sector.galaxy.name} <a href="/game/systemManager/select">(change)</a></h1> <h1>Selected system: {currentSystem.data.name} in {currentSystem.data.sector.name} in {currentSystem.data.sector.galaxy.name} <a href="/game/systemManager/select">(change)</a></h1>
<div class="system-links"> <div class="system-links">
<a href="/game/systemManager">Overview</a> <a href="/game/systemManager">Overview</a>
<a href="/game/systemManager/structures">System-wide structures</a> <a href="/game/systemManager/structures">System-wide structures</a>
<a href="/game/systemManager/spaceStations">Space stations</a> <a href="/game/systemManager/spaceStations">Space stations</a>
<a href="/game/systemManager/asteroids">Asteroids</a> <a href="/game/systemManager/asteroids">Asteroids</a>
</div> </div>
<div class="resources">
<p>Resources: {currentSystem.resources.resources.map(r => `${r.id}: ${r.amount}`).join(", ")}</p>
</div>
<div class="planet-list"> <div class="planet-list">
{currentSystem.planets.planets.length === 0 ? <span>No planets in this sector</span> : currentSystem.planets.planets.map(planet => ( {currentSystem.planets.length === 0 ? <span>No planets in this sector</span> : currentSystem.planets.map(planet => (
<div class="planet-card"> <div class="planet-card">
<h2>{planet.name}<div><form method="post"><input type="hidden" name="planetId" value={planet._id.toString()} /><input type="submit" value="Select" /></form></div></h2> <h2>{planet.name}<div><form method="post"><input type="hidden" name="planetId" value={planet._id.toString()} /><input type="submit" value="Select" /></form></div></h2>
<p>Fields: {planet.fields}</p> <p>Fields: {planet.fields}</p>
@ -70,6 +73,10 @@ if(Astro.request.method === "POST") {
</div> </div>
</Layout> </Layout>
<style> <style>
* {
color: white;
}
h1 { h1 {
text-align: center; text-align: center;
color: white; color: white;
@ -95,6 +102,13 @@ if(Astro.request.method === "POST") {
text-decoration: none; text-decoration: none;
} }
.resources {
display: flex;
flex-direction: row;
justify-content: center;
margin-bottom: 1rem;
}
.planet-list { .planet-list {
display: flex; display: flex;
flex-direction: row; flex-direction: row;

View File

@ -36,8 +36,8 @@ const systems = locationManager.getSystemsOwnedBy(checkUser._id);
<div class="systems-list"> <div class="systems-list">
{systems.map(system => ( {systems.map(system => (
<div class="system-card"> <div class="system-card">
<h2>{system.name}</h2> <h2>{system.data.name}</h2>
<div><form method="post"><input type="hidden" name="systemId" value={system._id.toString()} /><input type="submit" value="Select" /></form></div> <div><form method="post"><input type="hidden" name="systemId" value={system.data._id.toString()} /><input type="submit" value="Select" /></form></div>
</div> </div>
))} ))}
</div> </div>

View File

@ -46,7 +46,7 @@ if(Astro.request.method === "POST") {
const lang = await getLocales(Astro.cookies.get('language')?.value ?? await getHighestWeightedLanguage(Astro.request.headers.get('accept-language'))); const lang = await getLocales(Astro.cookies.get('language')?.value ?? await getHighestWeightedLanguage(Astro.request.headers.get('accept-language')));
const modalSet: { [key: string]: { resources: Array<any>, research: Array<any>, buildings: Array<any>, energy: number } } = {}; const modalSet: { [key: string]: { resources: Array<any>, research: Array<any>, structures: Array<any>, energy: number } } = {};
const structureList = currentSystem.structures.structuresDB; const structureList = currentSystem.structures.structuresDB;
for(const structure of structureList) { for(const structure of structureList) {
@ -58,7 +58,7 @@ for(const structure of structureList) {
}; };
}), }),
research: structure.requirements.research, research: structure.requirements.research,
buildings: structure.requirements.buildings, structures: structure.requirements.structures,
energy: structure.energy energy: structure.energy
}; };
} }
@ -67,7 +67,7 @@ for(const structure of structureList) {
<NavBar loggedIn="true" active="systemManager" /> <NavBar loggedIn="true" active="systemManager" />
<ResourceBar /> <ResourceBar />
<h1>Selected system: {currentSystem.name} <a href="/game/systemManager/select">(change)</a></h1> <h1>Selected system: {currentSystem.data.name} <a href="/game/systemManager/select">(change)</a></h1>
<div class="system-links"> <div class="system-links">
<a href="/game/systemManager">Overview</a> <a href="/game/systemManager">Overview</a>
<a href="/game/systemManager/structures">System-wide structures</a> <a href="/game/systemManager/structures">System-wide structures</a>
@ -78,8 +78,8 @@ for(const structure of structureList) {
<div id="structure-modal-details" data-structure-id=""> <div id="structure-modal-details" data-structure-id="">
<h3>Required resources</h3> <h3>Required resources</h3>
<div class="structure-modal-text" id="structure-modal-req-resources">None</div> <div class="structure-modal-text" id="structure-modal-req-resources">None</div>
<h3>Required buildings</h3> <h3>Required structures</h3>
<div class="structure-modal-text" id="structure-modal-req-buildings">None</div> <div class="structure-modal-text" id="structure-modal-req-structures">None</div>
<h3>Required research</h3> <h3>Required research</h3>
<div class="structure-modal-text" id="structure-modal-req-research">None</div> <div class="structure-modal-text" id="structure-modal-req-research">None</div>
</div> </div>
@ -87,6 +87,7 @@ for(const structure of structureList) {
<div class="structure-list"> <div class="structure-list">
{currentSystem.structures.structuresDB.map(structure => ( {currentSystem.structures.structuresDB.map(structure => (
<ItemCard <ItemCard
category="structures"
id={structure.id} id={structure.id}
name={getName(lang, 'structures', structure.id)} name={getName(lang, 'structures', structure.id)}
image={`/images/structures/${structure.id}.jpeg`} image={`/images/structures/${structure.id}.jpeg`}
@ -175,7 +176,7 @@ for(const structure of structureList) {
</style> </style>
<script define:vars={{ modalSet, lang }}> <script define:vars={{ modalSet, lang }}>
const modalResources = document.getElementById("structure-modal-req-resources"); const modalResources = document.getElementById("structure-modal-req-resources");
const modalBuildings = document.getElementById("structure-modal-req-buildings"); const modalStructures = document.getElementById("structure-modal-req-structures");
const modalResearch = document.getElementById("structure-modal-req-research"); const modalResearch = document.getElementById("structure-modal-req-research");
document.querySelectorAll('.item-card-info-button').forEach((el) => { document.querySelectorAll('.item-card-info-button').forEach((el) => {
@ -186,15 +187,15 @@ for(const structure of structureList) {
modalDiv.style.display = 'block'; modalDiv.style.display = 'block';
const reqResources = modalSet[el.parentElement.parentElement.dataset.id]?.resources ?? []; const reqResources = modalSet[el.parentElement.parentElement.dataset.id]?.resources ?? [];
const reqBuildings = modalSet[el.parentElement.parentElement.dataset.id]?.buildings ?? []; const reqStructures = modalSet[el.parentElement.parentElement.dataset.id]?.structures ?? [];
const reqResearch = modalSet[el.parentElement.parentElement.dataset.id]?.research ?? []; const reqResearch = modalSet[el.parentElement.parentElement.dataset.id]?.research ?? [];
modalResources.innerHTML = reqResources.length === 0 ? "None" : reqResources.map(resource => { modalResources.innerHTML = reqResources.length === 0 ? "None" : reqResources.map(resource => {
return `${lang['resources'].find(r => r.id === resource.id).name}: ${resource.amount}`; return `${lang['resources'].find(r => r.id === resource.id).name}: ${resource.amount}`;
}).join("<br />"); }).join("<br />");
modalBuildings.innerHTML = reqBuildings.length === 0 ? "None" : reqBuildings.map(building => { modalStructures.innerHTML = reqStructures.length === 0 ? "None" : reqStructures.map(structure => {
return `${lang['buildings'].find(b => b.id === building.id).name}: ${building.level}`; return `${lang['structures'].find(s => s.id === structure.id).name}: ${structure.level}`;
}).join("<br />"); }).join("<br />");
modalResearch.innerHTML = reqResearch.length === 0 ? "None" : reqResearch.map(research => { modalResearch.innerHTML = reqResearch.length === 0 ? "None" : reqResearch.map(research => {

View File

@ -5,7 +5,7 @@ export default interface DBStructure {
id: string; id: string;
description: string; description: string;
requirements: { requirements: {
buildings: Array<{ id: string, level: number }>, structures: Array<{ id: string, level: number }>,
research: Array<{ id: string, level: number }>, research: Array<{ id: string, level: number }>,
resources: Array<{ id: string, amount: number }>, resources: Array<{ id: string, amount: number }>,
}; };

View File

@ -9,4 +9,12 @@ export default interface DBSystem {
level: number level: number
}>; }>;
planets: Array<ObjectId>; planets: Array<ObjectId>;
resources: Array<{
id: string,
amount: number
}>;
ships: Array<{
id: string,
amount: number
}>;
} }