Implement spying mechanic
This commit is contained in:
parent
75d936b78a
commit
b21665ecae
|
@ -1,15 +1,16 @@
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
import MissionType from "../../../types/MissionType";
|
import MissionType from "../../../types/MissionType";
|
||||||
import DBFleet from "../../../types/db/DBFleet";
|
import DBFleet from "../../../types/db/DBFleet";
|
||||||
|
import { getAllDefenses } from "../../db/defenses";
|
||||||
import { updateFleet } from "../../db/fleet";
|
import { updateFleet } from "../../db/fleet";
|
||||||
import { sendMail } from "../../db/mails";
|
import { sendMail } from "../../db/mails";
|
||||||
import { getAllShips } from "../../db/ships";
|
import { getAllShips } from "../../db/ships";
|
||||||
|
import { addPlanetToExistingSpyReport, addSpyReport, getSpyReportBySystemId, updatePlanetSpyReport, updateSystemSpyReportWithoutPlanets } from "../../db/spyReports";
|
||||||
import getDistanceBetween from "../../utils/getDistanceBetween";
|
import getDistanceBetween from "../../utils/getDistanceBetween";
|
||||||
import { getRandomInRange, weightedRandom } from "../../utils/math";
|
import { getRandomInRange, weightedRandom } from "../../utils/math";
|
||||||
import { Sector } from "./LocationManager";
|
import { Sector } from "./LocationManager";
|
||||||
import { Planet } from "./PlanetManager";
|
import { Planet } from "./PlanetManager";
|
||||||
import SystemManager from "./SystemManager";
|
import SystemManager from "./SystemManager";
|
||||||
import { getAllDefenses } from "../../db/defenses";
|
|
||||||
|
|
||||||
export type Fleet = {
|
export type Fleet = {
|
||||||
id: ObjectId,
|
id: ObjectId,
|
||||||
|
@ -174,6 +175,86 @@ export default class FleetManager {
|
||||||
|
|
||||||
system.asteroids.asteroids = system.asteroids.asteroids.filter(a => !a.id.equals(asteroid.id));
|
system.asteroids.asteroids = system.asteroids.asteroids.filter(a => !a.id.equals(asteroid.id));
|
||||||
await system.asteroids.sync();
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,3 +99,8 @@ export const Mails = async() => {
|
||||||
const db = await getDB();
|
const db = await getDB();
|
||||||
return db.collection('mails');
|
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 DBUser from '../../types/db/DBUser';
|
||||||
import User from '../classes/User';
|
import User from '../classes/User';
|
||||||
import AccessToken from '../../types/AccessToken';
|
import AccessToken from '../../types/AccessToken';
|
||||||
|
import { getSpyReportById } from './spyReports';
|
||||||
|
import DBSpyReport from '../../types/db/DBSpyReport';
|
||||||
|
|
||||||
export const getAllUsers = async () => {
|
export const getAllUsers = async () => {
|
||||||
const users = await Users();
|
const users = await Users();
|
||||||
|
@ -20,7 +22,8 @@ export const createUser = async (id: ObjectId, username: string, email: string,
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
research: [],
|
research: [],
|
||||||
mainPlanet
|
mainPlanet,
|
||||||
|
spyReports: []
|
||||||
}
|
}
|
||||||
|
|
||||||
await (await Users()).insertOne(user);
|
await (await Users()).insertOne(user);
|
||||||
|
@ -76,3 +79,23 @@ export const updateUserResearch = async (user: User, research: Array<{ id: strin
|
||||||
const users = await Users();
|
const users = await Users();
|
||||||
users.updateOne({ username: user.username }, { $set: { research } });
|
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 SystemManager from '../../lib/classes/managers/SystemManager';
|
||||||
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 { getUserSpyReports } from '../../lib/db/users';
|
||||||
import { getName } from '../../lib/utils/langDriver';
|
import { getName } from '../../lib/utils/langDriver';
|
||||||
|
|
||||||
const { token, user, lang } = Astro.locals;
|
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 => {
|
const sectorsList = galaxies.map(galaxy => {
|
||||||
return {
|
return {
|
||||||
_id: galaxy._id,
|
_id: galaxy._id,
|
||||||
|
@ -98,6 +101,13 @@ const sectorsList = galaxies.map(galaxy => {
|
||||||
_id: sector._id,
|
_id: sector._id,
|
||||||
name: sector.name,
|
name: sector.name,
|
||||||
systems: sector.systems.map(system => {
|
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 {
|
return {
|
||||||
_id: system.data._id,
|
_id: system.data._id,
|
||||||
name: system.data.name,
|
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="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 for="expedition"><input type="radio" name="mission" value="EXPEDITION" id="expedition" />Expedition</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>
|
<label><input type="checkbox" name="toSystem" />Send to system</label>
|
||||||
<hr />
|
<hr />
|
||||||
<h2>Send to:</h2>
|
<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;
|
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;
|
updatedAt: Date;
|
||||||
research: Array<{ id: string, level: number }>;
|
research: Array<{ id: string, level: number }>;
|
||||||
mainPlanet: ObjectId;
|
mainPlanet: ObjectId;
|
||||||
|
spyReports: Array<ObjectId>;
|
||||||
}
|
}
|
Loading…
Reference in New Issue