Add planet support

This commit is contained in:
Aelita4 2024-06-18 15:19:52 +02:00
parent 57e87d314b
commit 2304ff48a3
Signed by: Aelita4
GPG Key ID: E44490C2025906C1
14 changed files with 214 additions and 101 deletions

View File

@ -0,0 +1,36 @@
---
import { ObjectId } from 'mongodb';
import { getHighestWeightedLanguage, getLocales } from '../lib/utils/langDriver';
import { getUserWithPlanets } from '../lib/db/users';
import { createPlanet } from '../lib/db/planets';
// await createPlanet({
// name: "BiałePodNapletem2",
// ownerId: new ObjectId(Astro.cookies.get('userid')?.value ?? ""),
// fields: 69
// })
if(!Astro.cookies.get('userid')?.value) return;
const planets = (await getUserWithPlanets(new ObjectId(Astro.cookies.get('userid')?.value ?? "")))?.planets.data;
if(!planets) return;
// console.log(planets);
// const resourceLang = await getLocales(await getHighestWeightedLanguage(Astro.request.headers.get('accept-language')), 'resources');
// const resBarLang = await getLocales(await getHighestWeightedLanguage(Astro.request.headers.get('accept-language')), 'resourcebar');
---
<div id="planetview">
{planets.map(planet => <div>
<b>{planet.name}</b><br />
<p>{planet.fields}</p>
</div>)}
</div>
<style>
#planetview {
color: red;
background-color: pink;
}
</style>

View File

@ -1,6 +1,6 @@
--- ---
import { ObjectId } from 'mongodb'; import { ObjectId } from 'mongodb';
import { calculateCurrentAvailableResources, getUserResources } from '../lib/utils/resourceManager'; import { calculateCurrentAvailableResources } from '../lib/utils/resourceManager';
import { getHighestWeightedLanguage, getLocales } from '../lib/utils/langDriver'; import { getHighestWeightedLanguage, getLocales } from '../lib/utils/langDriver';
import resourceTypes from '../lib/data/resources.json'; import resourceTypes from '../lib/data/resources.json';
@ -8,7 +8,7 @@ import resourceTypes from '../lib/data/resources.json';
const resourceLang = await getLocales(await getHighestWeightedLanguage(Astro.request.headers.get('accept-language')), 'resources'); const resourceLang = await getLocales(await getHighestWeightedLanguage(Astro.request.headers.get('accept-language')), 'resources');
const resBarLang = await getLocales(await getHighestWeightedLanguage(Astro.request.headers.get('accept-language')), 'resourcebar'); const resBarLang = await getLocales(await getHighestWeightedLanguage(Astro.request.headers.get('accept-language')), 'resourcebar');
const resources = await calculateCurrentAvailableResources(new ObjectId(Astro.cookies.get('userid')?.value ?? '')); const resources = await calculateCurrentAvailableResources(new ObjectId(Astro.cookies.get('planetid')?.value ?? ''));
const resourceArray = []; const resourceArray = [];
for(const key in resources) { for(const key in resources) {

View File

@ -1,4 +1,6 @@
--- ---
import PlanetView from '../components/PlanetView.astro';
interface Props { interface Props {
title: string; title: string;
} }
@ -18,6 +20,7 @@ const { title } = Astro.props;
</head> </head>
<body> <body>
<slot /> <slot />
<!-- <PlanetView /> -->
</body> </body>
</html> </html>
<style is:global> <style is:global>

48
src/lib/db/planets.ts Normal file
View File

@ -0,0 +1,48 @@
import { Planets } from '../db/mongodb';
import type User from '../../types/User';
import { ObjectId } from 'mongodb';
import type Planet from '../../types/Planet';
import { getUserById } from './users';
import type Building from '../../types/Building';
import type Ship from '../../types/Ship';
import type DBResource from '../../types/DBResource';
export const getAllPlanets = async (options?: { fetchUserPlanets: boolean }) => {
const planets = await Planets();
const fetched = (await planets.find({}).toArray()).map(async planet => {
planet.owner = await getUserById(planet.owner);
return planet;
})
return Promise.all(fetched) as unknown as Array<Planet>;
}
export const createPlanet = async (options: { name: string, owner?: User, ownerId?: ObjectId, fields?: number }) => {
if(options.owner !== undefined && options.ownerId !== undefined) throw new Error("Duplicate identifier");
let user: ObjectId;
if(options.ownerId) user = options.ownerId;
else if(options.owner) user = options.owner._id;
else throw new Error("Unknown error");
if(options.fields === undefined) options.fields = 20;
//@ts-ignore TODO: find another way of handling IDs from types before inserting to database
const planet = {
owner: user,
name: options.name,
fields: options.fields,
resources: new Array<DBResource>,
buildings: new Array<Building>,
ships: new Array<Ship>
}
await (await Planets()).insertOne(planet);
}
export const getPlanetById = async (id: ObjectId) => {
const planets = await Planets();
return planets.findOne({
_id: id
}) as Promise<Planet | null>;
}

View File

@ -1,13 +1,10 @@
import { Planets, Users } from '../db/mongodb'; import { Planets, Users } from '../db/mongodb';
import type User from '../../types/User'; import type User from '../../types/User';
import type Resources from '../../types/Resources';
import type Building from '../../types/Building';
import type AccessToken from '../../types/AccessToken'; import type AccessToken from '../../types/AccessToken';
import { ObjectId } from 'mongodb'; import { ObjectId } from 'mongodb';
import { hash } from 'argon2' import { hash } from 'argon2'
import { createInitialResources } from '../utils/resourceManager'; import { createInitialResources } from '../utils/resourceManager';
import type Research from '../../types/Research'; import type Research from '../../types/Research';
import type Ship from '../../types/Ship';
export const getAllUsers = async () => { export const getAllUsers = async () => {
const users = await Users(); const users = await Users();
@ -68,36 +65,6 @@ export const updateLastLogin = async (user: User) => {
return users.updateOne({ username: user.username }, { $set: { lastLogin: new Date() } }); return users.updateOne({ username: user.username }, { $set: { lastLogin: new Date() } });
} }
export const getUserBuildings = async (user: User): Promise<Array<Building>> => {
// const users = await Users();
// const user = await users.findOne({ username });
const buildings: Array<Building> = [];
if (user?.buildings !== undefined) {
user?.buildings.forEach((building: Building) => {
buildings.push(building);
});
}
return buildings;
}
export const createOrUpgradeBuilding = async (username: string, building: Building) => {
const users = await Users();
const result = await users.updateOne(
{ username, "buildings.name": building.id },
{ $set: { "buildings.$.level": building.level } }
);
if (result.modifiedCount === 0) {
await users.updateOne({ username },
{ $push: { buildings: building } }
);
}
}
export const getUserResearch = async (user: User): Promise<Array<Research>> => { export const getUserResearch = async (user: User): Promise<Array<Research>> => {
const research: Array<Research> = []; const research: Array<Research> = [];
@ -125,33 +92,6 @@ export const createOrUpgradeResearch = async (username: string, research: Resear
} }
} }
export const getUserShips = async (user: User): Promise<Array<Ship>> => {
const ships: Array<Ship> = [];
if (user?.ships !== undefined) {
user?.ships.forEach((ship: Ship) => {
ships.push(ship);
});
}
return ships;
}
export const createOrUpgradeShip = async (user: User, ship: Ship) => {
const users = await Users();
const result = await users.updateOne(
{ username: user.username, "ships.id": ship.id },
{ $set: { "ships.$.amount": ship.amount } }
);
if (result.modifiedCount === 0) {
await users.updateOne({ username: user.username },
{ $push: { ships: ship } }
);
}
}
export const getUserWithPlanets = async (id: ObjectId): Promise<User | null> => { export const getUserWithPlanets = async (id: ObjectId): Promise<User | null> => {
const users = await Users(); const users = await Users();
const planets = await Planets(); const planets = await Planets();

View File

@ -1,10 +1,9 @@
import { ObjectId } from "mongodb" import { ObjectId } from "mongodb"
import { getUserById } from "../db/users"; import { Planets } from "../db/mongodb";
import { Users } from "../db/mongodb";
import type DBResource from "../../types/DBResource"; import type DBResource from "../../types/DBResource";
import type Resource from "../../types/Resource"; import { getPlanetById } from "../db/planets";
export const createInitialResources = async (id: ObjectId) => { export const createInitialResources = async (planetId: ObjectId) => {
const resources: Array<DBResource> = [ const resources: Array<DBResource> = [
{ {
name: "coal", name: "coal",
@ -62,34 +61,32 @@ export const createInitialResources = async (id: ObjectId) => {
} }
]; ];
updateUserResources(id, resources); updatePlanetResources(planetId, resources);
} }
export const getUserResources = async (id: ObjectId): Promise<Array<DBResource>> => { export const getResourcesFromPlanet = async (planetId: ObjectId): Promise<Array<DBResource> | null> => {
const user = await getUserById(id); const planet = await getPlanetById(planetId);
const defaultResources: Array<DBResource> = []; if(!planet) return null;
return user?.resources === undefined ? defaultResources : user?.resources; return planet.resources;
} }
export const updateUserResources = async (id: ObjectId, resources: Array<DBResource>) => { export const updatePlanetResources = async (planetId: ObjectId, resources: Array<DBResource>) => {
const users = await Users(); const planets = await Planets();
await users.updateOne({ _id: id }, { await planets.updateOne({ _id: planetId }, {
$set: { $set: {
resources resources
} }
}); });
} }
export const calculateCurrentAvailableResources = async (id: ObjectId): Promise<Array<DBResource>> => { export const calculateCurrentAvailableResources = async (planetId: ObjectId): Promise<Array<DBResource>> => {
const user = await getUserById(id); const resources = await getResourcesFromPlanet(planetId);
if(user === null) return []; if(resources === null) return [];
const userResources = await getUserResources(id); resources.forEach(res => {
userResources.forEach(res => {
const timeDiff = Math.abs((new Date()).getTime() - res.lastUpdated.getTime()); const timeDiff = Math.abs((new Date()).getTime() - res.lastUpdated.getTime());
const hours = timeDiff / (1000 * 60 * 60); const hours = timeDiff / (1000 * 60 * 60);
const amountToAdd = hours * res.perHourMiningRate; const amountToAdd = hours * res.perHourMiningRate;
@ -97,6 +94,7 @@ export const calculateCurrentAvailableResources = async (id: ObjectId): Promise<
res.lastUpdated = new Date(); res.lastUpdated = new Date();
}); });
updateUserResources(id, userResources);
return userResources; updatePlanetResources(planetId, resources);
return resources;
} }

View File

@ -0,0 +1,22 @@
import { APIRoute } from "astro";
import { getAllPlanets } from "../../../lib/db/planets";
import Planet from "../../../types/Planet";
import { ObjectId } from "mongodb";
export const GET: APIRoute = async ({ request }) => {
const planets = await getAllPlanets();
const response: Array<{planetId: ObjectId, ownerId: ObjectId, name: string}> = [];
planets.forEach((planet: Planet) => {
response.push({
planetId: planet._id,
ownerId: planet.owner._id,
name: planet.name,
})
});
return new Response(
JSON.stringify(response)
);
}

View File

@ -0,0 +1,44 @@
import { APIRoute } from "astro";
import { getPlanetById } from "../../../../lib/db/planets";
import { ObjectId } from "mongodb";
import Planet from "../../../../types/Planet";
import { calculateCurrentAvailableResources } from "../../../../lib/utils/resourceManager";
export const GET: APIRoute = async ({ params, request }) => {
const planetId = params['planetId'];
if(!planetId) return new Response(
JSON.stringify({
code: 400,
message: "Bad Request"
}), { status: 400 }
);
let planet: Planet | null;
try {
planet = await getPlanetById(new ObjectId(planetId));
if(!planet) return new Response(
JSON.stringify({
code: 404,
message: "Not Found"
}), { status: 404 }
);
} catch(e) {
return new Response(
JSON.stringify({
code: 500,
message: "Internal Server Error"
}), { status: 500 }
);
}
await calculateCurrentAvailableResources(planet._id);
return new Response(
JSON.stringify({
code: 200,
message: "OK",
data: JSON.parse(JSON.stringify(planet).replace(/_id/g, 'id'))
})
)
}

View File

@ -1,9 +1,8 @@
--- ---
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 { getAllUsers, getUserByAccessToken } from '../../lib/db/users'; import { getUserByAccessToken } from '../../lib/db/users';
import { getHighestWeightedLanguage, getLocales } from '../../lib/utils/langDriver'; import { getAllPlanets } from '../../lib/db/planets';
import format from '../../lib/utils/format';
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 ?? "";
@ -12,17 +11,13 @@ if(loggedToken === null || username === "") return Astro.redirect('/logout');
const checkUser = await getUserByAccessToken(loggedToken); const checkUser = await getUserByAccessToken(loggedToken);
if(checkUser === null || checkUser.username !== username) return Astro.redirect('/logout'); if(checkUser === null || checkUser.username !== username) return Astro.redirect('/logout');
const allUsers = await getAllUsers(); const allPlanets = await getAllPlanets();
const langGame = await getLocales(await getHighestWeightedLanguage(Astro.request.headers.get('accept-language')), 'game');
--- ---
<Layout title="Galaxy view"> <Layout title="Galaxy view">
<NavBar loggedIn="true" active="galaxyView" /> <NavBar loggedIn="true" active="galaxyView" />
<h1>{format(langGame['Header_user'], username)}</h1>
<h1>Galaxy view</h1>
<ul> <ul>
{allUsers.map(user => <li>{user.username}</li>)} {allPlanets.map(planet => <li>{planet.name} ({planet.owner.username})</li>)}
</ul> </ul>
</Layout> </Layout>

View File

@ -3,7 +3,6 @@ import Layout from '../../layouts/Layout.astro';
import NavBar from '../../components/NavBar.astro'; import NavBar from '../../components/NavBar.astro';
import ResourceBar from '../../components/ResourceBar.astro'; import ResourceBar from '../../components/ResourceBar.astro';
import { getUserByAccessToken } from '../../lib/db/users'; import { getUserByAccessToken } from '../../lib/db/users';
// import { createInitialResources } from '../../lib/utils/resourceManager';
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 ?? "";
@ -11,10 +10,9 @@ 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');
// createInitialResources(checkUser._id);
--- ---
<Layout title="chujów sto"> <Layout title="Overview">
<NavBar loggedIn="true" active="overview" /> <NavBar loggedIn="true" active="overview" />
<ResourceBar /> <ResourceBar />
</Layout> </Layout>

View File

@ -2,7 +2,7 @@
import Layout from '../layouts/Layout.astro'; import Layout from '../layouts/Layout.astro';
import NavBar from '../components/NavBar.astro'; import NavBar from '../components/NavBar.astro';
import { getUserByNickOrEmail, updateLastLogin } from '../lib/db/users'; import { getUserByNickOrEmail, getUserWithPlanets, updateLastLogin } from '../lib/db/users';
import config from '../../config.json'; import config from '../../config.json';
@ -68,6 +68,17 @@ if(Astro.request.method === "POST") {
secure: true secure: true
}); });
const userWithPlanets = await getUserWithPlanets(user._id);
if(!userWithPlanets) return;
const planetId = userWithPlanets.planets.data[0]._id;
Astro.cookies.set("planetid", planetId.toString(), {
path: "/",
maxAge: sessionTime,
sameSite: "lax",
secure: true
});
return Astro.redirect("/game"); return Astro.redirect("/game");
} else { } else {
error = "invalid username or password"; error = "invalid username or password";

View File

@ -11,5 +11,9 @@ if(Astro.cookies.has('userid')) {
Astro.cookies.delete('userid'); Astro.cookies.delete('userid');
} }
if(Astro.cookies.has('planetid')) {
Astro.cookies.delete('planetid');
}
return Astro.redirect('/'); return Astro.redirect('/');
--- ---

15
src/types/Planet.ts Normal file
View File

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

View File

@ -1,8 +1,6 @@
import type { ObjectId } from "mongodb"; import type { ObjectId } from "mongodb";
import type Building from "./Building";
import type DBResource from "./DBResource";
import type Research from "./Research"; import type Research from "./Research";
import type Ship from "./Ship"; import type Planet from "./Planet";
export default interface User { export default interface User {
_id: ObjectId; _id: ObjectId;
@ -10,10 +8,11 @@ export default interface User {
email: string; email: string;
password: string; password: string;
lastLogin: Date; lastLogin: Date;
resources: Array<DBResource>;
buildings: Array<Building>;
research: Array<Research>; research: Array<Research>;
ships: Array<Ship> planets: {
partial: boolean;
data: Array<Planet>;
};
createdAt: Date; createdAt: Date;
updatedAt: Date; updatedAt: Date;
} }