Compare commits
No commits in common. "cc5d482a0f3b47e9a0f7e433952c33d6a437a91f" and "b13a116cd4d6ac98edce9389144ba439f53d24ef" have entirely different histories.
cc5d482a0f
...
b13a116cd4
|
@ -3,7 +3,6 @@ import { getHighestWeightedLanguage, getLocales, getName } from '../lib/utils/la
|
|||
|
||||
interface Props {
|
||||
id: string;
|
||||
level: string;
|
||||
name: string;
|
||||
description: string;
|
||||
image: string;
|
||||
|
@ -18,7 +17,7 @@ const lang = await getLocales(await getHighestWeightedLanguage(Astro.request.hea
|
|||
<div class="item-card" data-id={Astro.props.id}>
|
||||
<img class="item-card-image" src={Astro.props.image} />
|
||||
<div class="item-card-main-field">
|
||||
<div class="item-card-name">{Astro.props.name} | {Astro.props.level}</div>
|
||||
<div class="item-card-name">{Astro.props.name}</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>
|
||||
<div class="item-card-info-button">i</div>
|
||||
|
|
|
@ -1,26 +1,20 @@
|
|||
---
|
||||
import { ObjectId } from 'mongodb';
|
||||
import { calculateCurrentAvailableResources } from '../lib/utils/resourceManager';
|
||||
import { getHighestWeightedLanguage, getLocales, getName } from '../lib/utils/langDriver';
|
||||
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 lang = await getLocales(await getHighestWeightedLanguage(Astro.request.headers.get('accept-language')));
|
||||
|
||||
const planetId = new ObjectId(Astro.cookies.get('planetid')?.value ?? '');
|
||||
const resources = await calculateCurrentAvailableResources(new ObjectId(Astro.cookies.get('planetid')?.value ?? ''));
|
||||
|
||||
const resources = locationManager.getPlanet(planetId)?.resources;
|
||||
|
||||
if(!resources) return;
|
||||
|
||||
resources.calculateCurrentAvailableResources();
|
||||
|
||||
const resourceArray: Resource[] = [];
|
||||
for(const key of resources.resources) {
|
||||
resourceArray.push(key);
|
||||
const resourceArray = [];
|
||||
for(const key in resources) {
|
||||
resourceArray.push(resources[key as never]);
|
||||
}
|
||||
|
||||
---
|
||||
<div id="resourcebar">
|
||||
<div class="resourcebar-item-identifier">
|
||||
|
@ -29,16 +23,16 @@ for(const key of resources.resources) {
|
|||
<div id="resourcebar-elements" class="resourcebar-elements">
|
||||
{resourceArray.map(res =>
|
||||
<div class="resourcebar-item"
|
||||
data-res-type={resourceTypes.find(x => x.id === res.id)?.type ?? "solid"}
|
||||
data-res-type={resourceTypes.find(x => x.id === res.name)?.type ?? "solid"}
|
||||
data-res-amount={res.amount}
|
||||
data-res-mining-rate={res.perHourMiningRate}
|
||||
style={(resourceTypes.find(x => x.id === res.id)?.type ?? "solid") === "solid" ? "" : "display: none;"}
|
||||
style={(resourceTypes.find(x => x.id === res.name)?.type ?? "solid") === "solid" ? "" : "display: none;"}
|
||||
>
|
||||
<div class="resourcebar-item-icon">
|
||||
<img src={resourceTypes.find(x => x.id === res.id)?.icon ?? "#"} alt={res.id} />
|
||||
<img src={resourceTypes.find(x => x.id === res.name)?.icon ?? "#"} alt={res.name} />
|
||||
</div>
|
||||
<div class="resourcebar-item-text-wrapper" data-resname={res.id}>
|
||||
<div class="resourcebar-item-text">{getName(lang, 'resources', res.id)}</div>
|
||||
<div class="resourcebar-item-text-wrapper" data-resname={res.name}>
|
||||
<div class="resourcebar-item-text">{getName(lang, 'resources', res.name)}</div>
|
||||
<div class="resourcebar-item-amount">[fetching]</div>
|
||||
</div>
|
||||
<div class="resourcebar-item-tooltip">
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
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: ""
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
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 } }));
|
||||
}
|
||||
}
|
|
@ -1,153 +0,0 @@
|
|||
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;
|
|
@ -1,51 +0,0 @@
|
|||
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));
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
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 } }));
|
||||
}
|
||||
}
|
|
@ -1,152 +0,0 @@
|
|||
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,9 +1,7 @@
|
|||
import { AccessTokens } from './mongodb';
|
||||
import type AccessToken from '../../types/AccessToken';
|
||||
import { createHash } from 'crypto';
|
||||
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) => {
|
||||
const newAccessToken = await (await AccessTokens()).insertOne(accessToken);
|
||||
|
@ -25,7 +23,7 @@ export const getAccessToken = async (accessToken: string) => {
|
|||
{ createdAt },
|
||||
{ user },
|
||||
{ entropy }
|
||||
] }) as Promise<DBAccessToken | null>;
|
||||
] }) as Promise<AccessToken | null>;
|
||||
}
|
||||
|
||||
export const getAllAccessTokens = async () => {
|
||||
|
@ -39,24 +37,7 @@ export const getAllAccessTokens = async () => {
|
|||
}
|
||||
|
||||
const accessTokens = await AccessTokens();
|
||||
const arrayOfTokens = await accessTokens.find({}).toArray() as DBAccessToken[];
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
const arrayOfTokens = await accessTokens.find({}).toArray() as AccessToken[];
|
||||
let arr = [master].concat(arrayOfTokens);
|
||||
return arr;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import DBBuilding from '../../types/db/DBBuilding';
|
||||
import DBBuilding from '../../types/DBBuilding';
|
||||
import { Buildings } from '../db/mongodb';
|
||||
|
||||
export const getAllBuildings = async () => {
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
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,6 +8,7 @@ const mongo = new MongoClient(uri, options);
|
|||
|
||||
export const connect = async () => {
|
||||
await mongo.connect();
|
||||
// return mongo.db(dbName);
|
||||
}
|
||||
|
||||
export const disconnect = async () => {
|
||||
|
@ -29,21 +30,6 @@ export const AccessTokens = async () => {
|
|||
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 () => {
|
||||
const db = await getDB();
|
||||
return db.collection('planets');
|
||||
|
|
|
@ -1,29 +1,74 @@
|
|||
import { Planets } from '../db/mongodb';
|
||||
import type User from '../../types/User';
|
||||
import { ObjectId } from 'mongodb';
|
||||
import DBPlanet from '../../types/db/DBPlanet';
|
||||
import type Planet from '../../types/Planet';
|
||||
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 () => {
|
||||
return await (await Planets()).find({}).toArray() as DBPlanet[];
|
||||
export const getAllPlanets = async (options?: { fetchUserPlanets: boolean }) => {
|
||||
const planets = await Planets();
|
||||
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) => {
|
||||
return await (await Planets()).findOne({ _id: id }) as DBPlanet;
|
||||
const planets = await Planets();
|
||||
const planet = await planets.findOne({
|
||||
_id: id
|
||||
});
|
||||
|
||||
if(!planet) return null;
|
||||
|
||||
planet.owner = await getUserById(planet.owner);
|
||||
return planet as Planet;
|
||||
}
|
||||
|
||||
export const updatePlanetResources = async (planetId: ObjectId, resources: Array<any>) => {
|
||||
const planets = await Planets();
|
||||
await planets.updateOne({ _id: planetId }, {
|
||||
$set: {
|
||||
resources
|
||||
}
|
||||
});
|
||||
}
|
||||
export const createOrUpgradeBuilding = async (planetId: ObjectId, building: Building) => {
|
||||
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++;
|
||||
}
|
||||
|
||||
export const updatePlanetBuildings = async (planetId: ObjectId, buildings: Array<{ id: string, level: number }>) => {
|
||||
const planets = await Planets();
|
||||
await planets.updateOne({ _id: planetId }, {
|
||||
await planets.updateOne({
|
||||
_id: planetId
|
||||
}, {
|
||||
$set: {
|
||||
buildings
|
||||
buildings: planet.buildings
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import DBResearch from '../../types/db/DBResearch';
|
||||
import DBResearch from '../../types/DBResearch';
|
||||
import { Research } from '../db/mongodb';
|
||||
|
||||
export const getAllResearch = async () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import DBResource from '../../types/db/DBResource';
|
||||
import DBResource from '../../types/DBResource';
|
||||
import { Resources } from '../db/mongodb';
|
||||
|
||||
export const getAllResources = async () => {
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
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/db/DBShip';
|
||||
import DBShip from '../../types/DBShip';
|
||||
import { Ships } from '../db/mongodb';
|
||||
|
||||
export const getAllShips = async () => {
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
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,30 +1,33 @@
|
|||
import { Users } from '../db/mongodb';
|
||||
import { Planets, Users } from '../db/mongodb';
|
||||
import type User from '../../types/User';
|
||||
import type AccessToken from '../../types/AccessToken';
|
||||
import { ObjectId } from 'mongodb';
|
||||
import { hash } from 'argon2'
|
||||
import DBUser from '../../types/db/DBUser';
|
||||
import User from '../classes/User';
|
||||
import AccessToken from '../../types/AccessToken';
|
||||
import { createInitialResources } from '../utils/resourceManager';
|
||||
import type Research from '../../types/Research';
|
||||
|
||||
export const getAllUsers = async () => {
|
||||
const users = await Users();
|
||||
return users.find({}).toArray() as Promise<DBUser[]>;
|
||||
return users.find({}).toArray() as Promise<User[]>;
|
||||
}
|
||||
|
||||
export const createUser = async (username: string, email: string, password: string) => {
|
||||
const user = {
|
||||
const user: User = {
|
||||
username,
|
||||
email,
|
||||
password: await hash(password),
|
||||
lastLogin: new Date(),
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
research: [],
|
||||
//@ts-ignore
|
||||
resources: {}
|
||||
}
|
||||
|
||||
|
||||
await (await Users()).insertOne(user);
|
||||
const newUser = await getUserByNickOrEmail(username);
|
||||
if(!newUser) return user;
|
||||
createInitialResources(newUser._id);
|
||||
return newUser;
|
||||
}
|
||||
|
||||
|
@ -37,7 +40,7 @@ export const getUserById = async (id: ObjectId) => {
|
|||
const users = await Users();
|
||||
return users.findOne({
|
||||
_id: id
|
||||
}) as Promise<DBUser | null>;
|
||||
}) as Promise<User | null>;
|
||||
}
|
||||
|
||||
export const getUserByNickOrEmail = async (searchString: string) => {
|
||||
|
@ -47,18 +50,14 @@ export const getUserByNickOrEmail = async (searchString: string) => {
|
|||
{ username: searchString },
|
||||
{ email: searchString }
|
||||
]
|
||||
}) as Promise<DBUser | null>;
|
||||
}) as Promise<User | null>;
|
||||
}
|
||||
|
||||
export const getUserByAccessToken = async(accessToken: string | AccessToken): Promise<DBUser | null> => {
|
||||
export const getUserByAccessToken = async(accessToken: string | AccessToken): Promise<User | null> => {
|
||||
if(typeof accessToken === "string") {
|
||||
const userId = new ObjectId(Buffer.from(accessToken.split(".")[2], 'base64url').toString());
|
||||
return getUserById(userId);
|
||||
} else {
|
||||
const user = accessToken.user;
|
||||
if(!user) return null;
|
||||
return getUserById(user?.id);
|
||||
}
|
||||
} else return getUserById(accessToken.user as ObjectId)
|
||||
}
|
||||
|
||||
export const updateLastLogin = async (user: User) => {
|
||||
|
@ -66,14 +65,54 @@ export const updateLastLogin = async (user: User) => {
|
|||
return users.updateOne({ username: user.username }, { $set: { lastLogin: new Date() } });
|
||||
}
|
||||
|
||||
export const getUserResearch = async (user: User): Promise<Array<{ id: string, level: number }>> => {
|
||||
const users = await Users();
|
||||
const rawUser = await users.findOne({ username: user.username });
|
||||
if (!rawUser) return [];
|
||||
return rawUser.research;
|
||||
export const getUserResearch = async (user: User): Promise<Array<Research>> => {
|
||||
const research: Array<Research> = [];
|
||||
|
||||
if (user?.research !== undefined) {
|
||||
user?.research.forEach((res: Research) => {
|
||||
research.push(res);
|
||||
});
|
||||
}
|
||||
|
||||
return research;
|
||||
}
|
||||
|
||||
export const updateUserResearch = async (user: User, research: Array<{ id: string, level: number }>) => {
|
||||
export const createOrUpgradeResearch = async (userId: ObjectId, research: Research) => {
|
||||
const users = await Users();
|
||||
users.updateOne({ username: user.username }, { $set: { research } });
|
||||
|
||||
const result = await users.updateOne(
|
||||
{ _id: userId, "research.id": research.id },
|
||||
{ $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> => {
|
||||
const users = await Users();
|
||||
const planets = await Planets();
|
||||
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
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
|
||||
};
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
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,8 +1,7 @@
|
|||
import { ObjectId } from "mongodb";
|
||||
import AccessToken from "../../types/AccessToken";
|
||||
import type { ObjectId } from "mongodb";
|
||||
import type AccessToken from "../../types/AccessToken";
|
||||
import { getAccessToken } from "../db/accessTokens";
|
||||
import { getUserById } from "../db/users";
|
||||
import locationManager from "../classes/managers/LocationManager";
|
||||
|
||||
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];
|
||||
|
@ -59,12 +58,5 @@ export default async function validateAccessToken(request: Request): Promise<Res
|
|||
}), { status: 403 }
|
||||
);
|
||||
|
||||
return {
|
||||
type: response.type,
|
||||
user: locationManager.getUser(user._id),
|
||||
entropy: response.entropy,
|
||||
createdAt: response.createdAt,
|
||||
expiresAt: response.expiresAt,
|
||||
createdFrom: response.createdFrom
|
||||
} as AccessToken;
|
||||
return response;
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
import { randomBytes, createHash } from "crypto";
|
||||
import type { APIRoute } from "astro";
|
||||
import type AccessToken from "../../../types/AccessToken";
|
||||
import { createAccessToken } from "../../../lib/db/accessTokens";
|
||||
import { getUserByNickOrEmail } from "../../../lib/db/users";
|
||||
import config from '../../../../config.json';
|
||||
import AccessToken from "../../../types/AccessToken";
|
||||
import locationManager from "../../../lib/classes/managers/LocationManager";
|
||||
import type { ObjectId } from "mongodb";
|
||||
|
||||
export const POST: APIRoute = async({ request }) => {
|
||||
const data = await request.json().catch(() => {return new Response(
|
||||
|
@ -53,25 +53,16 @@ export const POST: APIRoute = async({ request }) => {
|
|||
|
||||
const now = new Date();
|
||||
const timestamp = Buffer.from(String(Date.now())).toString('base64url');
|
||||
const userEncoded = Buffer.from(userFromDb._id?.toString() ?? "").toString('base64url');
|
||||
const user = Buffer.from(userFromDb._id?.toString() ?? "").toString('base64url');
|
||||
const random = randomBytes(16).toString("base64url");
|
||||
const randomHashed = createHash("sha256").update(random).digest("hex");
|
||||
const expiresIn = (data.duration ?? 86400) * 1000;
|
||||
|
||||
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 tokenString = `A.${timestamp}.${user}.${random}`;
|
||||
|
||||
const accessToken: AccessToken = {
|
||||
type: "A",
|
||||
user,
|
||||
user: userFromDb._id as ObjectId,
|
||||
entropy: randomHashed.toString(),
|
||||
createdAt: now,
|
||||
expiresAt: new Date(now.getTime() + expiresIn),
|
||||
|
|
|
@ -1,20 +1,13 @@
|
|||
import type { APIRoute } from "astro";
|
||||
import validateAccessToken from "../../../lib/utils/validateAccessToken";
|
||||
import { getUserByAccessToken } from "../../../lib/db/users";
|
||||
import type User from "../../../types/User";
|
||||
|
||||
export const GET: APIRoute = async({ request }) => {
|
||||
const response = await validateAccessToken(request);
|
||||
if(response instanceof Response) return response;
|
||||
|
||||
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 }
|
||||
);
|
||||
const user = (await getUserByAccessToken(response)) as User;
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import { type APIRoute } from "astro";
|
||||
import { build, type APIRoute } from "astro";
|
||||
import validateAccessToken from "../../../lib/utils/validateAccessToken";
|
||||
import { getUserByAccessToken } from "../../../lib/db/users";
|
||||
import { calculateCurrentAvailableResources, updatePlanetResources } from "../../../lib/utils/resourceManager";
|
||||
import { getUserByAccessToken, getUserResearch } from "../../../lib/db/users";
|
||||
import Planet from "../../../types/Planet";
|
||||
import { createOrUpgradeBuilding, getPlanetById } from "../../../lib/db/planets";
|
||||
import { ObjectId } from "mongodb";
|
||||
import locationManager from "../../../lib/classes/managers/LocationManager";
|
||||
import Building from "../../../lib/classes/Building";
|
||||
import { getAllResources } from "../../../lib/db/resources";
|
||||
import DBResource from "../../../types/PlayerResource";
|
||||
import { getAllBuildings } from "../../../lib/db/buildings";
|
||||
import DBBuilding from "../../../types/DBBuilding";
|
||||
|
||||
export const POST: APIRoute = async({ request }) => {
|
||||
const response = await validateAccessToken(request);
|
||||
|
@ -33,77 +36,120 @@ export const POST: APIRoute = async({ request }) => {
|
|||
)
|
||||
}
|
||||
|
||||
const userPlanet = locationManager.getPlanet(new ObjectId(body.planet));
|
||||
const buildingId = body.building;
|
||||
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) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
code: 400,
|
||||
message: "Bad Request",
|
||||
error: "Invalid planet ID"
|
||||
}), { status: 400 }
|
||||
code: 404,
|
||||
message: "Not Found",
|
||||
error: "Planet not found"
|
||||
}), { status: 404 }
|
||||
)
|
||||
}
|
||||
|
||||
const buildingId: string = body.building;
|
||||
// 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(
|
||||
JSON.stringify({
|
||||
code: 400,
|
||||
message: "Bad Request",
|
||||
error: `${buildingReq.id} level ${buildingReq.level} required, found ${playerBuildings.filter((building) => building.id === buildingReq.id)[0].level}`
|
||||
}), { status: 400 }
|
||||
)
|
||||
}
|
||||
});
|
||||
|
||||
const buildingObj = userPlanet.buildings.buildingsDB.find(b => b.id === buildingId);
|
||||
// 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 }
|
||||
)
|
||||
}
|
||||
});
|
||||
|
||||
if(!buildingObj) return new Response(
|
||||
JSON.stringify({
|
||||
code: 400,
|
||||
message: "Bad Request",
|
||||
error: "Invalid building ID"
|
||||
}), { 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;
|
||||
|
||||
const building = new Building(userPlanet.buildings, buildingObj, 1);
|
||||
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;
|
||||
});
|
||||
|
||||
const requirements = await building.checkRequirements();
|
||||
const resources = await building.checkRequiredResources((userPlanet.buildings.getBuildingById(buildingId)?.level ?? 0) + 1);
|
||||
|
||||
if(!requirements.canBuild || !resources) {
|
||||
if(missingResources.length > 0) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
code: 400,
|
||||
message: "Bad Request",
|
||||
error: requirements.error + " | " + resources ? "" : "Not enough resources"
|
||||
data: missingResources
|
||||
}), { 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();
|
||||
await updatePlanetResources(userPlanet._id, newResources);
|
||||
await createOrUpgradeBuilding(userPlanet._id, { id: buildingId, level: level + 1 });
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
code: 200,
|
||||
message: "OK"
|
||||
}), { status: 200 }
|
||||
);
|
||||
)
|
||||
}
|
|
@ -1,21 +1,17 @@
|
|||
import { APIRoute } from "astro";
|
||||
import { getAllPlanets } from "../../../lib/db/planets";
|
||||
import Planet from "../../../types/Planet";
|
||||
import { ObjectId } from "mongodb";
|
||||
import locationManager from "../../../lib/classes/managers/LocationManager";
|
||||
|
||||
export const GET: APIRoute = async ({ request }) => {
|
||||
const planets = await getAllPlanets();
|
||||
|
||||
const response: Array<{planetId: ObjectId, ownerId: ObjectId, name: string}> = [];
|
||||
|
||||
planets.forEach(planet => {
|
||||
const playerPlanet = locationManager.getPlanet(planet._id);
|
||||
|
||||
if(!playerPlanet) return;
|
||||
|
||||
planets.forEach((planet: Planet) => {
|
||||
response.push({
|
||||
planetId: planet._id,
|
||||
ownerId: playerPlanet.manager.owner.id,
|
||||
ownerId: planet.owner._id,
|
||||
name: planet.name,
|
||||
})
|
||||
});
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import { APIRoute } from "astro";
|
||||
import { getPlanetById } from "../../../../lib/db/planets";
|
||||
import { ObjectId } from "mongodb";
|
||||
import Planet from "../../../../types/Planet";
|
||||
import { calculateCurrentAvailableResources } from "../../../../lib/utils/resourceManager";
|
||||
import validateAccessToken from "../../../../lib/utils/validateAccessToken";
|
||||
import { getUserByAccessToken } from "../../../../lib/db/users";
|
||||
import locationManager from "../../../../lib/classes/managers/LocationManager";
|
||||
|
||||
export const GET: APIRoute = async ({ params, request }) => {
|
||||
const response = await validateAccessToken(request);
|
||||
|
@ -26,23 +28,36 @@ export const GET: APIRoute = async ({ params, request }) => {
|
|||
}), { status: 400 }
|
||||
);
|
||||
|
||||
const planet = locationManager.getPlanet(new ObjectId(planetId));
|
||||
let planet: Planet | null;
|
||||
|
||||
if(!planet) return new Response(
|
||||
JSON.stringify({
|
||||
code: 500,
|
||||
message: "Internal Server Error"
|
||||
}), { status: 500 }
|
||||
);
|
||||
try {
|
||||
planet = await getPlanetById(new ObjectId(planetId));
|
||||
if(!planet) return new Response(
|
||||
JSON.stringify({
|
||||
code: 404,
|
||||
message: "Not Found"
|
||||
}), { status: 404 }
|
||||
);
|
||||
} catch(e) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
code: 500,
|
||||
message: "Internal Server Error"
|
||||
}), { status: 500 }
|
||||
);
|
||||
}
|
||||
|
||||
if(!planet.manager.owner.id.equals(user._id)) return new Response(
|
||||
if(planet.owner._id.toString() !== user._id.toString()) return new Response(
|
||||
JSON.stringify({
|
||||
code: 403,
|
||||
message: "Forbidden"
|
||||
}), { status: 403 }
|
||||
);
|
||||
|
||||
await locationManager.getPlanet(planet._id)?.resources.calculateCurrentAvailableResources();
|
||||
await calculateCurrentAvailableResources(planet._id);
|
||||
|
||||
//@ts-ignore
|
||||
delete planet.owner.password;
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { type APIRoute } from "astro";
|
||||
import validateAccessToken from "../../../lib/utils/validateAccessToken";
|
||||
import { getUserByAccessToken, getUserResearch } from "../../../lib/db/users";
|
||||
import locationManager from "../../../lib/classes/managers/LocationManager";
|
||||
|
||||
export const GET: APIRoute = async({ request }) => {
|
||||
const response = await validateAccessToken(request);
|
||||
|
@ -17,13 +16,11 @@ export const GET: APIRoute = async({ request }) => {
|
|||
)
|
||||
}
|
||||
|
||||
const userResearch = locationManager.getUser(user._id)?.research.research ?? [];
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
code: 200,
|
||||
message: "OK",
|
||||
data: userResearch
|
||||
data: await getUserResearch(user)
|
||||
}), { status: 200 }
|
||||
)
|
||||
}
|
|
@ -1,16 +1,20 @@
|
|||
import { type APIRoute } from "astro";
|
||||
import validateAccessToken from "../../../lib/utils/validateAccessToken";
|
||||
import { getUserByAccessToken } from "../../../lib/db/users";
|
||||
import { createOrUpgradeResearch, getUserByAccessToken, getUserResearch } from "../../../lib/db/users";
|
||||
import { getPlanetById } from "../../../lib/db/planets";
|
||||
import Planet from "../../../types/Planet";
|
||||
import { ObjectId } from "mongodb";
|
||||
import { getResearchById } from "../../../lib/db/research";
|
||||
import locationManager from "../../../lib/classes/managers/LocationManager";
|
||||
import { calculateCurrentAvailableResources, getResourcesFromPlanet, updatePlanetResources } from "../../../lib/utils/resourceManager";
|
||||
import PlayerResource from "../../../types/PlayerResource";
|
||||
import calculateAvailableResources from "../../../lib/utils/calculateAvailableResources";
|
||||
import { getAllResearch, getResearchById } from "../../../lib/db/research";
|
||||
|
||||
export const POST: APIRoute = async({ request }) => {
|
||||
const response = await validateAccessToken(request);
|
||||
if(response instanceof Response) return response;
|
||||
|
||||
const userDB = await getUserByAccessToken(response);
|
||||
if(userDB === null) {
|
||||
const user = await getUserByAccessToken(response);
|
||||
if(user === null) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
code: 401,
|
||||
|
@ -32,30 +36,8 @@ 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 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 researchId = body.research;
|
||||
const research = await getResearchById(researchId);
|
||||
|
||||
if(!research) {
|
||||
|
@ -67,27 +49,47 @@ export const POST: APIRoute = async({ request }) => {
|
|||
}), { 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
|
||||
// buildings
|
||||
const buildings = userPlanet.buildings;
|
||||
for(const buildingReq of research.requirements.buildings) {
|
||||
if((buildings.buildings.find((building) => building.data.id === buildingReq.id)?.level ?? 0) < buildingReq.level) {
|
||||
research.requirements.buildings.forEach((buildingReq) => {
|
||||
if(buildings.filter((building) => building.id === buildingReq.id)[0]?.level ?? 0 < buildingReq.level) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
code: 400,
|
||||
message: "Bad Request",
|
||||
error: `${buildingReq.id} level ${buildingReq.level} required, found ${buildings.buildings.filter((building) => building.data.id === buildingReq.id)[0]?.level ?? 0}`
|
||||
error: `${buildingReq.id} level ${buildingReq.level} required, found ${buildings.filter((building) => building.id === buildingReq.id)[0]?.level ?? 0}`
|
||||
}), { status: 400 }
|
||||
)
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// research
|
||||
const playerResearch = user.research.research;
|
||||
for(const researchReq of research.requirements.research) {
|
||||
if((playerResearch.find((research) => research.id === researchReq.id)?.level ?? 0) < researchReq.level) {
|
||||
const playerResearch = await getUserResearch(user);
|
||||
research.requirements.research.forEach((researchReq) => {
|
||||
if(playerResearch.filter((research) => research.id === researchReq.id)[0].level < researchReq.level) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
code: 400,
|
||||
|
@ -96,10 +98,10 @@ export const POST: APIRoute = async({ request }) => {
|
|||
}), { status: 400 }
|
||||
)
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// resources
|
||||
const resources = await userPlanet.resources.calculateCurrentAvailableResources();
|
||||
const resources = await calculateCurrentAvailableResources(userPlanet._id);
|
||||
if(!resources) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
|
@ -109,25 +111,24 @@ export const POST: APIRoute = async({ request }) => {
|
|||
}), { status: 500 }
|
||||
)
|
||||
}
|
||||
|
||||
const playerCurrentResearch = playerResearch.filter((element: any) => element.id === researchId)[0];
|
||||
const level = playerCurrentResearch ? playerCurrentResearch.level : 0;
|
||||
const newResources = structuredClone(resources);
|
||||
const missingResources: Array<{ id: string, required: number, available: number }> = [];
|
||||
for(const resource of research.requirements.resources) {
|
||||
const res = resources.filter((element) => element.id === resource.id)[0];
|
||||
const missingResources: Array<{}> = [];
|
||||
research.requirements.resources.forEach(resource => {
|
||||
const res = resources.filter((element: PlayerResource) => element.name === resource.name)[0];
|
||||
const cost = playerCurrentResearch ? resource.amount * Math.pow(research.multiplier, level) : resource.amount;
|
||||
|
||||
if(res.amount < cost) {
|
||||
missingResources.push({
|
||||
id: resource.id,
|
||||
name: resource.name,
|
||||
required: cost,
|
||||
available: res.amount
|
||||
});
|
||||
break;
|
||||
return;
|
||||
}
|
||||
else newResources.filter((element) => element.id === resource.id)[0].amount -= cost;
|
||||
};
|
||||
else newResources.filter((element: PlayerResource) => element.name === resource.name)[0].amount -= cost;
|
||||
});
|
||||
|
||||
if(missingResources.length > 0) {
|
||||
return new Response(
|
||||
|
@ -139,15 +140,8 @@ export const POST: APIRoute = async({ request }) => {
|
|||
)
|
||||
}
|
||||
|
||||
userPlanet.resources.update(newResources);
|
||||
userPlanet.manager.owner.research.addResearch({
|
||||
id: researchId,
|
||||
level: level + 1,
|
||||
data: research
|
||||
});
|
||||
|
||||
await userPlanet.resources.sync();
|
||||
await userPlanet.manager.owner.research.sync();
|
||||
await updatePlanetResources(userPlanet._id, newResources);
|
||||
await createOrUpgradeResearch(user._id, { id: researchId, level: level + 1 });
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
|
|
|
@ -6,9 +6,7 @@ import { getUserByAccessToken } from '../../lib/db/users';
|
|||
import { getHighestWeightedLanguage, getLocales, getName, getObj } from '../../lib/utils/langDriver';
|
||||
import ResourceBar from '../../components/ResourceBar.astro';
|
||||
import { getAllBuildings } from '../../lib/db/buildings';
|
||||
import locationManager from '../../lib/classes/managers/LocationManager';
|
||||
import { ObjectId } from 'mongodb';
|
||||
import DBBuilding from '../../types/db/DBBuilding';
|
||||
import DBBuilding from '../../types/DBBuilding';
|
||||
|
||||
const buildingsList = await getAllBuildings();
|
||||
|
||||
|
@ -23,31 +21,20 @@ const locale = await getHighestWeightedLanguage(Astro.request.headers.get('accep
|
|||
|
||||
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 } } = {};
|
||||
|
||||
for(const building of buildingsList) {
|
||||
modalSet[building.id] = {
|
||||
resources: building.requirements.resources.map(resource => {
|
||||
return {
|
||||
id: resource.id,
|
||||
amount: Math.pow(building.multiplier, (planet.buildings.getBuildingById(building.id)?.level ?? 0) ) * resource.amount
|
||||
};
|
||||
}),
|
||||
resources: building.requirements.resources,
|
||||
research: building.requirements.research,
|
||||
buildings: building.requirements.buildings,
|
||||
energy: building.energy
|
||||
};
|
||||
}
|
||||
|
||||
const buildingsByCategory = buildingsList.reduce((acc: { [key: string]: Array<DBBuilding & { level: number }> }, building) => {
|
||||
const buildingsByCategory = buildingsList.reduce((acc: { [key: string]: DBBuilding[] }, building) => {
|
||||
if(!acc[building.category]) acc[building.category] = [];
|
||||
acc[building.category].push({ ...building, level: planet.buildings.getBuildingById(building.id)?.level ?? 0 });
|
||||
acc[building.category].push(building);
|
||||
return acc;
|
||||
}, {});
|
||||
---
|
||||
|
@ -73,7 +60,6 @@ const buildingsByCategory = buildingsList.reduce((acc: { [key: string]: Array<DB
|
|||
{buildings.map(building => (
|
||||
<BuildingCard
|
||||
id={building.id}
|
||||
level={building.level.toString()}
|
||||
name={getObj(lang, "buildings", building.id).name}
|
||||
description={getObj(lang, "buildings", building.id).description ?? ""}
|
||||
image={`/images/buildings/${building.id}.jpeg`}
|
||||
|
@ -199,7 +185,7 @@ const buildingsByCategory = buildingsList.reduce((acc: { [key: string]: Array<DB
|
|||
color: lime;
|
||||
}
|
||||
</style>
|
||||
<script define:vars={{ modalSet, lang, planetId }}>
|
||||
<script define:vars={{ modalSet, lang }}>
|
||||
const modalResources = document.getElementById("building-modal-req-resources");
|
||||
const modalBuildings = document.getElementById("building-modal-req-buildings");
|
||||
const modalResearch = document.getElementById("building-modal-req-research");
|
||||
|
@ -216,7 +202,7 @@ const buildingsByCategory = buildingsList.reduce((acc: { [key: string]: Array<DB
|
|||
const reqResearch = modalSet[el.parentElement.parentElement.dataset.id]?.research ?? [];
|
||||
|
||||
modalResources.innerHTML = reqResources.length === 0 ? "None" : reqResources.map(resource => {
|
||||
return `${lang['resources'].find(r => r.id === resource.id).name}: ${resource.amount}`;
|
||||
return `${lang['resources'].find(r => r.id === resource.name).name}: ${resource.amount}`;
|
||||
}).join("<br />");
|
||||
|
||||
modalBuildings.innerHTML = reqBuildings.length === 0 ? "None" : reqBuildings.map(building => {
|
||||
|
@ -247,28 +233,21 @@ const buildingsByCategory = buildingsList.reduce((acc: { [key: string]: Array<DB
|
|||
backgroundDiv.style.display = 'none';
|
||||
});
|
||||
|
||||
const allButtons = document.getElementsByClassName("item-card-build");
|
||||
const allButtons = document.getElementsByClassName("a-button");
|
||||
|
||||
for(const buildingButton of allButtons) {
|
||||
buildingButton.addEventListener("click", async () => {
|
||||
const id = buildingButton.id.split("_")[1];
|
||||
|
||||
const response = await fetch('/api/build/createBuilding', {
|
||||
await fetch('/api/build/createBuilding', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
building: id,
|
||||
planet: planetId
|
||||
building: id
|
||||
})
|
||||
});
|
||||
|
||||
if(response.status === 200) {
|
||||
window.location.reload();
|
||||
} else {
|
||||
alert("Failed to build building: " + JSON.stringify(await response.json()));
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
|
@ -5,6 +5,7 @@ import { getUserByAccessToken } from '../../lib/db/users';
|
|||
import { getHighestWeightedLanguage, getLocales, getName, getObj } from '../../lib/utils/langDriver';
|
||||
import ResourceBar from '../../components/ResourceBar.astro';
|
||||
import ItemCard from '../../components/ItemCard.astro';
|
||||
import DBResearch from '../../types/DBResearch';
|
||||
import { getAllResearch } from '../../lib/db/research';
|
||||
|
||||
const researchList = await getAllResearch();
|
||||
|
@ -16,13 +17,23 @@ if(loggedToken === null || username === "") return Astro.redirect('/logout');
|
|||
const checkUser = await getUserByAccessToken(loggedToken);
|
||||
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 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> } } = {};
|
||||
|
||||
for(const research of researchList) {
|
||||
|
@ -55,7 +66,6 @@ for(const research of researchList) {
|
|||
<ItemCard
|
||||
id={research.id}
|
||||
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 ?? ""}
|
||||
image={`/images/research/${research.id}.jpeg`}
|
||||
button_type="general"
|
||||
|
@ -177,7 +187,7 @@ for(const research of researchList) {
|
|||
z-index: 101;
|
||||
}
|
||||
</style>
|
||||
<script define:vars={{ modalSet, lang, planetId }}>
|
||||
<script define:vars={{ modalSet, lang }}>
|
||||
const modalResources = document.getElementById("research-modal-req-resources");
|
||||
const modalBuildings = document.getElementById("research-modal-req-buildings");
|
||||
const modalResearch = document.getElementById("research-modal-req-research");
|
||||
|
@ -227,28 +237,23 @@ for(const research of researchList) {
|
|||
backgroundDiv.style.display = 'none';
|
||||
});
|
||||
|
||||
const allButtons = document.getElementsByClassName("item-card-build");
|
||||
const allButtons = document.getElementsByClassName("a-button");
|
||||
|
||||
for(const researchButton of allButtons) {
|
||||
researchButton.addEventListener("click", async () => {
|
||||
const id = researchButton.id.split("_")[1];
|
||||
|
||||
const response = await fetch('/api/research/performResearch', {
|
||||
console.log(id);
|
||||
|
||||
await fetch('/api/research/performResearch', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
research: id,
|
||||
planetId
|
||||
research: id
|
||||
})
|
||||
});
|
||||
|
||||
if(response.status === 200) {
|
||||
window.location.reload();
|
||||
} else {
|
||||
alert("Failed to build building: " + JSON.stringify(await response.json()));
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
|
@ -2,12 +2,11 @@
|
|||
import Layout from '../layouts/Layout.astro';
|
||||
import NavBar from '../components/NavBar.astro';
|
||||
|
||||
import { getUserByNickOrEmail, updateLastLogin } from '../lib/db/users';
|
||||
import { getUserByNickOrEmail, getUserWithPlanets, updateLastLogin } from '../lib/db/users';
|
||||
|
||||
import config from '../../config.json';
|
||||
|
||||
import { verify } from 'argon2';
|
||||
import locationManager from '../lib/classes/managers/LocationManager';
|
||||
|
||||
let error = "";
|
||||
|
||||
|
@ -26,11 +25,9 @@ if(Astro.request.method === "POST") {
|
|||
Astro.redirect("/login");
|
||||
}
|
||||
|
||||
const userDB = await getUserByNickOrEmail(username as string);
|
||||
const user = await getUserByNickOrEmail(username 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");
|
||||
if(user !== null && await verify(user.password, password as string)) {
|
||||
const sessionTime = config.SESSION_TIME_MINUTES * 60;
|
||||
|
||||
const res = await fetch(`http://localhost:4321/api/auth/generateAccessToken`, {
|
||||
|
@ -64,14 +61,18 @@ if(Astro.request.method === "POST") {
|
|||
secure: true
|
||||
});
|
||||
|
||||
Astro.cookies.set("userid", user.id?.toString() as string, {
|
||||
Astro.cookies.set("userid", user._id?.toString() as string, {
|
||||
path: "/",
|
||||
maxAge: sessionTime,
|
||||
sameSite: "lax",
|
||||
secure: true
|
||||
});
|
||||
|
||||
Astro.cookies.set("planetid", user.mainPlanet._id, {
|
||||
const userWithPlanets = await getUserWithPlanets(user._id);
|
||||
if(!userWithPlanets) return;
|
||||
const planetId = userWithPlanets.planets.data[0]._id;
|
||||
|
||||
Astro.cookies.set("planetid", planetId.toString(), {
|
||||
path: "/",
|
||||
maxAge: sessionTime,
|
||||
sameSite: "lax",
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import User from "../lib/classes/User";
|
||||
import type { ObjectId } from "mongodb";
|
||||
|
||||
export default interface AccessToken {
|
||||
type: string;
|
||||
user: User | null;
|
||||
_id?: ObjectId;
|
||||
type: "A" | "X";
|
||||
user: ObjectId | null;
|
||||
entropy: string;
|
||||
createdAt: Date;
|
||||
expiresAt: Date | null;
|
||||
createdFrom: string | null;
|
||||
createdFrom: null | 'loginForm';
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export default interface Building {
|
||||
id: string;
|
||||
level: number;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
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,
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
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,
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
export default interface DBResource {
|
||||
id: string,
|
||||
type: string,
|
||||
icon: string
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
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,
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
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>,
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
import type Resource from "./Resource";
|
||||
|
||||
export default interface DBResource extends Resource {
|
||||
lastUpdated: Date;
|
||||
perHourMiningRate: number;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export default interface Research {
|
||||
id: string;
|
||||
level: number;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export default interface Resource {
|
||||
name: string;
|
||||
amount: number;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
export default interface Resources {
|
||||
coal: number;
|
||||
iron: number;
|
||||
gold: number;
|
||||
|
||||
water: number;
|
||||
sulfuricAcid: number;
|
||||
liquidNitrogen: number;
|
||||
|
||||
hydrogen: number;
|
||||
oxygen: number;
|
||||
helium3: number;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export default interface Ship {
|
||||
id: string;
|
||||
amount: number;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
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;
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
import { ObjectId } from "mongodb";
|
||||
|
||||
export default interface DBAccessToken {
|
||||
_id: ObjectId;
|
||||
type: string;
|
||||
user: ObjectId;
|
||||
entropy: string;
|
||||
createdAt: Date;
|
||||
expiresAt: Date;
|
||||
createdFrom: string | null;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
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;
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
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 }>;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
import { ObjectId } from "mongodb";
|
||||
|
||||
export default interface DBGalaxy {
|
||||
_id: ObjectId;
|
||||
name: string;
|
||||
sectors: Array<ObjectId>;
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
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 }>;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
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;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
import { ObjectId } from "mongodb";
|
||||
|
||||
export default interface DBResource {
|
||||
_id: ObjectId;
|
||||
id: string;
|
||||
type: string;
|
||||
icon: string;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
import { ObjectId } from "mongodb";
|
||||
|
||||
export default interface DBSector {
|
||||
_id: ObjectId;
|
||||
name: string;
|
||||
expedition: any; // TODO: Define expedition type
|
||||
systems: Array<ObjectId>;
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
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;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
import { ObjectId } from "mongodb";
|
||||
|
||||
export default interface DBSystem {
|
||||
_id: ObjectId;
|
||||
name: string;
|
||||
ownedBy: ObjectId;
|
||||
planets: Array<ObjectId>;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
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;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
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);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,85 @@
|
|||
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