XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

SpaceNinjaServer

A simple server for a small space ninja game

公开
关注 0 Fork 1 Star 0
返回提交历史

XFEstudio/SpaceNinjaServer

Fix interface names, +genericUpdate (#51)

Co-authored-by: nk <nk@fbi.rocks> Co-authored-by: Ordis <134585663+OrdisPrime@users.noreply.github.com>

a9318632
7f8ddd <141754874+7f8ddd@users.noreply.github.com>
提交于

代码差异

17 个文件 +534 -488
Modified src/controllers/api/genericUpdateController.ts +25 -2
@@ -1,7 +1,30 @@
1 import { updateGeneric } from "@/src/services/inventoryService";
2 import { IGenericUpdate } from "@/src/types/genericUpdate";
1 3 import { RequestHandler } from "express";
2 4
3 const genericUpdateController: RequestHandler = (_req, res) => {
4 res.json({});
5 // TODO: Nightwave evidence submission support is the only thing missing.
6 // TODO: Also, you might want to test this, because I definitely didn't.
7 const genericUpdateController: RequestHandler = async (request, response) => {
8 const accountId = request.query.accountId as string;
9
10 const [body] = String(request.body).split("\n");
11
12 let reply = {};
13 try {
14 const update = JSON.parse(body) as IGenericUpdate;
15 if (typeof update !== "object") {
16 throw new Error("Invalid data format");
17 }
18
19 reply = await updateGeneric(update, accountId);
20 } catch (err) {
21 console.error("Error parsing JSON data:", err);
22 }
23
24 // Response support added for when Nightwave is supported below.
25 // response.json(reply);
26
27 response.json({});
5 28 };
6 29
7 30 export { genericUpdateController };
Modified src/controllers/api/missionInventoryUpdateController.ts +8 -9
@@ -1,6 +1,6 @@
1 1 import { RequestHandler } from "express";
2 2 import { missionInventoryUpdate } from "@/src/services/inventoryService";
3 import { MissionInventoryUpdate } from "@/src/types/missionInventoryUpdateType";
3 import { IMissionInventoryUpdate } from "@/src/types/missionInventoryUpdateType";
4 4 /*
5 5 - [ ] crossPlaySetting
6 6 - [ ] rewardsMultiplier
@@ -25,13 +25,13 @@ import { MissionInventoryUpdate } from "@/src/types/missionInventoryUpdateType";
25 25 - [ ] hosts
26 26 - [x] ChallengeProgress
27 27 - [ ] SeasonChallengeHistory
28 - [ ] PS
28 - [ ] PS (Passive anti-cheat data which includes your username, module list, process list, and system name.)
29 29 - [ ] ActiveDojoColorResearch
30 30 - [ ] RewardInfo
31 31 - [ ] ReceivedCeremonyMsg
32 32 - [ ] LastCeremonyResetDate
33 - [ ] MissionPTS
34 - [ ] RepHash
33 - [ ] MissionPTS (Used to validate the mission/alive time above.)
34 - [ ] RepHash (A hash from the replication manager/RepMgr Unknown what it does.)
35 35 - [ ] EndOfMatchUpload
36 36 - [ ] ObjectiveReached
37 37 - [ ] FpsAvg
@@ -42,20 +42,19 @@ import { MissionInventoryUpdate } from "@/src/types/missionInventoryUpdateType";
42 42
43 43 // eslint-disable-next-line @typescript-eslint/no-misused-promises
44 44 const missionInventoryUpdateController: RequestHandler = async (req, res) => {
45 const [data] = String(req.body).split("\n");
46 45 const id = req.query.accountId as string;
47 46
48 // TODO - salt check
47 const [data] = String(req.body).split("\n");
49 48
50 49 try {
51 const parsedData = JSON.parse(data) as MissionInventoryUpdate;
52 if (typeof parsedData !== "object" || parsedData === null) throw new Error("Invalid data format");
50 const parsedData = JSON.parse(data) as IMissionInventoryUpdate;
51 if (typeof parsedData !== "object") throw new Error("Invalid data format");
53 52 await missionInventoryUpdate(parsedData, id);
54 53 } catch (err) {
55 54 console.error("Error parsing JSON data:", err);
56 55 }
57 56
58 // TODO - get original response
57 // TODO - Return the updated inventory the way the game does it.
59 58 res.json({});
60 59 };
61 60
Modified src/managers/sessionManager.ts +10 -10
@@ -1,10 +1,10 @@
1 import { Session, FindSessionRequest } from "@/src/types/session";
1 import { ISession, IFindSessionRequest } from "@/src/types/session";
2 2
3 const sessions: Session[] = [];
3 const sessions: ISession[] = [];
4 4
5 function createNewSession(sessionData: Session, Creator: string): Session {
5 function createNewSession(sessionData: ISession, Creator: string): ISession {
6 6 const sessionId = getNewSessionID();
7 const newSession: Session = {
7 const newSession: ISession = {
8 8 sessionId,
9 9 creatorId: Creator,
10 10 maxPlayers: sessionData.maxPlayers || 4,
@@ -35,15 +35,15 @@ function createNewSession(sessionData: Session, Creator: string): Session {
35 35 return newSession;
36 36 }
37 37
38 function getAllSessions(): Session[] {
38 function getAllSessions(): ISession[] {
39 39 return sessions;
40 40 }
41 41
42 function getSessionByID(sessionId: string): Session | undefined {
42 function getSessionByID(sessionId: string): ISession | undefined {
43 43 return sessions.find(session => session.sessionId === sessionId);
44 44 }
45 45
46 function getSession(sessionIdOrRequest: string | FindSessionRequest): any[] {
46 function getSession(sessionIdOrRequest: string | IFindSessionRequest): any[] {
47 47 if (typeof sessionIdOrRequest === "string") {
48 48 const session = sessions.find(session => session.sessionId === sessionIdOrRequest);
49 49 if (session) {
@@ -58,10 +58,10 @@ function getSession(sessionIdOrRequest: string | FindSessionRequest): any[] {
58 58 return [];
59 59 }
60 60
61 const request = sessionIdOrRequest as FindSessionRequest;
61 const request = sessionIdOrRequest as IFindSessionRequest;
62 62 const matchingSessions = sessions.filter(session => {
63 63 for (const key in request) {
64 if (key !== "eloRating" && key !== "queryId" && request[key] !== session[key as keyof Session]) {
64 if (key !== "eloRating" && key !== "queryId" && request[key] !== session[key as keyof ISession]) {
65 65 return false;
66 66 }
67 67 }
@@ -74,7 +74,7 @@ function getSession(sessionIdOrRequest: string | FindSessionRequest): any[] {
74 74 }));
75 75 }
76 76
77 function getSessionByCreatorID(creatorId: string): Session | undefined {
77 function getSessionByCreatorID(creatorId: string): ISession | undefined {
78 78 return sessions.find(session => session.creatorId === creatorId);
79 79 }
80 80
Modified src/models/inventoryModel.ts +14 -8
@@ -1,6 +1,12 @@
1 1 import { Model, Schema, Types, model } from "mongoose";
2 import { FlavourItem, RawUpgrade, MiscItem, IInventoryDatabase, Booster } from "../types/inventoryTypes/inventoryTypes";
3 import { Oid } from "../types/commonTypes";
2 import {
3 IFlavourItem,
4 IRawUpgrade,
5 IMiscItem,
6 IInventoryDatabase,
7 IBooster
8 } from "../types/inventoryTypes/inventoryTypes";
9 import { IOid } from "../types/commonTypes";
4 10 import { ISuitDatabase, ISuitDocument } from "@/src/types/inventoryTypes/SuitTypes";
5 11 import { IWeaponDatabase } from "@/src/types/inventoryTypes/weaponTypes";
6 12
@@ -74,7 +80,7 @@ const BoosterSchema = new Schema({
74 80 WeaponSchema.set("toJSON", {
75 81 transform(_document, returnedObject) {
76 82 // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
77 returnedObject.ItemId = { $oid: returnedObject._id.toString() } satisfies Oid;
83 returnedObject.ItemId = { $oid: returnedObject._id.toString() } satisfies IOid;
78 84 delete returnedObject._id;
79 85 delete returnedObject.__v;
80 86 }
@@ -130,7 +136,7 @@ const suitSchema = new Schema<ISuitDatabase>({
130 136 suitSchema.set("toJSON", {
131 137 transform(_document, returnedObject) {
132 138 // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
133 returnedObject.ItemId = { $oid: returnedObject._id.toString() } satisfies Oid;
139 returnedObject.ItemId = { $oid: returnedObject._id.toString() } satisfies IOid;
134 140 delete returnedObject._id;
135 141 delete returnedObject.__v;
136 142 }
@@ -338,10 +344,10 @@ type InventoryDocumentProps = {
338 344 LongGuns: Types.DocumentArray<IWeaponDatabase>;
339 345 Pistols: Types.DocumentArray<IWeaponDatabase>;
340 346 Melee: Types.DocumentArray<IWeaponDatabase>;
341 FlavourItems: Types.DocumentArray<FlavourItem>;
342 RawUpgrades: Types.DocumentArray<RawUpgrade>;
343 MiscItems: Types.DocumentArray<MiscItem>;
344 Boosters: Types.DocumentArray<Booster>;
347 FlavourItems: Types.DocumentArray<IFlavourItem>;
348 RawUpgrades: Types.DocumentArray<IRawUpgrade>;
349 MiscItems: Types.DocumentArray<IMiscItem>;
350 Boosters: Types.DocumentArray<IBooster>;
345 351 };
346 352
347 353 type InventoryModelType = Model<IInventoryDatabase, {}, InventoryDocumentProps>;
Modified src/models/shipModel.ts +2 -2
@@ -1,6 +1,6 @@
1 1 import { Schema, model } from "mongoose";
2 2 import { IShip } from "../types/shipTypes";
3 import { Oid } from "../types/commonTypes";
3 import { IOid } from "../types/commonTypes";
4 4
5 5 const roomSchema = new Schema(
6 6 {
@@ -19,7 +19,7 @@ const shipSchema = new Schema({
19 19 shipSchema.set("toJSON", {
20 20 transform(_document, returnedObject) {
21 21 // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
22 returnedObject.ShipId = { $oid: returnedObject._id.toString() } satisfies Oid;
22 returnedObject.ShipId = { $oid: returnedObject._id.toString() } satisfies IOid;
23 23 delete returnedObject._id;
24 24 }
25 25 });
Modified src/services/inventoryService.ts +41 -18
@@ -5,13 +5,18 @@ import { Types } from "mongoose";
5 5 import { ISuitResponse } from "@/src/types/inventoryTypes/SuitTypes";
6 6 import { SlotType } from "@/src/types/purchaseTypes";
7 7 import { IWeaponResponse } from "@/src/types/inventoryTypes/weaponTypes";
8 import { ChallengeProgress, FlavourItem, IInventoryDatabaseDocument } from "@/src/types/inventoryTypes/inventoryTypes";
9 8 import {
10 MissionInventoryUpdate,
11 MissionInventoryUpdateCard,
12 MissionInventoryUpdateGear,
13 MissionInventoryUpdateItem
9 IChallengeProgress,
10 IFlavourItem,
11 IInventoryDatabaseDocument
12 } from "@/src/types/inventoryTypes/inventoryTypes";
13 import {
14 IMissionInventoryUpdate,
15 IMissionInventoryUpdateCard,
16 IMissionInventoryUpdateGear,
17 IMissionInventoryUpdateItem
14 18 } from "../types/missionInventoryUpdateType";
19 import { IGenericUpdate } from "../types/genericUpdate";
15 20
16 21 const createInventory = async (accountOwnerId: Types.ObjectId) => {
17 22 try {
@@ -76,6 +81,27 @@ export const updateCurrency = async (price: number, usePremium: boolean, account
76 81 return { [currencyName]: -price };
77 82 };
78 83
84 // TODO: AffiliationMods support (Nightwave).
85 export const updateGeneric = async (data: IGenericUpdate, accountId: string) => {
86 const inventory = await getInventory(accountId);
87
88 // Make it an array for easier parsing.
89 if (typeof data.NodeIntrosCompleted === "string") {
90 data.NodeIntrosCompleted = [data.NodeIntrosCompleted];
91 }
92
93 // Combine the two arrays into one.
94 data.NodeIntrosCompleted = inventory.NodeIntrosCompleted.concat(data.NodeIntrosCompleted);
95
96 // Remove duplicate entries.
97 const nodes = [...new Set(data.NodeIntrosCompleted)];
98
99 inventory.NodeIntrosCompleted = nodes;
100 await inventory.save();
101
102 return data;
103 };
104
79 105 export type WeaponTypeInternal = "LongGuns" | "Pistols" | "Melee";
80 106
81 107 export const addWeapon = async (
@@ -104,7 +130,7 @@ export const addWeapon = async (
104 130 return changedInventory[weaponType][weaponIndex - 1].toJSON();
105 131 };
106 132
107 export const addCustomization = async (customizatonName: string, accountId: string): Promise<FlavourItem> => {
133 export const addCustomization = async (customizatonName: string, accountId: string): Promise<IFlavourItem> => {
108 134 const inventory = await getInventory(accountId);
109 135
110 136 const flavourItemIndex = inventory.FlavourItems.push({ ItemType: customizatonName }) - 1;
@@ -114,7 +140,7 @@ export const addCustomization = async (customizatonName: string, accountId: stri
114 140
115 141 const addGearExpByCategory = (
116 142 inventory: IInventoryDatabaseDocument,
117 gearArray: MissionInventoryUpdateGear[] | undefined,
143 gearArray: IMissionInventoryUpdateGear[] | undefined,
118 144 categoryName: "Pistols" | "LongGuns" | "Melee" | "Suits"
119 145 ) => {
120 146 const category = inventory[categoryName];
@@ -132,7 +158,7 @@ const addGearExpByCategory = (
132 158
133 159 const addItemsByCategory = (
134 160 inventory: IInventoryDatabaseDocument,
135 itemsArray: (MissionInventoryUpdateItem | MissionInventoryUpdateCard)[] | undefined,
161 itemsArray: (IMissionInventoryUpdateItem | IMissionInventoryUpdateCard)[] | undefined,
136 162 categoryName: "RawUpgrades" | "MiscItems"
137 163 ) => {
138 164 const category = inventory[categoryName];
@@ -149,7 +175,7 @@ const addItemsByCategory = (
149 175 });
150 176 };
151 177
152 const addChallenges = (inventory: IInventoryDatabaseDocument, itemsArray: ChallengeProgress[] | undefined) => {
178 const addChallenges = (inventory: IInventoryDatabaseDocument, itemsArray: IChallengeProgress[] | undefined) => {
153 179 const category = inventory.ChallengeProgress;
154 180
155 181 itemsArray?.forEach(({ Name, Progress }) => {
@@ -167,19 +193,16 @@ const addChallenges = (inventory: IInventoryDatabaseDocument, itemsArray: Challe
167 193 const gearKeys = ["Suits", "Pistols", "LongGuns", "Melee"] as const;
168 194 type GearKeysType = (typeof gearKeys)[number];
169 195
170 export const missionInventoryUpdate = async (data: MissionInventoryUpdate, accountId: string): Promise<void> => {
196 export const missionInventoryUpdate = async (data: IMissionInventoryUpdate, accountId: string): Promise<void> => {
171 197 const { RawUpgrades, MiscItems, RegularCredits, ChallengeProgress } = data;
172 198 const inventory = await getInventory(accountId);
173 199
174 // TODO - multipliers logic
175 // credits
176 inventory.RegularCredits += RegularCredits || 0;
177
178 // gear exp
200 // Gear XP
179 201 gearKeys.forEach((key: GearKeysType) => addGearExpByCategory(inventory, data[key], key));
180 202
181 // other
182 addItemsByCategory(inventory, RawUpgrades, "RawUpgrades"); // TODO - check mods fusion level
203 // Other
204 // TODO: Ensure mods have a valid fusion level and items have a valid quantity, preferably inside of the functions themselves.
205 addItemsByCategory(inventory, RawUpgrades, "RawUpgrades");
183 206 addItemsByCategory(inventory, MiscItems, "MiscItems");
184 207 addChallenges(inventory, ChallengeProgress);
185 208
@@ -187,7 +210,7 @@ export const missionInventoryUpdate = async (data: MissionInventoryUpdate, accou
187 210 };
188 211
189 212 export const addBooster = async (ItemType: string, time: number, accountId: string): Promise<void> => {
190 const currentTime = Math.floor(Date.now() / 1000) - 129600; // booster time getting more without 129600, probably defence logic, idk
213 const currentTime = Math.floor(Date.now() / 1000) - 129600; // Value is wrong without 129600. Figure out why, please. :)
191 214
192 215 const inventory = await getInventory(accountId);
193 216 const { Boosters } = inventory;
Modified src/types/commonTypes.ts +1 -1
@@ -1,3 +1,3 @@
1 export interface Oid {
1 export interface IOid {
2 2 $oid: string;
3 3 }
Added src/types/genericUpdate.ts +4 -0
@@ -0,0 +1,4 @@
1 export interface IGenericUpdate {
2 NodeIntrosCompleted: string | string[];
3 // AffiliationMods: any[];
4 }
Modified src/types/inventoryTypes/SuitTypes.ts +9 -9
@@ -1,5 +1,5 @@
1 import { Oid } from "@/src/types/commonTypes";
2 import { AbilityOverride, Color, Polarity } from "@/src/types/inventoryTypes/commonInventoryTypes";
1 import { IOid } from "@/src/types/commonTypes";
2 import { IAbilityOverride, IColor, IPolarity } from "@/src/types/inventoryTypes/commonInventoryTypes";
3 3 import { Document, Types } from "mongoose";
4 4
5 5 // export interface ISuitDocument extends ISuitResponse, Document {}
@@ -8,7 +8,7 @@ export interface ISuitDocument extends Document, ISuitResponse {
8 8 }
9 9
10 10 export interface ISuitResponse extends ISuitDatabase {
11 ItemId: Oid;
11 ItemId: IOid;
12 12 }
13 13
14 14 export interface ISuitDatabase {
@@ -18,7 +18,7 @@ export interface ISuitDatabase {
18 18 XP?: number;
19 19 InfestationDate?: Date;
20 20 Features?: number;
21 Polarity?: Polarity[];
21 Polarity?: IPolarity[];
22 22 Polarized?: number;
23 23 ModSlotPurchases?: number;
24 24 FocusLens?: string;
@@ -28,14 +28,14 @@ export interface ISuitDatabase {
28 28
29 29 export interface SuitConfig {
30 30 Skins?: string[];
31 pricol?: Color;
32 attcol?: Color;
33 eyecol?: Color;
34 sigcol?: Color;
31 pricol?: IColor;
32 attcol?: IColor;
33 eyecol?: IColor;
34 sigcol?: IColor;
35 35 Upgrades?: string[];
36 36 Songs?: Song[];
37 37 Name?: string;
38 AbilityOverride?: AbilityOverride;
38 AbilityOverride?: IAbilityOverride;
39 39 PvpUpgrades?: string[];
40 40 ugly?: boolean;
41 41 }
Modified src/types/inventoryTypes/commonInventoryTypes.ts +6 -5
@@ -1,4 +1,4 @@
1 export interface Polarity {
1 export interface IPolarity {
2 2 Slot: number;
3 3 Value: FocusSchool;
4 4 }
@@ -15,7 +15,7 @@ export enum FocusSchool {
15 15 ApWard = "AP_WARD"
16 16 }
17 17
18 export interface Color {
18 export interface IColor {
19 19 t0?: number;
20 20 t1?: number;
21 21 t2?: number;
@@ -26,16 +26,17 @@ export interface Color {
26 26 m1?: number;
27 27 }
28 28
29 export interface AbilityOverride {
29 export interface IAbilityOverride {
30 30 Ability: string;
31 31 Index: number;
32 32 }
33 33
34 export interface SlotsBin {
34 export interface ISlotsBin {
35 35 Slots: number;
36 36 }
37 37
38 export interface sigcol {
38 // ISigCol? IsIgCoL? ISIGCOL!
39 export interface Isigcol {
39 40 t0: number;
40 41 t1: number;
41 42 en: number;
Modified src/types/inventoryTypes/weaponTypes.ts +8 -8
@@ -1,9 +1,9 @@
1 import { Oid } from "@/src/types/commonTypes";
2 import { Color, Polarity } from "@/src/types/inventoryTypes/commonInventoryTypes";
1 import { IOid } from "@/src/types/commonTypes";
2 import { IColor, IPolarity } from "@/src/types/inventoryTypes/commonInventoryTypes";
3 3 import { Types } from "mongoose";
4 4
5 5 export interface IWeaponResponse extends IWeaponDatabase {
6 ItemId: Oid;
6 ItemId: IOid;
7 7 }
8 8
9 9 export interface IWeaponDatabase {
@@ -13,7 +13,7 @@ export interface IWeaponDatabase {
13 13 XP?: number;
14 14 Features?: number;
15 15 Polarized?: number;
16 Polarity?: Polarity[];
16 Polarity?: IPolarity[];
17 17 FocusLens?: string;
18 18 ModSlotPurchases?: number;
19 19 UpgradeType?: string;
@@ -26,15 +26,15 @@ export interface IWeaponDatabase {
26 26
27 27 export interface WeaponConfig {
28 28 Skins?: string[];
29 pricol?: Color;
29 pricol?: IColor;
30 30 Upgrades?: string[];
31 attcol?: Color;
32 eyecol?: OperatorLoadOutSigcol;
31 attcol?: IColor;
32 eyecol?: IOperatorLoadOutSigcol;
33 33 Name?: string;
34 34 PvpUpgrades?: string[];
35 35 }
36 36
37 export interface OperatorLoadOutSigcol {
37 export interface IOperatorLoadOutSigcol {
38 38 t0?: number;
39 39 t1?: number;
40 40 en?: number;
Modified src/types/loginTypes.ts +1 -1
@@ -10,7 +10,7 @@ export interface ILoginResponse extends Omit<IDatabaseAccountDocument, "email" |
10 10 HUB: string;
11 11 }
12 12
13 //includes virtual id
13 // Includes virtual ID
14 14 export interface IDatabaseAccountDocument extends IDatabaseAccount {
15 15 id: string;
16 16 }
Modified src/types/missionInventoryUpdateType.ts +20 -27
Modified src/types/purchaseTypes.ts +2 -3
Modified src/types/session.ts +2 -2
Modified src/types/shipTypes.ts +3 -4