From e3be290d3d76bd7352c796c6b21f007c383f3736 Mon Sep 17 00:00:00 2001 From: Aelita4 Date: Fri, 7 Feb 2025 11:11:35 +0100 Subject: [PATCH] Implement colonization mechanic --- src/lib/classes/managers/FleetManager.ts | 142 ++++++++++++++++++++++- src/lib/db/systems.ts | 9 ++ src/pages/api/fleet/send.ts | 7 ++ src/pages/game/fleet.astro | 8 +- src/types/MissionType.ts | 2 +- 5 files changed, 164 insertions(+), 4 deletions(-) diff --git a/src/lib/classes/managers/FleetManager.ts b/src/lib/classes/managers/FleetManager.ts index 1cb81f0..2dd3631 100644 --- a/src/lib/classes/managers/FleetManager.ts +++ b/src/lib/classes/managers/FleetManager.ts @@ -10,7 +10,17 @@ import getDistanceBetween from "../../utils/getDistanceBetween"; import { getRandomInRange, weightedRandom } from "../../utils/math"; import { Sector } from "./LocationManager"; import { Planet } from "./PlanetManager"; -import SystemManager from "./SystemManager"; +import SystemManager, { System } from "./SystemManager"; +import DBSystem from "../../../types/db/DBSystem"; +import { addPlanetToSystem, createSystem, getSystemById } from "../../db/systems"; +import DBPlanet from "../../../types/db/DBPlanet"; +import { createPlanet } from "../../db/planets"; +import PlanetResourceManager from "./PlanetResourceManager"; +import BuildingManager from "./BuildingManager"; +import PlanetShipManager from "./PlanetShipManager"; +import PlanetDefenseManager from "./PlanetDefenseManager"; +import PlanetEnergyManager from "./PlanetEnergyManager"; +import { addSystemToSector } from "../../db/sectors"; export type Fleet = { id: ObjectId, @@ -256,6 +266,136 @@ export default class FleetManager { await this.initiateReturn(); return false; + case 'COLONIZE': + const destination = this.data.destination as Sector | SystemManager; + + if(destination instanceof SystemManager) { + if(!destination.data.ownedBy.id.equals(this.data.source instanceof SystemManager ? this.data.source.data.ownedBy.id : this.data.source.system.data.ownedBy.id)) { + throw new Error("Cannot colonize system owned by other player."); + } + + const planetData: DBPlanet = { + _id: new ObjectId(), + name: `Planet 1`, + owner: destination.data.ownedBy.id, + fields: 40, + resources: [], + buildings: [], + ships: [], + defenses: [] + } + + await createPlanet(planetData); + await addPlanetToSystem(destination.data._id, planetData._id); + + const planetObject: Planet = { + _id: planetData._id, + system: destination, + name: planetData.name, + fields: planetData.fields, + //@ts-ignore + resources: null, + //@ts-ignore + buildings: null, + //@ts-ignore + ships: null, + //@ts-ignore + defenses: null, + //@ts-ignore + energy: null + } + + planetObject.resources = await new PlanetResourceManager(planetObject).init(planetData.resources); + planetObject.buildings = await new BuildingManager(planetObject).init(planetData.buildings); + planetObject.ships = await new PlanetShipManager(planetObject).init(planetData.ships); + planetObject.defenses = await new PlanetDefenseManager(planetObject).init(planetData.defenses); + planetObject.energy = new PlanetEnergyManager(planetObject).update(); + + for(const ship of this.data.ships) { + if(ship.id === "colonizing-ship") continue; + planetObject.ships.addShips(ship.id, ship.amount); + } + planetObject.resources.setAmount(this.data.cargo); + + destination.planets.push(planetObject); + + await sendMail( + null, + this.data.source instanceof SystemManager ? this.data.source.data.ownedBy.id : this.data.source.system.data.ownedBy.id, + this.data.arrivalTime, + "New planet colonized", + `Your fleet has found a suitable planet for colonization in ${destination.data.name} system.\n + All the ships and resources have been used to establish a new colony.` + ); + } else { + const systemData: DBSystem = { + _id: new ObjectId(), + name: `System ${destination.systems.length + 1}`, + ownedBy: this.data.source instanceof SystemManager ? this.data.source.data.ownedBy.id : this.data.source.system.data.ownedBy.id, + planets: [], + structures: [], + resources: [], + ships: [], + defenses: [], + asteroids: [] + } + + const planetData: DBPlanet = { + _id: new ObjectId(), + name: `Planet 1`, + owner: systemData.ownedBy, + fields: 40, + resources: [], + buildings: [], + ships: [], + defenses: [] + } + + systemData.planets.push(planetData._id); + + await createSystem(systemData); + await createPlanet(planetData); + await addPlanetToSystem(systemData._id, planetData._id); + await addSystemToSector(destination._id, systemData._id); + + const systemObject: System = { + _id: systemData._id, + sector: destination, + name: systemData.name, + ownedBy: this.data.source instanceof SystemManager ? this.data.source.data.ownedBy : this.data.source.system.data.ownedBy, + //@ts-ignore + structures: null, + //@ts-ignore + resources: null, + //@ts-ignore + ships: null, + //@ts-ignore + defenses: null, + planets: [], + asteroids: [] + } + + const systemManager = await new SystemManager(systemObject).fillData(systemData); + const planet = systemManager.planets.find(p => p._id.equals(planetData._id)); + if(!planet) throw new Error("FATAL: Planet was not created properly in system manager."); + for(const ship of this.data.ships) { + if(ship.id === "colonizing-ship") continue; + planet.ships.addShips(ship.id, ship.amount); + } + planet.resources.setAmount(this.data.cargo); + destination.systems.push(systemManager); + + await sendMail( + null, + this.data.source instanceof SystemManager ? this.data.source.data.ownedBy.id : this.data.source.system.data.ownedBy.id, + this.data.arrivalTime, + "New system colonized", + `Your fleet has settled on a planet ${planet.name} in a new system ${systemManager.data.name} in ${destination.name} sector.\n + All the ships and resources have been used to establish a new colony.` + ); + } + + return true; } } } diff --git a/src/lib/db/systems.ts b/src/lib/db/systems.ts index faee6c9..b84b639 100644 --- a/src/lib/db/systems.ts +++ b/src/lib/db/systems.ts @@ -18,6 +18,15 @@ export const createSystem = async (system: DBSystem) => { return await systems.insertOne(system); } +export const addPlanetToSystem = async (systemId: ObjectId, planetId: ObjectId) => { + const systems = await Systems(); + await systems.updateOne({ _id: systemId }, { + $push: { + planets: planetId + } + }); +} + export const updateSystemStructures = async (systemId: ObjectId, structures: Array<{ id: string, level: number }>) => { const systems = await Systems(); await systems.updateOne({ _id: systemId }, { diff --git a/src/pages/api/fleet/send.ts b/src/pages/api/fleet/send.ts index 9a955a4..0b31351 100644 --- a/src/pages/api/fleet/send.ts +++ b/src/pages/api/fleet/send.ts @@ -69,6 +69,13 @@ export const POST: APIRoute = async({ request }) => { const destinationSector = checkSectorId(body.destination); if(typeof destinationSector.error !== "undefined") return new Response(JSON.stringify(destinationSector), { status: destinationSector.code }); dest = destinationSector.sector; + } else if(body.mission === "COLONIZE") { + const destinationSector = checkSectorId(body.destination); + if(typeof destinationSector.error !== "undefined") { + const destinationSystem = checkPlanetOrSystemId(body.destination, 'destination'); + if(typeof destinationSystem.error !== "undefined") return new Response(JSON.stringify(destinationSystem), { status: destinationSystem.code }); + dest = destinationSystem.planetOrSystem; + } else dest = destinationSector.sector; } else if(body.mission === "MINE") { const checkAsteroid = checkAsteroidId(body.destination, body.currentSystem ?? ""); if(typeof checkAsteroid.error !== "undefined") return new Response(JSON.stringify(checkAsteroid), { status: checkAsteroid.code }); diff --git a/src/pages/game/fleet.astro b/src/pages/game/fleet.astro index 36e8f96..1ef18dc 100644 --- a/src/pages/game/fleet.astro +++ b/src/pages/game/fleet.astro @@ -33,8 +33,11 @@ if(Astro.request.method === "POST") { } }); - const destination = form.get('mission') === "EXPEDITION" ? - form.get('destination-sector')?.toString() : + const destination = form.get('mission') === "EXPEDITION" || form.get('mission') === "COLONIZE" ? + form.get('toSystem') ? + form.get('destination-system')?.toString() : + form.get('destination-sector')?.toString() + : form.get('toSystem') ? form.get('destination-system')?.toString() : form.get('destination-planet')?.toString(); @@ -170,6 +173,7 @@ const sectorsList = galaxies.map(galaxy => { +

Send to

diff --git a/src/types/MissionType.ts b/src/types/MissionType.ts index eb4bec8..f689984 100644 --- a/src/types/MissionType.ts +++ b/src/types/MissionType.ts @@ -1,3 +1,3 @@ -type MissionType = "TRANSPORT" | "ATTACK" | "TRANSFER" | "EXPEDITION" | "MINE" | "SPY"; +type MissionType = "TRANSPORT" | "ATTACK" | "TRANSFER" | "EXPEDITION" | "MINE" | "SPY" | "COLONIZE"; export default MissionType; \ No newline at end of file