From de326fd4dd0b81fdd331d2270817098955b3415e Mon Sep 17 00:00:00 2001 From: Sainan Date: Fri, 10 May 2024 11:26:46 +0200 Subject: [PATCH 1/7] feat: more work on clans --- src/controllers/api/createGuildController.ts | 2 +- src/controllers/api/createGuildDojoController.ts | 13 +++++++++++++ src/controllers/api/dojoController.ts | 5 +++++ src/controllers/api/getGuildDojoController.ts | 5 +++++ src/controllers/api/getGuildLogController.ts | 11 +++++++++++ src/controllers/api/guildTechController.ts | 5 +++++ src/routes/api.ts | 10 ++++++++++ 7 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/controllers/api/createGuildDojoController.ts create mode 100644 src/controllers/api/dojoController.ts create mode 100644 src/controllers/api/getGuildDojoController.ts create mode 100644 src/controllers/api/getGuildLogController.ts create mode 100644 src/controllers/api/guildTechController.ts diff --git a/src/controllers/api/createGuildController.ts b/src/controllers/api/createGuildController.ts index cb101aba..badaa467 100644 --- a/src/controllers/api/createGuildController.ts +++ b/src/controllers/api/createGuildController.ts @@ -19,7 +19,7 @@ const createGuildController: RequestHandler = async (req, res) => { // Set GuildId inventory.GuildId = guild._id; - // Give clan key + // Give clan key (TODO: This should only be a blueprint) inventory.LevelKeys ??= []; inventory.LevelKeys.push({ ItemType: "/Lotus/Types/Keys/DojoKey", diff --git a/src/controllers/api/createGuildDojoController.ts b/src/controllers/api/createGuildDojoController.ts new file mode 100644 index 00000000..a52eafc3 --- /dev/null +++ b/src/controllers/api/createGuildDojoController.ts @@ -0,0 +1,13 @@ +import { RequestHandler } from "express"; + +export const createGuildDojoController: RequestHandler = (_req, res) => { + // _req.body.toString() -> {"SpawnComponent":{"id":{"$oid":"000000000000000000000000"},"pf":"/Lotus/Levels/ClanDojo/DojoHall.level","ppf":""}} + + // I'm guessing the response is same as getGuildDojo.php, but I have yet to log one of those for a fresh clan. + // This works to make the client load in, but can't build new rooms. + res.json({ + DojoComponents: [ + {"pf":"/Lotus/Levels/ClanDojo/DojoHall.level","ppf":""} + ] + }); +}; diff --git a/src/controllers/api/dojoController.ts b/src/controllers/api/dojoController.ts new file mode 100644 index 00000000..c14d9316 --- /dev/null +++ b/src/controllers/api/dojoController.ts @@ -0,0 +1,5 @@ +import { RequestHandler } from "express"; + +export const dojoController: RequestHandler = (_req, res) => { + res.json("-1"); // Tell client to use authorised request. +}; diff --git a/src/controllers/api/getGuildDojoController.ts b/src/controllers/api/getGuildDojoController.ts new file mode 100644 index 00000000..4c8b683b --- /dev/null +++ b/src/controllers/api/getGuildDojoController.ts @@ -0,0 +1,5 @@ +import { RequestHandler } from "express"; + +export const getGuildDojoController: RequestHandler = (_req, res) => { + res.json({}); // This is what I got for a fresh clan. +}; diff --git a/src/controllers/api/getGuildLogController.ts b/src/controllers/api/getGuildLogController.ts new file mode 100644 index 00000000..2919ce31 --- /dev/null +++ b/src/controllers/api/getGuildLogController.ts @@ -0,0 +1,11 @@ +import { RequestHandler } from "express"; + +export const getGuildLogController: RequestHandler = (_req, res) => { + res.json({ + RoomChanges: [], + TechChanges: [], + RosterActivity: [], + StandingsUpdates: [], + ClassChanges: [] + }); +}; diff --git a/src/controllers/api/guildTechController.ts b/src/controllers/api/guildTechController.ts new file mode 100644 index 00000000..9e4243da --- /dev/null +++ b/src/controllers/api/guildTechController.ts @@ -0,0 +1,5 @@ +import { RequestHandler } from "express"; + +export const guildTechController: RequestHandler = (_req, res) => { + res.status(500).end(); // This is what I got for a fresh clan. +}; diff --git a/src/routes/api.ts b/src/routes/api.ts index 5770ee11..3056baf9 100644 --- a/src/routes/api.ts +++ b/src/routes/api.ts @@ -48,6 +48,11 @@ import { sellController } from "@/src/controllers/api/sellController"; import { upgradesController } from "@/src/controllers/api/upgradesController"; import { setSupportedSyndicateController } from "@/src/controllers/api/setSupportedSyndicateController"; import { getDailyDealStockLevelsController } from "@/src/controllers/api/getDailyDealStockLevelsController"; +import { getGuildLogController } from "../controllers/api/getGuildLogController"; +import { guildTechController } from "../controllers/api/guildTechController"; +import { dojoController } from "@/src/controllers/api/dojoController"; +import { getGuildDojoController } from "@/src/controllers/api/getGuildDojoController"; +import { createGuildDojoController } from "@/src/controllers/api/createGuildDojoController"; const apiRouter = express.Router(); @@ -77,6 +82,9 @@ apiRouter.get("/setActiveShip.php", setActiveShipController); apiRouter.get("/getGuild.php", getGuildController); apiRouter.get("/setSupportedSyndicate.php", setSupportedSyndicateController); apiRouter.get("/getDailyDealStockLevels.php", getDailyDealStockLevelsController); +apiRouter.get("/getGuildLog.php", getGuildLogController); +apiRouter.get("/dojo", dojoController); +apiRouter.get("/getGuildDojo.php", getGuildDojoController); // post // eslint-disable-next-line @typescript-eslint/no-misused-promises @@ -106,5 +114,7 @@ apiRouter.post("/addFriendImage.php", addFriendImageController); apiRouter.post("/createGuild.php", createGuildController); apiRouter.post("/sell.php", sellController); apiRouter.post("/upgrades.php", upgradesController); +apiRouter.post("/guildTech.php", guildTechController); +apiRouter.post("/createGuildDojo.php", createGuildDojoController); export { apiRouter }; -- 2.47.2 From b7d574071edc48ea806857abcf619040b2d50029 Mon Sep 17 00:00:00 2001 From: Sainan Date: Fri, 10 May 2024 09:27:12 +0000 Subject: [PATCH 2/7] Apply prettier changes --- src/controllers/api/createGuildDojoController.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/controllers/api/createGuildDojoController.ts b/src/controllers/api/createGuildDojoController.ts index a52eafc3..d0849259 100644 --- a/src/controllers/api/createGuildDojoController.ts +++ b/src/controllers/api/createGuildDojoController.ts @@ -6,8 +6,6 @@ export const createGuildDojoController: RequestHandler = (_req, res) => { // I'm guessing the response is same as getGuildDojo.php, but I have yet to log one of those for a fresh clan. // This works to make the client load in, but can't build new rooms. res.json({ - DojoComponents: [ - {"pf":"/Lotus/Levels/ClanDojo/DojoHall.level","ppf":""} - ] + DojoComponents: [{ pf: "/Lotus/Levels/ClanDojo/DojoHall.level", ppf: "" }] }); }; -- 2.47.2 From c5666dc38739de241e045487d197ca895dd9835d Mon Sep 17 00:00:00 2001 From: Sainan Date: Sat, 11 May 2024 00:16:45 +0200 Subject: [PATCH 3/7] Give a proper response on createGuildDojo --- .../api/createGuildDojoController.ts | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/controllers/api/createGuildDojoController.ts b/src/controllers/api/createGuildDojoController.ts index d0849259..45e26a85 100644 --- a/src/controllers/api/createGuildDojoController.ts +++ b/src/controllers/api/createGuildDojoController.ts @@ -1,11 +1,27 @@ import { RequestHandler } from "express"; -export const createGuildDojoController: RequestHandler = (_req, res) => { - // _req.body.toString() -> {"SpawnComponent":{"id":{"$oid":"000000000000000000000000"},"pf":"/Lotus/Levels/ClanDojo/DojoHall.level","ppf":""}} +export const createGuildDojoController: RequestHandler = (req, res) => { + // req.body.toString() -> {"SpawnComponent":{"id":{"$oid":"000000000000000000000000"},"pf":"/Lotus/Levels/ClanDojo/DojoHall.level","ppf":""}} - // I'm guessing the response is same as getGuildDojo.php, but I have yet to log one of those for a fresh clan. - // This works to make the client load in, but can't build new rooms. + // I'm guessing the response is same as getGuildDojo.php, which responds like this for a fresh dojo: res.json({ - DojoComponents: [{ pf: "/Lotus/Levels/ClanDojo/DojoHall.level", ppf: "" }] + _id: { $oid: req.params.guildId }, + Name: "If you can read this in-game, tell me I need to fetch the clan name from the DB, lol.", + Tier: 1, + FixedContributions: true, + DojoRevision: 1, + RevisionTime: Math.round(Date.now() / 1000), + Energy: 5, + Capacity: 100, + DojoRequestStatus: 0, + DojoComponents: [ + { + pf: "/Lotus/Levels/ClanDojo/DojoHall.level", + ppf: "", + id: { $oid: "000000000000000000000000" }, + CompletionTime: { $date: { $numberLong: "" + Date.now() } }, + DecoCapacity: 600 + } + ] }); }; -- 2.47.2 From e066f0f23f87ed8f2621aee32deec4abd1a75145 Mon Sep 17 00:00:00 2001 From: Sainan Date: Sat, 11 May 2024 16:42:46 +0200 Subject: [PATCH 4/7] fix: superfluous fields after converting guild to client representation --- src/models/guildModel.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/models/guildModel.ts b/src/models/guildModel.ts index 601e73e3..99023d2f 100644 --- a/src/models/guildModel.ts +++ b/src/models/guildModel.ts @@ -2,14 +2,18 @@ import { IGuild } from "@/src/types/guildTypes"; import { model, Schema } from "mongoose"; import { toOid } from "@/src/helpers/inventoryHelpers"; -const guildSchema = new Schema({ - Name: { type: String, required: true } -}); +const guildSchema = new Schema( + { + Name: { type: String, required: true } + }, + { id: false } +); guildSchema.set("toJSON", { virtuals: true, transform(_document, guild) { guild._id = toOid(guild._id); + delete guild.__v; } }); -- 2.47.2 From 51ea9d5ca1254ba052c10fd5fe0be631fb55664f Mon Sep 17 00:00:00 2001 From: Sainan Date: Sat, 11 May 2024 16:49:27 +0200 Subject: [PATCH 5/7] Add types for dojo client representation --- .../api/createGuildDojoController.ts | 3 ++- src/types/guildTypes.ts | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/controllers/api/createGuildDojoController.ts b/src/controllers/api/createGuildDojoController.ts index 45e26a85..1f74fac1 100644 --- a/src/controllers/api/createGuildDojoController.ts +++ b/src/controllers/api/createGuildDojoController.ts @@ -1,4 +1,5 @@ import { RequestHandler } from "express"; +import { IDojoClient } from "@/src/types/guildTypes"; export const createGuildDojoController: RequestHandler = (req, res) => { // req.body.toString() -> {"SpawnComponent":{"id":{"$oid":"000000000000000000000000"},"pf":"/Lotus/Levels/ClanDojo/DojoHall.level","ppf":""}} @@ -23,5 +24,5 @@ export const createGuildDojoController: RequestHandler = (req, res) => { DecoCapacity: 600 } ] - }); + } satisfies IDojoClient); }; diff --git a/src/types/guildTypes.ts b/src/types/guildTypes.ts index c5f1f6f2..4cfa853b 100644 --- a/src/types/guildTypes.ts +++ b/src/types/guildTypes.ts @@ -1,3 +1,5 @@ +import { IOid, IMongoDate } from "@/src/types/commonTypes"; + export interface IGuild { Name: string; } @@ -5,3 +7,24 @@ export interface IGuild { export interface ICreateGuildRequest { guildName: string; } + +export interface IDojoClient { + _id: IOid; // ID of the guild + Name: string; + Tier: number; + FixedContributions: boolean; + DojoRevision: number; + RevisionTime: number; + Energy: number; + Capacity: number; + DojoRequestStatus: number; + DojoComponents: IDojoComponentClient[]; +} + +export interface IDojoComponentClient { + pf: string; + ppf: string; + id: IOid; + CompletionTime: IMongoDate; + DecoCapacity: number; +} -- 2.47.2 From 9aa8213f7b98a8b5d6a1d76193116925038289d4 Mon Sep 17 00:00:00 2001 From: Sainan Date: Sat, 11 May 2024 18:06:06 +0200 Subject: [PATCH 6/7] Store dojo components in database as subdocument array --- .../api/createGuildDojoController.ts | 28 ----------- src/controllers/api/getGuildDojoController.ts | 50 ++++++++++++++++++- src/models/guildModel.ts | 15 ++++-- src/routes/api.ts | 2 - src/types/guildTypes.ts | 15 +++++- 5 files changed, 73 insertions(+), 37 deletions(-) delete mode 100644 src/controllers/api/createGuildDojoController.ts diff --git a/src/controllers/api/createGuildDojoController.ts b/src/controllers/api/createGuildDojoController.ts deleted file mode 100644 index 1f74fac1..00000000 --- a/src/controllers/api/createGuildDojoController.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { RequestHandler } from "express"; -import { IDojoClient } from "@/src/types/guildTypes"; - -export const createGuildDojoController: RequestHandler = (req, res) => { - // req.body.toString() -> {"SpawnComponent":{"id":{"$oid":"000000000000000000000000"},"pf":"/Lotus/Levels/ClanDojo/DojoHall.level","ppf":""}} - - // I'm guessing the response is same as getGuildDojo.php, which responds like this for a fresh dojo: - res.json({ - _id: { $oid: req.params.guildId }, - Name: "If you can read this in-game, tell me I need to fetch the clan name from the DB, lol.", - Tier: 1, - FixedContributions: true, - DojoRevision: 1, - RevisionTime: Math.round(Date.now() / 1000), - Energy: 5, - Capacity: 100, - DojoRequestStatus: 0, - DojoComponents: [ - { - pf: "/Lotus/Levels/ClanDojo/DojoHall.level", - ppf: "", - id: { $oid: "000000000000000000000000" }, - CompletionTime: { $date: { $numberLong: "" + Date.now() } }, - DecoCapacity: 600 - } - ] - } satisfies IDojoClient); -}; diff --git a/src/controllers/api/getGuildDojoController.ts b/src/controllers/api/getGuildDojoController.ts index 4c8b683b..b38b23a9 100644 --- a/src/controllers/api/getGuildDojoController.ts +++ b/src/controllers/api/getGuildDojoController.ts @@ -1,5 +1,51 @@ import { RequestHandler } from "express"; +import { Types } from "mongoose"; +import { Guild } from "@/src/models/guildModel"; +import { IDojoClient } from "@/src/types/guildTypes"; +import { toOid, toMongoDate } from "@/src/helpers/inventoryHelpers"; -export const getGuildDojoController: RequestHandler = (_req, res) => { - res.json({}); // This is what I got for a fresh clan. +export const getGuildDojoController: RequestHandler = async (req, res) => { + const guildId = req.query.guildId as string; + + const guild = await Guild.findOne({ _id: guildId }); + if (!guild) { + res.status(404).end(); + return; + } + + // Populate dojo info if not present + if (!guild.DojoComponents || guild.DojoComponents.length == 0) { + guild.DojoComponents = [ + { + _id: new Types.ObjectId(), + pf: "/Lotus/Levels/ClanDojo/DojoHall.level", + ppf: "", + CompletionTime: new Date(Date.now()) + } + ]; + guild.save(); + } + + const dojo: IDojoClient = { + _id: { $oid: guildId }, + Name: guild.Name, + Tier: 1, + FixedContributions: true, + DojoRevision: 1, + RevisionTime: Math.round(Date.now() / 1000), + Energy: 5, + Capacity: 100, + DojoRequestStatus: 0, + DojoComponents: [] + }; + guild.DojoComponents.forEach(dojoComponent => { + dojo.DojoComponents.push({ + id: toOid(dojoComponent._id), + pf: dojoComponent.pf, + ppf: dojoComponent.ppf, + CompletionTime: toMongoDate(dojoComponent.CompletionTime), + DecoCapacity: 600 + }); + }); + res.json(dojo); }; diff --git a/src/models/guildModel.ts b/src/models/guildModel.ts index 99023d2f..450bf06c 100644 --- a/src/models/guildModel.ts +++ b/src/models/guildModel.ts @@ -1,10 +1,17 @@ -import { IGuild } from "@/src/types/guildTypes"; +import { IGuildDatabase, IDojoComponentDatabase } from "@/src/types/guildTypes"; import { model, Schema } from "mongoose"; import { toOid } from "@/src/helpers/inventoryHelpers"; -const guildSchema = new Schema( +const dojoComponentSchema = new Schema({ + pf: { type: String, required: true }, + ppf: String, + CompletionTime: Date +}); + +const guildSchema = new Schema( { - Name: { type: String, required: true } + Name: { type: String, required: true }, + DojoComponents: [dojoComponentSchema] }, { id: false } ); @@ -17,4 +24,4 @@ guildSchema.set("toJSON", { } }); -export const Guild = model("Guild", guildSchema); +export const Guild = model("Guild", guildSchema); diff --git a/src/routes/api.ts b/src/routes/api.ts index 3056baf9..8ca15002 100644 --- a/src/routes/api.ts +++ b/src/routes/api.ts @@ -52,7 +52,6 @@ import { getGuildLogController } from "../controllers/api/getGuildLogController" import { guildTechController } from "../controllers/api/guildTechController"; import { dojoController } from "@/src/controllers/api/dojoController"; import { getGuildDojoController } from "@/src/controllers/api/getGuildDojoController"; -import { createGuildDojoController } from "@/src/controllers/api/createGuildDojoController"; const apiRouter = express.Router(); @@ -115,6 +114,5 @@ apiRouter.post("/createGuild.php", createGuildController); apiRouter.post("/sell.php", sellController); apiRouter.post("/upgrades.php", upgradesController); apiRouter.post("/guildTech.php", guildTechController); -apiRouter.post("/createGuildDojo.php", createGuildDojoController); export { apiRouter }; diff --git a/src/types/guildTypes.ts b/src/types/guildTypes.ts index 4cfa853b..c969db6a 100644 --- a/src/types/guildTypes.ts +++ b/src/types/guildTypes.ts @@ -1,9 +1,15 @@ +import { Types } from "mongoose"; import { IOid, IMongoDate } from "@/src/types/commonTypes"; export interface IGuild { Name: string; } +export interface IGuildDatabase extends IGuild { + _id: Types.ObjectId; + DojoComponents?: IDojoComponentDatabase[]; +} + export interface ICreateGuildRequest { guildName: string; } @@ -22,9 +28,16 @@ export interface IDojoClient { } export interface IDojoComponentClient { + id: IOid; pf: string; ppf: string; - id: IOid; CompletionTime: IMongoDate; DecoCapacity: number; } + +export interface IDojoComponentDatabase { + _id: Types.ObjectId; + pf: string; + ppf: string; + CompletionTime: Date; +} -- 2.47.2 From 056d7364c0e0f787ac1e0325d57ca1921765db1a Mon Sep 17 00:00:00 2001 From: Sainan Date: Sat, 11 May 2024 19:46:27 +0200 Subject: [PATCH 7/7] Improve getGuild response so game knows we have all permissions --- src/controllers/api/createGuildController.ts | 4 +- src/controllers/api/getGuildController.ts | 52 +++++++++++++++++++- src/models/guildModel.ts | 9 ---- 3 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/controllers/api/createGuildController.ts b/src/controllers/api/createGuildController.ts index badaa467..88cace67 100644 --- a/src/controllers/api/createGuildController.ts +++ b/src/controllers/api/createGuildController.ts @@ -2,7 +2,7 @@ import { RequestHandler } from "express"; import { getJSONfromString } from "@/src/helpers/stringHelpers"; import { Inventory } from "@/src/models/inventoryModels/inventoryModel"; import { Guild } from "@/src/models/guildModel"; -import { IGuild, ICreateGuildRequest } from "@/src/types/guildTypes"; +import { ICreateGuildRequest } from "@/src/types/guildTypes"; const createGuildController: RequestHandler = async (req, res) => { const payload: ICreateGuildRequest = getJSONfromString(req.body.toString()); @@ -10,7 +10,7 @@ const createGuildController: RequestHandler = async (req, res) => { // Create guild on database const guild = new Guild({ Name: payload.guildName - } satisfies IGuild); + }); await guild.save(); // Update inventory diff --git a/src/controllers/api/getGuildController.ts b/src/controllers/api/getGuildController.ts index 81dfde24..a91bf5dd 100644 --- a/src/controllers/api/getGuildController.ts +++ b/src/controllers/api/getGuildController.ts @@ -1,6 +1,7 @@ import { RequestHandler } from "express"; import { Inventory } from "@/src/models/inventoryModels/inventoryModel"; import { Guild } from "@/src/models/guildModel"; +import { toOid } from "@/src/helpers/inventoryHelpers"; const getGuildController: RequestHandler = async (req, res) => { if (!req.query.accountId) { @@ -15,7 +16,56 @@ const getGuildController: RequestHandler = async (req, res) => { if (inventory.GuildId) { const guild = await Guild.findOne({ _id: inventory.GuildId }); if (guild) { - res.json(guild); + res.json({ + _id: toOid(guild._id), + Name: guild.Name, + Members: [ + { + _id: { $oid: req.query.accountId }, + Rank: 0, + Status: 0 + } + ], + Ranks: [ + { + Name: "/Lotus/Language/Game/Rank_Creator", + Permissions: 16351 + }, + { + Name: "/Lotus/Language/Game/Rank_Warlord", + Permissions: 14303 + }, + { + Name: "/Lotus/Language/Game/Rank_General", + Permissions: 4318 + }, + { + Name: "/Lotus/Language/Game/Rank_Officer", + Permissions: 4314 + }, + { + Name: "/Lotus/Language/Game/Rank_Leader", + Permissions: 4106 + }, + { + Name: "/Lotus/Language/Game/Rank_Sage", + Permissions: 4304 + }, + { + Name: "/Lotus/Language/Game/Rank_Soldier", + Permissions: 4098 + }, + { + Name: "/Lotus/Language/Game/Rank_Initiate", + Permissions: 4096 + }, + { + Name: "/Lotus/Language/Game/Rank_Utility", + Permissions: 4096 + } + ], + Tier: 1 + }); return; } } diff --git a/src/models/guildModel.ts b/src/models/guildModel.ts index 450bf06c..157007a0 100644 --- a/src/models/guildModel.ts +++ b/src/models/guildModel.ts @@ -1,6 +1,5 @@ import { IGuildDatabase, IDojoComponentDatabase } from "@/src/types/guildTypes"; import { model, Schema } from "mongoose"; -import { toOid } from "@/src/helpers/inventoryHelpers"; const dojoComponentSchema = new Schema({ pf: { type: String, required: true }, @@ -16,12 +15,4 @@ const guildSchema = new Schema( { id: false } ); -guildSchema.set("toJSON", { - virtuals: true, - transform(_document, guild) { - guild._id = toOid(guild._id); - delete guild.__v; - } -}); - export const Guild = model("Guild", guildSchema); -- 2.47.2