Compare commits
No commits in common. "cb402476fa429b32b005d4905745422bd94998bd" and "8b5eef482f9f43dc2fe4c949092cc7dba7113c3e" have entirely different histories.
cb402476fa
...
8b5eef482f
Before Width: | Height: | Size: 870 B |
Before Width: | Height: | Size: 399 B |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 956 B |
Before Width: | Height: | Size: 638 B |
Before Width: | Height: | Size: 864 B |
Before Width: | Height: | Size: 802 B |
|
@ -1,5 +1,4 @@
|
|||
---
|
||||
import { Image } from 'astro:assets';
|
||||
import { getHighestWeightedLanguage, getLocales, getName } from '../lib/utils/langDriver';
|
||||
|
||||
interface Props {
|
||||
|
@ -17,15 +16,13 @@ interface Props {
|
|||
const lang = await getLocales(Astro.cookies.get('language')?.value ?? await getHighestWeightedLanguage(Astro.request.headers.get('accept-language')));
|
||||
---
|
||||
<div class="item-card" data-id={Astro.props.id}>
|
||||
<Image class="item-card-image" src={Astro.props.image} alt={Astro.props.id} width={512} height={512} />
|
||||
<img class="item-card-image" src={Astro.props.image} />
|
||||
<div class="item-card-main-field">
|
||||
<form method="post">
|
||||
<input type="hidden" name="id" value={Astro.props.id} />
|
||||
<div class="item-card-name">{Astro.props.name} | {Astro.props.level}</div>
|
||||
<div class="item-card-description">{Astro.props.description} <a href={`/wiki/${Astro.props.category}/${Astro.props.id}`}>[more]</a></div>
|
||||
{Astro.props.button_name === "nav-researched" ?
|
||||
<input type="submit" class="item-card-build" value={getName(lang, Astro.props.button_type, "nav-researched")} disabled /> :
|
||||
<input type="submit" class="item-card-build" value={getName(lang, Astro.props.button_type, "nav-research")} />}
|
||||
<input type="submit" class="item-card-build" value={getName(lang, Astro.props.button_type, Astro.props.button_name)} />
|
||||
<div class="item-card-info-button">i</div>
|
||||
{Astro.props.has_amount_input === "true" && <input type="number" name="amount" />}
|
||||
</form>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
---
|
||||
import { ObjectId } from 'mongodb';
|
||||
import { Image } from 'astro:assets';
|
||||
import { checkForUnreadMails } from '../lib/db/mails';
|
||||
import { getHighestWeightedLanguage, getLocales, getName } from '../lib/utils/langDriver';
|
||||
|
||||
|
@ -74,13 +73,6 @@ const listOfElements: Array<NavElement> = [{
|
|||
url: "/game",
|
||||
show: "loggedInOnly",
|
||||
position: "bottom"
|
||||
}, {
|
||||
id: "energy",
|
||||
title: getName(lang, "general", "nav-energy"),
|
||||
type: "simple",
|
||||
url: "/game/energy",
|
||||
show: "loggedInOnly",
|
||||
position: "bottom"
|
||||
}, {
|
||||
id: "buildings",
|
||||
title: getName(lang, "general", "nav-buildings"),
|
||||
|
@ -109,13 +101,6 @@ const listOfElements: Array<NavElement> = [{
|
|||
url: "/game/fleet",
|
||||
show: "loggedInOnly",
|
||||
position: "bottom"
|
||||
},{
|
||||
id: "defenses",
|
||||
title: getName(lang, "general", "nav-defenses"),
|
||||
type: "simple",
|
||||
url: "/game/defenses",
|
||||
show: "loggedInOnly",
|
||||
position: "bottom"
|
||||
}, {
|
||||
id: "galaxyView",
|
||||
title: getName(lang, "general", "nav-galaxy-view"),
|
||||
|
@ -168,8 +153,8 @@ const hasUnreadMail = await checkForUnreadMails(new ObjectId(userId));
|
|||
<li class="nav-item"><a href={element.url} class={`nav-url ${active === element.id ? "active" : ""}`}>{element.title}</a></li>
|
||||
)}
|
||||
<li class="nav-item"><span class="nav-username nav-keep-right">{username}</span></li>
|
||||
{loggedIn === "true" ? <li class="nav-item"><Image src="/gargamel.png" alt="profile-pic" width={179} height={178} class="avatar-icon" /></li> : ""}
|
||||
{loggedIn === "true" ? <li class="nav-item"><a href="/game/mail"><Image src={`/mail${hasUnreadMail ? "-notif" : ""}.svg?${new Date().getTime()}`} alt="mail" width={800} height={800} class="mail-icon" /></a></li> : ""}
|
||||
{loggedIn === "true" ? <li class="nav-item"><img src="/gargamel.png" class="avatar-icon" /></li> : ""}
|
||||
{loggedIn === "true" ? <li class="nav-item"><a href="/game/mail"><img src={`/mail${hasUnreadMail ? "-notif" : ""}.svg?${new Date().getTime()}`} class="mail-icon" /></a></li> : ""}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
@ -233,7 +218,6 @@ nav ul {
|
|||
}
|
||||
|
||||
.avatar-icon {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid white;
|
||||
|
@ -242,7 +226,6 @@ nav ul {
|
|||
}
|
||||
|
||||
.mail-icon {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
/* border: 1px solid white; */
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
---
|
||||
import { ObjectId } from 'mongodb';
|
||||
import { Image } from 'astro:assets';
|
||||
import { getHighestWeightedLanguage, getLocales, getName } from '../lib/utils/langDriver';
|
||||
import { getAllResources } from '../lib/db/resources';
|
||||
import locationManager from '../lib/classes/managers/LocationManager';
|
||||
|
@ -19,146 +18,80 @@ if(!planet) return;
|
|||
|
||||
await planet.resources.calculateCurrentAvailableResources();
|
||||
|
||||
const resourceArray: (Resource & { capacity: number })[] = [];
|
||||
const resourceArray: Resource[] = [];
|
||||
for(const key of planet.resources.resources) {
|
||||
resourceArray.push({ ...key, capacity: 10_000 });
|
||||
}
|
||||
|
||||
if(!(planet instanceof SystemManager)) {
|
||||
const mapStorageToResource: { [key: string]: string } = {
|
||||
"coal-storage": "coal",
|
||||
"iron-storage": "iron",
|
||||
"gold-storage": "gold",
|
||||
"water-tank": "water",
|
||||
"acid-tank": "sulfuric-acid",
|
||||
"nitrogen-tank": "liquid-nitrogen",
|
||||
"hydrogen-tank": "hydrogen",
|
||||
"oxygen-tank": "oxygen",
|
||||
"helium3-tank": "helium-3",
|
||||
}
|
||||
|
||||
resourceArray.forEach(res => {
|
||||
res.capacity = 10_000;
|
||||
});
|
||||
|
||||
for(const building of planet.buildings.buildings) {
|
||||
if(building.data.category === 'storage') {
|
||||
const resource = mapStorageToResource[building.data.id];
|
||||
if(resource) {
|
||||
const res = resourceArray.find(x => x.id === resource);
|
||||
if(res) res.capacity += building.level * 10_000;
|
||||
}
|
||||
}
|
||||
}
|
||||
resourceArray.push(key);
|
||||
}
|
||||
---
|
||||
<div id="resourcebar">
|
||||
<!-- Energy: <span class={`${planet.energy.consumption > planet.energy.production ? "prod-full" : planet.energy.consumption >= (planet.energy.production * 0.9) ? "prod-almost-full" : ""}`}>{planet.energy.consumption}/{planet.energy.production}</span> -->
|
||||
<div class="resourcebar-item">
|
||||
<Image src="/images/resources/energy.png" alt="energy" class="icon" width={32} height={32} />
|
||||
<div class="text">
|
||||
<span class="line1"><!--{getName(lang, 'resources', 'energy')}-->Energy</span>
|
||||
<span class={`line2 ${planet.energy.consumption > planet.energy.production ? "prod-full" : planet.energy.consumption >= (planet.energy.production * 0.9) ? "prod-almost-full" : ""}`}>{planet.energy.consumption}/{planet.energy.production}</span>
|
||||
</div>
|
||||
<div class="resourcebar-item-tooltip">
|
||||
<span class="resourcebar-item-tooltip-name">{getName(lang, 'general', 'production')}</span><span class={`resourcebar-item-tooltip-amount`}>{planet.energy.production}</span>
|
||||
<span class="resourcebar-item-tooltip-name">{getName(lang, 'general', 'consumption')}</span><span class="resourcebar-item-tooltip-amount">{planet.energy.consumption}</span>
|
||||
<span class="resourcebar-item-tooltip-name">{getName(lang, 'general', 'balance')}</span><span class={`resourcebar-item-tooltip-amount ${planet.energy.consumption > planet.energy.production ? "prod-full" : planet.energy.consumption >= (planet.energy.production * 0.9) ? "prod-almost-full" : ""}`}>{planet.energy.production - planet.energy.consumption}</span>
|
||||
<div class="resourcebar-item-identifier">
|
||||
<div class="resourcebar-circle-id" data-type="solid"></div>
|
||||
</div>
|
||||
<div class="resourcebar-planetname">
|
||||
{planet instanceof SystemManager ? <span style="color: red;">{planet.data.name}</span> : planet.name}
|
||||
</div>
|
||||
<div id="resourcebar-elements" class="resourcebar-elements">
|
||||
{resourceArray.map(res =>
|
||||
<div class="resourcebar-item resourcebar-iterable"
|
||||
<div class="resourcebar-item"
|
||||
data-res-type={resourceTypes.find(x => x.id === res.id)?.type ?? "solid"}
|
||||
data-res-id={res.id}
|
||||
data-res-amount={res.amount}
|
||||
data-res-mining-rate={res.amount >= res.capacity ? 0 : res.perHourMiningRate}
|
||||
data-res-capacity={res.capacity}
|
||||
data-res-mining-rate={res.perHourMiningRate}
|
||||
style={(resourceTypes.find(x => x.id === res.id)?.type ?? "solid") === "solid" ? "" : "display: none;"}
|
||||
>
|
||||
<Image src={resourceTypes.find(x => x.id === res.id)?.icon ?? "#"} alt={res.id} class="icon" width={32} height={32} />
|
||||
<div class="text" data-resname={res.id}>
|
||||
<span class="line1">{getName(lang, 'resources', res.id)}</span>
|
||||
<span class={`line2 ${res.amount >= res.capacity ? "prod-full" : res.amount >= (res.capacity * 0.9) ? "prod-almost-full" : ""}`}></span>
|
||||
<div class="resourcebar-item-icon">
|
||||
<img src={resourceTypes.find(x => x.id === res.id)?.icon ?? "#"} alt={res.id} />
|
||||
</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-amount">[fetching]</div>
|
||||
</div>
|
||||
<div class="resourcebar-item-tooltip">
|
||||
<span class="resourcebar-item-tooltip-name">{getName(lang, 'general', 'avaliable')}</span><span class="resourcebar-item-tooltip-amount resourcebar-item-tooltip-avaliable">{Math.floor(res.amount).toString()}</span>
|
||||
<span class="resourcebar-item-tooltip-name">{getName(lang, 'general', 'production')}</span><span class={`resourcebar-item-tooltip-amount resourcebar-item-tooltip-production ${res.amount >= res.capacity ? "prod-full" : res.amount >= (res.capacity * 0.9) ? "prod-almost-full" : ""}`}>{res.amount >= res.capacity ? "0" : res.perHourMiningRate.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") ?? "0"}</span>
|
||||
<span class="resourcebar-item-tooltip-name">{getName(lang, 'general', 'capacity')}</span><span class="resourcebar-item-tooltip-amount resourcebar-item-tooltip-capacity">{res.capacity.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}</span>
|
||||
<div class="resourcebar-item-tooltip-name">{getName(lang, 'general', 'avaliable')} - <span class="resourcebar-item-tooltip-avaliable">{Math.floor(res.amount).toString()}</span></div>
|
||||
<div class="resourcebar-item-tooltip-name">{getName(lang, 'general', 'production')} - <span class="resourcebar-item-tooltip-production">{res.perHourMiningRate?.toString() ?? "0"}</span></div>
|
||||
<div class="resourcebar-item-tooltip-name">{getName(lang, 'general', 'capacity')} - <span class="resourcebar-item-tooltip-capacity">{'21372137'}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<style>
|
||||
#resourcebar {
|
||||
color: white;
|
||||
background-color: blueviolet;
|
||||
border-radius: 15px;
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px 20px;
|
||||
background: linear-gradient(135deg, #565656, #4a4a4a);
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.resourcebar-item {
|
||||
.resourcebar-item-identifier {
|
||||
left: 25px;
|
||||
flex-shrink: 0;
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
.resourcebar-circle-id {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background-color: #0f0;
|
||||
border-radius: 25px;
|
||||
margin-right: 8px;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.resourcebar-planetname {
|
||||
margin-top: 8px;
|
||||
font-size: 2.5em;
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
.resourcebar-elements {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.line1 {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.line2 {
|
||||
font-size: 12px;
|
||||
color: #b0b0b0;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.status-bar {
|
||||
padding: 10px 15px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.line1 {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.line2 {
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.status-bar {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.status-item {
|
||||
width: 100%;
|
||||
margin: 5px 0;
|
||||
}
|
||||
flex-direction: row;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.resourcebar-item {
|
||||
|
@ -177,44 +110,30 @@ if(!(planet instanceof SystemManager)) {
|
|||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.resourcebar-item-icon img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.resourcebar-item-text-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.resourcebar-item-tooltip-name {
|
||||
font-size: 16px;
|
||||
color: #b0b0b0;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
margin-top: 5px;
|
||||
.resourcebar-item-text {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.resourcebar-item-tooltip-amount {
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
margin-left: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.prod-almost-full {
|
||||
color: #ff9900;
|
||||
}
|
||||
|
||||
.prod-full {
|
||||
color: #ff0000;
|
||||
.resourcebar-item-amount {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.resourcebar-item .resourcebar-item-tooltip {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: #b0b0b0;
|
||||
background-color: rgb(58, 58, 58);
|
||||
margin-top: 220px;
|
||||
background-color: gray;
|
||||
margin-top: 70px;
|
||||
width: 150%;
|
||||
border-radius: 10px;
|
||||
min-width: 134px;
|
||||
transition: visibility 1s, opacity 1s;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
|
@ -234,35 +153,55 @@ if(!(planet instanceof SystemManager)) {
|
|||
return x.toString();
|
||||
}
|
||||
|
||||
function numWithSeparator(x: number) {
|
||||
x = Math.floor(x);
|
||||
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
}
|
||||
setInterval(() => {
|
||||
const resourcebarItems = document.getElementById('resourcebar')?.querySelectorAll('.resourcebar-item');
|
||||
|
||||
function init() {
|
||||
const resourcebarItems = document.getElementById('resourcebar')?.querySelectorAll('.resourcebar-iterable');
|
||||
resourcebarItems?.forEach((item: any) => {
|
||||
const resourceAmount = parseFloat(item.dataset.resAmount ?? '0');
|
||||
const miningRate = parseInt(item.dataset.resMiningRate ?? '0') / 3600;
|
||||
const newAmount = resourceAmount + miningRate;
|
||||
|
||||
item.dataset.resAmount = newAmount.toString();
|
||||
(item.querySelector('.line2') as HTMLElement).innerHTML = numWithPrefix(newAmount);
|
||||
(item.querySelector('.resourcebar-item-tooltip-avaliable') as HTMLElement).innerHTML = numWithSeparator(newAmount);
|
||||
(item.querySelector('.resourcebar-item-amount') as HTMLElement).innerHTML = numWithPrefix(newAmount);
|
||||
(item.querySelector('.resourcebar-item-tooltip .resourcebar-item-tooltip-avaliable') as HTMLElement).innerHTML = Math.floor(newAmount).toString();
|
||||
});
|
||||
}, 1_000);
|
||||
|
||||
if(newAmount >= parseFloat(item.dataset.resCapacity ?? '0')) {
|
||||
(item.querySelector('.line2') as HTMLElement).classList.remove('prod-almost-full');
|
||||
(item.querySelector('.line2') as HTMLElement).classList.add('prod-full');
|
||||
(item.querySelector('.resourcebar-item-tooltip-production') as HTMLElement).classList.remove('prod-almost-full');
|
||||
(item.querySelector('.resourcebar-item-tooltip-production') as HTMLElement).classList.add('prod-full');
|
||||
item.dataset.resMiningRate = '0';
|
||||
} else if(newAmount >= parseFloat(item.dataset.resCapacity ?? '0') * 0.9) {
|
||||
(item.querySelector('.line2') as HTMLElement).classList.add('prod-almost-full');
|
||||
(item.querySelector('.resourcebar-item-tooltip-production') as HTMLElement).classList.add('prod-almost-full');
|
||||
document.querySelector(".resourcebar-item-identifier")?.addEventListener("click", () => {
|
||||
switch((document.querySelector(".resourcebar-item-identifier")?.children[0] as HTMLElement)?.dataset.type) {
|
||||
case "solid":
|
||||
(document.querySelector(".resourcebar-item-identifier")?.children[0] as HTMLElement).dataset.type = "liquid";
|
||||
(document.querySelector(".resourcebar-item-identifier")?.children[0] as HTMLElement).style.backgroundColor = "#00f";
|
||||
(document.getElementById("resourcebar-elements")?.querySelectorAll(".resourcebar-item") as NodeListOf<HTMLElement>).forEach(item => {
|
||||
if(item.dataset.resType === "liquid") {
|
||||
item.style.display = "";
|
||||
} else {
|
||||
item.style.display = "none";
|
||||
}
|
||||
});
|
||||
break;
|
||||
case "liquid":
|
||||
(document.querySelector(".resourcebar-item-identifier")?.children[0] as HTMLElement).dataset.type = "gas";
|
||||
(document.querySelector(".resourcebar-item-identifier")?.children[0] as HTMLElement).style.backgroundColor = "#ff0";
|
||||
(document.getElementById("resourcebar-elements")?.querySelectorAll(".resourcebar-item") as NodeListOf<HTMLElement>).forEach(item => {
|
||||
if(item.dataset.resType === "gas") {
|
||||
item.style.display = "";
|
||||
} else {
|
||||
item.style.display = "none";
|
||||
}
|
||||
|
||||
init();
|
||||
setInterval(init, 1_000);
|
||||
});
|
||||
break;
|
||||
case "gas":
|
||||
(document.querySelector(".resourcebar-item-identifier")?.children[0] as HTMLElement).dataset.type = "solid";
|
||||
(document.querySelector(".resourcebar-item-identifier")?.children[0] as HTMLElement).style.backgroundColor = "#0f0";
|
||||
(document.getElementById("resourcebar-elements")?.querySelectorAll(".resourcebar-item") as NodeListOf<HTMLElement>).forEach(item => {
|
||||
if(item.dataset.resType === "solid") {
|
||||
item.style.display = "";
|
||||
} else {
|
||||
item.style.display = "none";
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -21,10 +21,8 @@ const { title } = Astro.props;
|
|||
<title>{title}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="bars">
|
||||
<NavBar loggedIn="true" active={Astro.props.id} />
|
||||
<ResourceBar />
|
||||
</div>
|
||||
<slot />
|
||||
</body>
|
||||
</html>
|
||||
|
@ -32,10 +30,5 @@ const { title } = Astro.props;
|
|||
html {
|
||||
font-family: system-ui, sans-serif;
|
||||
background: #13151a;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.bars {
|
||||
display: inline;
|
||||
}
|
||||
</style>
|
|
@ -5,13 +5,11 @@ export default class Building {
|
|||
manager: BuildingManager
|
||||
data: DBBuilding;
|
||||
level: number;
|
||||
activePercent: number = 100;
|
||||
|
||||
constructor(manager: BuildingManager, data: DBBuilding, level: number, activePercent?: number) {
|
||||
constructor(manager: BuildingManager, data: DBBuilding, level: number) {
|
||||
this.manager = manager;
|
||||
this.data = data;
|
||||
this.level = level;
|
||||
if(activePercent !== undefined) this.activePercent = activePercent;
|
||||
}
|
||||
|
||||
async checkRequiredResources(level: number): Promise<boolean> {
|
||||
|
@ -40,7 +38,7 @@ export default class Building {
|
|||
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) {
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
import DBDefenses from "../../types/db/DBDefenses";
|
||||
import DefenseManager from "./managers/abstract/DefenseManager";
|
||||
import SystemManager from "./managers/SystemManager";
|
||||
|
||||
export default class Defense {
|
||||
manager: DefenseManager;
|
||||
data: DBDefenses;
|
||||
amount: number;
|
||||
|
||||
constructor(manager: DefenseManager, data: DBDefenses, amount: number) {
|
||||
this.manager = manager;
|
||||
this.data = data;
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
async checkRequiredResources(): Promise<boolean> {
|
||||
const resources = await this.manager.manager.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;
|
||||
|
||||
if(resource.amount < (res.amount * this.amount)) {
|
||||
canBuild = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return canBuild;
|
||||
}
|
||||
|
||||
async checkRequirements(): Promise<{ canBuild: boolean, error: string }> {
|
||||
if(!(this.manager.manager instanceof SystemManager)) {
|
||||
const playerBuildings = this.manager.manager.buildings.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
|
||||
}
|
||||
} /*else { //TODO: check for structures requirements
|
||||
const structures = this.manager.manager.structures.structures;
|
||||
let playerStructuresCanBuild = { canBuild: true, missing: "" };
|
||||
this.data.requirements.structures.forEach((buildingReq: any) => {
|
||||
if((structures.filter((building) => building.data.id === buildingReq.id)[0]?.level ?? 0) < buildingReq.level) {
|
||||
playerStructuresCanBuild = { canBuild: false, missing: `${buildingReq.id} level ${buildingReq.level} required, found ${structures.filter((structure) => structure.data.id === buildingReq.id)[0]?.level ?? 0}` };
|
||||
return;
|
||||
}
|
||||
});
|
||||
if(!playerStructuresCanBuild.canBuild) return {
|
||||
canBuild: false,
|
||||
error: playerStructuresCanBuild.missing
|
||||
}
|
||||
}*/
|
||||
|
||||
// research
|
||||
const playerResearch = this.manager.manager instanceof SystemManager ? this.manager.manager.data.ownedBy.research : this.manager.manager.system.data.ownedBy.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,20 +0,0 @@
|
|||
import Asteroid from '../../../types/Asteroid';
|
||||
import SystemManager from './SystemManager';
|
||||
import { updateSystemAsteroids } from '../../db/systems';
|
||||
|
||||
export default class AsteroidManager {
|
||||
asteroids: Array<Asteroid> = [];
|
||||
system: SystemManager;
|
||||
|
||||
constructor(system: SystemManager) {
|
||||
this.system = system;
|
||||
}
|
||||
|
||||
init(asteroids: Array<Asteroid>) {
|
||||
this.asteroids = asteroids;
|
||||
}
|
||||
|
||||
async sync() {
|
||||
await updateSystemAsteroids(this.system.data._id, this.asteroids);
|
||||
}
|
||||
}
|
|
@ -9,7 +9,6 @@ import { getRandomInRange, weightedRandom } from "../../utils/math";
|
|||
import { Sector } from "./LocationManager";
|
||||
import { Planet } from "./PlanetManager";
|
||||
import SystemManager from "./SystemManager";
|
||||
import { getAllDefenses } from "../../db/defenses";
|
||||
|
||||
export type Fleet = {
|
||||
id: ObjectId,
|
||||
|
@ -20,8 +19,7 @@ export type Fleet = {
|
|||
returning: boolean,
|
||||
mission: MissionType,
|
||||
ships: Array<{ id: string, amount: number }>,
|
||||
cargo: Array<{ id: string, amount: number }>,
|
||||
additionalData?: string
|
||||
cargo: Array<{ id: string, amount: number }>
|
||||
}
|
||||
|
||||
export type BattleFleet = {
|
||||
|
@ -34,7 +32,7 @@ export type BattleFleet = {
|
|||
export default class FleetManager {
|
||||
data: Fleet;
|
||||
|
||||
constructor(id: ObjectId, source: Planet | SystemManager, destination: Planet | SystemManager | Sector, departureTime: Date, arrivalTime: Date, returning: boolean, mission: MissionType, ships: Array<{ id: string, amount: number }>, cargo: Array<{ id: string, amount: number }>, additionalData?: string) {
|
||||
constructor(id: ObjectId, source: Planet | SystemManager, destination: Planet | SystemManager | Sector, departureTime: Date, arrivalTime: Date, returning: boolean, mission: MissionType, ships: Array<{ id: string, amount: number }>, cargo: Array<{ id: string, amount: number }>) {
|
||||
this.data = {
|
||||
id,
|
||||
source,
|
||||
|
@ -44,8 +42,7 @@ export default class FleetManager {
|
|||
returning,
|
||||
mission,
|
||||
ships,
|
||||
cargo,
|
||||
additionalData
|
||||
cargo
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,7 +104,7 @@ export default class FleetManager {
|
|||
case 'ATTACK':
|
||||
if(!("expedition" in this.data.destination)) {
|
||||
const enemyShips = this.data.destination.ships.ships;
|
||||
return await this.battleResults(enemyShips.map(ship => { return { id: ship.data.id, amount: ship.amount } }), this.data.destination.defenses.defenses.map(defense => { return { id: defense.data.id, amount: defense.amount } }));
|
||||
return await this.battleResults(enemyShips.map(ship => { return { id: ship.data.id, amount: ship.amount } }));
|
||||
} else {
|
||||
throw new Error("Cannot attack sector.");
|
||||
}
|
||||
|
@ -150,30 +147,6 @@ export default class FleetManager {
|
|||
case 'EXPEDITION':
|
||||
await this.expeditionResults();
|
||||
|
||||
return false;
|
||||
case 'MINE':
|
||||
const system = this.data.destination as SystemManager;
|
||||
const asteroid = system.asteroids.asteroids.find(a => a.id.equals(this.data.additionalData ?? ""));
|
||||
if(!asteroid) throw new Error("Asteroid not found.");
|
||||
for(const res of asteroid.resources) {
|
||||
const resource = this.data.cargo.find(r => r.id === res.id);
|
||||
if(!resource) this.data.cargo.push(res);
|
||||
else resource.amount += res.amount;
|
||||
}
|
||||
|
||||
await this.initiateReturn();
|
||||
await sendMail(
|
||||
null,
|
||||
this.data.source instanceof SystemManager ? this.data.source.data.ownedBy.id : this.data.source.system.data.ownedBy.id,
|
||||
this.data.arrivalTime,
|
||||
"Asteroid mined",
|
||||
`Your fleet has arrived at AS-${this.data.additionalData} asteroid.\n
|
||||
Following resources were added to the cargo inventory:\n${asteroid.resources.map(r => `${r.id} - ${r.amount}`).join('\n')}\n
|
||||
Fleet will return at ${this.data.arrivalTime}`
|
||||
);
|
||||
|
||||
system.asteroids.asteroids = system.asteroids.asteroids.filter(a => !a.id.equals(asteroid.id));
|
||||
await system.asteroids.sync();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -188,19 +161,18 @@ export default class FleetManager {
|
|||
await this.sync();
|
||||
}
|
||||
|
||||
private async sendMail(user: ObjectId, title: string, description: string) {
|
||||
private async sendMail(title: string, description: string) {
|
||||
await sendMail(
|
||||
null,
|
||||
user,
|
||||
this.data.source instanceof SystemManager ? this.data.source.data.ownedBy.id : this.data.source.system.data.ownedBy.id,
|
||||
this.data.arrivalTime,
|
||||
title,
|
||||
description
|
||||
);
|
||||
}
|
||||
|
||||
async battleResults(enemyFleet: { id: string, amount: number }[], enemyDefenses: { id: string, amount: number }[] = []) {
|
||||
async battleResults(enemyFleet: { id: string, amount: number }[]) {
|
||||
const allShips = await getAllShips();
|
||||
const allDefenses = await getAllDefenses();
|
||||
|
||||
const playerStats = this.data.ships.reduce((acc, ship) => {
|
||||
const dbShip = allShips.find(s => s.id === ship.id);
|
||||
|
@ -211,14 +183,6 @@ export default class FleetManager {
|
|||
return acc;
|
||||
}, { attack: 0, defense: 0, hitpoints: 0 });
|
||||
|
||||
const enemyDefensesStats = enemyDefenses.reduce((acc, defense) => {
|
||||
const dbDefense = allDefenses.find(d => d.id === defense.id);
|
||||
if(!dbDefense) return acc;
|
||||
acc.defense += dbDefense.structure.defense * defense.amount;
|
||||
acc.hitpoints += dbDefense.structure.hitpoints * defense.amount;
|
||||
return acc;
|
||||
}, { attack: 0, defense: 0, hitpoints: 0 });
|
||||
|
||||
const enemyStats = enemyFleet.reduce((acc, ship) => {
|
||||
const dbShip = allShips.find(s => s.id === ship.id);
|
||||
if(!dbShip) return acc;
|
||||
|
@ -226,7 +190,7 @@ export default class FleetManager {
|
|||
acc.defense += dbShip.structure.defense * ship.amount;
|
||||
acc.hitpoints += dbShip.structure.hitpoints * ship.amount;
|
||||
return acc;
|
||||
}, enemyDefensesStats);
|
||||
}, { attack: 0, defense: 0, hitpoints: 0 });
|
||||
|
||||
const playerShipsStructure: BattleFleet[] = [];
|
||||
for(const playerShip of this.data.ships) {
|
||||
|
@ -318,12 +282,10 @@ export default class FleetManager {
|
|||
} else this.data.ships = [];
|
||||
|
||||
await this.sendMail(
|
||||
this.data.source instanceof SystemManager ? this.data.source.data.ownedBy.id : this.data.source.system.data.ownedBy.id,
|
||||
`Battle Results (${playerBalance > enemyBalance ? "Victory" : playerBalance < enemyBalance ? "Defeat" : "Draw"})`,
|
||||
`Results of battle at ${(this.data.destination instanceof SystemManager ? this.data.destination.data.name : this.data.destination.name)}:\n
|
||||
Player ships:\n${previousShips.map(ship => `${ship.amount} ${ship.id}`).join('\n')}\n
|
||||
Enemy ships:\n${enemyFleet.map(ship => `${ship.amount} ${ship.id}`).join('\n')}\n
|
||||
Enemy defenses:\n${enemyDefenses.map(defense => `${defense.amount} ${defense.id}`).join('\n')}\n
|
||||
Enemy ships:\n${enemyFleet.map(ship => `${ship.amount} ${ship.id}`).join('\n')}\n\n
|
||||
Player stats: ${playerStats.hitpoints} HP, ${playerStats.attack} ATK, ${playerStats.defense} DEF\n
|
||||
Enemy stats: ${enemyStats.hitpoints} HP, ${enemyStats.attack} ATK, ${enemyStats.defense} DEF\n\n
|
||||
Player ships left:\n${Object.keys(playerShipsLeft).map(key => `${key} - ${playerShipsLeft[key]}`).join('\n')}\n
|
||||
|
@ -331,22 +293,6 @@ export default class FleetManager {
|
|||
${playerBalance > enemyBalance ? `Resources stolen:\n${resourcesStolen.map(res => `${res.id} - ${res.amount}`).join('\n')}` : ""}`
|
||||
);
|
||||
|
||||
if(!("expedition" in this.data.destination)) {
|
||||
await this.sendMail(
|
||||
this.data.destination instanceof SystemManager ? this.data.destination.data.ownedBy.id : this.data.destination.system.data.ownedBy.id,
|
||||
`Battle Results (${playerBalance < enemyBalance ? "Victory" : playerBalance > enemyBalance ? "Defeat" : "Draw"})`,
|
||||
`Results of battle at ${(this.data.destination instanceof SystemManager ? this.data.destination.data.name : this.data.destination.name)}:\n
|
||||
Enemy ships:\n${previousShips.map(ship => `${ship.amount} ${ship.id}`).join('\n')}\n
|
||||
Player ships:\n${enemyFleet.map(ship => `${ship.amount} ${ship.id}`).join('\n')}\n
|
||||
Player defenses:\n${enemyDefenses.map(defense => `${defense.amount} ${defense.id}`).join('\n')}\n
|
||||
Enemy stats: ${playerStats.hitpoints} HP, ${playerStats.attack} ATK, ${playerStats.defense} DEF\n
|
||||
Player stats: ${enemyStats.hitpoints} HP, ${enemyStats.attack} ATK, ${enemyStats.defense} DEF\n\n
|
||||
Enemy ships left:\n${Object.keys(playerShipsLeft).map(key => `${key} - ${playerShipsLeft[key]}`).join('\n')}\n
|
||||
Player ships left:\n${Object.keys(enemyShipsLeft).map(key => `${key} - ${enemyShipsLeft[key]}`).join('\n')}\n
|
||||
${playerBalance > enemyBalance ? `Resources stolen:\n${resourcesStolen.map(res => `${res.id} - ${res.amount}`).join('\n')}` : ""}`
|
||||
);
|
||||
}
|
||||
|
||||
return !(playerShipsStructure.length > 0);
|
||||
}
|
||||
|
||||
|
@ -363,7 +309,7 @@ export default class FleetManager {
|
|||
|
||||
if(expeditionRandom < 0.02) { // 2% chance; lost all ships, black hole
|
||||
this.data.ships = [];
|
||||
await this.sendMail(this.data.source instanceof SystemManager ? this.data.source.data.ownedBy.id : this.data.source.system.data.ownedBy.id, "Expedition Results", `Your expedition to ${(this.data.destination as Sector).name} sector encountered a black hole. All ships were lost.`);
|
||||
await this.sendMail("Expedition Results", `Your expedition to ${(this.data.destination as Sector).name} sector encountered a black hole. All ships were lost.`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -378,7 +324,7 @@ export default class FleetManager {
|
|||
else ship.amount += s.amount;
|
||||
}
|
||||
|
||||
await this.sendMail(this.data.source instanceof SystemManager ? this.data.source.data.ownedBy.id : this.data.source.system.data.ownedBy.id, "Expedition Results", `Your expedition to ${(this.data.destination as Sector).name} sector encountered abandoned shipyard. Following ships were added to the fleet:\n${ships.map(s => `${s.id} - ${s.amount}`).join(', ')}`);
|
||||
await this.sendMail("Expedition Results", `Your expedition to ${(this.data.destination as Sector).name} sector encountered abandoned shipyard. Following ships were added to the fleet:\n${ships.map(s => `${s.id} - ${s.amount}`).join(', ')}`);
|
||||
await this.initiateReturn();
|
||||
return;
|
||||
}
|
||||
|
@ -410,7 +356,7 @@ export default class FleetManager {
|
|||
else resource.amount += res.amount;
|
||||
}
|
||||
|
||||
await this.sendMail(this.data.source instanceof SystemManager ? this.data.source.data.ownedBy.id : this.data.source.system.data.ownedBy.id, "Expedition Results", `Your expedition to ${(this.data.destination as Sector).name} sector encountered resource-rich asteroid. Following resources were added to the cargo inventory:\n${resources.map(r => `${r.id} - ${r.amount}`).join('\n')}`);
|
||||
await this.sendMail("Expedition Results", `Your expedition to ${(this.data.destination as Sector).name} sector encountered resource-rich asteroid. Following resources were added to the cargo inventory:\n${resources.map(r => `${r.id} - ${r.amount}`).join('\n')}`);
|
||||
await this.initiateReturn();
|
||||
return;
|
||||
}
|
||||
|
@ -421,7 +367,7 @@ export default class FleetManager {
|
|||
{ id: 'transporter', amount: getRandomInRange(0, 100) + valueAdded }
|
||||
];
|
||||
|
||||
await this.sendMail(this.data.source instanceof SystemManager ? this.data.source.data.ownedBy.id : this.data.source.system.data.ownedBy.id, "Expedition Results", `Your expedition to ${(this.data.destination as Sector).name} sector encountered drunk pirates. After attempting to communicate with them, they attacked your fleet.`)
|
||||
await this.sendMail("Expedition Results", `Your expedition to ${(this.data.destination as Sector).name} sector encountered drunk pirates. After attempting to communicate with them, they attacked your fleet.`)
|
||||
await this.battleResults(pirates);
|
||||
return;
|
||||
}
|
||||
|
@ -470,12 +416,12 @@ export default class FleetManager {
|
|||
else resource.amount += res.amount;
|
||||
}
|
||||
|
||||
await this.sendMail(this.data.source instanceof SystemManager ? this.data.source.data.ownedBy.id : this.data.source.system.data.ownedBy.id, "Expedition Results", `Your expedition to ${(this.data.destination as Sector).name} sector encountered resource-rich rouge planet. Your fleet could not extract all resources. Following resources were added to the cargo inventory:\n${addedResources.map(r => `${r.id} - ${r.amount}`).join('\n')}`);
|
||||
await this.sendMail("Expedition Results", `Your expedition to ${(this.data.destination as Sector).name} sector encountered resource-rich rouge planet. Your fleet could not extract all resources. Following resources were added to the cargo inventory:\n${addedResources.map(r => `${r.id} - ${r.amount}`).join('\n')}`);
|
||||
await this.initiateReturn();
|
||||
return;
|
||||
}
|
||||
|
||||
await this.sendMail(this.data.source instanceof SystemManager ? this.data.source.data.ownedBy.id : this.data.source.system.data.ownedBy.id, "Expedition Results", `Your expedition to ${(this.data.destination as Sector).name} sector scanned the sector for a long time, yet it haven't found anything.`);
|
||||
await this.sendMail("Expedition Results", `Your expedition to ${(this.data.destination as Sector).name} sector scanned the sector for a long time, yet it haven't found anything.`);
|
||||
await this.initiateReturn();
|
||||
return;
|
||||
}
|
||||
|
@ -493,8 +439,7 @@ export default class FleetManager {
|
|||
returning: this.data.returning,
|
||||
mission: this.data.mission,
|
||||
ships: this.data.ships,
|
||||
cargo: this.data.cargo,
|
||||
additionalData: this.data.additionalData
|
||||
cargo: this.data.cargo
|
||||
}
|
||||
|
||||
await updateFleet(data);
|
||||
|
|
|
@ -94,8 +94,7 @@ class LocationManager {
|
|||
resources: null,
|
||||
//@ts-ignore
|
||||
ships: null,
|
||||
planets: [],
|
||||
asteroids: [],
|
||||
planets: []
|
||||
};
|
||||
|
||||
const s = await new SystemManager(systemObject).fillData(systemData);
|
||||
|
@ -140,8 +139,7 @@ class LocationManager {
|
|||
fleet.returning,
|
||||
fleet.mission,
|
||||
fleet.ships,
|
||||
fleet.cargo,
|
||||
fleet.additionalData
|
||||
fleet.cargo
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
import { updatePlanetDefenses } from "../../db/planets";
|
||||
import { Planet } from "./PlanetManager";
|
||||
import DefenseManager from "./abstract/DefenseManager";
|
||||
|
||||
export default class PlanetDefenseManager extends DefenseManager {
|
||||
constructor(planet: Planet) {
|
||||
super(planet);
|
||||
}
|
||||
|
||||
get manager() {
|
||||
return this._manager as Planet;
|
||||
}
|
||||
|
||||
async sync() {
|
||||
await updatePlanetDefenses(this.manager._id, this.defenses.map(def => { return { id: def.data.id, amount: def.amount } }));
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
import { Planet } from "./PlanetManager";
|
||||
import EnergyManager from "./abstract/EnergyManager";
|
||||
|
||||
export default class PlanetEnergyManager extends EnergyManager {
|
||||
constructor(system: Planet) {
|
||||
super(system);
|
||||
}
|
||||
|
||||
get manager() {
|
||||
return this._manager as Planet;
|
||||
}
|
||||
|
||||
update() {
|
||||
const buildings = this.manager.buildings.buildings;
|
||||
|
||||
this.production = 0;
|
||||
this.consumption = 0;
|
||||
|
||||
for(const building of buildings) {
|
||||
if(building.data.category === "power-plants") {
|
||||
this.production += (building.data.energy * building.level);
|
||||
} else {
|
||||
this.consumption += (building.data.energy * building.level);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -3,8 +3,6 @@ import BuildingManager from "./BuildingManager";
|
|||
import PlanetResourceManager from "./PlanetResourceManager";
|
||||
import ShipManager from "./PlanetShipManager";
|
||||
import SystemManager from "./SystemManager";
|
||||
import PlanetDefenseManager from "./PlanetDefenseManager";
|
||||
import PlanetEnergyManager from "./PlanetEnergyManager";
|
||||
|
||||
export type Planet = {
|
||||
_id: ObjectId;
|
||||
|
@ -14,6 +12,4 @@ export type Planet = {
|
|||
resources: PlanetResourceManager;
|
||||
buildings: BuildingManager;
|
||||
ships: ShipManager;
|
||||
defenses: PlanetDefenseManager;
|
||||
energy: PlanetEnergyManager;
|
||||
}
|
|
@ -91,33 +91,6 @@ export default class PlanetResourceManager extends ResourceManager {
|
|||
return this;
|
||||
}
|
||||
|
||||
getStorageCapacities() {
|
||||
const mapStorageToResource: { [key: string]: string } = {
|
||||
"coal-storage": "coal",
|
||||
"iron-storage": "iron",
|
||||
"gold-storage": "gold",
|
||||
"water-tank": "water",
|
||||
"acid-tank": "sulfuric-acid",
|
||||
"nitrogen-tank": "liquid-nitrogen",
|
||||
"hydrogen-tank": "hydrogen",
|
||||
"oxygen-tank": "oxygen",
|
||||
"helium3-tank": "helium-3",
|
||||
}
|
||||
|
||||
const output: { id: string, capacity: number }[] = [];
|
||||
|
||||
for(const building of this.planet.buildings.buildings) {
|
||||
if(building.data.category === 'storage') {
|
||||
const resource = mapStorageToResource[building.data.id];
|
||||
if(resource) {
|
||||
output.push({ id: resource, capacity: building.level * 10_000 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
async sync() {
|
||||
await updatePlanetResources(this.planet._id, this.resources.map(res => {
|
||||
return {
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
import { updateSystemDefenses } from "../../db/systems";
|
||||
import SystemManager from "./SystemManager";
|
||||
import DefenseManager from "./abstract/DefenseManager";
|
||||
|
||||
export default class SystemDefenseManager extends DefenseManager {
|
||||
constructor(system: SystemManager) {
|
||||
super(system);
|
||||
}
|
||||
|
||||
get manager() {
|
||||
return this._manager as SystemManager;
|
||||
}
|
||||
|
||||
async sync() {
|
||||
await updateSystemDefenses(this.manager.data._id, this.defenses.map(def => { return { id: def.data.id, amount: def.amount } }));
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
import EnergyManager from "./abstract/EnergyManager";
|
||||
import SystemManager from "./SystemManager";
|
||||
|
||||
export default class SystemEnergyManager extends EnergyManager {
|
||||
constructor(system: SystemManager) {
|
||||
super(system);
|
||||
}
|
||||
|
||||
get manager() {
|
||||
return this._manager as SystemManager;
|
||||
}
|
||||
|
||||
update() {
|
||||
const structures = this.manager.structures.structures;
|
||||
|
||||
for(const structure of structures) {
|
||||
if(structure.data.id === "dyson-sphere") {
|
||||
this.production += (structure.data.energy * structure.level);
|
||||
} else {
|
||||
this.consumption += (structure.data.energy * structure.level);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import { ObjectId, UUID } from "mongodb";
|
||||
import { ObjectId } from "mongodb";
|
||||
import DBSystem from "../../../types/db/DBSystem";
|
||||
import { getPlanetById } from "../../db/planets";
|
||||
import User from "../User";
|
||||
|
@ -10,12 +10,6 @@ import PlanetShipManager from "./PlanetShipManager";
|
|||
import StructureManager from "./StructureManager";
|
||||
import SystemResourceManager from "./SystemResourceManager";
|
||||
import SystemShipManager from "./SystemShipManager";
|
||||
import PlanetDefenseManager from "./PlanetDefenseManager";
|
||||
import SystemDefenseManager from "./SystemDefenseManager";
|
||||
import SystemEnergyManager from "./SystemEnergyManager";
|
||||
import PlanetEnergyManager from "./PlanetEnergyManager";
|
||||
import AsteroidManager from "./AsteroidManager";
|
||||
import Asteroid from "../../../types/Asteroid";
|
||||
|
||||
export type System = {
|
||||
_id: ObjectId,
|
||||
|
@ -25,9 +19,7 @@ export type System = {
|
|||
structures: StructureManager,
|
||||
resources: SystemResourceManager,
|
||||
ships: SystemShipManager,
|
||||
defenses: SystemDefenseManager,
|
||||
planets: Planet[];
|
||||
asteroids: Asteroid[];
|
||||
}
|
||||
|
||||
export default class SystemManager {
|
||||
|
@ -35,9 +27,6 @@ export default class SystemManager {
|
|||
structures: StructureManager;
|
||||
resources: SystemResourceManager;
|
||||
ships: SystemShipManager;
|
||||
defenses: SystemDefenseManager;
|
||||
energy: SystemEnergyManager;
|
||||
asteroids: AsteroidManager;
|
||||
data: System;
|
||||
|
||||
constructor(data: System) {
|
||||
|
@ -45,18 +34,12 @@ export default class SystemManager {
|
|||
this.structures = new StructureManager(this);
|
||||
this.resources = new SystemResourceManager(this);
|
||||
this.ships = new SystemShipManager(this);
|
||||
this.defenses = new SystemDefenseManager(this);
|
||||
this.energy = new SystemEnergyManager(this);
|
||||
this.asteroids = new AsteroidManager(this);
|
||||
}
|
||||
|
||||
async fillData(systemData: DBSystem) {
|
||||
await this.structures.init(systemData.structures);
|
||||
await this.resources.init(systemData.resources);
|
||||
await this.ships.init(systemData.ships);
|
||||
await this.defenses.init(systemData.defenses);
|
||||
this.asteroids.init(systemData.asteroids);
|
||||
this.energy.update();
|
||||
|
||||
await Promise.all(systemData.planets.map(async planetId => {
|
||||
const planet = await getPlanetById(planetId);
|
||||
|
@ -71,18 +54,12 @@ export default class SystemManager {
|
|||
//@ts-ignore
|
||||
buildings: null,
|
||||
//@ts-ignore
|
||||
ships: null,
|
||||
//@ts-ignore
|
||||
defenses: null,
|
||||
//@ts-ignore
|
||||
energy: null
|
||||
ships: null
|
||||
}
|
||||
|
||||
planetObject.resources = await new PlanetResourceManager(planetObject).init(planet.resources);
|
||||
planetObject.buildings = await new BuildingManager(planetObject).init(planet.buildings);
|
||||
planetObject.ships = await new PlanetShipManager(planetObject).init(planet.ships);
|
||||
planetObject.defenses = await new PlanetDefenseManager(planetObject).init(planet.defenses);
|
||||
planetObject.energy = new PlanetEnergyManager(planetObject).update();
|
||||
|
||||
this.planets.push(planetObject);
|
||||
}));
|
||||
|
|
|
@ -73,14 +73,7 @@ export default class SystemResourceManager extends ResourceManager {
|
|||
return this;
|
||||
}
|
||||
|
||||
getStorageCapacities(): { id: string; capacity: number; }[] {
|
||||
return this.resources.map(res => {
|
||||
return {
|
||||
id: res.id,
|
||||
capacity: 10_000 //TODO: add structure for storage
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
async sync() {
|
||||
await updateSystemResources(this.system.data._id, this.resources.map(res => {
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
import { Planet } from '../PlanetManager';
|
||||
import SystemManager from '../SystemManager';
|
||||
import Defense from '../../Defense';
|
||||
import DBDefenses from '../../../../types/db/DBDefenses';
|
||||
import { getAllDefenses } from '../../../db/defenses';
|
||||
|
||||
export default abstract class DefenseManager {
|
||||
defenses: Array<Defense> = [];
|
||||
defensesDB: Array<DBDefenses> = [];
|
||||
protected _manager: Planet | SystemManager;
|
||||
|
||||
constructor(manager: Planet | SystemManager) {
|
||||
this._manager = manager;
|
||||
}
|
||||
|
||||
abstract sync(): Promise<void>;
|
||||
|
||||
abstract get manager(): Planet | SystemManager;
|
||||
|
||||
async init(defenseData: { id: string, amount: number }[]) {
|
||||
this.defensesDB = await getAllDefenses();
|
||||
|
||||
for(const def of defenseData) {
|
||||
const defToFind = this.defensesDB.find(d => d.id === def.id);
|
||||
|
||||
if(defToFind) this.defenses.push(new Defense(
|
||||
this,
|
||||
defToFind,
|
||||
def.amount
|
||||
))
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
getDefenseById(id: string) {
|
||||
return this.defenses.find(def => def.data.id === id);
|
||||
}
|
||||
|
||||
addDefenses(id: string, amount: number) {
|
||||
const findDef = this.defenses.find(d => d.data.id === id);
|
||||
if(!findDef) {
|
||||
const defData = this.defensesDB.find(d => d.id === id);
|
||||
if(!defData) return;
|
||||
|
||||
this.defenses.push(new Defense(
|
||||
this,
|
||||
defData,
|
||||
amount
|
||||
));
|
||||
}
|
||||
else findDef.amount += amount;
|
||||
}
|
||||
|
||||
removeDefenses(id: string, amount: number) {
|
||||
const findDef = this.defenses.find(d => d.data.id === id);
|
||||
if(findDef) {
|
||||
findDef.amount -= amount;
|
||||
if(findDef.amount <= 0) this.defenses.splice(this.defenses.indexOf(findDef), 1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
import { Planet } from "../PlanetManager";
|
||||
import SystemManager from "../SystemManager";
|
||||
|
||||
export default abstract class EnergyManager {
|
||||
protected _manager: Planet | SystemManager;
|
||||
production: number = 0;
|
||||
consumption: number = 0;
|
||||
|
||||
constructor(manager: Planet | SystemManager) {
|
||||
this._manager = manager;
|
||||
}
|
||||
|
||||
abstract update(): this;
|
||||
}
|
|
@ -14,23 +14,17 @@ export default abstract class ResourceManager {
|
|||
|
||||
abstract sync(): Promise<void>;
|
||||
|
||||
abstract getStorageCapacities(): { id: string, capacity: number }[];
|
||||
|
||||
getResourceById(resId: string) {
|
||||
return this.resources.find(res => res.id === resId);
|
||||
}
|
||||
|
||||
async calculateCurrentAvailableResources() {
|
||||
const storage = this.getStorageCapacities();
|
||||
for(const res of this.resources) {
|
||||
if(!res.lastUpdated || !res.perHourMiningRate) continue;
|
||||
|
||||
const maxStorage = 10_000 + (storage.find(s => s.id === res.id)?.capacity ?? 0);
|
||||
const timeDiff = Math.abs((new Date()).getTime() - res.lastUpdated.getTime());
|
||||
const hours = timeDiff / (1000 * 60 * 60);
|
||||
let amountToAdd = hours * res.perHourMiningRate;
|
||||
if(res.amount + amountToAdd > maxStorage) amountToAdd = Math.max(0, maxStorage - res.amount);
|
||||
|
||||
const amountToAdd = hours * res.perHourMiningRate;
|
||||
res.amount += amountToAdd;
|
||||
res.lastUpdated = new Date();
|
||||
};
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
import DBDefenses from '../../types/db/DBDefenses';
|
||||
import { Defenses } from '../db/mongodb';
|
||||
|
||||
export const getAllDefenses = async () => {
|
||||
return (await Defenses()).find({}).toArray() as unknown as Array<DBDefenses>;
|
||||
}
|
||||
|
||||
export const getDefenseById = async (id: string) => {
|
||||
return (await Defenses()).findOne({
|
||||
id
|
||||
}) as unknown as DBDefenses;
|
||||
}
|
|
@ -8,7 +8,6 @@ export const getLang = async (language = "en") => {
|
|||
ships: (await lang[2].find({}).toArray()).map(({ _id, ...rest }) => rest),
|
||||
resources: (await lang[3].find({}).toArray()).map(({ _id, ...rest }) => rest),
|
||||
research: (await lang[4].find({}).toArray()).map(({ _id, ...rest }) => rest),
|
||||
structures: (await lang[5].find({}).toArray()).map(({ _id, ...rest }) => rest),
|
||||
defenses: (await lang[6].find({}).toArray()).map(({ _id, ...rest }) => rest)
|
||||
structures: (await lang[5].find({}).toArray()).map(({ _id, ...rest }) => rest)
|
||||
}
|
||||
}
|
|
@ -67,11 +67,6 @@ export const Ships = async() => {
|
|||
return db.collection('ships');
|
||||
}
|
||||
|
||||
export const Defenses = async() => {
|
||||
const db = await getDB();
|
||||
return db.collection('defenses');
|
||||
}
|
||||
|
||||
export const Fleet = async() => {
|
||||
const db = await getDB();
|
||||
return db.collection('fleet');
|
||||
|
@ -90,8 +85,7 @@ export const Lang = async (language = "en") => {
|
|||
await db.collection('ships'),
|
||||
await db.collection('resources'),
|
||||
await db.collection('research'),
|
||||
await db.collection('structures'),
|
||||
await db.collection('defenses')
|
||||
await db.collection('structures')
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -41,12 +41,3 @@ export const updatePlanetShips = async (planetId: ObjectId, ships: Array<{ id: s
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
export const updatePlanetDefenses = async (planetId: ObjectId, defenses: Array<{ id: string, amount: number }>) => {
|
||||
const planets = await Planets();
|
||||
await planets.updateOne({ _id: planetId }, {
|
||||
$set: {
|
||||
defenses
|
||||
}
|
||||
});
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
import { ObjectId } from "mongodb";
|
||||
import { Systems } from "./mongodb";
|
||||
import DBSystem from "../../types/db/DBSystem";
|
||||
import Asteroid from "../../types/Asteroid";
|
||||
|
||||
export const getAllSystems = async () => {
|
||||
return await (await Systems()).find({}).toArray() as DBSystem[];
|
||||
|
@ -44,21 +43,3 @@ export const updateSystemShips = async (systemId: ObjectId, ships: Array<any>) =
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
export const updateSystemDefenses = async (systemId: ObjectId, defenses: Array<any>) => {
|
||||
const systems = await Systems();
|
||||
await systems.updateOne({ _id: systemId }, {
|
||||
$set: {
|
||||
defenses
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export const updateSystemAsteroids = async (systemId: ObjectId, asteroids: Array<Asteroid>) => {
|
||||
const systems = await Systems();
|
||||
await systems.updateOne({ _id: systemId }, {
|
||||
$set: {
|
||||
asteroids
|
||||
}
|
||||
});
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
export default function parseParams(url: string) {
|
||||
const rawParams = url.split("?")[1]?.split("&");
|
||||
if(typeof rawParams === "undefined") return {};
|
||||
if(typeof rawParams === "undefined") return [];
|
||||
const params: { [key: string]: any } = {};
|
||||
for(const rawParam of rawParams) {
|
||||
const k = rawParam.split("=")[0];
|
||||
|
|
|
@ -115,7 +115,6 @@ export const POST: APIRoute = async({ request }) => {
|
|||
|
||||
await userPlanet.buildings.sync();
|
||||
await userPlanet.resources.sync();
|
||||
userPlanet.energy.update();
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
|
|
|
@ -1,146 +0,0 @@
|
|||
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 { getAllResources } from "../../../lib/db/resources";
|
||||
import Defense from "../../../lib/classes/Defense";
|
||||
import { Planet } from "../../../lib/classes/managers/PlanetManager";
|
||||
import SystemManager from "../../../lib/classes/managers/SystemManager";
|
||||
|
||||
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 }
|
||||
)
|
||||
}
|
||||
|
||||
if(!body.id || !body.defense || !body.amount) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
code: 400,
|
||||
message: "Bad Request",
|
||||
error: "Missing required fields: id, defense, amount"
|
||||
}), { status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
const amount = parseInt(body.amount);
|
||||
if(isNaN(amount) || amount <= 0) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
code: 400,
|
||||
message: "Bad Request",
|
||||
error: "Invalid amount"
|
||||
}), { status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
let id: ObjectId;
|
||||
|
||||
try {
|
||||
id = new ObjectId(body.id);
|
||||
} catch(e) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
code: 400,
|
||||
message: "Bad Request",
|
||||
error: "Invalid ID"
|
||||
}), { status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
let planetOrSystem: Planet | SystemManager | undefined = locationManager.getPlanet(id);
|
||||
if(!planetOrSystem) planetOrSystem = locationManager.getSystem(id);
|
||||
if(!planetOrSystem) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
code: 400,
|
||||
message: "Bad Request",
|
||||
error: "Invalid ID"
|
||||
}), { status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
const defenseDB = planetOrSystem.defenses.defensesDB.find(d => d.id === body.defense);
|
||||
|
||||
if(!defenseDB) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
code: 400,
|
||||
message: "Bad Request",
|
||||
error: "Invalid defense ID"
|
||||
}), { status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
const defense = new Defense(planetOrSystem.defenses, defenseDB, amount);
|
||||
|
||||
const requirements = await defense.checkRequirements();
|
||||
const resources = await defense.checkRequiredResources();
|
||||
|
||||
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 planetOrSystem.resources.getDifference(defense.data.requirements.resources.map(res => {
|
||||
return {
|
||||
id: res.id,
|
||||
amount: amount * 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
|
||||
}
|
||||
});
|
||||
|
||||
planetOrSystem.resources.updateAmount(resourcesAfter.map(res => { return { id: res.id, amount: res.amount } }));
|
||||
planetOrSystem.defenses.addDefenses(defense.data.id, amount);
|
||||
|
||||
await planetOrSystem.defenses.sync();
|
||||
await planetOrSystem.resources.sync();
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
code: 200,
|
||||
message: "OK"
|
||||
}), { status: 200 }
|
||||
);
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import { APIRoute } from "astro";
|
||||
import validateAccessToken from "../../../lib/utils/validateAccessToken";
|
||||
import { getUserByAccessToken } from "../../../lib/db/users";
|
||||
import { ObjectId, UUID } from "mongodb";
|
||||
import { ObjectId } from "mongodb";
|
||||
import locationManager from "../../../lib/classes/managers/LocationManager";
|
||||
import { getAllShips } from "../../../lib/db/ships";
|
||||
import DBShip from "../../../types/db/DBShip";
|
||||
|
@ -36,7 +36,7 @@ export const POST: APIRoute = async({ request }) => {
|
|||
)
|
||||
}
|
||||
|
||||
let body: { source: string, destination: string, ships: Array<{ id: string, amount: number }>, cargo: Array<{ id: string, amount: number }>, mission: MissionType, currentSystem?: string };
|
||||
let body: { source: string, destination: string, ships: Array<{ id: string, amount: number }>, cargo: Array<{ id: string, amount: number }>, mission: MissionType };
|
||||
try {
|
||||
body = await request.json()
|
||||
} catch(e) {
|
||||
|
@ -64,16 +64,11 @@ export const POST: APIRoute = async({ request }) => {
|
|||
const checkCargoBody = checkCargo(body.cargo, body.ships, source, body.mission);
|
||||
if(typeof checkCargoBody.error !== "undefined") return new Response(JSON.stringify(checkCargoBody), { status: checkCargoBody.code });
|
||||
|
||||
let dest, additionalData;
|
||||
let dest;
|
||||
if(body.mission === "EXPEDITION") {
|
||||
const destinationSector = checkSectorId(body.destination);
|
||||
if(typeof destinationSector.error !== "undefined") return new Response(JSON.stringify(destinationSector), { status: destinationSector.code });
|
||||
dest = destinationSector.sector;
|
||||
} else if(body.mission === "MINE") {
|
||||
const checkAsteroid = checkAsteroidId(body.destination, body.currentSystem ?? "");
|
||||
if(typeof checkAsteroid.error !== "undefined") return new Response(JSON.stringify(checkAsteroid), { status: checkAsteroid.code });
|
||||
dest = checkAsteroid.system;
|
||||
additionalData = checkAsteroid.asteroid;
|
||||
} else {
|
||||
const checkDestination = checkPlanetOrSystemId(body.destination, 'destination');
|
||||
if(typeof checkDestination.error !== "undefined") return new Response(JSON.stringify(checkDestination), { status: checkDestination.code });
|
||||
|
@ -91,8 +86,7 @@ export const POST: APIRoute = async({ request }) => {
|
|||
false,
|
||||
body.mission,
|
||||
body.ships,
|
||||
body.cargo,
|
||||
body.mission === "MINE" ? additionalData?.id.toString() : ""
|
||||
body.cargo
|
||||
);
|
||||
|
||||
const resourceDiff = await source.resources.getDifference(body.cargo.map(c => ({ id: c.id, amount: c.amount })));
|
||||
|
@ -129,7 +123,7 @@ export const POST: APIRoute = async({ request }) => {
|
|||
}
|
||||
|
||||
function checkPlanetOrSystemId(id: string, type: string) {
|
||||
if(typeof id === "undefined") return {
|
||||
if(typeof ObjectId === "undefined") return {
|
||||
code: 400,
|
||||
message: "Bad Request",
|
||||
error: `Missing '${type}' in body`
|
||||
|
@ -161,66 +155,8 @@ function checkPlanetOrSystemId(id: string, type: string) {
|
|||
}
|
||||
}
|
||||
|
||||
function checkAsteroidId(id: string, systemId: string) {
|
||||
if(typeof id === "undefined") return {
|
||||
code: 400,
|
||||
message: "Bad Request",
|
||||
error: `Missing 'destination' in body`
|
||||
}
|
||||
|
||||
if(systemId === "") return {
|
||||
code: 400,
|
||||
message: "Bad Request",
|
||||
error: "Missing 'currentSystem' in body"
|
||||
}
|
||||
|
||||
let idToCheck;
|
||||
try {
|
||||
idToCheck = new UUID(id);
|
||||
} catch(e) {
|
||||
return {
|
||||
code: 400,
|
||||
message: "Bad Request",
|
||||
error: `Invalid UUID in 'destination'`
|
||||
}
|
||||
}
|
||||
|
||||
let systemObjectId;
|
||||
try {
|
||||
systemObjectId = new ObjectId(systemId);
|
||||
} catch(e) {
|
||||
return {
|
||||
code: 400,
|
||||
message: "Bad Request",
|
||||
error: "Invalid ID in 'currentSystem'"
|
||||
}
|
||||
}
|
||||
|
||||
const system = locationManager.getSystem(systemObjectId);
|
||||
|
||||
if(!system) return {
|
||||
code: 404,
|
||||
message: "Not Found",
|
||||
error: `Non-existent system provided in 'currentSystem'`
|
||||
}
|
||||
|
||||
const asteroid = system.asteroids.asteroids.find(asteroid => asteroid.id.equals(idToCheck));
|
||||
if(!asteroid) return {
|
||||
code: 404,
|
||||
message: "Not Found",
|
||||
error: "Non-existent asteroid provided in 'destination'"
|
||||
}
|
||||
|
||||
return {
|
||||
code: 200,
|
||||
message: "OK",
|
||||
asteroid,
|
||||
system
|
||||
}
|
||||
}
|
||||
|
||||
function checkSectorId(id: string) {
|
||||
if(typeof id === "undefined") return {
|
||||
if(typeof ObjectId === "undefined") return {
|
||||
code: 400,
|
||||
message: "Bad Request",
|
||||
error: "Missing 'sector' in body"
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
import { type APIRoute } from "astro";
|
||||
import validateAccessToken from "../../../../lib/utils/validateAccessToken";
|
||||
import { getUserByAccessToken } from "../../../../lib/db/users";
|
||||
import locationManager from "../../../../lib/classes/managers/LocationManager";
|
||||
import { ObjectId, UUID } from "mongodb";
|
||||
import Asteroid from "../../../../types/Asteroid";
|
||||
|
||||
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 }
|
||||
)
|
||||
}
|
||||
|
||||
const cookies = request.headers.get("Cookie")?.split(";").map((x) => x.trim().split("=")) ?? [];
|
||||
const systemId = cookies.filter((x) => x[0] === "currentSystem")[0]?.[1];
|
||||
|
||||
const userSystem = locationManager.getSystem(new ObjectId(systemId));
|
||||
|
||||
if(!userSystem) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
code: 400,
|
||||
message: "Bad Request",
|
||||
error: "Invalid system ID"
|
||||
}), { status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
if(userSystem.asteroids.asteroids.length >= 5) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
code: 400,
|
||||
message: "Bad Request",
|
||||
error: "You have reached the maximum number of asteroids in this system"
|
||||
}), { status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
const asteroidUUID = new UUID();
|
||||
const asteroid: Asteroid = {
|
||||
id: asteroidUUID,
|
||||
name: `AS-${asteroidUUID}`,
|
||||
resources: [
|
||||
{
|
||||
id: "coal",
|
||||
amount: Math.floor(Math.random() * 100) + 1
|
||||
}, {
|
||||
id: "iron",
|
||||
amount: Math.floor(Math.random() * 100) + 1
|
||||
}, {
|
||||
id: "gold",
|
||||
amount: Math.floor(Math.random() * 100) + 1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
userSystem.asteroids.asteroids.push(asteroid);
|
||||
await userSystem.asteroids.sync();
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
code: 200,
|
||||
message: "OK",
|
||||
asteroid
|
||||
}), { status: 200 }
|
||||
);
|
||||
}
|
|
@ -1,184 +0,0 @@
|
|||
---
|
||||
import ItemCard from '../../components/ItemCard.astro';
|
||||
import LoggedIn from '../../layouts/LoggedIn.astro';
|
||||
import { Planet } from '../../lib/classes/managers/PlanetManager';
|
||||
import SystemManager from '../../lib/classes/managers/SystemManager';
|
||||
import { getAllDefenses } from '../../lib/db/defenses';
|
||||
import { getObj } from '../../lib/utils/langDriver';
|
||||
|
||||
const { token, lang } = Astro.locals;
|
||||
const active: SystemManager | Planet = Astro.locals.active;
|
||||
|
||||
const defenses = await getAllDefenses();
|
||||
|
||||
if(Astro.request.method === "POST") {
|
||||
const body = await Astro.request.formData();
|
||||
|
||||
const id = body.get("id") as string;
|
||||
const amount = parseInt(body.get("amount") as string ?? "1");
|
||||
|
||||
await fetch(Astro.url.origin + '/api/defenses/add', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + token
|
||||
},
|
||||
body: JSON.stringify({
|
||||
id: active instanceof SystemManager ? active.data._id : active._id,
|
||||
defense: id,
|
||||
amount
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
const modalSet: { [key: string]: { resources: Array<any>, research: Array<any>, buildings: Array<any> } } = {};
|
||||
|
||||
for(const def of defenses) {
|
||||
modalSet[def.id] = {
|
||||
resources: def.requirements.resources,
|
||||
research: def.requirements.research,
|
||||
buildings: def.requirements.buildings,
|
||||
// energy: building.energy
|
||||
};
|
||||
}
|
||||
|
||||
const planetId = active instanceof SystemManager ? active.data._id : active._id;
|
||||
---
|
||||
<LoggedIn id="defenses" title="Defenses">
|
||||
<div id="ship-modal-background">
|
||||
<div id="ship-modal-details" data-building-id="">
|
||||
<h3>Required resources</h3>
|
||||
<div class="ship-modal-text" id="ship-modal-req-resources">None</div>
|
||||
<h3>Required buildings</h3>
|
||||
<div class="ship-modal-text" id="ship-modal-req-buildings">None</div>
|
||||
<h3>Required research</h3>
|
||||
<div class="ship-modal-text" id="ship-modal-req-research">None</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ship-cards">
|
||||
{defenses.map(def => <>
|
||||
<ItemCard
|
||||
category="ships"
|
||||
id={def.id}
|
||||
name={getObj(lang, "defenses", def.id).name}
|
||||
level={active.defenses.getDefenseById(def.id)?.amount.toString() ?? "0"}
|
||||
description={getObj(lang, "defenses", def.id).description ?? ""}
|
||||
image={`/images/defenses/${def.id}.png`}
|
||||
button_type="general"
|
||||
button_name="nav-build"
|
||||
has_amount_input="true" />
|
||||
</>)}
|
||||
</div>
|
||||
</LoggedIn>
|
||||
|
||||
<style>
|
||||
.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;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
<script define:vars={{ modalSet, lang, planetId }}>
|
||||
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';
|
||||
|
||||
const reqResources = modalSet[el.parentElement.parentElement.parentElement.dataset.id]?.resources ?? [];
|
||||
const reqBuildings = modalSet[el.parentElement.parentElement.parentElement.dataset.id]?.buildings ?? [];
|
||||
const reqResearch = modalSet[el.parentElement.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('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("item-card-build");
|
||||
|
||||
for(const shipButton of allButtons) {
|
||||
shipButton.addEventListener("click", async () => {
|
||||
const id = shipButton.id.split("_")[1];
|
||||
|
||||
const response = await fetch('/api/ships/addShip', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
planet: planetId,
|
||||
ship: id,
|
||||
amount: 1
|
||||
})
|
||||
});
|
||||
|
||||
if(response.status === 200) {
|
||||
window.location.reload();
|
||||
} else {
|
||||
alert("Failed to build ship: " + JSON.stringify(await response.json()));
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
|
@ -1,162 +0,0 @@
|
|||
---
|
||||
import LoggedIn from '../../layouts/LoggedIn.astro';
|
||||
import { Planet } from '../../lib/classes/managers/PlanetManager';
|
||||
import SystemManager from '../../lib/classes/managers/SystemManager';
|
||||
|
||||
const { token, lang } = Astro.locals;
|
||||
const active: SystemManager | Planet = Astro.locals.active;
|
||||
|
||||
if(active instanceof SystemManager) {
|
||||
return Astro.redirect('/game');
|
||||
}
|
||||
|
||||
if(Astro.request.method === "POST") {
|
||||
const body = await Astro.request.formData();
|
||||
|
||||
for(const [key, value] of body.entries()) {
|
||||
console.log(key, value);
|
||||
}
|
||||
|
||||
return Astro.redirect('/game/energy');
|
||||
}
|
||||
|
||||
const buildingsList = {
|
||||
"mines": active.buildings.buildings.filter(building => building.data.category === "mines"),
|
||||
"powerPlants": active.buildings.buildings.filter(building => building.data.category === "power-plants"),
|
||||
"utilities": active.buildings.buildings.filter(building => building.data.category === "utilities"),
|
||||
"storage": active.buildings.buildings.filter(building => building.data.category === "storage")
|
||||
}
|
||||
---
|
||||
<LoggedIn id="energy" title="Energy">
|
||||
<form method="post" class="form-container">
|
||||
<table>
|
||||
<tr class="table-col-header">
|
||||
<th>Building name</th>
|
||||
<th>Level</th>
|
||||
<th>Production %</th>
|
||||
<th>Production per hour</th>
|
||||
<th>Energy usage</th>
|
||||
</tr>
|
||||
<tr><td colspan="5" class="table-separator">Mines</td></tr>
|
||||
{buildingsList.mines.map(building => <tr>
|
||||
<td>{building.data.id}</td>
|
||||
<td>{building.level}</td>
|
||||
<td><select name={`percent_${building.data.id}`}>
|
||||
<option value="100" {...{ selected: (building.activePercent ?? 100) === 100 }}>100%</option>
|
||||
<option value="90" {...{ selected: (building.activePercent ?? 100) === 90 }}>90%</option>
|
||||
<option value="80" {...{ selected: (building.activePercent ?? 100) === 80 }}>80%</option>
|
||||
<option value="70" {...{ selected: (building.activePercent ?? 100) === 70 }}>70%</option>
|
||||
<option value="60" {...{ selected: (building.activePercent ?? 100) === 60 }}>60%</option>
|
||||
<option value="50" {...{ selected: (building.activePercent ?? 100) === 50 }}>50%</option>
|
||||
<option value="40" {...{ selected: (building.activePercent ?? 100) === 40 }}>40%</option>
|
||||
<option value="30" {...{ selected: (building.activePercent ?? 100) === 30 }}>30%</option>
|
||||
<option value="20" {...{ selected: (building.activePercent ?? 100) === 20 }}>20%</option>
|
||||
<option value="10" {...{ selected: (building.activePercent ?? 100) === 10 }}>10%</option>
|
||||
<option value="0" {...{ selected: (building.activePercent ?? 100) === 0 }}>0%</option>
|
||||
</select></td>
|
||||
<td>15</td>
|
||||
<td class="red">-{building.level * building.data.energy}</td>
|
||||
</tr>)}
|
||||
<tr><td colspan="5" class="table-separator">Power plants</td></tr>
|
||||
{buildingsList.powerPlants.map(building => <tr>
|
||||
<td>{building.data.id}</td>
|
||||
<td>{building.level}</td>
|
||||
<td><select name={`percent_${building.data.id}`}>
|
||||
<option value="100" {...{ selected: (building.activePercent ?? 100) === 100 }}>100%</option>
|
||||
<option value="90" {...{ selected: (building.activePercent ?? 100) === 90 }}>90%</option>
|
||||
<option value="80" {...{ selected: (building.activePercent ?? 100) === 80 }}>80%</option>
|
||||
<option value="70" {...{ selected: (building.activePercent ?? 100) === 70 }}>70%</option>
|
||||
<option value="60" {...{ selected: (building.activePercent ?? 100) === 60 }}>60%</option>
|
||||
<option value="50" {...{ selected: (building.activePercent ?? 100) === 50 }}>50%</option>
|
||||
<option value="40" {...{ selected: (building.activePercent ?? 100) === 40 }}>40%</option>
|
||||
<option value="30" {...{ selected: (building.activePercent ?? 100) === 30 }}>30%</option>
|
||||
<option value="20" {...{ selected: (building.activePercent ?? 100) === 20 }}>20%</option>
|
||||
<option value="10" {...{ selected: (building.activePercent ?? 100) === 10 }}>10%</option>
|
||||
<option value="0" {...{ selected: (building.activePercent ?? 100) === 0 }}>0%</option>
|
||||
</select></td>
|
||||
<td></td>
|
||||
<td class="green">+{building.level * building.data.energy}</td>
|
||||
</tr>)}
|
||||
<tr><td colspan="5" class="table-separator">Utilities</td></tr>
|
||||
{buildingsList.utilities.map(building => <tr>
|
||||
<td>{building.data.id}</td>
|
||||
<td>{building.level}</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td class="red">-{building.level * building.data.energy}</td>
|
||||
</tr>)}
|
||||
<tr><td colspan="5" class="table-separator">Storage</td></tr>
|
||||
{buildingsList.storage.map(building => <tr>
|
||||
<td>{building.data.id}</td>
|
||||
<td>{building.level}</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td class="red">-{building.level * building.data.energy}</td>
|
||||
</tr>)}
|
||||
</table>
|
||||
<input type="submit" value="Save" class="save-button" />
|
||||
</form>
|
||||
</LoggedIn>
|
||||
<style>
|
||||
.form-container {
|
||||
width: fit-content;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.green {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.red {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.table-col-header {
|
||||
background-color: #444;
|
||||
}
|
||||
|
||||
.table-separator {
|
||||
background-color: #222;
|
||||
font-weight: 1000;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.table-col-header th {
|
||||
border: 1px solid white;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
th {
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
tr {
|
||||
color: white;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 10px;
|
||||
border: 1px solid white;
|
||||
}
|
||||
|
||||
.form-container .save-button {
|
||||
flex-grow: 1;
|
||||
margin-top: 20px;
|
||||
padding: 10px;
|
||||
background-color: #444;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
|
@ -59,11 +59,11 @@ for(const research of researchList) {
|
|||
category="research"
|
||||
id={research.id}
|
||||
name={getObj(lang, "research", research.id).name}
|
||||
level={research.onetime === true ? user.research.getResearchById(research.id)?.level === 1 ? "Researched" : "Not researched" : user.research.getResearchById(research.id)?.level.toString() ?? "0"}
|
||||
level={user.research.getResearchById(research.id)?.level.toString() ?? "0"}
|
||||
description={getObj(lang, "research", research.id).description ?? ""}
|
||||
image={`/images/research/${research.id}.jpeg`}
|
||||
button_type="general"
|
||||
button_name={research.onetime ? user.research.getResearchById(research.id)?.level === 1 ? "nav-researched" : "nav-research" : "nav-research"} />
|
||||
button_name="nav-research" />
|
||||
</>)}
|
||||
</div>
|
||||
</LoggedIn>
|
||||
|
|
|
@ -1,90 +0,0 @@
|
|||
---
|
||||
import { ObjectId } from "mongodb";
|
||||
import LoggedIn from "../../../../layouts/LoggedIn.astro";
|
||||
import locationManager from "../../../../lib/classes/managers/LocationManager";
|
||||
|
||||
const { token, lang } = Astro.locals;
|
||||
|
||||
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');
|
||||
}
|
||||
|
||||
const discoveredAsteroids = currentSystem.asteroids.asteroids;
|
||||
---
|
||||
<LoggedIn id="systemManager" title="System Manager">
|
||||
<h1>Selected system: {currentSystem.data.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>
|
||||
<h2>Avaliable asteroids <button id="scan">Scan for new</button></h2>
|
||||
<div>
|
||||
{discoveredAsteroids.map((asteroid) => <div>
|
||||
<h3>{asteroid.name} <a href={`/game/systemManager/asteroids/send?dest=${asteroid.id}`}>Send</a></h3>
|
||||
<h4>Resources left: </h4>
|
||||
{asteroid.resources.map((resource) => <div><p>{resource.id} - {resource.amount}</p></div>)}
|
||||
</div>)}
|
||||
</div>
|
||||
</div>
|
||||
</LoggedIn>
|
||||
<style>
|
||||
* {
|
||||
color: white;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
color: white;
|
||||
}
|
||||
|
||||
h1 a {
|
||||
color: lime;
|
||||
}
|
||||
|
||||
button, a {
|
||||
color: white;
|
||||
background-color: #555;
|
||||
padding: 0.5rem;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
async function scan() {
|
||||
await fetch('/api/system/asteroids/scan', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
});
|
||||
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
document.getElementById('scan')?.addEventListener('click', scan);
|
||||
</script>
|
|
@ -1,165 +0,0 @@
|
|||
---
|
||||
import { ObjectId } from "mongodb";
|
||||
import ItemCard from "../../../../components/ItemCard.astro";
|
||||
import LoggedIn from "../../../../layouts/LoggedIn.astro";
|
||||
import locationManager from "../../../../lib/classes/managers/LocationManager";
|
||||
import { getName, getObj } from "../../../../lib/utils/langDriver";
|
||||
import parseParams from "../../../../lib/utils/parseParams";
|
||||
import { getAllSystems } from "../../../../lib/db/systems";
|
||||
|
||||
const { user, token, lang } = Astro.locals;
|
||||
|
||||
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 form = await Astro.request.formData();
|
||||
|
||||
const source = form.get('toSystem') ?
|
||||
form.get('source-system')?.toString() :
|
||||
form.get('source-planet')?.toString();
|
||||
|
||||
const fleetData = {
|
||||
source,
|
||||
destination: form.get('asteroid-id')?.toString(),
|
||||
mission: "MINE",
|
||||
ships: [{ id: "asteroid-miner", amount: 1 }],
|
||||
cargo: [],
|
||||
currentSystem: form.get('current-system')?.toString()
|
||||
}
|
||||
|
||||
const response = await fetch(`${Astro.url.origin}/api/fleet/send`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${token}`
|
||||
},
|
||||
body: JSON.stringify(fleetData)
|
||||
});
|
||||
|
||||
console.log(await response.json());
|
||||
|
||||
return Astro.redirect('/game/systemManager/asteroids');
|
||||
}
|
||||
|
||||
const params = parseParams(Astro.request.url);
|
||||
|
||||
const systems = locationManager.getSystemsOwnedBy(user.id).map(sys => { return { id: sys.data._id, name: sys.data.name, hasAsteroidMiner: sys.ships.ships.find(ship => ship.data.id === "asteroid-miner") !== undefined, planets: sys.planets.map(planet => { return { id: planet._id, name: planet.name, hasAsteroidMiner: planet.ships.ships.find(ship => ship.data.id === "asteroid-miner") !== undefined } }) } });
|
||||
---
|
||||
<LoggedIn id="systemManager" title="System Manager">
|
||||
<h1><a href="/game/systemManager/asteroids"><= go back</a>Sending</h1>
|
||||
<form method="post">
|
||||
<input type="hidden" name="asteroid-id" value={params.dest} />
|
||||
<input type="hidden" name="current-system" value={currentSystemId} />
|
||||
<label><input type="checkbox" name="fromSystem" />Send from system</label>
|
||||
<h3>System</h3>
|
||||
<select id="source-system" name="source-system"></select>
|
||||
<h3>Planet</h3>
|
||||
<select id="source-planet" name="source-planet"></select>
|
||||
<hr />
|
||||
<button type="submit">Send fleet</button>
|
||||
</form>
|
||||
</LoggedIn>
|
||||
<style>
|
||||
* {
|
||||
color: white;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
color: white;
|
||||
}
|
||||
|
||||
h1 a {
|
||||
color: lime;
|
||||
}
|
||||
|
||||
button {
|
||||
color: white;
|
||||
background-color: #555;
|
||||
padding: 0.5rem;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.system-links {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
a {
|
||||
color: white;
|
||||
background-color: #555;
|
||||
padding: 0.5rem;
|
||||
margin: 0 1rem;
|
||||
border-radius: 5px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
select {
|
||||
width: 10rem;
|
||||
height: 3rem;
|
||||
color: black;
|
||||
background-color: darkgray;
|
||||
}
|
||||
</style>
|
||||
<script define:vars={{ systems }}>
|
||||
const sourceSystem = document.getElementById('source-system');
|
||||
const sourcePlanet = document.getElementById('source-planet');
|
||||
const fromSystemCheckbox = document.querySelector('input[name="fromSystem"]');
|
||||
|
||||
if(!sourceSystem || !sourcePlanet || !fromSystemCheckbox) {
|
||||
console.error('Could not find all elements');
|
||||
return;
|
||||
}
|
||||
|
||||
for(const system of systems) {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = system.id;
|
||||
opt.innerText = system.hasAsteroidMiner ? system.name : `${system.name} (no miner)`;
|
||||
sourceSystem.appendChild(opt);
|
||||
}
|
||||
|
||||
sourceSystem.addEventListener('change', () => {
|
||||
const system = systems.find(system => system.id === sourceSystem.value);
|
||||
if(!system) {
|
||||
sourcePlanet.innerHTML = '';
|
||||
const opt = document.createElement('option');
|
||||
opt.value = '';
|
||||
opt.innerText = 'No planets';
|
||||
sourcePlanet.appendChild(opt);
|
||||
return;
|
||||
}
|
||||
|
||||
sourcePlanet.innerHTML = '';
|
||||
|
||||
for(const planet of system.planets) {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = planet.id;
|
||||
opt.innerText = planet.hasAsteroidMiner ? planet.name : `${planet.name} (no miner)`;
|
||||
sourcePlanet.appendChild(opt);
|
||||
}
|
||||
|
||||
if(sourcePlanet.children.length === 0) {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = '';
|
||||
opt.innerText = 'No planets';
|
||||
sourcePlanet.appendChild(opt);
|
||||
}
|
||||
});
|
||||
|
||||
sourceSystem.dispatchEvent(new Event('change'));
|
||||
|
||||
fromSystemCheckbox.addEventListener('change', () => {
|
||||
sourcePlanet.disabled = fromSystemCheckbox.checked;
|
||||
});
|
||||
</script>
|
|
@ -1,10 +0,0 @@
|
|||
import { UUID } from "mongodb";
|
||||
|
||||
export default interface Asteroid {
|
||||
id: UUID;
|
||||
name: string;
|
||||
resources: {
|
||||
id: string;
|
||||
amount: number;
|
||||
}[];
|
||||
}
|
|
@ -1,3 +1,3 @@
|
|||
type MissionType = "TRANSPORT" | "ATTACK" | "TRANSFER" | "EXPEDITION" | "MINE";
|
||||
type MissionType = "TRANSPORT" | "ATTACK" | "TRANSFER" | "EXPEDITION";
|
||||
|
||||
export default MissionType;
|
|
@ -1,18 +0,0 @@
|
|||
import { ObjectId } from "mongodb";
|
||||
|
||||
export default interface DBDefenses {
|
||||
_id: ObjectId;
|
||||
id: string;
|
||||
requirements: {
|
||||
buildings: Array<{ id: string, level: number }>,
|
||||
research: Array<{ id: string, level: number }>,
|
||||
resources: Array<{ id: string, amount: number }>,
|
||||
};
|
||||
energy: number;
|
||||
time: number;
|
||||
structure: {
|
||||
hitpoints: number;
|
||||
defense: number;
|
||||
attack: number;
|
||||
};
|
||||
}
|
|
@ -6,7 +6,6 @@ export default interface DBPlanet {
|
|||
owner: ObjectId; // shouldn't be here
|
||||
fields: number;
|
||||
resources: Array<{ id: string, amount: number, lastUpdated: Date, perHourMiningRate: number }>;
|
||||
buildings: Array<{ id: string, level: number, activePercent?: number }>;
|
||||
buildings: Array<{ id: string, level: number }>;
|
||||
ships: Array<{ id: string, amount: number }>;
|
||||
defenses: Array<{ id: string, amount: number }>;
|
||||
}
|
|
@ -10,5 +10,4 @@ export default interface DBResearch {
|
|||
};
|
||||
time: number;
|
||||
multiplier: number;
|
||||
onetime?: boolean;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import { ObjectId, UUID } from "mongodb";
|
||||
import { ObjectId } from "mongodb";
|
||||
|
||||
export default interface DBSystem {
|
||||
_id: ObjectId;
|
||||
|
@ -17,16 +17,4 @@ export default interface DBSystem {
|
|||
id: string,
|
||||
amount: number
|
||||
}>;
|
||||
defenses: Array<{
|
||||
id: string,
|
||||
amount: number
|
||||
}>;
|
||||
asteroids: Array<{
|
||||
id: UUID,
|
||||
name: string,
|
||||
resources: Array<{
|
||||
id: string,
|
||||
amount: number
|
||||
}>
|
||||
}>;
|
||||
}
|