Compare commits

..

No commits in common. "b13a116cd4d6ac98edce9389144ba439f53d24ef" and "c74e61716c80b683e8cc9daa3d88da47d990e8a5" have entirely different histories.

42 changed files with 629 additions and 479 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

View File

@ -6,25 +6,23 @@ interface Props {
name: string; name: string;
description: string; description: string;
image: string; image: string;
button_type: string;
button_name: string;
} }
const lang = await getLocales(await getHighestWeightedLanguage(Astro.request.headers.get('accept-language'))); const lang = await getLocales(await getHighestWeightedLanguage(Astro.request.headers.get('accept-language')));
--- ---
<div class="item-card" data-id={Astro.props.id}> <div class="building-card" data-id={Astro.props.id}>
<img class="item-card-image" src={Astro.props.image} /> <div><img src={Astro.props.image} /></div>
<div class="item-card-main-field"> <div>
<div class="item-card-name">{Astro.props.name}</div> <div class="building-card-name">{Astro.props.name}</div>
<div class="item-card-description">{Astro.props.description}</div> <div class="building-card-description">{Astro.props.description}</div>
<a id={`button_${Astro.props.id}`} href="#" class="item-card-build">{getName(lang, Astro.props.button_type, Astro.props.button_name)}</a> <a id={`build_${Astro.props.id}`} href="#" class="building-card-build">{getName(lang, "general", "nav-build")}</a>
<div class="item-card-info-button">i</div> <div class="building-card-info-button">i</div>
</div> </div>
</div> </div>
<style> <style>
.item-card { .building-card {
background-color: #fff; background-color: #fff;
color: #333; color: #333;
border-radius: 8px; border-radius: 8px;
@ -37,38 +35,21 @@ const lang = await getLocales(await getHighestWeightedLanguage(Astro.request.hea
width: 49%; width: 49%;
} }
.item-card-expanded { .building-card-expanded {
height: auto; height: auto;
} }
.item-card-image { .building-card-name {
width: 150px;
height: 150px;
margin: 4px;
border-radius: 8px;
object-fit: cover;
}
.item-card-main-field {
background-color: #ccc;
width: 100%;
margin: 4px;
border-radius: 8px;
padding-left: 8px;
padding-right: 100px;
}
.item-card-name {
font-size: 48px; font-size: 48px;
} }
.item-card-description { .building-card-description {
font-size: 24px; font-size: 24px;
margin-top: 16px; margin-top: 16px;
margin-bottom: 16px; margin-bottom: 16px;
} }
.item-card-build { .building-card-build {
background-color: #333; background-color: #333;
color: #fff; color: #fff;
border-radius: 8px; border-radius: 8px;
@ -80,7 +61,7 @@ const lang = await getLocales(await getHighestWeightedLanguage(Astro.request.hea
right: 16px; right: 16px;
} }
.item-card-info-button { .building-card-info-button {
background-color: #333; background-color: #333;
color: #fff; color: #fff;
border-radius: 50%; border-radius: 50%;

View File

@ -2,9 +2,8 @@
import { ObjectId } from 'mongodb'; import { ObjectId } from 'mongodb';
import { calculateCurrentAvailableResources } from '../lib/utils/resourceManager'; import { calculateCurrentAvailableResources } from '../lib/utils/resourceManager';
import { getHighestWeightedLanguage, getLocales, getName } from '../lib/utils/langDriver'; import { getHighestWeightedLanguage, getLocales, getName } from '../lib/utils/langDriver';
import { getAllResources } from '../lib/db/resources';
const resourceTypes = await getAllResources(); import resourceTypes from '../lib/data/resources.json';
const lang = await getLocales(await getHighestWeightedLanguage(Astro.request.headers.get('accept-language'))); const lang = await getLocales(await getHighestWeightedLanguage(Astro.request.headers.get('accept-language')));
@ -23,13 +22,13 @@ for(const key in resources) {
<div id="resourcebar-elements" class="resourcebar-elements"> <div id="resourcebar-elements" class="resourcebar-elements">
{resourceArray.map(res => {resourceArray.map(res =>
<div class="resourcebar-item" <div class="resourcebar-item"
data-res-type={resourceTypes.find(x => x.id === res.name)?.type ?? "solid"} data-res-type={resourceTypes.find(x => x.name === res.name)?.type ?? "solid"}
data-res-amount={res.amount} data-res-amount={res.amount}
data-res-mining-rate={res.perHourMiningRate} data-res-mining-rate={res.perHourMiningRate}
style={(resourceTypes.find(x => x.id === res.name)?.type ?? "solid") === "solid" ? "" : "display: none;"} style={(resourceTypes.find(x => x.name === res.name)?.type ?? "solid") === "solid" ? "" : "display: none;"}
> >
<div class="resourcebar-item-icon"> <div class="resourcebar-item-icon">
<img src={resourceTypes.find(x => x.id === res.name)?.icon ?? "#"} alt={res.name} /> <img src={resourceTypes.find(x => x.name === res.name)?.icon ?? "#"} alt={res.name} />
</div> </div>
<div class="resourcebar-item-text-wrapper" data-resname={res.name}> <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-text">{getName(lang, 'resources', res.name)}</div>

196
src/lib/data/buildings.json Normal file
View File

@ -0,0 +1,196 @@
[
{
"category": "mines",
"buildings": [
{
"id": "iron-mine",
"requirements": {
"buildings": [],
"research": [],
"resources": [
{
"name": "iron",
"amount": 1
},
{
"name": "gold",
"amount": 1
},
{
"name": "coal",
"amount": 1
}
]
},
"energy": 11,
"multiplier": 2
},
{
"id": "gold-mine",
"requirements": {
"buildings": [],
"research": [],
"resources": [
{
"name": "iron",
"amount": 1
},
{
"name": "gold",
"amount": 1
},
{
"name": "coal",
"amount": 1
}
]
},
"energy": 11,
"multiplier": 2.5
},
{
"id": "coal-mine",
"requirements": {
"buildings": [],
"research": [],
"resources": [
{
"name": "iron",
"amount": 1
},
{
"name": "gold",
"amount": 1
},
{
"name": "coal",
"amount": 1
}
]
},
"energy": 11,
"multiplier": 3
}
]
}, {
"category": "utilities",
"buildings": [
{
"id": "research-lab",
"requirements": {
"buildings": [],
"research": [],
"resources": [
{
"name": "iron",
"amount": 1
},
{
"name": "gold",
"amount": 1
},
{
"name": "coal",
"amount": 1
}
]
},
"energy": 100,
"multiplier": 3
},
{
"id": "research-facility",
"requirements": {
"buildings": [
{
"id": "research-lab",
"level": 3
}
],
"research": [
{
"id": "advanced-technologies",
"level": 2
}
],
"resources": [
{
"name": "iron",
"amount": 1
},
{
"name": "gold",
"amount": 1
},
{
"name": "coal",
"amount": 1
}
]
},
"energy": 100,
"multiplier": 2
}
]
}, {
"category": "power-plants",
"buildings": [
{
"id": "coal-power-plant",
"requirements": {
"buildings": [],
"research": [],
"resources": [
{
"name": "iron",
"amount": 1
},
{
"name": "gold",
"amount": 1
},
{
"name": "coal",
"amount": 1
}
]
},
"energy": 100,
"multiplier": 3
},
{
"id": "nuclear-power-plant",
"requirements": {
"buildings": [
{
"id": "coal-power-plant",
"level": 3
}
],
"research": [
{
"id": "nuclear-power",
"level": 2
}
],
"resources": [
{
"name": "iron",
"amount": 1
},
{
"name": "gold",
"amount": 1
},
{
"name": "coal",
"amount": 1
}
]
},
"energy": 100,
"multiplier": 2
}
]
}
]

144
src/lib/data/research.json Normal file
View File

@ -0,0 +1,144 @@
[
{
"id": "basic-engine",
"requirements": {
"buildings": [
{
"id": "research-lab",
"level": 1
}
],
"research": [],
"resources": {
"iron": 1000,
"gold": 500
}
},
"time": 60,
"multiplier": 2
}, {
"id": "advanced-engine",
"requirements": {
"buildings": [
{
"id": "research-lab",
"level": 5
}
],
"research": [
{
"id": "basic-engine",
"level": 1
}
],
"resources": {
"iron": 2000,
"gold": 1000
}
},
"time": 120,
"multiplier": 3
}, {
"id": "combat-utilities",
"requirements": {
"buildings": [
{
"id": "research-lab",
"level": 1
}
],
"research": [],
"resources": {
"iron": 1000,
"gold": 500
}
},
"time": 60,
"multiplier": 2
}, {
"id": "defensive-utilities",
"requirements": {
"buildings": [
{
"id": "research-lab",
"level": 1
}
],
"research": [],
"resources": {
"iron": 1000,
"gold": 500
}
},
"time": 60,
"multiplier": 2
}, {
"id": "oxygen-production",
"requirements": {
"buildings": [
{
"id": "research-lab",
"level": 1
}
],
"research": [],
"resources": {
"iron": 1000,
"gold": 500
}
},
"time": 200,
"multiplier": 2
}, {
"id": "terraforming",
"requirements": {
"buildings": [
{
"id": "research-lab",
"level": 1
}
],
"research": [],
"resources": {
"iron": 1000,
"gold": 500
}
},
"time": 500,
"multiplier": 3
}, {
"id": "advanced-technologies",
"requirements": {
"buildings": [
{
"id": "research-lab",
"level": 6
}
],
"research": [],
"resources": {
"iron": 1000,
"gold": 500
}
},
"time": 1500,
"multiplier": 4
}, {
"id": "nuclear-power",
"requirements": {
"buildings": [
{
"id": "research-lab",
"level": 10
}
],
"research": [],
"resources": {
"iron": 1000,
"gold": 500
}
},
"time": 3000,
"multiplier": 5
}
]

View File

@ -0,0 +1,49 @@
[
{
"name": "coal",
"type": "solid",
"icon": "https://gamepedia.cursecdn.com/minecraft_gamepedia/5/58/Coal_JE4_BE3.png"
},
{
"name": "iron",
"type": "solid",
"icon": "https://vignette.wikia.nocookie.net/minecraft/images/e/e8/New_Iron_IngotB.png/revision/latest?cb=20190520101024"
},
{
"name": "gold",
"type": "solid",
"icon": "https://gamepedia.cursecdn.com/minecraft_gamepedia/5/57/Gold_Ingot_JE3_BE2.png"
},
{
"name": "water",
"type": "liquid",
"icon": "https://ael.ovh/uranium.png"
},
{
"name": "sulfuricAcid",
"type": "liquid",
"icon": "https://ael.ovh/uranium.png"
},
{
"name": "liquidNitrogen",
"type": "liquid",
"icon": "https://ael.ovh/uranium.png"
},
{
"name": "hydrogen",
"type": "gas",
"icon": "https://ael.ovh/uranium.png"
},
{
"name": "oxygen",
"type": "gas",
"icon": "https://ael.ovh/uranium.png"
},
{
"name": "helium3",
"type": "gas",
"icon": "https://ael.ovh/uranium.png"
}
]

57
src/lib/data/ships.json Normal file
View File

@ -0,0 +1,57 @@
[
{
"id": "transporter",
"capacity": {
"solid": 10000,
"liquid": 10000,
"gas": 10000
},
"requirements": {
"buildings": [
{
"id": "shipyard",
"level": 1
}
],
"research": [],
"resources": {
"iron": 1000,
"gold": 500
}
},
"time": 40,
"structure": {
"hitpoints": 1000,
"defense": 10,
"attack": 0
},
"speed": 10
}, {
"id": "fighter",
"capacity": {
"solid": 100,
"liquid": 100,
"gas": 100
},
"requirements": {
"buildings": [
{
"id": "shipyard",
"level": 1
}
],
"research": [],
"resources": {
"iron": 500,
"gold": 200
}
},
"time": 15,
"structure": {
"hitpoints": 800,
"defense": 20,
"attack": 20
},
"speed": 12
}
]

View File

@ -1,18 +0,0 @@
import DBBuilding from '../../types/DBBuilding';
import { Buildings } from '../db/mongodb';
export const getAllBuildings = async () => {
return (await Buildings()).find({}).toArray() as unknown as Array<DBBuilding>;
}
export const getBuildingById = async (id: string) => {
return (await Buildings()).findOne({
id
}) as unknown as DBBuilding;
}
export const getBuildingsByCategory = async (category: string) => {
return (await Buildings()).find({
category
}).toArray() as unknown as Array<DBBuilding>;
}

View File

@ -35,26 +35,6 @@ export const Planets = async () => {
return db.collection('planets'); return db.collection('planets');
} }
export const Buildings = async() => {
const db = await getDB();
return db.collection('buildings');
}
export const Research = async() => {
const db = await getDB();
return db.collection('research');
}
export const Resources = async() => {
const db = await getDB();
return db.collection('resources');
}
export const Ships = async() => {
const db = await getDB();
return db.collection('ships');
}
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 [

View File

@ -5,7 +5,7 @@ import type Planet from '../../types/Planet';
import { getUserById } from './users'; import { getUserById } from './users';
import type Building from '../../types/Building'; import type Building from '../../types/Building';
import type Ship from '../../types/Ship'; import type Ship from '../../types/Ship';
import type PlayerResource from '../../types/PlayerResource'; import type DBResource from '../../types/DBResource';
export const getAllPlanets = async (options?: { fetchUserPlanets: boolean }) => { export const getAllPlanets = async (options?: { fetchUserPlanets: boolean }) => {
const planets = await Planets(); const planets = await Planets();
@ -32,7 +32,7 @@ export const createPlanet = async (options: { name: string, owner?: User, ownerI
owner: user, owner: user,
name: options.name, name: options.name,
fields: options.fields, fields: options.fields,
resources: new Array<PlayerResource>, resources: new Array<DBResource>,
buildings: new Array<Building>, buildings: new Array<Building>,
ships: new Array<Ship> ships: new Array<Ship>
} }

View File

@ -1,12 +0,0 @@
import DBResearch from '../../types/DBResearch';
import { Research } from '../db/mongodb';
export const getAllResearch = async () => {
return (await Research()).find({}).toArray() as unknown as Array<DBResearch>;
}
export const getResearchById = async (id: string) => {
return (await Research()).findOne({
id
}) as unknown as DBResearch;
}

View File

@ -1,12 +0,0 @@
import DBResource from '../../types/DBResource';
import { Resources } from '../db/mongodb';
export const getAllResources = async () => {
return (await Resources()).find({}).toArray() as unknown as Array<DBResource>;
}
export const getResourceById = async (id: string) => {
return (await Resources()).findOne({
id
}) as unknown as DBResource;
}

View File

@ -1,12 +0,0 @@
import DBShip from '../../types/DBShip';
import { Ships } from '../db/mongodb';
export const getAllShips = async () => {
return (await Ships()).find({}).toArray() as unknown as Array<DBShip>;
}
export const getResourceById = async (id: string) => {
return (await Ships()).findOne({
id
}) as unknown as DBShip;
}

View File

@ -1,10 +1,10 @@
import { ObjectId } from "mongodb" import { ObjectId } from "mongodb"
import { Planets } from "../db/mongodb"; import { Planets } from "../db/mongodb";
import type PlayerResource from "../../types/PlayerResource"; import type DBResource from "../../types/DBResource";
import { getPlanetById } from "../db/planets"; import { getPlanetById } from "../db/planets";
export const createInitialResources = async (planetId: ObjectId) => { export const createInitialResources = async (planetId: ObjectId) => {
const resources: Array<PlayerResource> = [ const resources: Array<DBResource> = [
{ {
name: "coal", name: "coal",
amount: 11, amount: 11,
@ -64,7 +64,7 @@ export const createInitialResources = async (planetId: ObjectId) => {
updatePlanetResources(planetId, resources); updatePlanetResources(planetId, resources);
} }
export const getResourcesFromPlanet = async (planetId: ObjectId): Promise<Array<PlayerResource> | null> => { export const getResourcesFromPlanet = async (planetId: ObjectId): Promise<Array<DBResource> | null> => {
const planet = await getPlanetById(planetId); const planet = await getPlanetById(planetId);
if(!planet) return null; if(!planet) return null;
@ -72,7 +72,7 @@ export const getResourcesFromPlanet = async (planetId: ObjectId): Promise<Array<
return planet.resources; return planet.resources;
} }
export const updatePlanetResources = async (planetId: ObjectId, resources: Array<PlayerResource>) => { export const updatePlanetResources = async (planetId: ObjectId, resources: Array<DBResource>) => {
const planets = await Planets(); const planets = await Planets();
await planets.updateOne({ _id: planetId }, { await planets.updateOne({ _id: planetId }, {
$set: { $set: {
@ -81,7 +81,7 @@ export const updatePlanetResources = async (planetId: ObjectId, resources: Array
}); });
} }
export const calculateCurrentAvailableResources = async (planetId: ObjectId): Promise<Array<PlayerResource>> => { export const calculateCurrentAvailableResources = async (planetId: ObjectId): Promise<Array<DBResource>> => {
const resources = await getResourcesFromPlanet(planetId); const resources = await getResourcesFromPlanet(planetId);
if(resources === null) return []; if(resources === null) return [];

View File

@ -1,13 +1,12 @@
import { build, type APIRoute } from "astro"; import { build, type APIRoute } from "astro";
import validateAccessToken from "../../../lib/utils/validateAccessToken"; import validateAccessToken from "../../../lib/utils/validateAccessToken";
import { calculateCurrentAvailableResources, updatePlanetResources } from "../../../lib/utils/resourceManager"; import { calculateCurrentAvailableResources, updatePlanetResources } from "../../../lib/utils/resourceManager";
import buildings from '../../../lib/data/buildings.json';
import { getUserByAccessToken, getUserResearch } from "../../../lib/db/users"; import { getUserByAccessToken, getUserResearch } from "../../../lib/db/users";
import Planet from "../../../types/Planet"; import Planet from "../../../types/Planet";
import { createOrUpgradeBuilding, getPlanetById } from "../../../lib/db/planets"; import { createOrUpgradeBuilding, getPlanetById } from "../../../lib/db/planets";
import { ObjectId } from "mongodb"; import { ObjectId } from "mongodb";
import DBResource from "../../../types/PlayerResource"; import DBResource from "../../../types/DBResource";
import { getAllBuildings } from "../../../lib/db/buildings";
import DBBuilding from "../../../types/DBBuilding";
export const POST: APIRoute = async({ request }) => { export const POST: APIRoute = async({ request }) => {
const response = await validateAccessToken(request); const response = await validateAccessToken(request);
@ -37,12 +36,12 @@ export const POST: APIRoute = async({ request }) => {
} }
const buildingId = body.building; const buildingId = body.building;
let buildingData: DBBuilding | null = null; let buildingData: {id: string, name: string, requirements: { buildings: Array<{}>, research: Array<{}>, resources: Array<DBResource> }, multiplier: number} | null = null;
buildings.forEach((category: any) => {
const buildings = await getAllBuildings(); // console.log(category.buildings.filter((element: any) => element.id === buildingId)[0]);
if(buildingData !== null) return;
buildingData = buildings.find((element) => element.id === buildingId) ?? null; buildingData = category.buildings.find((element: any) => element.id === buildingId);
});
if(!buildingData) { if(!buildingData) {
return new Response( return new Response(
JSON.stringify({ JSON.stringify({
@ -52,6 +51,7 @@ export const POST: APIRoute = async({ request }) => {
}), { status: 400 } }), { status: 400 }
) )
} }
buildingData = buildingData as {id: string, name: string, requirements: { buildings: Array<{}>, research: Array<{}>, resources: Array<DBResource> }, multiplier: number}; // fuck you typescript
let userPlanet: Planet | null; let userPlanet: Planet | null;
try { try {
userPlanet = await getPlanetById(new ObjectId(body.planetId)); userPlanet = await getPlanetById(new ObjectId(body.planetId));

View File

@ -1,13 +1,13 @@
import { type APIRoute } from "astro"; import { type APIRoute } from "astro";
import validateAccessToken from "../../../lib/utils/validateAccessToken"; import validateAccessToken from "../../../lib/utils/validateAccessToken";
import research from '../../../lib/data/research.json';
import { createOrUpgradeResearch, getUserByAccessToken, getUserResearch } from "../../../lib/db/users"; import { createOrUpgradeResearch, getUserByAccessToken, getUserResearch } from "../../../lib/db/users";
import { getPlanetById } from "../../../lib/db/planets"; import { getPlanetById } from "../../../lib/db/planets";
import Planet from "../../../types/Planet"; import Planet from "../../../types/Planet";
import { ObjectId } from "mongodb"; import { ObjectId } from "mongodb";
import { calculateCurrentAvailableResources, getResourcesFromPlanet, updatePlanetResources } from "../../../lib/utils/resourceManager"; import { calculateCurrentAvailableResources, getResourcesFromPlanet, updatePlanetResources } from "../../../lib/utils/resourceManager";
import PlayerResource from "../../../types/PlayerResource"; import DBResource from "../../../types/DBResource";
import calculateAvailableResources from "../../../lib/utils/calculateAvailableResources"; import calculateAvailableResources from "../../../lib/utils/calculateAvailableResources";
import { getAllResearch, getResearchById } from "../../../lib/db/research";
export const POST: APIRoute = async({ request }) => { export const POST: APIRoute = async({ request }) => {
const response = await validateAccessToken(request); const response = await validateAccessToken(request);
@ -36,11 +36,9 @@ export const POST: APIRoute = async({ request }) => {
) )
} }
const researchId = body.research; const researchId = body.research;
const research = await getResearchById(researchId); const researchData = research.filter((element: any) => element.id === researchId)[0];
if(!researchId || !researchData) {
if(!research) {
return new Response( return new Response(
JSON.stringify({ JSON.stringify({
code: 400, code: 400,
@ -74,7 +72,7 @@ export const POST: APIRoute = async({ request }) => {
// check requirements // check requirements
// buildings // buildings
const buildings = userPlanet.buildings; const buildings = userPlanet.buildings;
research.requirements.buildings.forEach((buildingReq) => { researchData.requirements.buildings.forEach((buildingReq) => {
if(buildings.filter((building) => building.id === buildingReq.id)[0]?.level ?? 0 < buildingReq.level) { if(buildings.filter((building) => building.id === buildingReq.id)[0]?.level ?? 0 < buildingReq.level) {
return new Response( return new Response(
JSON.stringify({ JSON.stringify({
@ -88,7 +86,7 @@ export const POST: APIRoute = async({ request }) => {
// research // research
const playerResearch = await getUserResearch(user); const playerResearch = await getUserResearch(user);
research.requirements.research.forEach((researchReq) => { researchData.requirements.research.forEach((researchReq) => {
if(playerResearch.filter((research) => research.id === researchReq.id)[0].level < researchReq.level) { if(playerResearch.filter((research) => research.id === researchReq.id)[0].level < researchReq.level) {
return new Response( return new Response(
JSON.stringify({ JSON.stringify({
@ -115,19 +113,19 @@ export const POST: APIRoute = async({ request }) => {
const level = playerCurrentResearch ? playerCurrentResearch.level : 0; const level = playerCurrentResearch ? playerCurrentResearch.level : 0;
const newResources = structuredClone(resources); const newResources = structuredClone(resources);
const missingResources: Array<{}> = []; const missingResources: Array<{}> = [];
research.requirements.resources.forEach(resource => { Object.entries(researchData.requirements.resources).forEach(([key, value]) => {
const res = resources.filter((element: PlayerResource) => element.name === resource.name)[0]; const res = resources.filter((element: DBResource) => element.name === key)[0];
const cost = playerCurrentResearch ? resource.amount * Math.pow(research.multiplier, level) : resource.amount; const cost = playerCurrentResearch ? value * Math.pow(researchData.multiplier, level) : value;
if(res.amount < cost) { if(res.amount < cost) {
missingResources.push({ missingResources.push({
name: resource.name, name: key,
required: cost, required: cost,
available: res.amount available: res.amount
}); });
return; return;
} }
else newResources.filter((element: PlayerResource) => element.name === resource.name)[0].amount -= cost; else newResources.filter((element: DBResource) => element.name === key)[0].amount -= cost;
}); });
if(missingResources.length > 0) { if(missingResources.length > 0) {

View File

@ -1,14 +1,12 @@
--- ---
import Layout from '../../layouts/Layout.astro'; import Layout from '../../layouts/Layout.astro';
import NavBar from '../../components/NavBar.astro'; import NavBar from '../../components/NavBar.astro';
import BuildingCard from '../../components/ItemCard.astro'; import BuildingCard from '../../components/BuildingCard.astro';
import { getUserByAccessToken } from '../../lib/db/users'; import { getUserByAccessToken } from '../../lib/db/users';
import { getHighestWeightedLanguage, getLocales, getName, getObj } from '../../lib/utils/langDriver'; import { getHighestWeightedLanguage, getLocales, getObj } from '../../lib/utils/langDriver';
import ResourceBar from '../../components/ResourceBar.astro'; import ResourceBar from '../../components/ResourceBar.astro';
import { getAllBuildings } from '../../lib/db/buildings';
import DBBuilding from '../../types/DBBuilding';
const buildingsList = await getAllBuildings(); const buildingsList = (await import('../../lib/data/buildings.json')).default;
const loggedToken = Astro.cookies.get('sessionToken')?.value ?? null; const loggedToken = Astro.cookies.get('sessionToken')?.value ?? null;
const username = Astro.cookies.get('username')?.value ?? ""; const username = Astro.cookies.get('username')?.value ?? "";
@ -23,20 +21,16 @@ const lang = await getLocales(locale);
const modalSet: { [key: string]: { resources: Array<any>, research: Array<any>, buildings: Array<any>, energy: number } } = {}; const modalSet: { [key: string]: { resources: Array<any>, research: Array<any>, buildings: Array<any>, energy: number } } = {};
for(const building of buildingsList) { buildingsList.forEach(cat => {
modalSet[building.id] = { cat.buildings.forEach(building => {
resources: building.requirements.resources, modalSet[building.id] = {
research: building.requirements.research, "resources": building.requirements.resources,
buildings: building.requirements.buildings, "research": building.requirements.research,
energy: building.energy "buildings": building.requirements.buildings,
}; "energy": building.energy
} };
});
const buildingsByCategory = buildingsList.reduce((acc: { [key: string]: DBBuilding[] }, building) => { });
if(!acc[building.category]) acc[building.category] = [];
acc[building.category].push(building);
return acc;
}, {});
--- ---
<Layout title="Buildings"> <Layout title="Buildings">
@ -54,20 +48,19 @@ const buildingsByCategory = buildingsList.reduce((acc: { [key: string]: DBBuildi
</div> </div>
</div> </div>
{Object.entries(buildingsByCategory).map(([category, buildings]) => <> {buildingsList.map(cat => (
<h1>{getName(lang, 'buildings', `cat-${category}`)}</h1> <div class="building-card">
<div class="building-cat"> {console.log(cat.category)}
{buildings.map(building => ( <h3>{lang["buildings"][`Label_${cat.category}`]}</h3>
<BuildingCard <div class="building-cat">
{cat.buildings.map(building => <BuildingCard
id={building.id} id={building.id}
name={getObj(lang, "buildings", building.id).name} name={getObj(lang, "buildings", building.id).name}
description={getObj(lang, "buildings", building.id).description ?? ""} description={getObj(lang, "buildings", building.id).description ?? ""}
image={`/images/buildings/${building.id}.jpeg`} image="/favicon.svg" />)}
button_type="general" </div>
button_name="nav-build" />
))}
</div> </div>
</>)} ))}
</Layout> </Layout>
<style> <style>
@ -190,27 +183,23 @@ const buildingsByCategory = buildingsList.reduce((acc: { [key: string]: DBBuildi
const modalBuildings = document.getElementById("building-modal-req-buildings"); const modalBuildings = document.getElementById("building-modal-req-buildings");
const modalResearch = document.getElementById("building-modal-req-research"); const modalResearch = document.getElementById("building-modal-req-research");
document.querySelectorAll('.item-card-info-button').forEach((el) => { document.querySelectorAll('.building-card-info-button').forEach((el) => {
el.addEventListener('click', () => { el.addEventListener('click', () => {
// modal // modal
const modalDiv = document.getElementById('building-modal-details'); const modalDiv = document.getElementById('building-modal-details');
if(!modalDiv) return; if(!modalDiv) return;
modalDiv.style.display = 'block'; modalDiv.style.display = 'block';
const reqResources = modalSet[el.parentElement.parentElement.dataset.id]?.resources ?? []; modalResources.innerHTML = modalSet[el.parentElement.parentElement.dataset.id].resources.map(resource => {
const reqBuildings = modalSet[el.parentElement.parentElement.dataset.id]?.buildings ?? []; return `${lang['resources'][`Label_${resource.name}`]}: ${resource.amount}`;
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.name).name}: ${resource.amount}`;
}).join("<br />"); }).join("<br />");
modalBuildings.innerHTML = reqBuildings.length === 0 ? "None" : reqBuildings.map(building => { modalBuildings.innerHTML = modalSet[el.parentElement.parentElement.dataset.id].buildings.map(building => {
return `${lang['buildings'].find(b => b.id === building.id).name}: ${building.level}`; return `${lang['buildings'][`Label_${building.id}`].name}: ${building.level}`;
}).join("<br />"); }).join("<br />");
modalResearch.innerHTML = reqResearch.length === 0 ? "None" : reqResearch.map(research => { modalResearch.innerHTML = modalSet[el.parentElement.parentElement.dataset.id].research.map(research => {
return `${lang['research'].find(r => r.id === research.id).name}: ${research.level}`; return `${lang['research'][`Label_${research.id}`].name}: ${research.level}`;
}).join("<br />"); }).join("<br />");
// background // background

View File

@ -1,14 +1,15 @@
--- ---
import { Icon } from 'astro-icon/components'
import Layout from '../../layouts/Layout.astro'; import Layout from '../../layouts/Layout.astro';
import NavBar from '../../components/NavBar.astro'; import NavBar from '../../components/NavBar.astro';
import { getUserByAccessToken } from '../../lib/db/users'; import { getUserByAccessToken } from '../../lib/db/users';
import { getHighestWeightedLanguage, getLocales, getName, getObj } from '../../lib/utils/langDriver'; import { getHighestWeightedLanguage, getLocales, getName, getObj } from '../../lib/utils/langDriver';
import ResourceBar from '../../components/ResourceBar.astro'; import ResourceBar from '../../components/ResourceBar.astro';
import ItemCard from '../../components/ItemCard.astro';
import DBResearch from '../../types/DBResearch';
import { getAllResearch } from '../../lib/db/research';
const researchList = await getAllResearch(); type ResearchDetail = { id: string, level: number, requiredResearch: { id: string, level: number}[], cost: { [key: string]: number } };
const researchList = (await import('../../lib/data/research.json')).default;
const loggedToken = Astro.cookies.get('sessionToken')?.value ?? null; const loggedToken = Astro.cookies.get('sessionToken')?.value ?? null;
const username = Astro.cookies.get('username')?.value ?? ""; const username = Astro.cookies.get('username')?.value ?? "";
@ -21,57 +22,57 @@ const locale = await getHighestWeightedLanguage(Astro.request.headers.get('accep
const lang = await getLocales(locale); const lang = await getLocales(locale);
// type DBResearchDetails = DBResearch & { level: number }; const researchDetails: ResearchDetail[] = []; //TODO: Add union type for cost keys
// const researchDetails: DBResearchDetails[] = []; researchList.forEach(element => {
// researchList.forEach(element => { const userLevel = checkUser.research.find(x => x.id === element.id)?.level ?? 0;
// const userLevel = checkUser.research.find(x => x.id === element.id)?.level ?? 0; const tempResDetails: ResearchDetail = {
// const tempResDetails: DBResearchDetails = { id: element.id,
// level: userLevel, level: userLevel,
// ...element requiredResearch: element.requirements.research,
// } cost: {}
}
// researchDetails.push(tempResDetails); Object.entries(element.requirements.resources).forEach(([key, value]) => {
// }); tempResDetails.cost[key] = value * Math.pow(element.multiplier, userLevel);
});
researchDetails.push(tempResDetails);
const modalSet: { [key: string]: { resources: Array<any>, research: Array<any>, buildings: Array<any> } } = {}; });
for(const research of researchList) {
modalSet[research.id] = {
resources: research.requirements.resources,
research: research.requirements.research,
buildings: research.requirements.buildings,
// energy: building.energy
};
}
--- ---
<Layout title="Research"> <Layout title="Research">
<NavBar loggedIn="true" active="research" /> <NavBar loggedIn="true" active="research" />
<ResourceBar /> <ResourceBar />
<div id="research-modal-background"> {researchDetails.map(research => (
<div id="research-modal-details" data-building-id=""> <div class="research-card">
<h3>Required resources</h3> <h2>{getObj(lang, "research", research.id).name}</h2>
<div class="research-modal-text" id="research-modal-req-resources">None</div> <div class="research-card-wrapper">
<h3>Required buildings</h3> <div class="research-image"></div>
<div class="research-modal-text" id="research-modal-req-buildings">None</div> {getObj(lang, "research", research.id).description}<br />
<h3>Required research</h3>
<div class="research-modal-text" id="research-modal-req-research">None</div>
</div>
</div>
<div class="research-cards"> <a id={`research_${research.id}`} href="#" class="a-button">{getName(lang, "general", "nav-research")}</a>
{researchList.map(research => <> <div class="research-req-icon">
<ItemCard <Icon class="research-req-icon-proper" name="mdi:help" />
id={research.id} <div class="research-req-tooltip">
name={getObj(lang, "research", research.id).name} <div>{getName(lang, "general", "required")}:</div>
description={getObj(lang, "research", research.id).description ?? ""} {research.requiredResearch.length !== 0 ? research.requiredResearch.map(req => (
image={`/images/research/${research.id}.jpeg`} <div>
button_type="general" {getObj(lang, "research", req.id).name} - {req.level}
button_name="nav-research" /> </div>
</>)} )) : getName(lang, "general", "none")}
</div> </div>
</div>
</div>
<div>
Level: {research.level}
</div>
<div class="research-cost-wrapper">
{Object.entries(research.cost).map(([key, value]) => <div>
{getName(lang, "resources", key)}: {value} ||
</div>)}
</div>
</div>
))}
</Layout> </Layout>
<style> <style>
@ -153,90 +154,53 @@ for(const research of researchList) {
color: lime; color: lime;
} }
.research-cards { .research-card {
display: flex; background: rgba(0, 0, 0, 0.5);
flex-direction: row; padding: 1rem;
flex-wrap: wrap; margin: 1rem;
row-gap: 40px; border-radius: 8px;
column-gap: 2%;
margin-top: 40px;
} }
#research-modal-background { .research-card-wrapper {
display: none; display: flex;
position: fixed; }
top: 0;
left: 0; .research-image {
background-color: pink;
border-radius: 20px;
width: 10em;
height: 10em;
}
.research-cost-wrapper {
display: flex;
}
.research-req-icon {
background-color: gray;
width: 2em;
height: 2em;
font-size: 1em;
}
.research-req-icon-proper {
width: 100%; width: 100%;
height: 100%; height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 100;
} }
#research-modal-details { .research-req-icon .research-req-tooltip {
display: none; position: absolute;
position: fixed; background-color: grey;
top: 50%; border-radius: 5px;
left: 50%; transition: opacity 1s;
transform: translate(-50%, -50%); opacity: 0;
width: 80%; }
max-width: 800px;
background: rgba(0, 0, 0, 0.9); .research-req-icon:hover .research-req-tooltip {
border-radius: 8px; opacity: 1;
padding: 1rem;
z-index: 101;
} }
</style> </style>
<script define:vars={{ modalSet, lang }}> <script>
const modalResources = document.getElementById("research-modal-req-resources");
const modalBuildings = document.getElementById("research-modal-req-buildings");
const modalResearch = document.getElementById("research-modal-req-research");
document.querySelectorAll('.item-card-info-button').forEach((el) => {
el.addEventListener('click', () => {
// modal
const modalDiv = document.getElementById('research-modal-details');
if(!modalDiv) return;
modalDiv.style.display = 'block';
console.log(modalSet)
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('research-modal-background');
if(!backgroundDiv) return;
backgroundDiv.style.display = 'block';
});
});
// close modal on background click
const bg = document.getElementById('research-modal-background');
bg?.addEventListener('click', () => {
const modalDiv = document.getElementById('research-modal-details');
if(!modalDiv) return;
modalDiv.style.display = 'none';
const backgroundDiv = document.getElementById('research-modal-background');
if(!backgroundDiv) return;
backgroundDiv.style.display = 'none';
});
const allButtons = document.getElementsByClassName("a-button"); const allButtons = document.getElementsByClassName("a-button");
for(const researchButton of allButtons) { for(const researchButton of allButtons) {

View File

@ -2,10 +2,12 @@
import Layout from '../../layouts/Layout.astro'; import Layout from '../../layouts/Layout.astro';
import NavBar from '../../components/NavBar.astro'; import NavBar from '../../components/NavBar.astro';
import { getUserByAccessToken } from '../../lib/db/users'; import { getUserByAccessToken } from '../../lib/db/users';
import { getHighestWeightedLanguage, getLocales, getObj } from '../../lib/utils/langDriver'; import { getHighestWeightedLanguage, getLocales } from '../../lib/utils/langDriver';
import ResourceBar from '../../components/ResourceBar.astro'; import ResourceBar from '../../components/ResourceBar.astro';
import { getAllShips } from '../../lib/db/ships';
import ItemCard from '../../components/ItemCard.astro'; import ships from '../../lib/data/ships.json';
import { getPlanetById } from '../../lib/db/planets';
import { ObjectId } from 'mongodb';
const loggedToken = Astro.cookies.get('sessionToken')?.value ?? null; const loggedToken = Astro.cookies.get('sessionToken')?.value ?? null;
const username = Astro.cookies.get('username')?.value ?? ""; const username = Astro.cookies.get('username')?.value ?? "";
@ -14,48 +16,24 @@ if(loggedToken === null || username === "") return Astro.redirect('/logout');
const checkUser = await getUserByAccessToken(loggedToken); const checkUser = await getUserByAccessToken(loggedToken);
if(checkUser === null || checkUser.username !== username) return Astro.redirect('/logout'); if(checkUser === null || checkUser.username !== username) return Astro.redirect('/logout');
const ships = await getAllShips(); const planet = await getPlanetById(new ObjectId(Astro.cookies.get('planetid')?.value));
if(!planet) return;
const lang = await getLocales(await getHighestWeightedLanguage(Astro.request.headers.get('accept-language'))); const lang = await getLocales(await getHighestWeightedLanguage(Astro.request.headers.get('accept-language')));
const modalSet: { [key: string]: { resources: Array<any>, research: Array<any>, buildings: Array<any> } } = {};
for(const ship of ships) {
modalSet[ship.id] = {
resources: ship.requirements.resources,
research: ship.requirements.research,
buildings: ship.requirements.buildings,
// energy: building.energy
};
}
--- ---
<Layout title="Ships"> <Layout title="Ships">
<NavBar loggedIn="true" active="ships" /> <NavBar loggedIn="true" active="ships" />
<ResourceBar /> <ResourceBar />
<div id="ship-modal-background"> {ships.map(ship => (
<div id="ship-modal-details" data-building-id=""> <div class="ship-card">
<h3>Required resources</h3> <div class="ship-title">
<div class="ship-modal-text" id="ship-modal-req-resources">None</div> <b>({planet.ships.find((s => s.id === ship.id))?.amount ?? 0})</b> <i>{ship.id}</i>
<h3>Required buildings</h3> </div>
<div class="ship-modal-text" id="ship-modal-req-buildings">None</div> </div>
<h3>Required research</h3> ))}
<div class="ship-modal-text" id="ship-modal-req-research">None</div>
</div>
</div>
<div class="ship-cards">
{ships.map(ship => <>
<ItemCard
id={ship.id}
name={getObj(lang, "ships", ship.id).name}
description={getObj(lang, "ships", ship.id).description ?? ""}
image={`/images/ships/${ship.id}.jpeg`}
button_type="general"
button_name="nav-build" />
</>)}
</div>
</Layout> </Layout>
<style> <style>
@ -136,93 +114,8 @@ for(const ship of ships) {
.a-button:hover { .a-button:hover {
color: lime; color: lime;
} }
.ship-cards {
display: flex;
flex-direction: row;
flex-wrap: wrap;
row-gap: 40px;
column-gap: 2%;
margin-top: 40px;
}
#ship-modal-background {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 100;
}
#ship-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;
}
</style> </style>
<script define:vars={{ modalSet, lang }}> <script>
const modalResources = document.getElementById("ship-modal-req-resources");
const modalBuildings = document.getElementById("ship-modal-req-buildings");
const modalResearch = document.getElementById("ship-modal-req-research");
document.querySelectorAll('.item-card-info-button').forEach((el) => {
el.addEventListener('click', () => {
// modal
const modalDiv = document.getElementById('ship-modal-details');
if(!modalDiv) return;
modalDiv.style.display = 'block';
console.log(modalSet)
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 ?? [];
console.log(modalSet)
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('ship-modal-background');
if(!backgroundDiv) return;
backgroundDiv.style.display = 'block';
});
});
// close modal on background click
const bg = document.getElementById('ship-modal-background');
bg?.addEventListener('click', () => {
const modalDiv = document.getElementById('ship-modal-details');
if(!modalDiv) return;
modalDiv.style.display = 'none';
const backgroundDiv = document.getElementById('ship-modal-background');
if(!backgroundDiv) return;
backgroundDiv.style.display = 'none';
});
const allButtons = document.getElementsByClassName("a-button"); const allButtons = document.getElementsByClassName("a-button");
for(const researchButton of allButtons) { for(const researchButton of allButtons) {

View File

@ -1,11 +0,0 @@
export default interface DBBuilding {
id: string,
category: string,
requirements: {
buildings: Array<{ id: string, level: number }>,
research: Array<{ id: string, level: number }>,
resources: Array<{ name: string, amount: number }>,
},
energy: number,
multiplier: number,
}

View File

@ -1,10 +0,0 @@
export default interface DBResearch {
id: string,
requirements: {
buildings: Array<{ id: string, level: number }>,
research: Array<{ id: string, level: number }>,
resources: Array<{ name: string, amount: number }>,
},
time: number,
multiplier: number,
}

View File

@ -1,5 +1,6 @@
export default interface DBResource { import type Resource from "./Resource";
id: string,
type: string, export default interface DBResource extends Resource {
icon: string lastUpdated: Date;
perHourMiningRate: number;
} }

View File

@ -1,20 +0,0 @@
export default interface DBShip {
id: string,
capacity: {
solid: number,
liquid: number,
gas: number,
},
requirements: {
buildings: Array<{ id: string, level: number }>,
research: Array<{ id: string, level: number }>,
resources: Array<{ name: string, amount: number }>,
},
time: number,
structure: {
hitpoints: number,
defense: number,
attack: number,
},
speed: number,
}

View File

@ -1,5 +1,5 @@
import type { ObjectId } from "mongodb"; import type { ObjectId } from "mongodb";
import type PlayerResource from "./PlayerResource"; import type DBResource from "./DBResource";
import type Building from "./Building"; import type Building from "./Building";
import type Ship from "./Ship"; import type Ship from "./Ship";
import type User from "./User"; import type User from "./User";
@ -9,7 +9,7 @@ export default interface Planet {
owner: User, owner: User,
name: string, name: string,
fields: number, fields: number,
resources: Array<PlayerResource>, resources: Array<DBResource>,
buildings: Array<Building>, buildings: Array<Building>,
ships: Array<Ship>, ships: Array<Ship>,
} }

View File

@ -1,6 +0,0 @@
import type Resource from "./Resource";
export default interface DBResource extends Resource {
lastUpdated: Date;
perHourMiningRate: number;
}