Implement structure manager
Not yet fully functional (fleet needs to be done first to provide a way to have resources available in the system.
This commit is contained in:
parent
c463476a3f
commit
fd3dfcab3f
Binary file not shown.
After Width: | Height: | Size: 93 KiB |
Binary file not shown.
After Width: | Height: | Size: 61 KiB |
Binary file not shown.
After Width: | Height: | Size: 70 KiB |
|
@ -0,0 +1,70 @@
|
||||||
|
import DBStructure from "../../types/db/DBStructure";
|
||||||
|
import StructureManager from "./managers/StructureManager";
|
||||||
|
|
||||||
|
export default class Structure {
|
||||||
|
manager: StructureManager
|
||||||
|
data: DBStructure;
|
||||||
|
level: number;
|
||||||
|
|
||||||
|
constructor(manager: StructureManager, data: DBStructure, 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: ""
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ import { getSectorById } from "../../db/sectors";
|
||||||
import { getSystemById } from "../../db/systems";
|
import { getSystemById } from "../../db/systems";
|
||||||
import { getAllUsers } from "../../db/users";
|
import { getAllUsers } from "../../db/users";
|
||||||
import User from "../User";
|
import User from "../User";
|
||||||
|
import StructureManager from "./StructureManager";
|
||||||
|
|
||||||
export type Galaxy = {
|
export type Galaxy = {
|
||||||
_id: ObjectId,
|
_id: ObjectId,
|
||||||
|
@ -29,6 +30,7 @@ export type System = {
|
||||||
sector: Sector,
|
sector: Sector,
|
||||||
name: string,
|
name: string,
|
||||||
ownedBy: User,
|
ownedBy: User,
|
||||||
|
structures: StructureManager,
|
||||||
planets: PlanetManager
|
planets: PlanetManager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +50,9 @@ class LocationManager {
|
||||||
users: User[] = [];
|
users: User[] = [];
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
|
this.galaxies = [];
|
||||||
|
this.users = [];
|
||||||
|
|
||||||
const users = await getAllUsers();
|
const users = await getAllUsers();
|
||||||
users.forEach(async user => {
|
users.forEach(async user => {
|
||||||
this.users.push(new User(user._id, user.username, user.email, user.createdAt, user.updatedAt, user.lastLogin));
|
this.users.push(new User(user._id, user.username, user.email, user.createdAt, user.updatedAt, user.lastLogin));
|
||||||
|
@ -86,9 +91,13 @@ class LocationManager {
|
||||||
sector: sectorObject,
|
sector: sectorObject,
|
||||||
name: systemData.name,
|
name: systemData.name,
|
||||||
ownedBy: user,
|
ownedBy: user,
|
||||||
|
//@ts-ignore
|
||||||
|
structures: null,
|
||||||
planets: new PlanetManager(user)
|
planets: new PlanetManager(user)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
systemObject.structures = await new StructureManager(systemObject).init(systemData.structures);
|
||||||
|
|
||||||
await systemObject.planets.fillData(systemObject, systemData.planets);
|
await systemObject.planets.fillData(systemObject, systemData.planets);
|
||||||
|
|
||||||
sectorObject.systems.push(systemObject);
|
sectorObject.systems.push(systemObject);
|
||||||
|
@ -176,5 +185,5 @@ class LocationManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
const locationManager = LocationManager.getInstance();
|
const locationManager = LocationManager.getInstance();
|
||||||
locationManager.init();
|
await locationManager.init();
|
||||||
export default locationManager;
|
export default locationManager;
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { updatePlanetBuildings } from '../../db/planets';
|
||||||
|
import Building from '../Building';
|
||||||
|
import DBStructure from '../../../types/db/DBStructure';
|
||||||
|
import { System } from './LocationManager';
|
||||||
|
import { getAllStructures } from '../../db/structures';
|
||||||
|
import Structure from '../Structure';
|
||||||
|
import { updateSystemStructures } from '../../db/systems';
|
||||||
|
|
||||||
|
export default class StructureManager {
|
||||||
|
structures: Array<Structure> = [];
|
||||||
|
structuresDB: Array<DBStructure> = []
|
||||||
|
system: System;
|
||||||
|
|
||||||
|
constructor(system: System) {
|
||||||
|
this.system = system;
|
||||||
|
}
|
||||||
|
|
||||||
|
async init(structureData: { id: string, level: number }[]) {
|
||||||
|
this.structuresDB = await getAllStructures();
|
||||||
|
structureData.forEach(structure => {
|
||||||
|
const structureToFind = this.structuresDB.find(s => s.id === structure.id);
|
||||||
|
|
||||||
|
if(structureToFind) this.structures.push(new Structure(
|
||||||
|
this,
|
||||||
|
structureToFind,
|
||||||
|
structure.level
|
||||||
|
))
|
||||||
|
})
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
getStructureById(id: string) {
|
||||||
|
return this.structures.find(structure => structure.data.id === id);
|
||||||
|
}
|
||||||
|
|
||||||
|
addStructure(structure: Structure) {
|
||||||
|
const findStructure = this.structures.find(s => s.data.id === structure.data.id);
|
||||||
|
if(!findStructure) this.structures.push(structure);
|
||||||
|
else findStructure.level++;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeStructure(id: string) {
|
||||||
|
this.structures = this.structures.filter(structure => structure.data.id !== id);
|
||||||
|
}
|
||||||
|
|
||||||
|
async sync() {
|
||||||
|
await updateSystemStructures(this.system._id, this.structures.map(structure => { return { id: structure.data.id, level: structure.level } }));
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ export const getLang = async (language = "en") => {
|
||||||
buildings: await lang[1].find({}).toArray(),
|
buildings: await lang[1].find({}).toArray(),
|
||||||
ships: await lang[2].find({}).toArray(),
|
ships: await lang[2].find({}).toArray(),
|
||||||
resources: await lang[3].find({}).toArray(),
|
resources: await lang[3].find({}).toArray(),
|
||||||
research: await lang[4].find({}).toArray()
|
research: await lang[4].find({}).toArray(),
|
||||||
|
structures: await lang[5].find({}).toArray()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -76,6 +76,11 @@ export const Fleet = async() => {
|
||||||
return db.collection('fleet');
|
return db.collection('fleet');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const Structures = async() => {
|
||||||
|
const db = await getDB();
|
||||||
|
return db.collection('structures');
|
||||||
|
}
|
||||||
|
|
||||||
export const Lang = async (language = "en") => {
|
export const Lang = async (language = "en") => {
|
||||||
const db = await getDB(`${config.MONGODB_DB}_${language}`);
|
const db = await getDB(`${config.MONGODB_DB}_${language}`);
|
||||||
return [
|
return [
|
||||||
|
@ -83,6 +88,7 @@ export const Lang = async (language = "en") => {
|
||||||
await db.collection('buildings'),
|
await db.collection('buildings'),
|
||||||
await db.collection('ships'),
|
await db.collection('ships'),
|
||||||
await db.collection('resources'),
|
await db.collection('resources'),
|
||||||
await db.collection('research')
|
await db.collection('research'),
|
||||||
|
await db.collection('structures')
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
import DBStructure from '../../types/db/DBStructure';
|
||||||
|
import { Structures } from '../db/mongodb';
|
||||||
|
|
||||||
|
export const getAllStructures = async () => {
|
||||||
|
return (await Structures()).find({}).toArray() as unknown as Array<DBStructure>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getStructureById = async (id: string) => {
|
||||||
|
return (await Structures()).findOne({
|
||||||
|
id
|
||||||
|
}) as unknown as DBStructure;
|
||||||
|
}
|
|
@ -10,4 +10,13 @@ export const getSystemById = async (id: ObjectId) => {
|
||||||
return await (await Systems()).findOne({
|
return await (await Systems()).findOne({
|
||||||
_id: id
|
_id: id
|
||||||
}) as DBSystem;
|
}) as DBSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const updateSystemStructures = async (systemId: ObjectId, structures: Array<{ id: string, level: number }>) => {
|
||||||
|
const systems = await Systems();
|
||||||
|
await systems.updateOne({ _id: systemId }, {
|
||||||
|
$set: {
|
||||||
|
structures
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
import { type APIRoute } from "astro";
|
||||||
|
import validateAccessToken from "../../../lib/utils/validateAccessToken";
|
||||||
|
import { getUserByAccessToken } from "../../../lib/db/users";
|
||||||
|
import { ObjectId } from "mongodb";
|
||||||
|
import locationManager from "../../../lib/classes/managers/LocationManager";
|
||||||
|
import Building from "../../../lib/classes/Building";
|
||||||
|
import { getAllResources } from "../../../lib/db/resources";
|
||||||
|
import Structure from "../../../lib/classes/Structure";
|
||||||
|
|
||||||
|
export const POST: APIRoute = async({ request }) => {
|
||||||
|
const response = await validateAccessToken(request);
|
||||||
|
if(response instanceof Response) return response;
|
||||||
|
|
||||||
|
const user = await getUserByAccessToken(response);
|
||||||
|
if(user === null) {
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
code: 401,
|
||||||
|
message: "Unauthorized"
|
||||||
|
}), { status: 401 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
let body;
|
||||||
|
try {
|
||||||
|
body = await request.json()
|
||||||
|
} catch(e) {
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
code: 400,
|
||||||
|
message: "Bad Request",
|
||||||
|
error: "Invalid JSON body"
|
||||||
|
}), { status: 400 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const userSystem = locationManager.getSystem(new ObjectId(body.system));
|
||||||
|
|
||||||
|
if(!userSystem) {
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
code: 400,
|
||||||
|
message: "Bad Request",
|
||||||
|
error: "Invalid system ID"
|
||||||
|
}), { status: 400 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const structureId: string = body.structureId;
|
||||||
|
|
||||||
|
const structureObj = userSystem.structures.structuresDB.find(s => s.id === structureId);
|
||||||
|
|
||||||
|
if(!structureObj) return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
code: 400,
|
||||||
|
message: "Bad Request",
|
||||||
|
error: "Invalid structure ID"
|
||||||
|
}), { status: 400 }
|
||||||
|
)
|
||||||
|
|
||||||
|
const structure = new Structure(userSystem.structures, structureObj, 1);
|
||||||
|
|
||||||
|
// const requirements = await structure.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);
|
||||||
|
// userSystem.structures.addStructure(structure);
|
||||||
|
|
||||||
|
// await userSystem.structures.sync();
|
||||||
|
// await userPlanet.resources.sync();
|
||||||
|
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
code: 200,
|
||||||
|
message: "OK"
|
||||||
|
}), { status: 200 }
|
||||||
|
);
|
||||||
|
}
|
|
@ -41,10 +41,16 @@ if(Astro.request.method === "POST") {
|
||||||
<NavBar loggedIn="true" active="systemManager" />
|
<NavBar loggedIn="true" active="systemManager" />
|
||||||
<ResourceBar />
|
<ResourceBar />
|
||||||
|
|
||||||
<h1>Selected system: {currentSystem.name} <a href="/game/systemManager/select">(change)</a></h1>
|
<h1>Selected system: {currentSystem.name} in {currentSystem.sector.name} in {currentSystem.sector.galaxy.name} <a href="/game/systemManager/select">(change)</a></h1>
|
||||||
<div class="planetList">
|
<div class="system-links">
|
||||||
|
<a href="/game/systemManager">Overview</a>
|
||||||
|
<a href="/game/systemManager/structures">System-wide structures</a>
|
||||||
|
<a href="/game/systemManager/spaceStations">Space stations</a>
|
||||||
|
<a href="/game/systemManager/asteroids">Asteroids</a>
|
||||||
|
</div>
|
||||||
|
<div class="planet-list">
|
||||||
{currentSystem.planets.planets.length === 0 ? <span>No planets in this sector</span> : currentSystem.planets.planets.map(planet => (
|
{currentSystem.planets.planets.length === 0 ? <span>No planets in this sector</span> : currentSystem.planets.planets.map(planet => (
|
||||||
<div class="planetCard">
|
<div class="planet-card">
|
||||||
<h2>{planet.name}<div><form method="post"><input type="hidden" name="planetId" value={planet._id.toString()} /><input type="submit" value="Select" /></form></div></h2>
|
<h2>{planet.name}<div><form method="post"><input type="hidden" name="planetId" value={planet._id.toString()} /><input type="submit" value="Select" /></form></div></h2>
|
||||||
<p>Fields: {planet.fields}</p>
|
<p>Fields: {planet.fields}</p>
|
||||||
<h3>Buildings:</h3>
|
<h3>Buildings:</h3>
|
||||||
|
@ -69,7 +75,27 @@ if(Astro.request.method === "POST") {
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.planetList {
|
h1 a {
|
||||||
|
color: lime;
|
||||||
|
}
|
||||||
|
|
||||||
|
.system-links {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.system-links a {
|
||||||
|
color: white;
|
||||||
|
background-color: #555;
|
||||||
|
padding: 0.5rem;
|
||||||
|
margin: 0 1rem;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.planet-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
|
@ -0,0 +1,223 @@
|
||||||
|
---
|
||||||
|
import { ObjectId } from "mongodb";
|
||||||
|
import NavBar from "../../../components/NavBar.astro";
|
||||||
|
import ResourceBar from "../../../components/ResourceBar.astro";
|
||||||
|
import Layout from "../../../layouts/Layout.astro";
|
||||||
|
import locationManager from "../../../lib/classes/managers/LocationManager";
|
||||||
|
import { getUserByAccessToken } from "../../../lib/db/users";
|
||||||
|
import { getHighestWeightedLanguage, getLocales, getName, getObj } from "../../../lib/utils/langDriver";
|
||||||
|
import ItemCard from "../../../components/ItemCard.astro";
|
||||||
|
|
||||||
|
const loggedToken = Astro.cookies.get('sessionToken')?.value ?? null;
|
||||||
|
const username = Astro.cookies.get('username')?.value ?? "";
|
||||||
|
if(loggedToken === null || username === "") return Astro.redirect('/logout');
|
||||||
|
|
||||||
|
const checkUser = await getUserByAccessToken(loggedToken);
|
||||||
|
if(checkUser === null || checkUser.username !== username) return Astro.redirect('/logout');
|
||||||
|
|
||||||
|
const currentSystemId = Astro.cookies.get('currentSystem')?.value ?? null;
|
||||||
|
|
||||||
|
if(currentSystemId === null) return Astro.redirect('/game/systemManager/select');
|
||||||
|
|
||||||
|
const currentSystem = locationManager.getSystem(new ObjectId(currentSystemId));
|
||||||
|
|
||||||
|
if(currentSystem === undefined) {
|
||||||
|
Astro.cookies.delete('currentSystem');
|
||||||
|
return Astro.redirect('/game/systemManager/select');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Astro.request.method === "POST") {
|
||||||
|
const selectedStructureId = (await Astro.request.formData()).get('id') as string | null;
|
||||||
|
|
||||||
|
const request = await (await fetch(Astro.url.origin + '/api/structures/createStructure', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': 'Bearer ' + loggedToken
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
system: currentSystemId,
|
||||||
|
structureId: selectedStructureId
|
||||||
|
})
|
||||||
|
})).json();
|
||||||
|
|
||||||
|
console.log(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
const lang = await getLocales(Astro.cookies.get('language')?.value ?? await getHighestWeightedLanguage(Astro.request.headers.get('accept-language')));
|
||||||
|
|
||||||
|
const modalSet: { [key: string]: { resources: Array<any>, research: Array<any>, buildings: Array<any>, energy: number } } = {};
|
||||||
|
|
||||||
|
const structureList = currentSystem.structures.structuresDB;
|
||||||
|
for(const structure of structureList) {
|
||||||
|
modalSet[structure.id] = {
|
||||||
|
resources: structure.requirements.resources.map(resource => {
|
||||||
|
return {
|
||||||
|
id: resource.id,
|
||||||
|
amount: Math.pow(structure.multiplier, (currentSystem.structures.getStructureById(structure.id)?.level ?? 0) ) * resource.amount
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
research: structure.requirements.research,
|
||||||
|
buildings: structure.requirements.buildings,
|
||||||
|
energy: structure.energy
|
||||||
|
};
|
||||||
|
}
|
||||||
|
---
|
||||||
|
<Layout title="System Manager">
|
||||||
|
<NavBar loggedIn="true" active="systemManager" />
|
||||||
|
<ResourceBar />
|
||||||
|
|
||||||
|
<h1>Selected system: {currentSystem.name} <a href="/game/systemManager/select">(change)</a></h1>
|
||||||
|
<div class="system-links">
|
||||||
|
<a href="/game/systemManager">Overview</a>
|
||||||
|
<a href="/game/systemManager/structures">System-wide structures</a>
|
||||||
|
<a href="/game/systemManager/spaceStations">Space stations</a>
|
||||||
|
<a href="/game/systemManager/asteroids">Asteroids</a>
|
||||||
|
</div>
|
||||||
|
<div id="structure-modal-background">
|
||||||
|
<div id="structure-modal-details" data-structure-id="">
|
||||||
|
<h3>Required resources</h3>
|
||||||
|
<div class="structure-modal-text" id="structure-modal-req-resources">None</div>
|
||||||
|
<h3>Required buildings</h3>
|
||||||
|
<div class="structure-modal-text" id="structure-modal-req-buildings">None</div>
|
||||||
|
<h3>Required research</h3>
|
||||||
|
<div class="structure-modal-text" id="structure-modal-req-research">None</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="structure-list">
|
||||||
|
{currentSystem.structures.structuresDB.map(structure => (
|
||||||
|
<ItemCard
|
||||||
|
id={structure.id}
|
||||||
|
name={getName(lang, 'structures', structure.id)}
|
||||||
|
image={`/images/structures/${structure.id}.jpeg`}
|
||||||
|
level={(currentSystem.structures.getStructureById(structure.id)?.level ?? 0).toString()}
|
||||||
|
description={getObj(lang, 'structures', structure.id).description ?? ""}
|
||||||
|
button_type="general"
|
||||||
|
button_name="nav-build"
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
text-align: center;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 a {
|
||||||
|
color: lime;
|
||||||
|
}
|
||||||
|
|
||||||
|
#structure-modal-background {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
#structure-modal-details {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: 80%;
|
||||||
|
max-width: 800px;
|
||||||
|
background: rgba(0, 0, 0, 0.9);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 1rem;
|
||||||
|
z-index: 101;
|
||||||
|
}
|
||||||
|
|
||||||
|
.structure-modal-text {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.system-links {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.system-links a {
|
||||||
|
color: white;
|
||||||
|
background-color: #555;
|
||||||
|
padding: 0.5rem;
|
||||||
|
margin: 0 1rem;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.structure-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
color: white;
|
||||||
|
row-gap: 40px;
|
||||||
|
column-gap: 2%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.structure-card div {
|
||||||
|
margin-top: auto;
|
||||||
|
margin-bottom: auto;
|
||||||
|
margin-left: 2rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script define:vars={{ modalSet, lang }}>
|
||||||
|
const modalResources = document.getElementById("structure-modal-req-resources");
|
||||||
|
const modalBuildings = document.getElementById("structure-modal-req-buildings");
|
||||||
|
const modalResearch = document.getElementById("structure-modal-req-research");
|
||||||
|
|
||||||
|
document.querySelectorAll('.item-card-info-button').forEach((el) => {
|
||||||
|
el.addEventListener('click', () => {
|
||||||
|
// modal
|
||||||
|
const modalDiv = document.getElementById('structure-modal-details');
|
||||||
|
if(!modalDiv) return;
|
||||||
|
modalDiv.style.display = 'block';
|
||||||
|
|
||||||
|
const reqResources = modalSet[el.parentElement.parentElement.dataset.id]?.resources ?? [];
|
||||||
|
const reqBuildings = modalSet[el.parentElement.parentElement.dataset.id]?.buildings ?? [];
|
||||||
|
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}`;
|
||||||
|
}).join("<br />");
|
||||||
|
|
||||||
|
modalBuildings.innerHTML = reqBuildings.length === 0 ? "None" : reqBuildings.map(building => {
|
||||||
|
return `${lang['buildings'].find(b => b.id === building.id).name}: ${building.level}`;
|
||||||
|
}).join("<br />");
|
||||||
|
|
||||||
|
modalResearch.innerHTML = reqResearch.length === 0 ? "None" : reqResearch.map(research => {
|
||||||
|
return `${lang['research'].find(r => r.id === research.id).name}: ${research.level}`;
|
||||||
|
}).join("<br />");
|
||||||
|
|
||||||
|
// background
|
||||||
|
const backgroundDiv = document.getElementById('structure-modal-background');
|
||||||
|
if(!backgroundDiv) return;
|
||||||
|
backgroundDiv.style.display = 'block';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// close modal on background click
|
||||||
|
const bg = document.getElementById('structure-modal-background');
|
||||||
|
|
||||||
|
bg?.addEventListener('click', () => {
|
||||||
|
const modalDiv = document.getElementById('structure-modal-details');
|
||||||
|
if(!modalDiv) return;
|
||||||
|
modalDiv.style.display = 'none';
|
||||||
|
|
||||||
|
const backgroundDiv = document.getElementById('structure-modal-background');
|
||||||
|
if(!backgroundDiv) return;
|
||||||
|
backgroundDiv.style.display = 'none';
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { ObjectId } from "mongodb";
|
||||||
|
|
||||||
|
export default interface DBStructure {
|
||||||
|
_id: ObjectId;
|
||||||
|
id: string;
|
||||||
|
description: 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;
|
||||||
|
}
|
|
@ -4,5 +4,9 @@ export default interface DBSystem {
|
||||||
_id: ObjectId;
|
_id: ObjectId;
|
||||||
name: string;
|
name: string;
|
||||||
ownedBy: ObjectId;
|
ownedBy: ObjectId;
|
||||||
|
structures: Array<{
|
||||||
|
id: string,
|
||||||
|
level: number
|
||||||
|
}>;
|
||||||
planets: Array<ObjectId>;
|
planets: Array<ObjectId>;
|
||||||
}
|
}
|
Loading…
Reference in New Issue