Implement spying mechanic
This commit is contained in:
parent
75d936b78a
commit
b21665ecae
|
@ -1,15 +1,16 @@
|
|||
import { ObjectId } from "mongodb";
|
||||
import MissionType from "../../../types/MissionType";
|
||||
import DBFleet from "../../../types/db/DBFleet";
|
||||
import { getAllDefenses } from "../../db/defenses";
|
||||
import { updateFleet } from "../../db/fleet";
|
||||
import { sendMail } from "../../db/mails";
|
||||
import { getAllShips } from "../../db/ships";
|
||||
import { addPlanetToExistingSpyReport, addSpyReport, getSpyReportBySystemId, updatePlanetSpyReport, updateSystemSpyReportWithoutPlanets } from "../../db/spyReports";
|
||||
import getDistanceBetween from "../../utils/getDistanceBetween";
|
||||
import { getRandomInRange, weightedRandom } from "../../utils/math";
|
||||
import { Sector } from "./LocationManager";
|
||||
import { Planet } from "./PlanetManager";
|
||||
import SystemManager from "./SystemManager";
|
||||
import { getAllDefenses } from "../../db/defenses";
|
||||
|
||||
export type Fleet = {
|
||||
id: ObjectId,
|
||||
|
@ -174,6 +175,86 @@ export default class FleetManager {
|
|||
|
||||
system.asteroids.asteroids = system.asteroids.asteroids.filter(a => !a.id.equals(asteroid.id));
|
||||
await system.asteroids.sync();
|
||||
return false;
|
||||
case 'SPY':
|
||||
if(this.data.destination instanceof SystemManager) {
|
||||
const existing = await getSpyReportBySystemId(this.data.destination.data._id);
|
||||
|
||||
if(existing) {
|
||||
await updateSystemSpyReportWithoutPlanets(
|
||||
existing._id,
|
||||
this.data.destination.resources.resources,
|
||||
this.data.destination.structures.structures.map(structure => { return { id: structure.data.id, level: structure.level } }),
|
||||
this.data.destination.ships.ships.map(ship => { return { id: ship.data.id, amount: ship.amount } }),
|
||||
this.data.destination.defenses.defenses.map(defense => { return { id: defense.data.id, amount: defense.amount } })
|
||||
);
|
||||
} else {
|
||||
const gatheredData = {
|
||||
systemId: this.data.destination.data._id,
|
||||
resources: this.data.destination.resources.resources.map(res => { return { id: res.id, amount: res.amount } }),
|
||||
structures: this.data.destination.structures.structures.map(structure => { return { id: structure.data.id, level: structure.level } }),
|
||||
ships: this.data.destination.ships.ships.map(ship => { return { id: ship.data.id, amount: ship.amount } }),
|
||||
defense: this.data.destination.defenses.defenses.map(defense => { return { id: defense.data.id, amount: defense.amount } }),
|
||||
planets: []
|
||||
}
|
||||
|
||||
await addSpyReport(
|
||||
this.data.source instanceof SystemManager ? this.data.source.data.ownedBy.id : this.data.source.system.data.ownedBy.id,
|
||||
this.data.destination.data.ownedBy.id,
|
||||
new Date(),
|
||||
[],
|
||||
gatheredData
|
||||
);
|
||||
}
|
||||
} else if("fields" in this.data.destination) {
|
||||
const existing = await getSpyReportBySystemId(this.data.destination.system.data._id);
|
||||
|
||||
if(!existing) {
|
||||
throw new Error("Impossible to spy on planet without system report.");
|
||||
}
|
||||
|
||||
const gatheredData = {
|
||||
resources: this.data.destination.resources.resources.map(res => { return { id: res.id, amount: res.amount } }),
|
||||
buildings: this.data.destination.buildings.buildings.map(building => { return { id: building.data.id, level: building.level } }),
|
||||
ships: this.data.destination.ships.ships.map(ship => { return { id: ship.data.id, amount: ship.amount } }),
|
||||
defense: this.data.destination.defenses.defenses.map(defense => { return { id: defense.data.id, amount: defense.amount } })
|
||||
}
|
||||
|
||||
const planetId = this.data.destination._id;
|
||||
if(existing.planets.find(p => p.id.equals(planetId))) {
|
||||
await updatePlanetSpyReport(existing._id, planetId, gatheredData);
|
||||
} else {
|
||||
await addPlanetToExistingSpyReport(existing._id, gatheredData);
|
||||
}
|
||||
}
|
||||
|
||||
await sendMail(
|
||||
null,
|
||||
this.data.source instanceof SystemManager ? this.data.source.data.ownedBy.id : this.data.source.system.data.ownedBy.id,
|
||||
this.data.arrivalTime,
|
||||
"Spy report",
|
||||
`Your fleet has arrived at ${this.data.destination instanceof SystemManager ? `${this.data.destination.data.name} system` : `planet ${this.data.destination.name}`}.\n
|
||||
Following information was gathered:\n\n
|
||||
${this.data.destination instanceof SystemManager ? `Research:\n${this.data.destination.data.ownedBy.research.research.map(research => `${research.id} - ${research.level}`).join('\n')}\n` : ""}
|
||||
Resources:\n${(this.data.destination as Planet | SystemManager).resources.resources.map(res => `${res.amount} ${res.id}`).join('\n')}\n
|
||||
${this.data.destination instanceof SystemManager ? `Structures:\n${(this.data.destination as SystemManager).structures.structures.map(structure => `${structure.level} ${structure.data.id}`).join('\n')}\n` : `Buildings:\n${(this.data.destination as Planet).buildings.buildings.map(building => `${building.level} ${building.data.id}`).join('\n')}\n`}
|
||||
Ships:\n${(this.data.destination as Planet | SystemManager).ships.ships.map(ship => `${ship.amount} ${ship.data.id}`).join('\n')}\n
|
||||
Defense:\n${(this.data.destination as Planet | SystemManager).defenses.defenses.map(defense => `${defense.amount} ${defense.data.id}`).join('\n')}\n
|
||||
${this.data.destination instanceof SystemManager ? `Planets:\n${(this.data.destination as SystemManager).planets.map(planet => `${planet.name}`).join('\n')}` : ""}
|
||||
Fleet will return at ${this.data.arrivalTime}`
|
||||
);
|
||||
|
||||
await sendMail(
|
||||
null,
|
||||
this.data.destination instanceof SystemManager ? this.data.destination.data.ownedBy.id : (this.data.destination as Planet).system.data.ownedBy.id,
|
||||
this.data.arrivalTime,
|
||||
"Spy probe detected",
|
||||
`Your systems have detected enemy spy probe at ${this.data.destination instanceof SystemManager ? `${this.data.destination.data.name} system` : `planet ${this.data.destination.name}`}.\n
|
||||
Probe was identified to belong to ${this.data.source instanceof SystemManager ? this.data.source.data.ownedBy.username : this.data.source.system.data.ownedBy.username}.`
|
||||
);
|
||||
|
||||
await this.initiateReturn();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,3 +99,8 @@ export const Mails = async() => {
|
|||
const db = await getDB();
|
||||
return db.collection('mails');
|
||||
}
|
||||
|
||||
export const SpyReports = async() => {
|
||||
const db = await getDB();
|
||||
return db.collection('spyReports');
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
import { ObjectId } from "mongodb";
|
||||
import { SpyReports } from "./mongodb"
|
||||
import DBSpyReport, { DBSpyReportPlanet } from "../../types/db/DBSpyReport";
|
||||
import { addSpyReportToUser } from "./users";
|
||||
|
||||
export const getSpyReportById = async (id: ObjectId) => {
|
||||
return await (await SpyReports()).findOne({
|
||||
_id: id
|
||||
}) as DBSpyReport;
|
||||
}
|
||||
|
||||
export const getSpyReportBySystemId = async (id: ObjectId) => {
|
||||
return await (await SpyReports()).findOne({
|
||||
systemId: id
|
||||
}) as DBSpyReport;
|
||||
}
|
||||
|
||||
export const addSpyReport = async (
|
||||
toPlayer: ObjectId,
|
||||
victimId: ObjectId,
|
||||
scannedAt: Date,
|
||||
research: Array<{ id: string, level: number }>,
|
||||
data: {
|
||||
systemId: ObjectId,
|
||||
resources: Array<{ id: string, amount: number }>,
|
||||
structures: Array<{ id: string, level: number }>,
|
||||
ships: Array<{ id: string, amount: number }>,
|
||||
defense: Array<{ id: string, amount: number }>,
|
||||
planets: Array<DBSpyReportPlanet>
|
||||
}
|
||||
) => {
|
||||
const report = await (await SpyReports()).insertOne({
|
||||
victimId,
|
||||
scannedAt,
|
||||
research,
|
||||
systemId: data.systemId,
|
||||
resources: data.resources,
|
||||
structures: data.structures,
|
||||
ships: data.ships,
|
||||
defense: data.defense,
|
||||
planets: data.planets
|
||||
});
|
||||
|
||||
await addSpyReportToUser(toPlayer, report.insertedId);
|
||||
}
|
||||
|
||||
export const updateSystemSpyReportWithoutPlanets = async (
|
||||
id: ObjectId,
|
||||
resources: Array<{ id: string, amount: number }>,
|
||||
structures: Array<{ id: string, level: number }>,
|
||||
ships: Array<{ id: string, amount: number }>,
|
||||
defense: Array<{ id: string, amount: number }>
|
||||
) => {
|
||||
await (await SpyReports()).updateOne({
|
||||
_id: id
|
||||
}, {
|
||||
$set: {
|
||||
resources,
|
||||
structures,
|
||||
ships,
|
||||
defense
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export const addPlanetToExistingSpyReport = async (
|
||||
id: ObjectId,
|
||||
data: {
|
||||
resources: Array<{ id: string, amount: number }>,
|
||||
buildings: Array<{ id: string, level: number }>,
|
||||
ships: Array<{ id: string, amount: number }>,
|
||||
defense: Array<{ id: string, amount: number }>
|
||||
}
|
||||
) => {
|
||||
await (await SpyReports()).updateOne({
|
||||
_id: id
|
||||
}, {
|
||||
$push: {
|
||||
planets: {
|
||||
id: new ObjectId(),
|
||||
scanned: true,
|
||||
scannedAt: new Date(),
|
||||
resources: data.resources,
|
||||
buildings: data.buildings,
|
||||
ships: data.ships,
|
||||
defense: data.defense
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export const updatePlanetSpyReport = async (
|
||||
id: ObjectId,
|
||||
planetId: ObjectId,
|
||||
data: {
|
||||
resources: Array<{ id: string, amount: number }>,
|
||||
buildings: Array<{ id: string, level: number }>,
|
||||
ships: Array<{ id: string, amount: number }>,
|
||||
defense: Array<{ id: string, amount: number }>
|
||||
}
|
||||
) => {
|
||||
await (await SpyReports()).updateOne({
|
||||
_id: id,
|
||||
"planets.id": planetId
|
||||
}, {
|
||||
$set: {
|
||||
"planets.$.scanned": true,
|
||||
"planets.$.scannedAt": new Date(),
|
||||
"planets.$.resources": data.resources,
|
||||
"planets.$.buildings": data.buildings,
|
||||
"planets.$.ships": data.ships,
|
||||
"planets.$.defense": data.defense
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export const overwriteSpyReport = async (id: ObjectId, report: DBSpyReport) => {
|
||||
await (await SpyReports()).replaceOne({
|
||||
_id: id
|
||||
}, report);
|
||||
}
|
|
@ -4,6 +4,8 @@ import { hash } from 'argon2'
|
|||
import DBUser from '../../types/db/DBUser';
|
||||
import User from '../classes/User';
|
||||
import AccessToken from '../../types/AccessToken';
|
||||
import { getSpyReportById } from './spyReports';
|
||||
import DBSpyReport from '../../types/db/DBSpyReport';
|
||||
|
||||
export const getAllUsers = async () => {
|
||||
const users = await Users();
|
||||
|
@ -20,7 +22,8 @@ export const createUser = async (id: ObjectId, username: string, email: string,
|
|||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
research: [],
|
||||
mainPlanet
|
||||
mainPlanet,
|
||||
spyReports: []
|
||||
}
|
||||
|
||||
await (await Users()).insertOne(user);
|
||||
|
@ -76,3 +79,23 @@ export const updateUserResearch = async (user: User, research: Array<{ id: strin
|
|||
const users = await Users();
|
||||
users.updateOne({ username: user.username }, { $set: { research } });
|
||||
}
|
||||
|
||||
export const addSpyReportToUser = async (userId: ObjectId, spyReportId: ObjectId) => {
|
||||
const users = await Users();
|
||||
users.updateOne({ _id: userId }, { $push: { spyReports: spyReportId } });
|
||||
}
|
||||
|
||||
export const getUserSpyReports = async (userId: ObjectId) => {
|
||||
const users = await Users();
|
||||
const user = await users.findOne({ _id: userId });
|
||||
if (!user) return [];
|
||||
|
||||
const out: DBSpyReport[] = [];
|
||||
|
||||
for(const spyId of user.spyReports) {
|
||||
const spyReport = await getSpyReportById(spyId);
|
||||
if(spyReport) out.push(spyReport);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
|
@ -5,6 +5,7 @@ import { Planet } from '../../lib/classes/managers/PlanetManager';
|
|||
import SystemManager from '../../lib/classes/managers/SystemManager';
|
||||
import { getAllFleetByUser } from '../../lib/db/fleet';
|
||||
import { getAllShips } from '../../lib/db/ships';
|
||||
import { getUserSpyReports } from '../../lib/db/users';
|
||||
import { getName } from '../../lib/utils/langDriver';
|
||||
|
||||
const { token, user, lang } = Astro.locals;
|
||||
|
@ -89,6 +90,8 @@ for(const f of fleet) {
|
|||
}
|
||||
}
|
||||
|
||||
const discoveredSectors = await getUserSpyReports(user.id);
|
||||
|
||||
const sectorsList = galaxies.map(galaxy => {
|
||||
return {
|
||||
_id: galaxy._id,
|
||||
|
@ -98,6 +101,13 @@ const sectorsList = galaxies.map(galaxy => {
|
|||
_id: sector._id,
|
||||
name: sector.name,
|
||||
systems: sector.systems.map(system => {
|
||||
const discovered = discoveredSectors.find(s => s.systemId.equals(system.data._id));
|
||||
if(!discovered && !system.data.ownedBy.id.equals(user.id)) return {
|
||||
_id: system.data._id,
|
||||
name: `${system.data.name} (not discovered)`,
|
||||
planets: []
|
||||
}
|
||||
|
||||
return {
|
||||
_id: system.data._id,
|
||||
name: system.data.name,
|
||||
|
@ -158,6 +168,7 @@ const sectorsList = galaxies.map(galaxy => {
|
|||
<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="expedition"><input type="radio" name="mission" value="EXPEDITION" id="expedition" />Expedition</label>
|
||||
<label for="spy"><input type="radio" name="mission" value="SPY" id="spy" />Spying</label>
|
||||
<label><input type="checkbox" name="toSystem" />Send to system</label>
|
||||
<hr />
|
||||
<h2>Send to:</h2>
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
type MissionType = "TRANSPORT" | "ATTACK" | "TRANSFER" | "EXPEDITION" | "MINE";
|
||||
type MissionType = "TRANSPORT" | "ATTACK" | "TRANSFER" | "EXPEDITION" | "MINE" | "SPY";
|
||||
|
||||
export default MissionType;
|
|
@ -0,0 +1,16 @@
|
|||
export default interface SpyData {
|
||||
id: string;
|
||||
resources: Array<{ id: string, amount: number }>;
|
||||
structures: Array<{ id: string, level: number }>;
|
||||
ships: Array<{ id: string, amount: number }>;
|
||||
defense: Array<{ id: string, amount: number }>;
|
||||
planets: Array<{
|
||||
id: string;
|
||||
scanned: boolean;
|
||||
scannedAt: Date;
|
||||
resources: Array<{ id: string, amount: number }>;
|
||||
buildings: Array<{ id: string, level: number }>;
|
||||
ships: Array<{ id: string, amount: number }>;
|
||||
defense: Array<{ id: string, amount: number }>;
|
||||
}>;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
import { ObjectId } from "mongodb";
|
||||
|
||||
export interface DBSpyReportPlanet {
|
||||
id: ObjectId;
|
||||
scanned: boolean;
|
||||
scannedAt: Date;
|
||||
resources: Array<{ id: string, amount: number }>;
|
||||
buildings: Array<{ id: string, level: number }>;
|
||||
ships: Array<{ id: string, amount: number }>;
|
||||
defense: Array<{ id: string, amount: number }>;
|
||||
}
|
||||
|
||||
export default interface DBSpyReport {
|
||||
_id: ObjectId;
|
||||
victimId: ObjectId;
|
||||
scannedAt: Date;
|
||||
research: Array<{ id: string, level: number }>;
|
||||
systemId: ObjectId;
|
||||
resources: Array<{ id: string, amount: number }>;
|
||||
structures: Array<{ id: string, level: number }>;
|
||||
ships: Array<{ id: string, amount: number }>;
|
||||
defense: Array<{ id: string, amount: number }>;
|
||||
planets: Array<DBSpyReportPlanet>;
|
||||
}
|
|
@ -10,4 +10,5 @@ export default interface DBUser {
|
|||
updatedAt: Date;
|
||||
research: Array<{ id: string, level: number }>;
|
||||
mainPlanet: ObjectId;
|
||||
spyReports: Array<ObjectId>;
|
||||
}
|
Loading…
Reference in New Issue