Compare commits
2 Commits
b13a116cd4
...
cc5d482a0f
Author | SHA1 | Date |
---|---|---|
Aelita4 | cc5d482a0f | |
Aelita4 | 56eabc303e |
|
@ -3,6 +3,7 @@ import { getHighestWeightedLanguage, getLocales, getName } from '../lib/utils/la
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
id: string;
|
id: string;
|
||||||
|
level: string;
|
||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description: string;
|
||||||
image: string;
|
image: string;
|
||||||
|
@ -17,7 +18,7 @@ const lang = await getLocales(await getHighestWeightedLanguage(Astro.request.hea
|
||||||
<div class="item-card" data-id={Astro.props.id}>
|
<div class="item-card" data-id={Astro.props.id}>
|
||||||
<img class="item-card-image" src={Astro.props.image} />
|
<img class="item-card-image" src={Astro.props.image} />
|
||||||
<div class="item-card-main-field">
|
<div class="item-card-main-field">
|
||||||
<div class="item-card-name">{Astro.props.name}</div>
|
<div class="item-card-name">{Astro.props.name} | {Astro.props.level}</div>
|
||||||
<div class="item-card-description">{Astro.props.description}</div>
|
<div class="item-card-description">{Astro.props.description}</div>
|
||||||
<a id={`button_${Astro.props.id}`} href="#" class="item-card-build">{getName(lang, Astro.props.button_type, Astro.props.button_name)}</a>
|
<a id={`button_${Astro.props.id}`} href="#" class="item-card-build">{getName(lang, Astro.props.button_type, Astro.props.button_name)}</a>
|
||||||
<div class="item-card-info-button">i</div>
|
<div class="item-card-info-button">i</div>
|
||||||
|
|
|
@ -1,20 +1,26 @@
|
||||||
---
|
---
|
||||||
import { ObjectId } from 'mongodb';
|
import { ObjectId } from 'mongodb';
|
||||||
import { calculateCurrentAvailableResources } from '../lib/utils/resourceManager';
|
|
||||||
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 { Resource } from '../lib/classes/managers/ResourceManager';
|
||||||
|
|
||||||
const resourceTypes = await getAllResources();
|
const resourceTypes = await getAllResources();
|
||||||
|
|
||||||
const lang = await getLocales(await getHighestWeightedLanguage(Astro.request.headers.get('accept-language')));
|
const lang = await getLocales(await getHighestWeightedLanguage(Astro.request.headers.get('accept-language')));
|
||||||
|
|
||||||
const resources = await calculateCurrentAvailableResources(new ObjectId(Astro.cookies.get('planetid')?.value ?? ''));
|
const planetId = new ObjectId(Astro.cookies.get('planetid')?.value ?? '');
|
||||||
|
|
||||||
const resourceArray = [];
|
const resources = locationManager.getPlanet(planetId)?.resources;
|
||||||
for(const key in resources) {
|
|
||||||
resourceArray.push(resources[key as never]);
|
if(!resources) return;
|
||||||
|
|
||||||
|
resources.calculateCurrentAvailableResources();
|
||||||
|
|
||||||
|
const resourceArray: Resource[] = [];
|
||||||
|
for(const key of resources.resources) {
|
||||||
|
resourceArray.push(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
<div id="resourcebar">
|
<div id="resourcebar">
|
||||||
<div class="resourcebar-item-identifier">
|
<div class="resourcebar-item-identifier">
|
||||||
|
@ -23,16 +29,16 @@ for(const key in resources) {
|
||||||
<div id="resourcebar-elements" class="resourcebar-elements">
|
<div id="resourcebar-elements" class="resourcebar-elements">
|
||||||
{resourceArray.map(res =>
|
{resourceArray.map(res =>
|
||||||
<div class="resourcebar-item"
|
<div class="resourcebar-item"
|
||||||
data-res-type={resourceTypes.find(x => x.id === res.name)?.type ?? "solid"}
|
data-res-type={resourceTypes.find(x => x.id === res.id)?.type ?? "solid"}
|
||||||
data-res-amount={res.amount}
|
data-res-amount={res.amount}
|
||||||
data-res-mining-rate={res.perHourMiningRate}
|
data-res-mining-rate={res.perHourMiningRate}
|
||||||
style={(resourceTypes.find(x => x.id === res.name)?.type ?? "solid") === "solid" ? "" : "display: none;"}
|
style={(resourceTypes.find(x => x.id === res.id)?.type ?? "solid") === "solid" ? "" : "display: none;"}
|
||||||
>
|
>
|
||||||
<div class="resourcebar-item-icon">
|
<div class="resourcebar-item-icon">
|
||||||
<img src={resourceTypes.find(x => x.id === res.name)?.icon ?? "#"} alt={res.name} />
|
<img src={resourceTypes.find(x => x.id === res.id)?.icon ?? "#"} alt={res.id} />
|
||||||
</div>
|
</div>
|
||||||
<div class="resourcebar-item-text-wrapper" data-resname={res.name}>
|
<div class="resourcebar-item-text-wrapper" data-resname={res.id}>
|
||||||
<div class="resourcebar-item-text">{getName(lang, 'resources', res.name)}</div>
|
<div class="resourcebar-item-text">{getName(lang, 'resources', res.id)}</div>
|
||||||
<div class="resourcebar-item-amount">[fetching]</div>
|
<div class="resourcebar-item-amount">[fetching]</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="resourcebar-item-tooltip">
|
<div class="resourcebar-item-tooltip">
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
import DBBuilding from "../../types/db/DBBuilding";
|
||||||
|
import BuildingManager from "./managers/BuildingManager";
|
||||||
|
|
||||||
|
export default class Building {
|
||||||
|
manager: BuildingManager
|
||||||
|
data: DBBuilding;
|
||||||
|
level: number;
|
||||||
|
|
||||||
|
constructor(manager: BuildingManager, data: DBBuilding, level: number) {
|
||||||
|
this.manager = manager;
|
||||||
|
this.data = data;
|
||||||
|
this.level = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkRequiredResources(level: number): Promise<boolean> {
|
||||||
|
const resources = await this.manager.planet.resources.calculateCurrentAvailableResources();
|
||||||
|
|
||||||
|
const requirements = this.data.requirements.resources;
|
||||||
|
|
||||||
|
let canBuild = true;
|
||||||
|
|
||||||
|
for(let res of requirements) {
|
||||||
|
const resource = resources.find(r => r.id === res.id);
|
||||||
|
if(!resource) return false;
|
||||||
|
|
||||||
|
const required = Math.pow(this.data.multiplier, level) * res.amount;
|
||||||
|
|
||||||
|
if(resource.amount < required) {
|
||||||
|
canBuild = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return canBuild;
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkRequirements(): Promise<{ canBuild: boolean, error: string }> {
|
||||||
|
const playerBuildings = this.manager.buildings;
|
||||||
|
let playerBuildingsCanBuild = { canBuild: true, missing: "" };
|
||||||
|
this.data.requirements.buildings.forEach((buildingReq: any) => {
|
||||||
|
if(playerBuildings.filter((building) => building.data.id === buildingReq.id)[0]?.level ?? 0 < buildingReq.level) {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// research
|
||||||
|
const playerResearch = this.manager.planet.manager.owner.research;
|
||||||
|
let playerResearchCanBuild = { canBuild: true, missing: "" };
|
||||||
|
for(const researchReq of this.data.requirements.research) {
|
||||||
|
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}` };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if(!playerResearchCanBuild.canBuild) return {
|
||||||
|
canBuild: false,
|
||||||
|
error: playerResearchCanBuild.missing
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
canBuild: true,
|
||||||
|
error: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { ObjectId } from "mongodb";
|
||||||
|
import ResearchManager from "./managers/ResearchManager";
|
||||||
|
import { Planet } from "./managers/PlanetManager";
|
||||||
|
|
||||||
|
export default class User {
|
||||||
|
id: ObjectId;
|
||||||
|
username: string;
|
||||||
|
email: string;
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
|
lastLogin: Date;
|
||||||
|
research: ResearchManager;
|
||||||
|
mainPlanet!: Planet;
|
||||||
|
|
||||||
|
constructor(id: ObjectId, username: string, email: string, createdAt: Date, updatedAt: Date, lastLogin: Date) {
|
||||||
|
this.id = id;
|
||||||
|
this.username = username;
|
||||||
|
this.email = email;
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
this.updatedAt = updatedAt;
|
||||||
|
this.lastLogin = lastLogin;
|
||||||
|
this.research = new ResearchManager(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
async init() {
|
||||||
|
await this.research.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
addMainPlanet(planet: Planet) {
|
||||||
|
this.mainPlanet = planet;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
import { getAllBuildings } from '../../db/buildings';
|
||||||
|
import DBBuilding from '../../../types/db/DBBuilding';
|
||||||
|
import { Planet } from './PlanetManager';
|
||||||
|
import { updatePlanetBuildings } from '../../db/planets';
|
||||||
|
import Building from '../Building';
|
||||||
|
|
||||||
|
export default class BuildingManager {
|
||||||
|
buildings: Array<Building> = [];
|
||||||
|
buildingsDB: Array<DBBuilding> = []
|
||||||
|
planet: Planet;
|
||||||
|
|
||||||
|
constructor(planet: Planet) {
|
||||||
|
this.planet = planet;
|
||||||
|
}
|
||||||
|
|
||||||
|
async init(buildingData: { id: string, level: number }[]) {
|
||||||
|
this.buildingsDB = await getAllBuildings();
|
||||||
|
buildingData.forEach(building => {
|
||||||
|
const buildingToFind = this.buildingsDB.find(b => b.id === building.id);
|
||||||
|
|
||||||
|
if(buildingToFind) this.buildings.push(new Building(
|
||||||
|
this,
|
||||||
|
buildingToFind,
|
||||||
|
building.level
|
||||||
|
))
|
||||||
|
})
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
getBuildingById(id: string) {
|
||||||
|
return this.buildings.find(building => building.data.id === id);
|
||||||
|
}
|
||||||
|
|
||||||
|
addBuilding(building: Building) {
|
||||||
|
const findBuilding = this.buildings.find(b => b.data.id === building.data.id);
|
||||||
|
if(!findBuilding) this.buildings.push(building);
|
||||||
|
else findBuilding.level++;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeBuilding(id: string) {
|
||||||
|
this.buildings = this.buildings.filter(building => building.data.id !== id);
|
||||||
|
}
|
||||||
|
|
||||||
|
async sync() {
|
||||||
|
await updatePlanetBuildings(this.planet._id, this.buildings.map(building => { return { id: building.data.id, level: building.level } }));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,153 @@
|
||||||
|
import { ObjectId } from "mongodb";
|
||||||
|
import PlanetManager, { Planet } from "./PlanetManager";
|
||||||
|
import { getAllGalaxies } from "../../db/galaxies";
|
||||||
|
import { getSectorById } from "../../db/sectors";
|
||||||
|
import { getSystemById } from "../../db/systems";
|
||||||
|
import { getAllUsers } from "../../db/users";
|
||||||
|
import User from "../User";
|
||||||
|
|
||||||
|
export type Galaxy = {
|
||||||
|
_id: ObjectId,
|
||||||
|
name: string,
|
||||||
|
sectors: Array<Sector>
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Sector = {
|
||||||
|
_id: ObjectId,
|
||||||
|
galaxy: Galaxy,
|
||||||
|
name: string,
|
||||||
|
expedition: null,
|
||||||
|
systems: Array<System>
|
||||||
|
}
|
||||||
|
|
||||||
|
export type System = {
|
||||||
|
_id: ObjectId,
|
||||||
|
sector: Sector,
|
||||||
|
name: string,
|
||||||
|
ownedBy: User,
|
||||||
|
planets: PlanetManager
|
||||||
|
}
|
||||||
|
|
||||||
|
class LocationManager {
|
||||||
|
private static instance: LocationManager;
|
||||||
|
|
||||||
|
private constructor() {}
|
||||||
|
|
||||||
|
public static getInstance(): LocationManager {
|
||||||
|
if (!LocationManager.instance) {
|
||||||
|
LocationManager.instance = new LocationManager();
|
||||||
|
}
|
||||||
|
return LocationManager.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
galaxies: Galaxy[] = [];
|
||||||
|
users: User[] = [];
|
||||||
|
|
||||||
|
async init() {
|
||||||
|
const users = await getAllUsers();
|
||||||
|
users.forEach(async user => {
|
||||||
|
this.users.push(new User(user._id, user.username, user.email, user.createdAt, user.updatedAt, user.lastLogin));
|
||||||
|
});
|
||||||
|
|
||||||
|
const galaxies = await getAllGalaxies();
|
||||||
|
for(const galaxy of galaxies) {
|
||||||
|
const galaxyObject: Galaxy = {
|
||||||
|
_id: galaxy._id,
|
||||||
|
name: galaxy.name,
|
||||||
|
sectors: []
|
||||||
|
};
|
||||||
|
|
||||||
|
for(const sectorId of galaxy.sectors) {
|
||||||
|
const sectorData = await getSectorById(sectorId);
|
||||||
|
|
||||||
|
const sectorObject: Sector = {
|
||||||
|
_id: sectorData._id,
|
||||||
|
galaxy: galaxyObject,
|
||||||
|
name: sectorData.name,
|
||||||
|
expedition: null,
|
||||||
|
systems: []
|
||||||
|
};
|
||||||
|
|
||||||
|
for(const systemId of sectorData.systems) {
|
||||||
|
const systemData = await getSystemById(systemId);
|
||||||
|
const user = this.users.find(user => user.id.equals(systemData.ownedBy));
|
||||||
|
|
||||||
|
if(!user) throw new Error("User not found");
|
||||||
|
|
||||||
|
const systemObject: System = {
|
||||||
|
_id: systemData._id,
|
||||||
|
sector: sectorObject,
|
||||||
|
name: systemData.name,
|
||||||
|
ownedBy: user,
|
||||||
|
planets: new PlanetManager(user)
|
||||||
|
};
|
||||||
|
|
||||||
|
await systemObject.planets.fillData(systemData.planets);
|
||||||
|
|
||||||
|
sectorObject.systems.push(systemObject);
|
||||||
|
};
|
||||||
|
|
||||||
|
galaxyObject.sectors.push(sectorObject);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.galaxies.push(galaxyObject);
|
||||||
|
};
|
||||||
|
|
||||||
|
for(const user of this.users) {
|
||||||
|
await user.init();
|
||||||
|
const userDB = users.find(u => u._id.equals(user.id));
|
||||||
|
const mainPlanet = this.getPlanet(userDB?.mainPlanet as ObjectId);
|
||||||
|
|
||||||
|
if(!mainPlanet) throw new Error("Main planet not found");
|
||||||
|
|
||||||
|
user.mainPlanet = mainPlanet;
|
||||||
|
};
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
getGalaxy(_id: ObjectId) {
|
||||||
|
return this.galaxies.find(galaxy => galaxy._id.equals(_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
getSector(_id: ObjectId) {
|
||||||
|
let foundSector: Sector | undefined;
|
||||||
|
this.galaxies.find(galaxy => galaxy.sectors.find(sector => {
|
||||||
|
if(sector._id.equals(_id)) foundSector = sector;
|
||||||
|
}));
|
||||||
|
return foundSector;
|
||||||
|
}
|
||||||
|
|
||||||
|
getSystem(_id: ObjectId) {
|
||||||
|
let foundSystem: System | undefined;
|
||||||
|
this.galaxies.find(galaxy => galaxy.sectors.find(sector => sector.systems.find(system => {
|
||||||
|
if(system._id.equals(_id)) foundSystem = system
|
||||||
|
})));
|
||||||
|
return foundSystem
|
||||||
|
}
|
||||||
|
|
||||||
|
getPlanet(_id: ObjectId) {
|
||||||
|
let foundPlanet: Planet | undefined;
|
||||||
|
|
||||||
|
for(const galaxy of this.galaxies) {
|
||||||
|
for(const sector of galaxy.sectors) {
|
||||||
|
for(const system of sector.systems) {
|
||||||
|
foundPlanet = system.planets.getPlanetById(_id);
|
||||||
|
if(foundPlanet) break;
|
||||||
|
}
|
||||||
|
if(foundPlanet) break;
|
||||||
|
}
|
||||||
|
if(foundPlanet) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return foundPlanet;
|
||||||
|
}
|
||||||
|
|
||||||
|
getUser(_id: ObjectId) {
|
||||||
|
return this.users.find(user => user.id.equals(_id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const locationManager = LocationManager.getInstance();
|
||||||
|
locationManager.init();
|
||||||
|
export default locationManager;
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { ObjectId } from "mongodb";
|
||||||
|
import BuildingManager from "./BuildingManager";
|
||||||
|
import { getPlanetById } from "../../db/planets";
|
||||||
|
import ResourceManager from "./ResourceManager";
|
||||||
|
import User from "../User";
|
||||||
|
|
||||||
|
export type Planet = {
|
||||||
|
_id: ObjectId;
|
||||||
|
manager: PlanetManager;
|
||||||
|
name: string;
|
||||||
|
fields: number;
|
||||||
|
resources: ResourceManager;
|
||||||
|
buildings: BuildingManager;
|
||||||
|
ships: Array<any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class PlanetManager {
|
||||||
|
planets: Array<Planet> = [];
|
||||||
|
owner: User;
|
||||||
|
|
||||||
|
constructor(user: User) {
|
||||||
|
this.owner = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fillData(planets: ObjectId[]) {
|
||||||
|
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,
|
||||||
|
ships: planet.ships
|
||||||
|
}
|
||||||
|
|
||||||
|
planetObject.resources = await new ResourceManager(planetObject).init(planet.resources);
|
||||||
|
planetObject.buildings = await new BuildingManager(planetObject).init(planet.buildings);
|
||||||
|
|
||||||
|
this.planets.push(planetObject);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
getPlanetById(id: ObjectId) {
|
||||||
|
return this.planets.find(planet => planet._id.equals(id));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
import DBResearch from "../../../types/db/DBResearch";
|
||||||
|
import { getAllResearch } from "../../db/research";
|
||||||
|
import { getUserResearch, updateUserResearch } from "../../db/users";
|
||||||
|
import User from "../User";
|
||||||
|
|
||||||
|
export type Research = {
|
||||||
|
id: string,
|
||||||
|
level: number,
|
||||||
|
data: DBResearch
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class ResearchManager {
|
||||||
|
research: Array<Research> = [];
|
||||||
|
researchDB: Array<DBResearch> = [];
|
||||||
|
owner: User;
|
||||||
|
|
||||||
|
constructor(user: User) {
|
||||||
|
this.owner = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
async init() {
|
||||||
|
this.researchDB = await getAllResearch();
|
||||||
|
const research = await getUserResearch(this.owner);
|
||||||
|
this.research = research.map(r => {
|
||||||
|
const researchData = this.researchDB.find(research => research.id === r.id);
|
||||||
|
if(!researchData) throw new Error(`Research ${r.id} not found`);
|
||||||
|
return {
|
||||||
|
id: r.id,
|
||||||
|
level: r.level,
|
||||||
|
data: researchData
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
getResearchById(id: string) {
|
||||||
|
return this.research.find(research => research.data.id === id);
|
||||||
|
}
|
||||||
|
|
||||||
|
addResearch(research: Research) {
|
||||||
|
const findResearch = this.research.find(r => r.data.id === research.data.id);
|
||||||
|
if(!findResearch) this.research.push(research);
|
||||||
|
else findResearch.level++;
|
||||||
|
}
|
||||||
|
|
||||||
|
async sync() {
|
||||||
|
await updateUserResearch(this.owner, this.research.map(r => { return { id: r.data.id, level: r.level } }));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,152 @@
|
||||||
|
import DBResource from "../../../types/db/DBResource";
|
||||||
|
import { updatePlanetResources } from "../../db/planets";
|
||||||
|
import { getAllResources } from "../../db/resources";
|
||||||
|
import { Planet } from "./PlanetManager";
|
||||||
|
|
||||||
|
export type Resource = {
|
||||||
|
id: string,
|
||||||
|
amount: number,
|
||||||
|
lastUpdated: Date,
|
||||||
|
perHourMiningRate: number,
|
||||||
|
data: DBResource
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class ResourceManager {
|
||||||
|
resources: Array<Resource> = [];
|
||||||
|
planet: Planet;
|
||||||
|
|
||||||
|
constructor(planet: Planet) {
|
||||||
|
this.planet = planet;
|
||||||
|
}
|
||||||
|
|
||||||
|
async init(resourceData: { id: string, amount: number, lastUpdated: Date, perHourMiningRate: number }[]) {
|
||||||
|
const resources = await getAllResources();
|
||||||
|
|
||||||
|
if(resourceData.length === 0) {
|
||||||
|
resourceData = [
|
||||||
|
{
|
||||||
|
id: "coal",
|
||||||
|
amount: 11,
|
||||||
|
lastUpdated: new Date(),
|
||||||
|
perHourMiningRate: 11
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "iron",
|
||||||
|
amount: 22,
|
||||||
|
lastUpdated: new Date(),
|
||||||
|
perHourMiningRate: 22
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "gold",
|
||||||
|
amount: 33,
|
||||||
|
lastUpdated: new Date(),
|
||||||
|
perHourMiningRate: 33
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "water",
|
||||||
|
amount: 44,
|
||||||
|
lastUpdated: new Date(),
|
||||||
|
perHourMiningRate: 44
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "sulfuric-acid",
|
||||||
|
amount: 55,
|
||||||
|
lastUpdated: new Date(),
|
||||||
|
perHourMiningRate: 55
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "liquid-nitrogen",
|
||||||
|
amount: 66,
|
||||||
|
lastUpdated: new Date(),
|
||||||
|
perHourMiningRate: 66
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "hydrogen",
|
||||||
|
amount: 77,
|
||||||
|
lastUpdated: new Date(),
|
||||||
|
perHourMiningRate: 77
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "oxygen",
|
||||||
|
amount: 88,
|
||||||
|
lastUpdated: new Date(),
|
||||||
|
perHourMiningRate: 88
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "helium-3",
|
||||||
|
amount: 99,
|
||||||
|
lastUpdated: new Date(),
|
||||||
|
perHourMiningRate: 99
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
await updatePlanetResources(this.planet._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: resource.lastUpdated,
|
||||||
|
perHourMiningRate: resource.perHourMiningRate,
|
||||||
|
data: resFromDB
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
update(resources: Resource[]) {
|
||||||
|
this.resources = resources;
|
||||||
|
}
|
||||||
|
|
||||||
|
async sync() {
|
||||||
|
await updatePlanetResources(this.planet._id, this.resources.map(res => {
|
||||||
|
return {
|
||||||
|
id: res.id,
|
||||||
|
amount: res.amount,
|
||||||
|
lastUpdated: res.lastUpdated,
|
||||||
|
perHourMiningRate: res.perHourMiningRate
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
import { AccessTokens } from './mongodb';
|
import { AccessTokens } from './mongodb';
|
||||||
import type AccessToken from '../../types/AccessToken';
|
|
||||||
import { createHash } from 'crypto';
|
import { createHash } from 'crypto';
|
||||||
import { ObjectId } from 'mongodb';
|
import { ObjectId } from 'mongodb';
|
||||||
|
import DBAccessToken from '../../types/db/DBAccessToken';
|
||||||
|
import AccessToken from '../../types/AccessToken';
|
||||||
|
import locationManager from '../classes/managers/LocationManager';
|
||||||
|
|
||||||
export const createAccessToken = async (accessToken: AccessToken) => {
|
export const createAccessToken = async (accessToken: AccessToken) => {
|
||||||
const newAccessToken = await (await AccessTokens()).insertOne(accessToken);
|
const newAccessToken = await (await AccessTokens()).insertOne(accessToken);
|
||||||
|
@ -23,7 +25,7 @@ export const getAccessToken = async (accessToken: string) => {
|
||||||
{ createdAt },
|
{ createdAt },
|
||||||
{ user },
|
{ user },
|
||||||
{ entropy }
|
{ entropy }
|
||||||
] }) as Promise<AccessToken | null>;
|
] }) as Promise<DBAccessToken | null>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getAllAccessTokens = async () => {
|
export const getAllAccessTokens = async () => {
|
||||||
|
@ -37,7 +39,24 @@ export const getAllAccessTokens = async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const accessTokens = await AccessTokens();
|
const accessTokens = await AccessTokens();
|
||||||
const arrayOfTokens = await accessTokens.find({}).toArray() as AccessToken[];
|
const arrayOfTokens = await accessTokens.find({}).toArray() as DBAccessToken[];
|
||||||
let arr = [master].concat(arrayOfTokens);
|
|
||||||
|
const arr = [master];
|
||||||
|
|
||||||
|
for(const token of arrayOfTokens) {
|
||||||
|
const user = locationManager.getUser(token.user) ?? null;
|
||||||
|
|
||||||
|
const tokenObject: AccessToken = {
|
||||||
|
type: token.type,
|
||||||
|
user,
|
||||||
|
entropy: token.entropy,
|
||||||
|
createdAt: token.createdAt,
|
||||||
|
expiresAt: token.expiresAt,
|
||||||
|
createdFrom: token.createdFrom
|
||||||
|
}
|
||||||
|
|
||||||
|
arr.push(tokenObject);
|
||||||
|
}
|
||||||
|
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import DBBuilding from '../../types/DBBuilding';
|
import DBBuilding from '../../types/db/DBBuilding';
|
||||||
import { Buildings } from '../db/mongodb';
|
import { Buildings } from '../db/mongodb';
|
||||||
|
|
||||||
export const getAllBuildings = async () => {
|
export const getAllBuildings = async () => {
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { ObjectId } from "mongodb";
|
||||||
|
import { Galaxies } from "./mongodb"
|
||||||
|
import DBGalaxy from "../../types/db/DBGalaxy";
|
||||||
|
|
||||||
|
export const getAllGalaxies = async () => {
|
||||||
|
return await (await Galaxies()).find({}).toArray() as DBGalaxy[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getGalaxyById = async (id: ObjectId) => {
|
||||||
|
return await (await Galaxies()).findOne({
|
||||||
|
_id: id
|
||||||
|
}) as DBGalaxy;
|
||||||
|
}
|
|
@ -8,7 +8,6 @@ const mongo = new MongoClient(uri, options);
|
||||||
|
|
||||||
export const connect = async () => {
|
export const connect = async () => {
|
||||||
await mongo.connect();
|
await mongo.connect();
|
||||||
// return mongo.db(dbName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const disconnect = async () => {
|
export const disconnect = async () => {
|
||||||
|
@ -30,6 +29,21 @@ export const AccessTokens = async () => {
|
||||||
return db.collection('accessTokens');
|
return db.collection('accessTokens');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const Galaxies = async () => {
|
||||||
|
const db = await getDB();
|
||||||
|
return db.collection('galaxies');
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Sectors = async () => {
|
||||||
|
const db = await getDB();
|
||||||
|
return db.collection('sectors');
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Systems = async () => {
|
||||||
|
const db = await getDB();
|
||||||
|
return db.collection('systems');
|
||||||
|
}
|
||||||
|
|
||||||
export const Planets = async () => {
|
export const Planets = async () => {
|
||||||
const db = await getDB();
|
const db = await getDB();
|
||||||
return db.collection('planets');
|
return db.collection('planets');
|
||||||
|
|
|
@ -1,74 +1,29 @@
|
||||||
import { Planets } from '../db/mongodb';
|
import { Planets } from '../db/mongodb';
|
||||||
import type User from '../../types/User';
|
|
||||||
import { ObjectId } from 'mongodb';
|
import { ObjectId } from 'mongodb';
|
||||||
import type Planet from '../../types/Planet';
|
import DBPlanet from '../../types/db/DBPlanet';
|
||||||
import { getUserById } from './users';
|
|
||||||
import type Building from '../../types/Building';
|
|
||||||
import type Ship from '../../types/Ship';
|
|
||||||
import type PlayerResource from '../../types/PlayerResource';
|
|
||||||
|
|
||||||
export const getAllPlanets = async (options?: { fetchUserPlanets: boolean }) => {
|
export const getAllPlanets = async () => {
|
||||||
const planets = await Planets();
|
return await (await Planets()).find({}).toArray() as DBPlanet[];
|
||||||
const fetched = (await planets.find({}).toArray()).map(async planet => {
|
|
||||||
planet.owner = await getUserById(planet.owner);
|
|
||||||
return planet;
|
|
||||||
})
|
|
||||||
|
|
||||||
return Promise.all(fetched) as unknown as Array<Planet>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const createPlanet = async (options: { name: string, owner?: User, ownerId?: ObjectId, fields?: number }) => {
|
|
||||||
if(options.owner !== undefined && options.ownerId !== undefined) throw new Error("Duplicate identifier");
|
|
||||||
|
|
||||||
let user: ObjectId;
|
|
||||||
if(options.ownerId) user = options.ownerId;
|
|
||||||
else if(options.owner) user = options.owner._id;
|
|
||||||
else throw new Error("Unknown error");
|
|
||||||
|
|
||||||
if(options.fields === undefined) options.fields = 20;
|
|
||||||
|
|
||||||
//@ts-ignore TODO: find another way of handling IDs from types before inserting to database
|
|
||||||
const planet = {
|
|
||||||
owner: user,
|
|
||||||
name: options.name,
|
|
||||||
fields: options.fields,
|
|
||||||
resources: new Array<PlayerResource>,
|
|
||||||
buildings: new Array<Building>,
|
|
||||||
ships: new Array<Ship>
|
|
||||||
}
|
|
||||||
|
|
||||||
await (await Planets()).insertOne(planet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getPlanetById = async (id: ObjectId) => {
|
export const getPlanetById = async (id: ObjectId) => {
|
||||||
const planets = await Planets();
|
return await (await Planets()).findOne({ _id: id }) as DBPlanet;
|
||||||
const planet = await planets.findOne({
|
|
||||||
_id: id
|
|
||||||
});
|
|
||||||
|
|
||||||
if(!planet) return null;
|
|
||||||
|
|
||||||
planet.owner = await getUserById(planet.owner);
|
|
||||||
return planet as Planet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createOrUpgradeBuilding = async (planetId: ObjectId, building: Building) => {
|
export const updatePlanetResources = async (planetId: ObjectId, resources: Array<any>) => {
|
||||||
const planet = await getPlanetById(planetId);
|
|
||||||
if(!planet) throw new Error("Planet not found");
|
|
||||||
|
|
||||||
const buildingIndex = planet.buildings.findIndex(b => b.id === building.id);
|
|
||||||
if(buildingIndex === -1) {
|
|
||||||
planet.buildings.push(building);
|
|
||||||
} else {
|
|
||||||
planet.buildings[buildingIndex].level++;
|
|
||||||
}
|
|
||||||
|
|
||||||
const planets = await Planets();
|
const planets = await Planets();
|
||||||
await planets.updateOne({
|
await planets.updateOne({ _id: planetId }, {
|
||||||
_id: planetId
|
|
||||||
}, {
|
|
||||||
$set: {
|
$set: {
|
||||||
buildings: planet.buildings
|
resources
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const updatePlanetBuildings = async (planetId: ObjectId, buildings: Array<{ id: string, level: number }>) => {
|
||||||
|
const planets = await Planets();
|
||||||
|
await planets.updateOne({ _id: planetId }, {
|
||||||
|
$set: {
|
||||||
|
buildings
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import DBResearch from '../../types/DBResearch';
|
import DBResearch from '../../types/db/DBResearch';
|
||||||
import { Research } from '../db/mongodb';
|
import { Research } from '../db/mongodb';
|
||||||
|
|
||||||
export const getAllResearch = async () => {
|
export const getAllResearch = async () => {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import DBResource from '../../types/DBResource';
|
import DBResource from '../../types/db/DBResource';
|
||||||
import { Resources } from '../db/mongodb';
|
import { Resources } from '../db/mongodb';
|
||||||
|
|
||||||
export const getAllResources = async () => {
|
export const getAllResources = async () => {
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { ObjectId } from "mongodb";
|
||||||
|
import { Sectors } from "./mongodb";
|
||||||
|
import DBSector from "../../types/db/DBSector";
|
||||||
|
|
||||||
|
export const getAllSectors = async () => {
|
||||||
|
return await (await Sectors()).find({}).toArray() as DBSector[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getSectorById = async (id: ObjectId) => {
|
||||||
|
return await (await Sectors()).findOne({
|
||||||
|
_id: id
|
||||||
|
}) as DBSector;
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import DBShip from '../../types/DBShip';
|
import DBShip from '../../types/db/DBShip';
|
||||||
import { Ships } from '../db/mongodb';
|
import { Ships } from '../db/mongodb';
|
||||||
|
|
||||||
export const getAllShips = async () => {
|
export const getAllShips = async () => {
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { ObjectId } from "mongodb";
|
||||||
|
import { Systems } from "./mongodb";
|
||||||
|
import DBSystem from "../../types/db/DBSystem";
|
||||||
|
|
||||||
|
export const getAllSystems = async () => {
|
||||||
|
return await (await Systems()).find({}).toArray() as DBSystem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getSystemById = async (id: ObjectId) => {
|
||||||
|
return await (await Systems()).findOne({
|
||||||
|
_id: id
|
||||||
|
}) as DBSystem;
|
||||||
|
}
|
|
@ -1,33 +1,30 @@
|
||||||
import { Planets, Users } from '../db/mongodb';
|
import { Users } from '../db/mongodb';
|
||||||
import type User from '../../types/User';
|
|
||||||
import type AccessToken from '../../types/AccessToken';
|
|
||||||
import { ObjectId } from 'mongodb';
|
import { ObjectId } from 'mongodb';
|
||||||
import { hash } from 'argon2'
|
import { hash } from 'argon2'
|
||||||
import { createInitialResources } from '../utils/resourceManager';
|
import DBUser from '../../types/db/DBUser';
|
||||||
import type Research from '../../types/Research';
|
import User from '../classes/User';
|
||||||
|
import AccessToken from '../../types/AccessToken';
|
||||||
|
|
||||||
export const getAllUsers = async () => {
|
export const getAllUsers = async () => {
|
||||||
const users = await Users();
|
const users = await Users();
|
||||||
return users.find({}).toArray() as Promise<User[]>;
|
return users.find({}).toArray() as Promise<DBUser[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createUser = async (username: string, email: string, password: string) => {
|
export const createUser = async (username: string, email: string, password: string) => {
|
||||||
const user: User = {
|
const user = {
|
||||||
username,
|
username,
|
||||||
email,
|
email,
|
||||||
password: await hash(password),
|
password: await hash(password),
|
||||||
lastLogin: new Date(),
|
lastLogin: new Date(),
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
//@ts-ignore
|
research: [],
|
||||||
resources: {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
await (await Users()).insertOne(user);
|
await (await Users()).insertOne(user);
|
||||||
const newUser = await getUserByNickOrEmail(username);
|
const newUser = await getUserByNickOrEmail(username);
|
||||||
if(!newUser) return user;
|
if(!newUser) return user;
|
||||||
createInitialResources(newUser._id);
|
|
||||||
return newUser;
|
return newUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +37,7 @@ export const getUserById = async (id: ObjectId) => {
|
||||||
const users = await Users();
|
const users = await Users();
|
||||||
return users.findOne({
|
return users.findOne({
|
||||||
_id: id
|
_id: id
|
||||||
}) as Promise<User | null>;
|
}) as Promise<DBUser | null>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getUserByNickOrEmail = async (searchString: string) => {
|
export const getUserByNickOrEmail = async (searchString: string) => {
|
||||||
|
@ -50,14 +47,18 @@ export const getUserByNickOrEmail = async (searchString: string) => {
|
||||||
{ username: searchString },
|
{ username: searchString },
|
||||||
{ email: searchString }
|
{ email: searchString }
|
||||||
]
|
]
|
||||||
}) as Promise<User | null>;
|
}) as Promise<DBUser | null>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getUserByAccessToken = async(accessToken: string | AccessToken): Promise<User | null> => {
|
export const getUserByAccessToken = async(accessToken: string | AccessToken): Promise<DBUser | null> => {
|
||||||
if(typeof accessToken === "string") {
|
if(typeof accessToken === "string") {
|
||||||
const userId = new ObjectId(Buffer.from(accessToken.split(".")[2], 'base64url').toString());
|
const userId = new ObjectId(Buffer.from(accessToken.split(".")[2], 'base64url').toString());
|
||||||
return getUserById(userId);
|
return getUserById(userId);
|
||||||
} else return getUserById(accessToken.user as ObjectId)
|
} else {
|
||||||
|
const user = accessToken.user;
|
||||||
|
if(!user) return null;
|
||||||
|
return getUserById(user?.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const updateLastLogin = async (user: User) => {
|
export const updateLastLogin = async (user: User) => {
|
||||||
|
@ -65,54 +66,14 @@ export const updateLastLogin = async (user: User) => {
|
||||||
return users.updateOne({ username: user.username }, { $set: { lastLogin: new Date() } });
|
return users.updateOne({ username: user.username }, { $set: { lastLogin: new Date() } });
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getUserResearch = async (user: User): Promise<Array<Research>> => {
|
export const getUserResearch = async (user: User): Promise<Array<{ id: string, level: number }>> => {
|
||||||
const research: Array<Research> = [];
|
|
||||||
|
|
||||||
if (user?.research !== undefined) {
|
|
||||||
user?.research.forEach((res: Research) => {
|
|
||||||
research.push(res);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return research;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const createOrUpgradeResearch = async (userId: ObjectId, research: Research) => {
|
|
||||||
const users = await Users();
|
const users = await Users();
|
||||||
|
const rawUser = await users.findOne({ username: user.username });
|
||||||
const result = await users.updateOne(
|
if (!rawUser) return [];
|
||||||
{ _id: userId, "research.id": research.id },
|
return rawUser.research;
|
||||||
{ $set: { "research.$.level": research.level } }
|
|
||||||
);
|
|
||||||
|
|
||||||
if (result.modifiedCount === 0) {
|
|
||||||
await users.updateOne({ _id: userId },
|
|
||||||
{ $push: { research } }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getUserWithPlanets = async (id: ObjectId): Promise<User | null> => {
|
export const updateUserResearch = async (user: User, research: Array<{ id: string, level: number }>) => {
|
||||||
const users = await Users();
|
const users = await Users();
|
||||||
const planets = await Planets();
|
users.updateOne({ username: user.username }, { $set: { research } });
|
||||||
|
|
||||||
const rawUser = await users.findOne({
|
|
||||||
_id: id
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!rawUser) return null;
|
|
||||||
|
|
||||||
const userPlanets = (await planets.find({
|
|
||||||
owner: id
|
|
||||||
}).toArray()).map(planet => {
|
|
||||||
planet.owner = rawUser;
|
|
||||||
return planet;
|
|
||||||
});
|
|
||||||
|
|
||||||
rawUser.planets = {
|
|
||||||
partial: false,
|
|
||||||
data: userPlanets
|
|
||||||
}
|
|
||||||
|
|
||||||
return rawUser as User;
|
|
||||||
}
|
}
|
|
@ -1,23 +0,0 @@
|
||||||
import type Resource from "../../types/Resource";
|
|
||||||
import type Resources from "../../types/Resources";
|
|
||||||
|
|
||||||
export default function calculateAvailableResources(userResources: Array<Resource>, buildingCost: Array<Resource>) {
|
|
||||||
let canBuild = true;
|
|
||||||
const resources = {} as Array<Resource>;
|
|
||||||
|
|
||||||
userResources.forEach((userResource) => {
|
|
||||||
const resource = buildingCost.find((buildingResource) => buildingResource.name === userResource.name);
|
|
||||||
if (resource) {
|
|
||||||
resources.push({
|
|
||||||
name: userResource.name,
|
|
||||||
amount: userResource.amount - resource.amount
|
|
||||||
});
|
|
||||||
if (userResource.amount < resource.amount) canBuild = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
canBuild,
|
|
||||||
resources
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,100 +0,0 @@
|
||||||
import { ObjectId } from "mongodb"
|
|
||||||
import { Planets } from "../db/mongodb";
|
|
||||||
import type PlayerResource from "../../types/PlayerResource";
|
|
||||||
import { getPlanetById } from "../db/planets";
|
|
||||||
|
|
||||||
export const createInitialResources = async (planetId: ObjectId) => {
|
|
||||||
const resources: Array<PlayerResource> = [
|
|
||||||
{
|
|
||||||
name: "coal",
|
|
||||||
amount: 11,
|
|
||||||
lastUpdated: new Date(),
|
|
||||||
perHourMiningRate: 11
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "iron",
|
|
||||||
amount: 22,
|
|
||||||
lastUpdated: new Date(),
|
|
||||||
perHourMiningRate: 22
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gold",
|
|
||||||
amount: 33,
|
|
||||||
lastUpdated: new Date(),
|
|
||||||
perHourMiningRate: 33
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "water",
|
|
||||||
amount: 44,
|
|
||||||
lastUpdated: new Date(),
|
|
||||||
perHourMiningRate: 44
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "sulfuricAcid",
|
|
||||||
amount: 55,
|
|
||||||
lastUpdated: new Date(),
|
|
||||||
perHourMiningRate: 55
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "liquidNitrogen",
|
|
||||||
amount: 66,
|
|
||||||
lastUpdated: new Date(),
|
|
||||||
perHourMiningRate: 66
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "hydrogen",
|
|
||||||
amount: 77,
|
|
||||||
lastUpdated: new Date(),
|
|
||||||
perHourMiningRate: 77
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "oxygen",
|
|
||||||
amount: 88,
|
|
||||||
lastUpdated: new Date(),
|
|
||||||
perHourMiningRate: 88
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "helium3",
|
|
||||||
amount: 99,
|
|
||||||
lastUpdated: new Date(),
|
|
||||||
perHourMiningRate: 99
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
updatePlanetResources(planetId, resources);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getResourcesFromPlanet = async (planetId: ObjectId): Promise<Array<PlayerResource> | null> => {
|
|
||||||
const planet = await getPlanetById(planetId);
|
|
||||||
|
|
||||||
if(!planet) return null;
|
|
||||||
|
|
||||||
return planet.resources;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const updatePlanetResources = async (planetId: ObjectId, resources: Array<PlayerResource>) => {
|
|
||||||
const planets = await Planets();
|
|
||||||
await planets.updateOne({ _id: planetId }, {
|
|
||||||
$set: {
|
|
||||||
resources
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export const calculateCurrentAvailableResources = async (planetId: ObjectId): Promise<Array<PlayerResource>> => {
|
|
||||||
const resources = await getResourcesFromPlanet(planetId);
|
|
||||||
|
|
||||||
if(resources === null) return [];
|
|
||||||
|
|
||||||
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();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
updatePlanetResources(planetId, resources);
|
|
||||||
return resources;
|
|
||||||
}
|
|
|
@ -1,7 +1,8 @@
|
||||||
import type { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
import type AccessToken from "../../types/AccessToken";
|
import AccessToken from "../../types/AccessToken";
|
||||||
import { getAccessToken } from "../db/accessTokens";
|
import { getAccessToken } from "../db/accessTokens";
|
||||||
import { getUserById } from "../db/users";
|
import { getUserById } from "../db/users";
|
||||||
|
import locationManager from "../classes/managers/LocationManager";
|
||||||
|
|
||||||
export default async function validateAccessToken(request: Request): Promise<Response | AccessToken> {
|
export default async function validateAccessToken(request: Request): Promise<Response | AccessToken> {
|
||||||
let accessToken = request.url.split("?")[1]?.split("&").filter((x) => x.split("=")[0] === "token")[0].split("=")[1];
|
let accessToken = request.url.split("?")[1]?.split("&").filter((x) => x.split("=")[0] === "token")[0].split("=")[1];
|
||||||
|
@ -58,5 +59,12 @@ export default async function validateAccessToken(request: Request): Promise<Res
|
||||||
}), { status: 403 }
|
}), { status: 403 }
|
||||||
);
|
);
|
||||||
|
|
||||||
return response;
|
return {
|
||||||
|
type: response.type,
|
||||||
|
user: locationManager.getUser(user._id),
|
||||||
|
entropy: response.entropy,
|
||||||
|
createdAt: response.createdAt,
|
||||||
|
expiresAt: response.expiresAt,
|
||||||
|
createdFrom: response.createdFrom
|
||||||
|
} as AccessToken;
|
||||||
}
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
import { randomBytes, createHash } from "crypto";
|
import { randomBytes, createHash } from "crypto";
|
||||||
import type { APIRoute } from "astro";
|
import type { APIRoute } from "astro";
|
||||||
import type AccessToken from "../../../types/AccessToken";
|
|
||||||
import { createAccessToken } from "../../../lib/db/accessTokens";
|
import { createAccessToken } from "../../../lib/db/accessTokens";
|
||||||
import { getUserByNickOrEmail } from "../../../lib/db/users";
|
import { getUserByNickOrEmail } from "../../../lib/db/users";
|
||||||
import config from '../../../../config.json';
|
import config from '../../../../config.json';
|
||||||
import type { ObjectId } from "mongodb";
|
import AccessToken from "../../../types/AccessToken";
|
||||||
|
import locationManager from "../../../lib/classes/managers/LocationManager";
|
||||||
|
|
||||||
export const POST: APIRoute = async({ request }) => {
|
export const POST: APIRoute = async({ request }) => {
|
||||||
const data = await request.json().catch(() => {return new Response(
|
const data = await request.json().catch(() => {return new Response(
|
||||||
|
@ -53,16 +53,25 @@ export const POST: APIRoute = async({ request }) => {
|
||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const timestamp = Buffer.from(String(Date.now())).toString('base64url');
|
const timestamp = Buffer.from(String(Date.now())).toString('base64url');
|
||||||
const user = Buffer.from(userFromDb._id?.toString() ?? "").toString('base64url');
|
const userEncoded = Buffer.from(userFromDb._id?.toString() ?? "").toString('base64url');
|
||||||
const random = randomBytes(16).toString("base64url");
|
const random = randomBytes(16).toString("base64url");
|
||||||
const randomHashed = createHash("sha256").update(random).digest("hex");
|
const randomHashed = createHash("sha256").update(random).digest("hex");
|
||||||
const expiresIn = (data.duration ?? 86400) * 1000;
|
const expiresIn = (data.duration ?? 86400) * 1000;
|
||||||
|
|
||||||
const tokenString = `A.${timestamp}.${user}.${random}`;
|
const tokenString = `A.${timestamp}.${userEncoded}.${random}`;
|
||||||
|
|
||||||
|
const user = locationManager.getUser(userFromDb._id);
|
||||||
|
if(!user) return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
code: 404,
|
||||||
|
message: "Not found",
|
||||||
|
error: `User ${data.username} not found`
|
||||||
|
}), { status: 404 }
|
||||||
|
)
|
||||||
|
|
||||||
const accessToken: AccessToken = {
|
const accessToken: AccessToken = {
|
||||||
type: "A",
|
type: "A",
|
||||||
user: userFromDb._id as ObjectId,
|
user,
|
||||||
entropy: randomHashed.toString(),
|
entropy: randomHashed.toString(),
|
||||||
createdAt: now,
|
createdAt: now,
|
||||||
expiresAt: new Date(now.getTime() + expiresIn),
|
expiresAt: new Date(now.getTime() + expiresIn),
|
||||||
|
|
|
@ -1,13 +1,20 @@
|
||||||
import type { APIRoute } from "astro";
|
import type { APIRoute } from "astro";
|
||||||
import validateAccessToken from "../../../lib/utils/validateAccessToken";
|
import validateAccessToken from "../../../lib/utils/validateAccessToken";
|
||||||
import { getUserByAccessToken } from "../../../lib/db/users";
|
import { getUserByAccessToken } from "../../../lib/db/users";
|
||||||
import type User from "../../../types/User";
|
|
||||||
|
|
||||||
export const GET: APIRoute = async({ request }) => {
|
export const GET: APIRoute = async({ request }) => {
|
||||||
const response = await validateAccessToken(request);
|
const response = await validateAccessToken(request);
|
||||||
if(response instanceof Response) return response;
|
if(response instanceof Response) return response;
|
||||||
|
|
||||||
const user = (await getUserByAccessToken(response)) as User;
|
const user = await getUserByAccessToken(response);
|
||||||
|
|
||||||
|
if(!user) return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
code: 404,
|
||||||
|
message: "Not found",
|
||||||
|
data: "Access token does not match any user"
|
||||||
|
}), { status: 404 }
|
||||||
|
);
|
||||||
|
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
import { build, type APIRoute } from "astro";
|
import { type APIRoute } from "astro";
|
||||||
import validateAccessToken from "../../../lib/utils/validateAccessToken";
|
import validateAccessToken from "../../../lib/utils/validateAccessToken";
|
||||||
import { calculateCurrentAvailableResources, updatePlanetResources } from "../../../lib/utils/resourceManager";
|
import { getUserByAccessToken } from "../../../lib/db/users";
|
||||||
import { getUserByAccessToken, getUserResearch } from "../../../lib/db/users";
|
|
||||||
import Planet from "../../../types/Planet";
|
|
||||||
import { createOrUpgradeBuilding, getPlanetById } from "../../../lib/db/planets";
|
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
import DBResource from "../../../types/PlayerResource";
|
import locationManager from "../../../lib/classes/managers/LocationManager";
|
||||||
import { getAllBuildings } from "../../../lib/db/buildings";
|
import Building from "../../../lib/classes/Building";
|
||||||
import DBBuilding from "../../../types/DBBuilding";
|
import { getAllResources } from "../../../lib/db/resources";
|
||||||
|
|
||||||
export const POST: APIRoute = async({ request }) => {
|
export const POST: APIRoute = async({ request }) => {
|
||||||
const response = await validateAccessToken(request);
|
const response = await validateAccessToken(request);
|
||||||
|
@ -36,120 +33,77 @@ export const POST: APIRoute = async({ request }) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildingId = body.building;
|
const userPlanet = locationManager.getPlanet(new ObjectId(body.planet));
|
||||||
let buildingData: DBBuilding | null = null;
|
|
||||||
|
|
||||||
const buildings = await getAllBuildings();
|
|
||||||
|
|
||||||
buildingData = buildings.find((element) => element.id === buildingId) ?? null;
|
|
||||||
|
|
||||||
if(!buildingData) {
|
|
||||||
return new Response(
|
|
||||||
JSON.stringify({
|
|
||||||
code: 400,
|
|
||||||
message: "Bad Request",
|
|
||||||
error: "Invalid building id"
|
|
||||||
}), { status: 400 }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
let userPlanet: Planet | null;
|
|
||||||
try {
|
|
||||||
userPlanet = await getPlanetById(new ObjectId(body.planetId));
|
|
||||||
} catch(e) {
|
|
||||||
return new Response(
|
|
||||||
JSON.stringify({
|
|
||||||
code: 400,
|
|
||||||
message: "Bad Request",
|
|
||||||
error: "Invalid planet id"
|
|
||||||
}), { status: 400 }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if(!userPlanet) {
|
if(!userPlanet) {
|
||||||
return new Response(
|
|
||||||
JSON.stringify({
|
|
||||||
code: 404,
|
|
||||||
message: "Not Found",
|
|
||||||
error: "Planet not found"
|
|
||||||
}), { status: 404 }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// check requirements
|
|
||||||
// buildings
|
|
||||||
const playerBuildings = userPlanet.buildings;
|
|
||||||
buildingData.requirements.buildings.forEach((buildingReq: any) => {
|
|
||||||
if(playerBuildings.filter((building) => building.id === buildingReq.id)[0].level < buildingReq.level) {
|
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
code: 400,
|
code: 400,
|
||||||
message: "Bad Request",
|
message: "Bad Request",
|
||||||
error: `${buildingReq.id} level ${buildingReq.level} required, found ${playerBuildings.filter((building) => building.id === buildingReq.id)[0].level}`
|
error: "Invalid planet ID"
|
||||||
}), { status: 400 }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// research
|
|
||||||
const playerResearch = await getUserResearch(user);
|
|
||||||
buildingData.requirements.research.forEach((researchReq: any) => {
|
|
||||||
if(playerResearch.filter((research) => research.id === researchReq.id)[0].level < researchReq.level) {
|
|
||||||
return new Response(
|
|
||||||
JSON.stringify({
|
|
||||||
code: 400,
|
|
||||||
message: "Bad Request",
|
|
||||||
error: `${researchReq.id} level ${researchReq.level} required, found ${playerResearch.filter((research) => research.id === researchReq.id)[0].level}`
|
|
||||||
}), { status: 400 }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// resources
|
|
||||||
const resources = await calculateCurrentAvailableResources(userPlanet._id);
|
|
||||||
if(!resources) {
|
|
||||||
return new Response(
|
|
||||||
JSON.stringify({
|
|
||||||
code: 500,
|
|
||||||
message: "Internal Server Error",
|
|
||||||
error: "Failed to get resources"
|
|
||||||
}), { status: 500 }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
const playerCurrentResearch = playerResearch.filter((element: any) => element.id === buildingId)[0];
|
|
||||||
const level = playerCurrentResearch ? playerCurrentResearch.level : 0;
|
|
||||||
const newResources = structuredClone(resources);
|
|
||||||
const missingResources: Array<{}> = [];
|
|
||||||
Object.entries(buildingData.requirements.resources).forEach(([key, value]) => {
|
|
||||||
const res = resources.filter((element: DBResource) => element.name === value.name)[0];
|
|
||||||
const cost = playerCurrentResearch ? value.amount * Math.pow((buildingData as {multiplier: number}).multiplier, level) : value.amount;
|
|
||||||
|
|
||||||
if(res.amount < cost) {
|
|
||||||
missingResources.push({
|
|
||||||
name: key,
|
|
||||||
required: cost,
|
|
||||||
available: res.amount
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else newResources.filter((element: DBResource) => element.name === value.name)[0].amount -= cost;
|
|
||||||
});
|
|
||||||
|
|
||||||
if(missingResources.length > 0) {
|
|
||||||
return new Response(
|
|
||||||
JSON.stringify({
|
|
||||||
code: 400,
|
|
||||||
message: "Bad Request",
|
|
||||||
data: missingResources
|
|
||||||
}), { status: 400 }
|
}), { status: 400 }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
await updatePlanetResources(userPlanet._id, newResources);
|
const buildingId: string = body.building;
|
||||||
await createOrUpgradeBuilding(userPlanet._id, { id: buildingId, level: level + 1 });
|
|
||||||
|
const buildingObj = userPlanet.buildings.buildingsDB.find(b => b.id === buildingId);
|
||||||
|
|
||||||
|
if(!buildingObj) return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
code: 400,
|
||||||
|
message: "Bad Request",
|
||||||
|
error: "Invalid building ID"
|
||||||
|
}), { status: 400 }
|
||||||
|
)
|
||||||
|
|
||||||
|
const building = new Building(userPlanet.buildings, buildingObj, 1);
|
||||||
|
|
||||||
|
const requirements = await building.checkRequirements();
|
||||||
|
const resources = await building.checkRequiredResources((userPlanet.buildings.getBuildingById(buildingId)?.level ?? 0) + 1);
|
||||||
|
|
||||||
|
if(!requirements.canBuild || !resources) {
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
code: 400,
|
||||||
|
message: "Bad Request",
|
||||||
|
error: requirements.error + " | " + resources ? "" : "Not enough resources"
|
||||||
|
}), { status: 400 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const resourcesDiff = await userPlanet.resources.getDifference(building.data.requirements.resources.map(res => {
|
||||||
|
return {
|
||||||
|
id: res.id,
|
||||||
|
amount: Math.pow(building.data.multiplier, (userPlanet.buildings.getBuildingById(buildingId)?.level ?? 0) + 1) * res.amount
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
const resourceDB = await getAllResources();
|
||||||
|
const resourcesAfter = resourcesDiff.map(res => {
|
||||||
|
const data = resourceDB.find(r => r.id === res.id);
|
||||||
|
|
||||||
|
if(!data) throw new Error("Resource not found");
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: res.id,
|
||||||
|
amount: res.amount,
|
||||||
|
lastUpdated: res.lastUpdated,
|
||||||
|
perHourMiningRate: res.perHourMiningRate,
|
||||||
|
data
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
userPlanet.resources.update(resourcesAfter);
|
||||||
|
userPlanet.buildings.addBuilding(building);
|
||||||
|
|
||||||
|
await userPlanet.buildings.sync();
|
||||||
|
await userPlanet.resources.sync();
|
||||||
|
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
code: 200,
|
code: 200,
|
||||||
message: "OK"
|
message: "OK"
|
||||||
}), { status: 200 }
|
}), { status: 200 }
|
||||||
)
|
);
|
||||||
}
|
}
|
|
@ -1,17 +1,21 @@
|
||||||
import { APIRoute } from "astro";
|
import { APIRoute } from "astro";
|
||||||
import { getAllPlanets } from "../../../lib/db/planets";
|
import { getAllPlanets } from "../../../lib/db/planets";
|
||||||
import Planet from "../../../types/Planet";
|
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
|
import locationManager from "../../../lib/classes/managers/LocationManager";
|
||||||
|
|
||||||
export const GET: APIRoute = async ({ request }) => {
|
export const GET: APIRoute = async ({ request }) => {
|
||||||
const planets = await getAllPlanets();
|
const planets = await getAllPlanets();
|
||||||
|
|
||||||
const response: Array<{planetId: ObjectId, ownerId: ObjectId, name: string}> = [];
|
const response: Array<{planetId: ObjectId, ownerId: ObjectId, name: string}> = [];
|
||||||
|
|
||||||
planets.forEach((planet: Planet) => {
|
planets.forEach(planet => {
|
||||||
|
const playerPlanet = locationManager.getPlanet(planet._id);
|
||||||
|
|
||||||
|
if(!playerPlanet) return;
|
||||||
|
|
||||||
response.push({
|
response.push({
|
||||||
planetId: planet._id,
|
planetId: planet._id,
|
||||||
ownerId: planet.owner._id,
|
ownerId: playerPlanet.manager.owner.id,
|
||||||
name: planet.name,
|
name: planet.name,
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
import { APIRoute } from "astro";
|
import { APIRoute } from "astro";
|
||||||
import { getPlanetById } from "../../../../lib/db/planets";
|
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
import Planet from "../../../../types/Planet";
|
|
||||||
import { calculateCurrentAvailableResources } from "../../../../lib/utils/resourceManager";
|
|
||||||
import validateAccessToken from "../../../../lib/utils/validateAccessToken";
|
import validateAccessToken from "../../../../lib/utils/validateAccessToken";
|
||||||
import { getUserByAccessToken } from "../../../../lib/db/users";
|
import { getUserByAccessToken } from "../../../../lib/db/users";
|
||||||
|
import locationManager from "../../../../lib/classes/managers/LocationManager";
|
||||||
|
|
||||||
export const GET: APIRoute = async ({ params, request }) => {
|
export const GET: APIRoute = async ({ params, request }) => {
|
||||||
const response = await validateAccessToken(request);
|
const response = await validateAccessToken(request);
|
||||||
|
@ -28,36 +26,23 @@ export const GET: APIRoute = async ({ params, request }) => {
|
||||||
}), { status: 400 }
|
}), { status: 400 }
|
||||||
);
|
);
|
||||||
|
|
||||||
let planet: Planet | null;
|
const planet = locationManager.getPlanet(new ObjectId(planetId));
|
||||||
|
|
||||||
try {
|
|
||||||
planet = await getPlanetById(new ObjectId(planetId));
|
|
||||||
if(!planet) return new Response(
|
if(!planet) return new Response(
|
||||||
JSON.stringify({
|
|
||||||
code: 404,
|
|
||||||
message: "Not Found"
|
|
||||||
}), { status: 404 }
|
|
||||||
);
|
|
||||||
} catch(e) {
|
|
||||||
return new Response(
|
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
code: 500,
|
code: 500,
|
||||||
message: "Internal Server Error"
|
message: "Internal Server Error"
|
||||||
}), { status: 500 }
|
}), { status: 500 }
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
if(planet.owner._id.toString() !== user._id.toString()) return new Response(
|
if(!planet.manager.owner.id.equals(user._id)) return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
code: 403,
|
code: 403,
|
||||||
message: "Forbidden"
|
message: "Forbidden"
|
||||||
}), { status: 403 }
|
}), { status: 403 }
|
||||||
);
|
);
|
||||||
|
|
||||||
await calculateCurrentAvailableResources(planet._id);
|
await locationManager.getPlanet(planet._id)?.resources.calculateCurrentAvailableResources();
|
||||||
|
|
||||||
//@ts-ignore
|
|
||||||
delete planet.owner.password;
|
|
||||||
|
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { type APIRoute } from "astro";
|
import { type APIRoute } from "astro";
|
||||||
import validateAccessToken from "../../../lib/utils/validateAccessToken";
|
import validateAccessToken from "../../../lib/utils/validateAccessToken";
|
||||||
import { getUserByAccessToken, getUserResearch } from "../../../lib/db/users";
|
import { getUserByAccessToken, getUserResearch } from "../../../lib/db/users";
|
||||||
|
import locationManager from "../../../lib/classes/managers/LocationManager";
|
||||||
|
|
||||||
export const GET: APIRoute = async({ request }) => {
|
export const GET: APIRoute = async({ request }) => {
|
||||||
const response = await validateAccessToken(request);
|
const response = await validateAccessToken(request);
|
||||||
|
@ -16,11 +17,13 @@ export const GET: APIRoute = async({ request }) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const userResearch = locationManager.getUser(user._id)?.research.research ?? [];
|
||||||
|
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
code: 200,
|
code: 200,
|
||||||
message: "OK",
|
message: "OK",
|
||||||
data: await getUserResearch(user)
|
data: userResearch
|
||||||
}), { status: 200 }
|
}), { status: 200 }
|
||||||
)
|
)
|
||||||
}
|
}
|
|
@ -1,20 +1,16 @@
|
||||||
import { type APIRoute } from "astro";
|
import { type APIRoute } from "astro";
|
||||||
import validateAccessToken from "../../../lib/utils/validateAccessToken";
|
import validateAccessToken from "../../../lib/utils/validateAccessToken";
|
||||||
import { createOrUpgradeResearch, getUserByAccessToken, getUserResearch } from "../../../lib/db/users";
|
import { getUserByAccessToken } from "../../../lib/db/users";
|
||||||
import { getPlanetById } from "../../../lib/db/planets";
|
|
||||||
import Planet from "../../../types/Planet";
|
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
import { calculateCurrentAvailableResources, getResourcesFromPlanet, updatePlanetResources } from "../../../lib/utils/resourceManager";
|
import { getResearchById } from "../../../lib/db/research";
|
||||||
import PlayerResource from "../../../types/PlayerResource";
|
import locationManager from "../../../lib/classes/managers/LocationManager";
|
||||||
import calculateAvailableResources from "../../../lib/utils/calculateAvailableResources";
|
|
||||||
import { getAllResearch, getResearchById } from "../../../lib/db/research";
|
|
||||||
|
|
||||||
export const POST: APIRoute = async({ request }) => {
|
export const POST: APIRoute = async({ request }) => {
|
||||||
const response = await validateAccessToken(request);
|
const response = await validateAccessToken(request);
|
||||||
if(response instanceof Response) return response;
|
if(response instanceof Response) return response;
|
||||||
|
|
||||||
const user = await getUserByAccessToken(response);
|
const userDB = await getUserByAccessToken(response);
|
||||||
if(user === null) {
|
if(userDB === null) {
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
code: 401,
|
code: 401,
|
||||||
|
@ -36,8 +32,30 @@ export const POST: APIRoute = async({ request }) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const userPlanet = locationManager.getPlanet(new ObjectId(body.planetId));
|
||||||
|
if(!userPlanet) {
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
code: 404,
|
||||||
|
message: "Not Found",
|
||||||
|
error: "Planet not found"
|
||||||
|
}), { status: 404 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const researchId = body.research;
|
const user = userPlanet.manager.owner;
|
||||||
|
|
||||||
|
if(!user.id.equals(userDB._id)) {
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
code: 403,
|
||||||
|
message: "Forbidden",
|
||||||
|
error: "You don't own this planet"
|
||||||
|
}), { status: 403 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const researchId = body.research as string;
|
||||||
const research = await getResearchById(researchId);
|
const research = await getResearchById(researchId);
|
||||||
|
|
||||||
if(!research) {
|
if(!research) {
|
||||||
|
@ -49,47 +67,27 @@ export const POST: APIRoute = async({ request }) => {
|
||||||
}), { status: 400 }
|
}), { status: 400 }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
let userPlanet: Planet | null;
|
|
||||||
try {
|
|
||||||
userPlanet = await getPlanetById(new ObjectId(body.planetId));
|
|
||||||
} catch(e) {
|
|
||||||
return new Response(
|
|
||||||
JSON.stringify({
|
|
||||||
code: 400,
|
|
||||||
message: "Bad Request",
|
|
||||||
error: "Invalid planet id"
|
|
||||||
}), { status: 400 }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if(!userPlanet) {
|
|
||||||
return new Response(
|
|
||||||
JSON.stringify({
|
|
||||||
code: 404,
|
|
||||||
message: "Not Found",
|
|
||||||
error: "Planet not found"
|
|
||||||
}), { status: 404 }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// check requirements
|
// check requirements
|
||||||
// buildings
|
// buildings
|
||||||
const buildings = userPlanet.buildings;
|
const buildings = userPlanet.buildings;
|
||||||
research.requirements.buildings.forEach((buildingReq) => {
|
for(const buildingReq of research.requirements.buildings) {
|
||||||
if(buildings.filter((building) => building.id === buildingReq.id)[0]?.level ?? 0 < buildingReq.level) {
|
if((buildings.buildings.find((building) => building.data.id === buildingReq.id)?.level ?? 0) < buildingReq.level) {
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
code: 400,
|
code: 400,
|
||||||
message: "Bad Request",
|
message: "Bad Request",
|
||||||
error: `${buildingReq.id} level ${buildingReq.level} required, found ${buildings.filter((building) => building.id === buildingReq.id)[0]?.level ?? 0}`
|
error: `${buildingReq.id} level ${buildingReq.level} required, found ${buildings.buildings.filter((building) => building.data.id === buildingReq.id)[0]?.level ?? 0}`
|
||||||
}), { status: 400 }
|
}), { status: 400 }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
// research
|
// research
|
||||||
const playerResearch = await getUserResearch(user);
|
const playerResearch = user.research.research;
|
||||||
research.requirements.research.forEach((researchReq) => {
|
for(const researchReq of research.requirements.research) {
|
||||||
if(playerResearch.filter((research) => research.id === researchReq.id)[0].level < researchReq.level) {
|
if((playerResearch.find((research) => research.id === researchReq.id)?.level ?? 0) < researchReq.level) {
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
code: 400,
|
code: 400,
|
||||||
|
@ -98,10 +96,10 @@ export const POST: APIRoute = async({ request }) => {
|
||||||
}), { status: 400 }
|
}), { status: 400 }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
// resources
|
// resources
|
||||||
const resources = await calculateCurrentAvailableResources(userPlanet._id);
|
const resources = await userPlanet.resources.calculateCurrentAvailableResources();
|
||||||
if(!resources) {
|
if(!resources) {
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
|
@ -111,24 +109,25 @@ export const POST: APIRoute = async({ request }) => {
|
||||||
}), { status: 500 }
|
}), { status: 500 }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const playerCurrentResearch = playerResearch.filter((element: any) => element.id === researchId)[0];
|
const playerCurrentResearch = playerResearch.filter((element: any) => element.id === researchId)[0];
|
||||||
const level = playerCurrentResearch ? playerCurrentResearch.level : 0;
|
const level = playerCurrentResearch ? playerCurrentResearch.level : 0;
|
||||||
const newResources = structuredClone(resources);
|
const newResources = structuredClone(resources);
|
||||||
const missingResources: Array<{}> = [];
|
const missingResources: Array<{ id: string, required: number, available: number }> = [];
|
||||||
research.requirements.resources.forEach(resource => {
|
for(const resource of research.requirements.resources) {
|
||||||
const res = resources.filter((element: PlayerResource) => element.name === resource.name)[0];
|
const res = resources.filter((element) => element.id === resource.id)[0];
|
||||||
const cost = playerCurrentResearch ? resource.amount * Math.pow(research.multiplier, level) : resource.amount;
|
const cost = playerCurrentResearch ? resource.amount * Math.pow(research.multiplier, level) : resource.amount;
|
||||||
|
|
||||||
if(res.amount < cost) {
|
if(res.amount < cost) {
|
||||||
missingResources.push({
|
missingResources.push({
|
||||||
name: resource.name,
|
id: resource.id,
|
||||||
required: cost,
|
required: cost,
|
||||||
available: res.amount
|
available: res.amount
|
||||||
});
|
});
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
else newResources.filter((element: PlayerResource) => element.name === resource.name)[0].amount -= cost;
|
else newResources.filter((element) => element.id === resource.id)[0].amount -= cost;
|
||||||
});
|
};
|
||||||
|
|
||||||
if(missingResources.length > 0) {
|
if(missingResources.length > 0) {
|
||||||
return new Response(
|
return new Response(
|
||||||
|
@ -140,8 +139,15 @@ export const POST: APIRoute = async({ request }) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
await updatePlanetResources(userPlanet._id, newResources);
|
userPlanet.resources.update(newResources);
|
||||||
await createOrUpgradeResearch(user._id, { id: researchId, level: level + 1 });
|
userPlanet.manager.owner.research.addResearch({
|
||||||
|
id: researchId,
|
||||||
|
level: level + 1,
|
||||||
|
data: research
|
||||||
|
});
|
||||||
|
|
||||||
|
await userPlanet.resources.sync();
|
||||||
|
await userPlanet.manager.owner.research.sync();
|
||||||
|
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
|
|
|
@ -6,7 +6,9 @@ import { getUserByAccessToken } from '../../lib/db/users';
|
||||||
import { getHighestWeightedLanguage, getLocales, getName, getObj } from '../../lib/utils/langDriver';
|
import { getHighestWeightedLanguage, getLocales, getName, getObj } from '../../lib/utils/langDriver';
|
||||||
import ResourceBar from '../../components/ResourceBar.astro';
|
import ResourceBar from '../../components/ResourceBar.astro';
|
||||||
import { getAllBuildings } from '../../lib/db/buildings';
|
import { getAllBuildings } from '../../lib/db/buildings';
|
||||||
import DBBuilding from '../../types/DBBuilding';
|
import locationManager from '../../lib/classes/managers/LocationManager';
|
||||||
|
import { ObjectId } from 'mongodb';
|
||||||
|
import DBBuilding from '../../types/db/DBBuilding';
|
||||||
|
|
||||||
const buildingsList = await getAllBuildings();
|
const buildingsList = await getAllBuildings();
|
||||||
|
|
||||||
|
@ -21,20 +23,31 @@ const locale = await getHighestWeightedLanguage(Astro.request.headers.get('accep
|
||||||
|
|
||||||
const lang = await getLocales(locale);
|
const lang = await getLocales(locale);
|
||||||
|
|
||||||
|
const planetId = Astro.cookies.get('planetid')?.value ?? "";
|
||||||
|
if(planetId === "") return "No planet selected";
|
||||||
|
|
||||||
|
const planet = locationManager.getPlanet(new ObjectId(planetId));
|
||||||
|
if(!planet) return "Planet not found";
|
||||||
|
|
||||||
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>, buildings: Array<any>, energy: number } } = {};
|
||||||
|
|
||||||
for(const building of buildingsList) {
|
for(const building of buildingsList) {
|
||||||
modalSet[building.id] = {
|
modalSet[building.id] = {
|
||||||
resources: building.requirements.resources,
|
resources: building.requirements.resources.map(resource => {
|
||||||
|
return {
|
||||||
|
id: resource.id,
|
||||||
|
amount: Math.pow(building.multiplier, (planet.buildings.getBuildingById(building.id)?.level ?? 0) ) * resource.amount
|
||||||
|
};
|
||||||
|
}),
|
||||||
research: building.requirements.research,
|
research: building.requirements.research,
|
||||||
buildings: building.requirements.buildings,
|
buildings: building.requirements.buildings,
|
||||||
energy: building.energy
|
energy: building.energy
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildingsByCategory = buildingsList.reduce((acc: { [key: string]: DBBuilding[] }, building) => {
|
const buildingsByCategory = buildingsList.reduce((acc: { [key: string]: Array<DBBuilding & { level: number }> }, building) => {
|
||||||
if(!acc[building.category]) acc[building.category] = [];
|
if(!acc[building.category]) acc[building.category] = [];
|
||||||
acc[building.category].push(building);
|
acc[building.category].push({ ...building, level: planet.buildings.getBuildingById(building.id)?.level ?? 0 });
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
---
|
---
|
||||||
|
@ -60,6 +73,7 @@ const buildingsByCategory = buildingsList.reduce((acc: { [key: string]: DBBuildi
|
||||||
{buildings.map(building => (
|
{buildings.map(building => (
|
||||||
<BuildingCard
|
<BuildingCard
|
||||||
id={building.id}
|
id={building.id}
|
||||||
|
level={building.level.toString()}
|
||||||
name={getObj(lang, "buildings", building.id).name}
|
name={getObj(lang, "buildings", building.id).name}
|
||||||
description={getObj(lang, "buildings", building.id).description ?? ""}
|
description={getObj(lang, "buildings", building.id).description ?? ""}
|
||||||
image={`/images/buildings/${building.id}.jpeg`}
|
image={`/images/buildings/${building.id}.jpeg`}
|
||||||
|
@ -185,7 +199,7 @@ const buildingsByCategory = buildingsList.reduce((acc: { [key: string]: DBBuildi
|
||||||
color: lime;
|
color: lime;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script define:vars={{ modalSet, lang }}>
|
<script define:vars={{ modalSet, lang, planetId }}>
|
||||||
const modalResources = document.getElementById("building-modal-req-resources");
|
const modalResources = document.getElementById("building-modal-req-resources");
|
||||||
const modalBuildings = document.getElementById("building-modal-req-buildings");
|
const modalBuildings = document.getElementById("building-modal-req-buildings");
|
||||||
const modalResearch = document.getElementById("building-modal-req-research");
|
const modalResearch = document.getElementById("building-modal-req-research");
|
||||||
|
@ -202,7 +216,7 @@ const buildingsByCategory = buildingsList.reduce((acc: { [key: string]: DBBuildi
|
||||||
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.name).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 => {
|
modalBuildings.innerHTML = reqBuildings.length === 0 ? "None" : reqBuildings.map(building => {
|
||||||
|
@ -233,21 +247,28 @@ const buildingsByCategory = buildingsList.reduce((acc: { [key: string]: DBBuildi
|
||||||
backgroundDiv.style.display = 'none';
|
backgroundDiv.style.display = 'none';
|
||||||
});
|
});
|
||||||
|
|
||||||
const allButtons = document.getElementsByClassName("a-button");
|
const allButtons = document.getElementsByClassName("item-card-build");
|
||||||
|
|
||||||
for(const buildingButton of allButtons) {
|
for(const buildingButton of allButtons) {
|
||||||
buildingButton.addEventListener("click", async () => {
|
buildingButton.addEventListener("click", async () => {
|
||||||
const id = buildingButton.id.split("_")[1];
|
const id = buildingButton.id.split("_")[1];
|
||||||
|
|
||||||
await fetch('/api/build/createBuilding', {
|
const response = await fetch('/api/build/createBuilding', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
building: id
|
building: id,
|
||||||
|
planet: planetId
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(response.status === 200) {
|
||||||
|
window.location.reload();
|
||||||
|
} else {
|
||||||
|
alert("Failed to build building: " + JSON.stringify(await response.json()));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
|
@ -5,7 +5,6 @@ import { getUserByAccessToken } from '../../lib/db/users';
|
||||||
import { getHighestWeightedLanguage, getLocales, getName, getObj } from '../../lib/utils/langDriver';
|
import { getHighestWeightedLanguage, getLocales, getName, getObj } from '../../lib/utils/langDriver';
|
||||||
import ResourceBar from '../../components/ResourceBar.astro';
|
import ResourceBar from '../../components/ResourceBar.astro';
|
||||||
import ItemCard from '../../components/ItemCard.astro';
|
import ItemCard from '../../components/ItemCard.astro';
|
||||||
import DBResearch from '../../types/DBResearch';
|
|
||||||
import { getAllResearch } from '../../lib/db/research';
|
import { getAllResearch } from '../../lib/db/research';
|
||||||
|
|
||||||
const researchList = await getAllResearch();
|
const researchList = await getAllResearch();
|
||||||
|
@ -17,23 +16,13 @@ if(loggedToken === null || username === "") return Astro.redirect('/logout');
|
||||||
const checkUser = await getUserByAccessToken(loggedToken);
|
const checkUser = await getUserByAccessToken(loggedToken);
|
||||||
if(checkUser === null || checkUser.username !== username) return Astro.redirect('/logout');
|
if(checkUser === null || checkUser.username !== username) return Astro.redirect('/logout');
|
||||||
|
|
||||||
|
const planetId = Astro.cookies.get('planetid')?.value ?? "";
|
||||||
|
if(planetId === "") return Astro.redirect('/logout');
|
||||||
|
|
||||||
const locale = await getHighestWeightedLanguage(Astro.request.headers.get('accept-language'));
|
const locale = await getHighestWeightedLanguage(Astro.request.headers.get('accept-language'));
|
||||||
|
|
||||||
const lang = await getLocales(locale);
|
const lang = await getLocales(locale);
|
||||||
|
|
||||||
// type DBResearchDetails = DBResearch & { level: number };
|
|
||||||
// const researchDetails: DBResearchDetails[] = [];
|
|
||||||
// researchList.forEach(element => {
|
|
||||||
// const userLevel = checkUser.research.find(x => x.id === element.id)?.level ?? 0;
|
|
||||||
// const tempResDetails: DBResearchDetails = {
|
|
||||||
// level: userLevel,
|
|
||||||
// ...element
|
|
||||||
// }
|
|
||||||
|
|
||||||
// researchDetails.push(tempResDetails);
|
|
||||||
// });
|
|
||||||
|
|
||||||
|
|
||||||
const modalSet: { [key: string]: { resources: Array<any>, research: Array<any>, buildings: Array<any> } } = {};
|
const modalSet: { [key: string]: { resources: Array<any>, research: Array<any>, buildings: Array<any> } } = {};
|
||||||
|
|
||||||
for(const research of researchList) {
|
for(const research of researchList) {
|
||||||
|
@ -66,6 +55,7 @@ for(const research of researchList) {
|
||||||
<ItemCard
|
<ItemCard
|
||||||
id={research.id}
|
id={research.id}
|
||||||
name={getObj(lang, "research", research.id).name}
|
name={getObj(lang, "research", research.id).name}
|
||||||
|
level={checkUser.research.find(x => x.id === research.id)?.level.toString() ?? "0"}
|
||||||
description={getObj(lang, "research", research.id).description ?? ""}
|
description={getObj(lang, "research", research.id).description ?? ""}
|
||||||
image={`/images/research/${research.id}.jpeg`}
|
image={`/images/research/${research.id}.jpeg`}
|
||||||
button_type="general"
|
button_type="general"
|
||||||
|
@ -187,7 +177,7 @@ for(const research of researchList) {
|
||||||
z-index: 101;
|
z-index: 101;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script define:vars={{ modalSet, lang }}>
|
<script define:vars={{ modalSet, lang, planetId }}>
|
||||||
const modalResources = document.getElementById("research-modal-req-resources");
|
const modalResources = document.getElementById("research-modal-req-resources");
|
||||||
const modalBuildings = document.getElementById("research-modal-req-buildings");
|
const modalBuildings = document.getElementById("research-modal-req-buildings");
|
||||||
const modalResearch = document.getElementById("research-modal-req-research");
|
const modalResearch = document.getElementById("research-modal-req-research");
|
||||||
|
@ -237,23 +227,28 @@ for(const research of researchList) {
|
||||||
backgroundDiv.style.display = 'none';
|
backgroundDiv.style.display = 'none';
|
||||||
});
|
});
|
||||||
|
|
||||||
const allButtons = document.getElementsByClassName("a-button");
|
const allButtons = document.getElementsByClassName("item-card-build");
|
||||||
|
|
||||||
for(const researchButton of allButtons) {
|
for(const researchButton of allButtons) {
|
||||||
researchButton.addEventListener("click", async () => {
|
researchButton.addEventListener("click", async () => {
|
||||||
const id = researchButton.id.split("_")[1];
|
const id = researchButton.id.split("_")[1];
|
||||||
|
|
||||||
console.log(id);
|
const response = await fetch('/api/research/performResearch', {
|
||||||
|
|
||||||
await fetch('/api/research/performResearch', {
|
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
research: id
|
research: id,
|
||||||
|
planetId
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(response.status === 200) {
|
||||||
|
window.location.reload();
|
||||||
|
} else {
|
||||||
|
alert("Failed to build building: " + JSON.stringify(await response.json()));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
|
@ -2,11 +2,12 @@
|
||||||
import Layout from '../layouts/Layout.astro';
|
import Layout from '../layouts/Layout.astro';
|
||||||
import NavBar from '../components/NavBar.astro';
|
import NavBar from '../components/NavBar.astro';
|
||||||
|
|
||||||
import { getUserByNickOrEmail, getUserWithPlanets, updateLastLogin } from '../lib/db/users';
|
import { getUserByNickOrEmail, updateLastLogin } from '../lib/db/users';
|
||||||
|
|
||||||
import config from '../../config.json';
|
import config from '../../config.json';
|
||||||
|
|
||||||
import { verify } from 'argon2';
|
import { verify } from 'argon2';
|
||||||
|
import locationManager from '../lib/classes/managers/LocationManager';
|
||||||
|
|
||||||
let error = "";
|
let error = "";
|
||||||
|
|
||||||
|
@ -25,9 +26,11 @@ if(Astro.request.method === "POST") {
|
||||||
Astro.redirect("/login");
|
Astro.redirect("/login");
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = await getUserByNickOrEmail(username as string);
|
const userDB = await getUserByNickOrEmail(username as string);
|
||||||
|
|
||||||
if(user !== null && await verify(user.password, password as string)) {
|
if(userDB !== null && await verify(userDB.password, password as string)) {
|
||||||
|
const user = locationManager.getUser(userDB._id);
|
||||||
|
if(!user) throw new Error("User not found");
|
||||||
const sessionTime = config.SESSION_TIME_MINUTES * 60;
|
const sessionTime = config.SESSION_TIME_MINUTES * 60;
|
||||||
|
|
||||||
const res = await fetch(`http://localhost:4321/api/auth/generateAccessToken`, {
|
const res = await fetch(`http://localhost:4321/api/auth/generateAccessToken`, {
|
||||||
|
@ -61,18 +64,14 @@ if(Astro.request.method === "POST") {
|
||||||
secure: true
|
secure: true
|
||||||
});
|
});
|
||||||
|
|
||||||
Astro.cookies.set("userid", user._id?.toString() as string, {
|
Astro.cookies.set("userid", user.id?.toString() as string, {
|
||||||
path: "/",
|
path: "/",
|
||||||
maxAge: sessionTime,
|
maxAge: sessionTime,
|
||||||
sameSite: "lax",
|
sameSite: "lax",
|
||||||
secure: true
|
secure: true
|
||||||
});
|
});
|
||||||
|
|
||||||
const userWithPlanets = await getUserWithPlanets(user._id);
|
Astro.cookies.set("planetid", user.mainPlanet._id, {
|
||||||
if(!userWithPlanets) return;
|
|
||||||
const planetId = userWithPlanets.planets.data[0]._id;
|
|
||||||
|
|
||||||
Astro.cookies.set("planetid", planetId.toString(), {
|
|
||||||
path: "/",
|
path: "/",
|
||||||
maxAge: sessionTime,
|
maxAge: sessionTime,
|
||||||
sameSite: "lax",
|
sameSite: "lax",
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import type { ObjectId } from "mongodb";
|
import User from "../lib/classes/User";
|
||||||
|
|
||||||
export default interface AccessToken {
|
export default interface AccessToken {
|
||||||
_id?: ObjectId;
|
type: string;
|
||||||
type: "A" | "X";
|
user: User | null;
|
||||||
user: ObjectId | null;
|
|
||||||
entropy: string;
|
entropy: string;
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
expiresAt: Date | null;
|
expiresAt: Date | null;
|
||||||
createdFrom: null | 'loginForm';
|
createdFrom: string | null;
|
||||||
}
|
}
|
|
@ -1,4 +0,0 @@
|
||||||
export default interface Building {
|
|
||||||
id: string;
|
|
||||||
level: number;
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
export default interface DBBuilding {
|
|
||||||
id: string,
|
|
||||||
category: string,
|
|
||||||
requirements: {
|
|
||||||
buildings: Array<{ id: string, level: number }>,
|
|
||||||
research: Array<{ id: string, level: number }>,
|
|
||||||
resources: Array<{ name: string, amount: number }>,
|
|
||||||
},
|
|
||||||
energy: number,
|
|
||||||
multiplier: number,
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
export default interface DBResearch {
|
|
||||||
id: string,
|
|
||||||
requirements: {
|
|
||||||
buildings: Array<{ id: string, level: number }>,
|
|
||||||
research: Array<{ id: string, level: number }>,
|
|
||||||
resources: Array<{ name: string, amount: number }>,
|
|
||||||
},
|
|
||||||
time: number,
|
|
||||||
multiplier: number,
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
export default interface DBResource {
|
|
||||||
id: string,
|
|
||||||
type: string,
|
|
||||||
icon: string
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
export default interface DBShip {
|
|
||||||
id: string,
|
|
||||||
capacity: {
|
|
||||||
solid: number,
|
|
||||||
liquid: number,
|
|
||||||
gas: number,
|
|
||||||
},
|
|
||||||
requirements: {
|
|
||||||
buildings: Array<{ id: string, level: number }>,
|
|
||||||
research: Array<{ id: string, level: number }>,
|
|
||||||
resources: Array<{ name: string, amount: number }>,
|
|
||||||
},
|
|
||||||
time: number,
|
|
||||||
structure: {
|
|
||||||
hitpoints: number,
|
|
||||||
defense: number,
|
|
||||||
attack: number,
|
|
||||||
},
|
|
||||||
speed: number,
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
import type { ObjectId } from "mongodb";
|
|
||||||
import type PlayerResource from "./PlayerResource";
|
|
||||||
import type Building from "./Building";
|
|
||||||
import type Ship from "./Ship";
|
|
||||||
import type User from "./User";
|
|
||||||
|
|
||||||
export default interface Planet {
|
|
||||||
_id: ObjectId,
|
|
||||||
owner: User,
|
|
||||||
name: string,
|
|
||||||
fields: number,
|
|
||||||
resources: Array<PlayerResource>,
|
|
||||||
buildings: Array<Building>,
|
|
||||||
ships: Array<Ship>,
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
import type Resource from "./Resource";
|
|
||||||
|
|
||||||
export default interface DBResource extends Resource {
|
|
||||||
lastUpdated: Date;
|
|
||||||
perHourMiningRate: number;
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
export default interface Research {
|
|
||||||
id: string;
|
|
||||||
level: number;
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
export default interface Resource {
|
|
||||||
name: string;
|
|
||||||
amount: number;
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
export default interface Resources {
|
|
||||||
coal: number;
|
|
||||||
iron: number;
|
|
||||||
gold: number;
|
|
||||||
|
|
||||||
water: number;
|
|
||||||
sulfuricAcid: number;
|
|
||||||
liquidNitrogen: number;
|
|
||||||
|
|
||||||
hydrogen: number;
|
|
||||||
oxygen: number;
|
|
||||||
helium3: number;
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
export default interface Ship {
|
|
||||||
id: string;
|
|
||||||
amount: number;
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
import type { ObjectId } from "mongodb";
|
|
||||||
import type Research from "./Research";
|
|
||||||
import type Planet from "./Planet";
|
|
||||||
|
|
||||||
export default interface User {
|
|
||||||
_id: ObjectId;
|
|
||||||
username: string;
|
|
||||||
email: string;
|
|
||||||
password: string;
|
|
||||||
lastLogin: Date;
|
|
||||||
research: Array<Research>;
|
|
||||||
planets: {
|
|
||||||
partial: boolean;
|
|
||||||
data: Array<Planet>;
|
|
||||||
};
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
}
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { ObjectId } from "mongodb";
|
||||||
|
|
||||||
|
export default interface DBAccessToken {
|
||||||
|
_id: ObjectId;
|
||||||
|
type: string;
|
||||||
|
user: ObjectId;
|
||||||
|
entropy: string;
|
||||||
|
createdAt: Date;
|
||||||
|
expiresAt: Date;
|
||||||
|
createdFrom: string | null;
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { ObjectId } from "mongodb";
|
||||||
|
|
||||||
|
export default interface DBBuilding {
|
||||||
|
_id: ObjectId;
|
||||||
|
id: string;
|
||||||
|
category: string;
|
||||||
|
requirements: {
|
||||||
|
buildings: Array<{ id: string, level: number }>,
|
||||||
|
research: Array<{ id: string, level: number }>,
|
||||||
|
resources: Array<{ id: string, amount: number }>,
|
||||||
|
};
|
||||||
|
energy: number;
|
||||||
|
time: number;
|
||||||
|
multiplier: number;
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { ObjectId } from "mongodb";
|
||||||
|
|
||||||
|
export default interface DBFleet {
|
||||||
|
_id: ObjectId;
|
||||||
|
source: ObjectId;
|
||||||
|
destination: ObjectId;
|
||||||
|
finished: boolean;
|
||||||
|
returning: boolean;
|
||||||
|
mission: string;
|
||||||
|
ships: Array<{ id: string, amount: number }>;
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { ObjectId } from "mongodb";
|
||||||
|
|
||||||
|
export default interface DBGalaxy {
|
||||||
|
_id: ObjectId;
|
||||||
|
name: string;
|
||||||
|
sectors: Array<ObjectId>;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { ObjectId } from "mongodb";
|
||||||
|
|
||||||
|
export default interface DBPlanet {
|
||||||
|
_id: ObjectId;
|
||||||
|
name: string;
|
||||||
|
fields: number;
|
||||||
|
resources: Array<{ id: string, amount: number, lastUpdated: Date, perHourMiningRate: number }>;
|
||||||
|
buildings: Array<{ id: string, level: number }>;
|
||||||
|
ships: Array<{ id: string, amount: number }>;
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { ObjectId } from "mongodb";
|
||||||
|
|
||||||
|
export default interface DBResearch {
|
||||||
|
_id: ObjectId;
|
||||||
|
id: string;
|
||||||
|
requirements: {
|
||||||
|
buildings: Array<{ id: string, level: number }>,
|
||||||
|
research: Array<{ id: string, level: number }>,
|
||||||
|
resources: Array<{ id: string, amount: number }>,
|
||||||
|
};
|
||||||
|
time: number;
|
||||||
|
multiplier: number;
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { ObjectId } from "mongodb";
|
||||||
|
|
||||||
|
export default interface DBResource {
|
||||||
|
_id: ObjectId;
|
||||||
|
id: string;
|
||||||
|
type: string;
|
||||||
|
icon: string;
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { ObjectId } from "mongodb";
|
||||||
|
|
||||||
|
export default interface DBSector {
|
||||||
|
_id: ObjectId;
|
||||||
|
name: string;
|
||||||
|
expedition: any; // TODO: Define expedition type
|
||||||
|
systems: Array<ObjectId>;
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ObjectId } from "mongodb";
|
||||||
|
|
||||||
|
export default interface DBShip {
|
||||||
|
_id: ObjectId;
|
||||||
|
id: string;
|
||||||
|
capacity: {
|
||||||
|
solid: number;
|
||||||
|
liquid: number;
|
||||||
|
gas: number;
|
||||||
|
};
|
||||||
|
requirements: {
|
||||||
|
buildings: Array<{ id: string, level: number }>,
|
||||||
|
research: Array<{ id: string, level: number }>,
|
||||||
|
resources: Array<{ id: string, amount: number }>,
|
||||||
|
};
|
||||||
|
time: number;
|
||||||
|
structure: {
|
||||||
|
hitpoints: number;
|
||||||
|
defense: number;
|
||||||
|
attack: number;
|
||||||
|
};
|
||||||
|
speed: number;
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { ObjectId } from "mongodb";
|
||||||
|
|
||||||
|
export default interface DBSystem {
|
||||||
|
_id: ObjectId;
|
||||||
|
name: string;
|
||||||
|
ownedBy: ObjectId;
|
||||||
|
planets: Array<ObjectId>;
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { ObjectId } from "mongodb";
|
||||||
|
|
||||||
|
export default interface DBUser {
|
||||||
|
_id: ObjectId;
|
||||||
|
username: string;
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
lastLogin: Date;
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
|
research: Array<{ id: string, level: number }>;
|
||||||
|
mainPlanet: ObjectId;
|
||||||
|
}
|
|
@ -1,31 +0,0 @@
|
||||||
import { createUser, deleteUser, getUserByNickOrEmail } from '../src/lib/db/users';
|
|
||||||
import { connect, disconnect } from '../src/lib/db/mongodb';
|
|
||||||
import { verify } from 'argon2';
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await connect();
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(async () => {
|
|
||||||
await disconnect();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Test user database functions', () => {
|
|
||||||
test('getUserByNickOrEmail', async () => {
|
|
||||||
const user = await getUserByNickOrEmail("gargamel");
|
|
||||||
expect(user).not.toBeNull();
|
|
||||||
expect(user?.username).toBe("gargamel");
|
|
||||||
expect(user?.email).toBe("gargamel@smerfy.pl");
|
|
||||||
});
|
|
||||||
|
|
||||||
test('createAndVerifyUser', async () => {
|
|
||||||
await createUser("test", "test@example.com", "password");
|
|
||||||
const user = await getUserByNickOrEmail("test");
|
|
||||||
expect(user).not.toBeNull();
|
|
||||||
if(!user) return;
|
|
||||||
expect(user?.username).toBe("test");
|
|
||||||
expect(user?.email).toBe("test@example.com");
|
|
||||||
expect(await verify(user?.password as string, "password")).toBe(true);
|
|
||||||
await deleteUser(user._id);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,85 +0,0 @@
|
||||||
import { connect, disconnect } from "../src/lib/db/mongodb";
|
|
||||||
import { createUser, deleteUser } from "../src/lib/db/users";
|
|
||||||
import { calculateCurrentAvailableResources, getUserResources, updateUserResources } from "../src/lib/utils/resourceManager";
|
|
||||||
import User from "../src/types/User";
|
|
||||||
|
|
||||||
let user: User;
|
|
||||||
|
|
||||||
describe('Test resource manager', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
await connect();
|
|
||||||
user = await createUser("test", "test@example.com", "password");
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(async () => {
|
|
||||||
await deleteUser(user._id);
|
|
||||||
await disconnect();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Test initial resources amount', () => {
|
|
||||||
test('initialResourcesAmount', async () => {
|
|
||||||
const resources = await getUserResources(user._id);
|
|
||||||
let i = 1;
|
|
||||||
resources.forEach(res => {
|
|
||||||
expect(res.amount).toBe(i * 11);
|
|
||||||
expect(res.perHourMiningRate).toBe(i * 11);
|
|
||||||
i++;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Test calculation of available resources', () => {
|
|
||||||
test('calculationOfAvailableResources', async () => {
|
|
||||||
const resources = await getUserResources(user._id);
|
|
||||||
|
|
||||||
resources.forEach(res => {
|
|
||||||
res.amount = 0;
|
|
||||||
res.lastUpdated = new Date(Date.now() - 1000 * 60 * 60);
|
|
||||||
});
|
|
||||||
|
|
||||||
await updateUserResources(user._id, resources);
|
|
||||||
const availableResources = await calculateCurrentAvailableResources(user._id);
|
|
||||||
let i = 1;
|
|
||||||
availableResources.forEach(res => {
|
|
||||||
expect(res.amount).toBeCloseTo(i * 11);
|
|
||||||
i++;
|
|
||||||
});
|
|
||||||
|
|
||||||
const resourcesAfter = await getUserResources(user._id);
|
|
||||||
i = 1;
|
|
||||||
resourcesAfter.forEach(res => {
|
|
||||||
expect(res.amount).toBeCloseTo(i * 11);
|
|
||||||
i++;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Test taking resources', () => {
|
|
||||||
test('takingResources', async () => {
|
|
||||||
const resources = await getUserResources(user._id);
|
|
||||||
resources.forEach(res => {
|
|
||||||
res.amount = 10_000;
|
|
||||||
});
|
|
||||||
|
|
||||||
let i = 1;
|
|
||||||
|
|
||||||
resources.forEach(res => {
|
|
||||||
res.amount -= i * 100;
|
|
||||||
i++;
|
|
||||||
});
|
|
||||||
|
|
||||||
await updateUserResources(user._id, resources);
|
|
||||||
|
|
||||||
const resourcesAfter = await getUserResources(user._id);
|
|
||||||
i = 1;
|
|
||||||
resourcesAfter.forEach(res => {
|
|
||||||
expect(res.amount).toBeCloseTo(10_000 - i * 100);
|
|
||||||
i++;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue