From cddd4bdf5c68ca3b5da11fea71b76cea0b7e76fe Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Thu, 1 May 2025 13:51:31 -0700 Subject: [PATCH 1/9] fix: filter sortie armor/shields modifier based on mission faction (#1934) Closes #1931 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1934 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- src/services/worldStateService.ts | 86 ++++++++++++++++--------------- 1 file changed, 45 insertions(+), 41 deletions(-) diff --git a/src/services/worldStateService.ts b/src/services/worldStateService.ts index a8b4cf5a..634fc10e 100644 --- a/src/services/worldStateService.ts +++ b/src/services/worldStateService.ts @@ -230,40 +230,6 @@ const pushSortieIfRelevant = (worldState: IWorldState, day: number): void => { const boss = rng.randomElement(sortieBosses)!; - const modifiers = [ - "SORTIE_MODIFIER_LOW_ENERGY", - "SORTIE_MODIFIER_IMPACT", - "SORTIE_MODIFIER_SLASH", - "SORTIE_MODIFIER_PUNCTURE", - "SORTIE_MODIFIER_EXIMUS", - "SORTIE_MODIFIER_MAGNETIC", - "SORTIE_MODIFIER_CORROSIVE", - "SORTIE_MODIFIER_VIRAL", - "SORTIE_MODIFIER_ELECTRICITY", - "SORTIE_MODIFIER_RADIATION", - "SORTIE_MODIFIER_GAS", - "SORTIE_MODIFIER_FIRE", - "SORTIE_MODIFIER_EXPLOSION", - "SORTIE_MODIFIER_FREEZE", - "SORTIE_MODIFIER_TOXIN", - "SORTIE_MODIFIER_POISON", - "SORTIE_MODIFIER_HAZARD_RADIATION", - "SORTIE_MODIFIER_HAZARD_MAGNETIC", - "SORTIE_MODIFIER_HAZARD_FOG", // TODO: push this if the mission tileset is Grineer Forest - "SORTIE_MODIFIER_HAZARD_FIRE", // TODO: push this if the mission tileset is Corpus Ship or Grineer Galleon - "SORTIE_MODIFIER_HAZARD_ICE", - "SORTIE_MODIFIER_HAZARD_COLD", - "SORTIE_MODIFIER_SECONDARY_ONLY", - "SORTIE_MODIFIER_SHOTGUN_ONLY", - "SORTIE_MODIFIER_SNIPER_ONLY", - "SORTIE_MODIFIER_RIFLE_ONLY", - "SORTIE_MODIFIER_MELEE_ONLY", - "SORTIE_MODIFIER_BOW_ONLY" - ]; - - if (sortieBossToFaction[boss] == "FC_CORPUS") modifiers.push("SORTIE_MODIFIER_SHIELDS"); - if (sortieBossToFaction[boss] != "FC_CORPUS") modifiers.push("SORTIE_MODIFIER_ARMOR"); - const nodes: string[] = []; const availableMissionIndexes: number[] = []; for (const [key, value] of Object.entries(ExportRegions)) { @@ -314,9 +280,38 @@ const pushSortieIfRelevant = (worldState: IWorldState, day: number): void => { sortieFactionToSpecialMissionTileset[sortieBossToFaction[boss]] ); + const modifiers = [ + "SORTIE_MODIFIER_LOW_ENERGY", + "SORTIE_MODIFIER_IMPACT", + "SORTIE_MODIFIER_SLASH", + "SORTIE_MODIFIER_PUNCTURE", + "SORTIE_MODIFIER_EXIMUS", + "SORTIE_MODIFIER_MAGNETIC", + "SORTIE_MODIFIER_CORROSIVE", + "SORTIE_MODIFIER_VIRAL", + "SORTIE_MODIFIER_ELECTRICITY", + "SORTIE_MODIFIER_RADIATION", + "SORTIE_MODIFIER_GAS", + "SORTIE_MODIFIER_FIRE", + "SORTIE_MODIFIER_EXPLOSION", + "SORTIE_MODIFIER_FREEZE", + "SORTIE_MODIFIER_TOXIN", + "SORTIE_MODIFIER_POISON", + "SORTIE_MODIFIER_HAZARD_RADIATION", + "SORTIE_MODIFIER_HAZARD_MAGNETIC", + "SORTIE_MODIFIER_HAZARD_FOG", // TODO: push this if the mission tileset is Grineer Forest + "SORTIE_MODIFIER_HAZARD_FIRE", // TODO: push this if the mission tileset is Corpus Ship or Grineer Galleon + "SORTIE_MODIFIER_HAZARD_ICE", + "SORTIE_MODIFIER_HAZARD_COLD", + "SORTIE_MODIFIER_SECONDARY_ONLY", + "SORTIE_MODIFIER_SHOTGUN_ONLY", + "SORTIE_MODIFIER_SNIPER_ONLY", + "SORTIE_MODIFIER_RIFLE_ONLY", + "SORTIE_MODIFIER_BOW_ONLY" + ]; + if (i == 2 && boss != "SORTIE_BOSS_CORRUPTED_VOR" && rng.randomInt(0, 2) == 2) { - const filteredModifiers = modifiers.filter(mod => mod !== "SORTIE_MODIFIER_MELEE_ONLY"); - const modifierType = rng.randomElement(filteredModifiers)!; + const modifierType = rng.randomElement(modifiers)!; selectedNodes.push({ missionType: "MT_ASSASSINATION", @@ -334,12 +329,21 @@ const pushSortieIfRelevant = (worldState: IWorldState, day: number): void => { continue; } - const filteredModifiers = - missionType === "MT_TERRITORY" - ? modifiers.filter(mod => mod != "SORTIE_MODIFIER_HAZARD_RADIATION") - : modifiers; + modifiers.push("SORTIE_MODIFIER_MELEE_ONLY"); // not an assassination mission, can now push this - const modifierType = rng.randomElement(filteredModifiers)!; + if (missionType != "MT_TERRITORY") { + modifiers.push("SORTIE_MODIFIER_HAZARD_RADIATION"); + } + + if (ExportRegions[node].factionIndex == 0) { + // Grineer + modifiers.push("SORTIE_MODIFIER_ARMOR"); + } else if (ExportRegions[node].factionIndex == 1) { + // Corpus + modifiers.push("SORTIE_MODIFIER_SHIELDS"); + } + + const modifierType = rng.randomElement(modifiers)!; selectedNodes.push({ missionType, From 19b04533df4f83ccc852c43e0818932cfc19aa6d Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Thu, 1 May 2025 13:52:43 -0700 Subject: [PATCH 2/9] fix: omit void fissures for U35.1 (#1935) This version also has a script error even tho it should know most of the new deimos nodes... Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1935 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- src/services/worldStateService.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/worldStateService.ts b/src/services/worldStateService.ts index 634fc10e..77650d0f 100644 --- a/src/services/worldStateService.ts +++ b/src/services/worldStateService.ts @@ -721,8 +721,8 @@ export const getWorldState = (buildLabel?: string): IWorldState => { SyndicateMissions: [...staticWorldState.SyndicateMissions] }; - // Omit void fissures for versions prior to Whispers in the Walls to avoid errors with the unknown deimos nodes having void fissures. - if (buildLabel && version_compare(buildLabel, "2023.11.06.13.39") <= 0) { + // Omit void fissures for versions prior to Dante Unbound to avoid script errors. + if (buildLabel && version_compare(buildLabel, "2024.03.24.20.00") < 0) { worldState.ActiveMissions = []; } From 9b652f5c3c7a9eba2d641cd334dae31e0c48a1fc Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Thu, 1 May 2025 13:53:10 -0700 Subject: [PATCH 3/9] fix: spoof nemesis to avoid script errors in older versions (#1936) Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1936 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- src/controllers/api/inventoryController.ts | 23 ++++++++++--- src/controllers/api/loginController.ts | 4 ++- .../api/missionInventoryUpdateController.ts | 10 +++--- src/helpers/nemesisHelpers.ts | 32 ++++++++++++++++--- src/models/loginModel.ts | 1 + src/types/loginTypes.ts | 1 + 6 files changed, 56 insertions(+), 15 deletions(-) diff --git a/src/controllers/api/inventoryController.ts b/src/controllers/api/inventoryController.ts index 4f73a5f7..8febdcf7 100644 --- a/src/controllers/api/inventoryController.ts +++ b/src/controllers/api/inventoryController.ts @@ -1,5 +1,5 @@ import { RequestHandler } from "express"; -import { getAccountIdForRequest } from "@/src/services/loginService"; +import { getAccountForRequest } from "@/src/services/loginService"; import { Inventory, TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel"; import { config } from "@/src/services/configService"; import allDialogue from "@/static/fixed_responses/allDialogue.json"; @@ -24,11 +24,12 @@ import { import { logger } from "@/src/utils/logger"; import { catBreadHash } from "@/src/helpers/stringHelpers"; import { Types } from "mongoose"; +import { isNemesisCompatibleWithVersion } from "@/src/helpers/nemesisHelpers"; export const inventoryController: RequestHandler = async (request, response) => { - const accountId = await getAccountIdForRequest(request); + const account = await getAccountForRequest(request); - const inventory = await Inventory.findOne({ accountOwnerId: accountId }); + const inventory = await Inventory.findOne({ accountOwnerId: account._id }); if (!inventory) { response.status(400).json({ error: "inventory was undefined" }); @@ -119,12 +120,15 @@ export const inventoryController: RequestHandler = async (request, response) => inventory.LastInventorySync = new Types.ObjectId(); await inventory.save(); - response.json(await getInventoryResponse(inventory, "xpBasedLevelCapDisabled" in request.query)); + response.json( + await getInventoryResponse(inventory, "xpBasedLevelCapDisabled" in request.query, account.BuildLabel) + ); }; export const getInventoryResponse = async ( inventory: TInventoryDatabaseDocument, - xpBasedLevelCapDisabled: boolean + xpBasedLevelCapDisabled: boolean, + buildLabel: string | undefined ): Promise => { const inventoryWithLoadOutPresets = await inventory.populate<{ LoadOutPresets: ILoadoutDatabase }>( "LoadOutPresets" @@ -299,6 +303,15 @@ export const getInventoryResponse = async ( // Set 2FA enabled so trading post can be used inventoryResponse.HWIDProtectEnabled = true; + // Fix nemesis for older versions + if ( + inventoryResponse.Nemesis && + buildLabel && + !isNemesisCompatibleWithVersion(inventoryResponse.Nemesis, buildLabel) + ) { + inventoryResponse.Nemesis = undefined; + } + return inventoryResponse; }; diff --git a/src/controllers/api/loginController.ts b/src/controllers/api/loginController.ts index 0d595e95..366e87c3 100644 --- a/src/controllers/api/loginController.ts +++ b/src/controllers/api/loginController.ts @@ -47,7 +47,8 @@ export const loginController: RequestHandler = async (request, response) => { ForceLogoutVersion: 0, ConsentNeeded: false, TrackedSettings: [], - Nonce: nonce + Nonce: nonce, + BuildLabel: buildLabel }); logger.debug("created new account"); response.json(createLoginResponse(myAddress, newAccount, buildLabel)); @@ -88,6 +89,7 @@ export const loginController: RequestHandler = async (request, response) => { account.ClientType = loginRequest.ClientType; account.Nonce = nonce; account.CountryCode = loginRequest.lang.toUpperCase(); + account.BuildLabel = buildLabel; } await account.save(); diff --git a/src/controllers/api/missionInventoryUpdateController.ts b/src/controllers/api/missionInventoryUpdateController.ts index ff181e0b..5e642c27 100644 --- a/src/controllers/api/missionInventoryUpdateController.ts +++ b/src/controllers/api/missionInventoryUpdateController.ts @@ -1,6 +1,6 @@ import { RequestHandler } from "express"; import { getJSONfromString } from "@/src/helpers/stringHelpers"; -import { getAccountIdForRequest } from "@/src/services/loginService"; +import { getAccountForRequest } from "@/src/services/loginService"; import { IMissionInventoryUpdateRequest } from "@/src/types/requestTypes"; import { addMissionInventoryUpdates, addMissionRewards } from "@/src/services/missionInventoryUpdateService"; import { generateRewardSeed, getInventory } from "@/src/services/inventoryService"; @@ -49,11 +49,11 @@ import { IMissionInventoryUpdateResponse } from "@/src/types/missionTypes"; */ //move credit calc in here, return MissionRewards: [] if no reward info export const missionInventoryUpdateController: RequestHandler = async (req, res): Promise => { - const accountId = await getAccountIdForRequest(req); + const account = await getAccountForRequest(req); const missionReport = getJSONfromString((req.body as string).toString()); logger.debug("mission report:", missionReport); - const inventory = await getInventory(accountId); + const inventory = await getInventory(account._id.toString()); const firstCompletion = missionReport.SortieId ? inventory.CompletedSorties.indexOf(missionReport.SortieId) == -1 : false; @@ -65,7 +65,7 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res) ) { inventory.RewardSeed = generateRewardSeed(); await inventory.save(); - const inventoryResponse = await getInventoryResponse(inventory, true); + const inventoryResponse = await getInventoryResponse(inventory, true, account.BuildLabel); res.json({ InventoryJson: JSON.stringify(inventoryResponse), MissionRewards: [] @@ -84,7 +84,7 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res) inventory.RewardSeed = generateRewardSeed(); await inventory.save(); - const inventoryResponse = await getInventoryResponse(inventory, true); + const inventoryResponse = await getInventoryResponse(inventory, true, account.BuildLabel); //TODO: figure out when to send inventory. it is needed for many cases. res.json({ diff --git a/src/helpers/nemesisHelpers.ts b/src/helpers/nemesisHelpers.ts index 3a146831..5df1ad9a 100644 --- a/src/helpers/nemesisHelpers.ts +++ b/src/helpers/nemesisHelpers.ts @@ -6,7 +6,7 @@ import { logger } from "../utils/logger"; import { IOid } from "../types/commonTypes"; import { Types } from "mongoose"; import { addMods, generateRewardSeed } from "../services/inventoryService"; -import { isArchwingMission } from "../services/worldStateService"; +import { isArchwingMission, version_compare } from "../services/worldStateService"; import { fromStoreItem, toStoreItem } from "../services/itemDataService"; import { createMessage } from "../services/inboxService"; @@ -237,15 +237,39 @@ const corpusVersionThreeWeapons = [ export const getWeaponsForManifest = (manifest: string): readonly string[] => { switch (manifest) { - case "/Lotus/Types/Game/Nemesis/KuvaLich/KuvaLichManifestVersionSix": + case "/Lotus/Types/Game/Nemesis/KuvaLich/KuvaLichManifestVersionSix": // >= 35.6.0 return kuvaLichVersionSixWeapons; - case "/Lotus/Types/Enemies/Corpus/Lawyers/LawyerManifestVersionThree": - case "/Lotus/Types/Enemies/Corpus/Lawyers/LawyerManifestVersionFour": + case "/Lotus/Types/Enemies/Corpus/Lawyers/LawyerManifestVersionThree": // >= 35.6.0 + case "/Lotus/Types/Enemies/Corpus/Lawyers/LawyerManifestVersionFour": // >= 37.0.0 return corpusVersionThreeWeapons; } throw new Error(`unknown nemesis manifest: ${manifest}`); }; +export const isNemesisCompatibleWithVersion = ( + nemesis: { manifest: string; Faction: string }, + buildLabel: string +): boolean => { + // Anything below 35.6.0 is not going to be okay given our set of supported manifests. + if (version_compare(buildLabel, "2024.05.15.11.07") < 0) { + return false; + } + + if (nemesis.Faction == "FC_INFESTATION") { + // Anything below 38.5.0 isn't gonna like an infested lich. + if (version_compare(buildLabel, "2025.03.18.16.07") < 0) { + return false; + } + } else if (nemesis.manifest == "/Lotus/Types/Enemies/Corpus/Lawyers/LawyerManifestVersionFour") { + // Anything below 37.0.0 isn't gonna know version 4, but version 3 is identical in terms of weapon choices, so we can spoof it to that. + if (version_compare(buildLabel, "2024.10.01.11.03") < 0) { + nemesis.manifest = "/Lotus/Types/Enemies/Corpus/Lawyers/LawyerManifestVersionThree"; + } + } + + return true; +}; + export const getInnateDamageTag = ( KillingSuit: string ): diff --git a/src/models/loginModel.ts b/src/models/loginModel.ts index 3e564aa6..fe9d0b5f 100644 --- a/src/models/loginModel.ts +++ b/src/models/loginModel.ts @@ -20,6 +20,7 @@ const databaseAccountSchema = new Schema( ConsentNeeded: { type: Boolean, required: true }, TrackedSettings: { type: [String], default: [] }, Nonce: { type: Number, default: 0 }, + BuildLabel: String, Dropped: Boolean, LatestEventMessageDate: { type: Date, default: 0 }, LastLoginRewardDate: { type: Number, default: 0 }, diff --git a/src/types/loginTypes.ts b/src/types/loginTypes.ts index 79cf538d..dfdebe0e 100644 --- a/src/types/loginTypes.ts +++ b/src/types/loginTypes.ts @@ -16,6 +16,7 @@ export interface IAccountAndLoginResponseCommons { export interface IDatabaseAccountRequiredFields extends IAccountAndLoginResponseCommons { email: string; password: string; + BuildLabel?: string; } export interface IDatabaseAccount extends IDatabaseAccountRequiredFields { From 49834172014b1269ec759d6e3615526f53941d94 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Thu, 1 May 2025 13:53:28 -0700 Subject: [PATCH 4/9] chore: update certificate (#1937) This is good for *.faketls.com until March 2026. Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1937 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- static/certs/cert.pem | 58 +++++++++++++++++++++---------------------- static/certs/key.pem | 52 +++++++++++++++++++------------------- 2 files changed, 55 insertions(+), 55 deletions(-) diff --git a/static/certs/cert.pem b/static/certs/cert.pem index 4f043e8a..4bce415b 100644 --- a/static/certs/cert.pem +++ b/static/certs/cert.pem @@ -1,38 +1,38 @@ -----BEGIN CERTIFICATE----- -MIIGLzCCBRegAwIBAgIRAILIyLcitteoEGcJt1QBXvcwDQYJKoZIhvcNAQELBQAw -gY8xCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO -BgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDE3MDUGA1UE -AxMuU2VjdGlnbyBSU0EgRG9tYWluIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZlciBD -QTAeFw0yNDA4MDIwMDAwMDBaFw0yNTA4MDIyMzU5NTlaMBcxFTATBgNVBAMMDCou -dmlhdGxzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMTToSjY -3aUIxjghIkikJfFExVwSEzIM2XaQNJE+SxQ6Cc+xUR5QJrMJnM/39sH5c5imMEUo -2OnstCIaVMPx5ZPN+HXLsvmoVAe2/xYe7emnZ5ZFTUXPyqkzDRg0hkMJiWWo/Nmf -ypZfUJoz6hVkXwsgNFPTVuo7aECQFlZslh2HQVDOfBaNBxQBaOJ5vf6nllf/aLyB -tZ74nlLynVYV9kYzISP4dUcxQ+D4HZgIxyOQfcN3EHUS1ZVaIp8hupOygF8zGQyJ -uzFozzg5I59U+hT1yQG3FlwTBnP+sA0+hW0LBTbWSISm0If1SgHlUEqxLlosjuTG -BG45h9o2bAz9po0CAwEAAaOCAvswggL3MB8GA1UdIwQYMBaAFI2MXsRUrYrhd+mb -+ZsF4bgBjWHhMB0GA1UdDgQWBBQ/OeA2gLbVIKIuIitYRqSRUWMP3TAOBgNVHQ8B +MIIGMDCCBRigAwIBAgIQX4800cgswlDH/QexMSnnnjANBgkqhkiG9w0BAQsFADCB +jzELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTcwNQYDVQQD +Ey5TZWN0aWdvIFJTQSBEb21haW4gVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENB +MB4XDTI1MDMwNjAwMDAwMFoXDTI2MDMwNjIzNTk1OVowGDEWMBQGA1UEAwwNKi5m +YWtldGxzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMe42XWK +HJuR7doFTX79zrEKfTlD2hjRIif3dHKJNTJNvZa52mIoHelP7RVUuFOhp7aZCNLh +IEzDyZObl8vwO6L2PVu5tbBEEoNixbpfhc8ZICEBuVo2UAhnJFcMJtuvtrCq+7ye +oczM/k/nh8FBz2WnLzWs4CZt1sa5knZXFmBmsHJQtQIC6vx7QzVcKGOlAosIEHSK +X4nIz5fLgWSzor1Gay56j31PTk+qRvlPQM2aKiLWnlLfRED4zHJqLe94itu8llPX +b6g+cLxxRKUpMqtG/15cDdBZwv40Dja7bmNfe1u4w2QCVLjvHVaVpNXbcRay/Mhn +M1w5LzDZmV58b18CAwEAAaOCAvwwggL4MB8GA1UdIwQYMBaAFI2MXsRUrYrhd+mb ++ZsF4bgBjWHhMB0GA1UdDgQWBBS6/x/N38wMJrQq/cE1oIcRERMonTAOBgNVHQ8B Af8EBAMCBaAwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB BQUHAwIwSQYDVR0gBEIwQDA0BgsrBgEEAbIxAQICBzAlMCMGCCsGAQUFBwIBFhdo dHRwczovL3NlY3RpZ28uY29tL0NQUzAIBgZngQwBAgEwgYQGCCsGAQUFBwEBBHgw djBPBggrBgEFBQcwAoZDaHR0cDovL2NydC5zZWN0aWdvLmNvbS9TZWN0aWdvUlNB RG9tYWluVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNydDAjBggrBgEFBQcwAYYX -aHR0cDovL29jc3Auc2VjdGlnby5jb20wIwYDVR0RBBwwGoIMKi52aWF0bHMuY29t -ggp2aWF0bHMuY29tMIIBfwYKKwYBBAHWeQIEAgSCAW8EggFrAWkAdQDd3Mo0ldfh -FgXnlTL6x5/4PRxQ39sAOhQSdgosrLvIKgAAAZEVLi9VAAAEAwBGMEQCIGiZNOV7 -IvcHKU7nEaxFgWPpUu2CxyULg1ueJTYwTT12AiAJWQv3RrqCtOJC7JEdztILs3Bn -an9s0Bf93uOE4C/LiAB3AA3h8jAr0w3BQGISCepVLvxHdHyx1+kw7w5CHrR+Tqo0 -AAABkRUuLxAAAAQDAEgwRgIhAOhlC+IpJV3uAaDCRXi6RZ+V8++QaLaTEtqFp2UP -yWeSAiEA8qtGDk1RE1VGwQQcJCf3CBYU5YTlsZNi7F6hEONLuzMAdwAS8U40vVNy -TIQGGcOPP3oT+Oe1YoeInG0wBYTr5YYmOgAAAZEVLi7kAAAEAwBIMEYCIQDWCnSm -N+2/xxo8bl3pbpNBEBZZIwnYPQW0A+SJ0+dboQIhANjH2L0xV/+rPuPMzK40vk3J -1fWHLocLjpgaxGhsBAOzMA0GCSqGSIb3DQEBCwUAA4IBAQBcObVjc1zFdOER50ZF -mI+WyVF8t6nV6dm3zIDraLA4++zKUu9UKNJm9YPqLdPP7uTLHz6wuBNmyuWPdF0r -qAf4vsK3tcAds7kjK8injewEUCPG20mtNMUHyhlNEOJR2ySPPQ6Q+t+TtGAnimKa -Zr86quYgYaJYhoEEXcbB9fMoDQYlJDzgT2DXvfM4cyoden2tYZ3gQS6ftiXacBe0 -WzFWYZ8mIP2Kb+D9tCapB9MVUzu3XJVy3S2FLQEWcWIvjnpad73a0/35i/nro6/k -TSK+MKBEBaNZuHJ8ubCToo1BftnsS8HuEPTNe8W1hyc2YmT9f5YQP6HWB2rxjH42 -OTXh +aHR0cDovL29jc3Auc2VjdGlnby5jb20wJQYDVR0RBB4wHIINKi5mYWtldGxzLmNv +bYILZmFrZXRscy5jb20wggF+BgorBgEEAdZ5AgQCBIIBbgSCAWoBaAB2AJaXZL9V +WJet90OHaDcIQnfp8DrV9qTzNm5GpD8PyqnGAAABlWsz5fgAAAQDAEcwRQIgTN7Y +/mDqiD3RbGVLEOQK2wvXsboBolBRwGJFuFEsDScCIQCQ0qfb/0V8qqSxrkx/PiVS +1lSn5gBEnQUiQOkefcnW0gB2ABmG1Mcoqm/+ugNveCpNAZGqzi1yMQ+uzl1wQS0l +TMfUAAABlWsz5dAAAAQDAEcwRQIhAJnQJyrSCWWdi9Kyoa7XuMGyDKt183jJMY0E +71abTuBOAiBC+WnK1esG6xr8aVGHRcc+1U/I7LiaG3LCRMYtCKrTGwB2AMs49xWJ +fIShRF9bwd37yW7ymlnNRwppBYWwyxTDFFjnAAABlWsz5f4AAAQDAEcwRQIhAJUs +4PWDwyQJnCxCyEwFlFUY2uYQkGrQPA9f9Sw5Xk1fAiB63eQtZQGjvzvhOghy6z9a +8oGYbDfDQ/zfisMYO7rM6zANBgkqhkiG9w0BAQsFAAOCAQEAEHnSoeBbWiK3CS3a +px0BL+YXxRxdUcTMHgn5o+LlI9sWlpf+JLXmn7Z4QA6fAwT4k/Ue7xsmIq0OraDk +/pEVXWm1HO/9wUkGQg0DBi77BpfHircd7OWIMdt250Q8UAmZkOyhVgnwBcScqMwq +2T5CPaYvYGgYWx/qkIBv7JqhVbrP82rnF9b9ZUZ8GIE31chBmtMva9AsnAN5dmRw +81bVvPWXUfX30CYu5sxeWL06Zpy9nfJumxZri1SWXNTBjSvud2jsZ8tSCUAWLL/4 +ui3Vien9m2oMOpaA8xbS88ZTk9Alm/o5febEKJZUPlytQzij8gQpiovFw2v+Cdei ++tFXKw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIGEzCCA/ugAwIBAgIQfVtRJrR2uhHbdBYLvFMNpzANBgkqhkiG9w0BAQwFADCB diff --git a/static/certs/key.pem b/static/certs/key.pem index 42a099a8..6135769a 100644 --- a/static/certs/key.pem +++ b/static/certs/key.pem @@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDE06Eo2N2lCMY4 -ISJIpCXxRMVcEhMyDNl2kDSRPksUOgnPsVEeUCazCZzP9/bB+XOYpjBFKNjp7LQi -GlTD8eWTzfh1y7L5qFQHtv8WHu3pp2eWRU1Fz8qpMw0YNIZDCYllqPzZn8qWX1Ca -M+oVZF8LIDRT01bqO2hAkBZWbJYdh0FQznwWjQcUAWjieb3+p5ZX/2i8gbWe+J5S -8p1WFfZGMyEj+HVHMUPg+B2YCMcjkH3DdxB1EtWVWiKfIbqTsoBfMxkMibsxaM84 -OSOfVPoU9ckBtxZcEwZz/rANPoVtCwU21kiEptCH9UoB5VBKsS5aLI7kxgRuOYfa -NmwM/aaNAgMBAAECggEAEYK8bzxf96tAq0SzXqAP6heSsV7AS28eN7CbpKJUnp+N -OOePDnHWB46e31exoc82DAoY+EYqiiEvY2tRSD9wi8ZCyQQOz6w8kZUju42T3/ov -Ooy+06upXYU3sIQXv8YM7bjridbv+JHRQ27D8BRGamB6l0yRinQvkbLf8d9mOYkj -P5yYrpMPV/mfgkCir/aBlGOzmI+CuOv7FdF9DIz2OehtPXOzbExuab4xOQ4NQrN9 -TfzWWS798D86e5uDx+Ab0pfege8IJvEBjU5ngZo3aeS/F5i2us+BXImu1P6IrYdb -ekXUo9VJPEHiD02iyLW/gFz3/AsWa3ztinXN0I069wKBgQD7yGPX6LG7MXlXEqL2 -DuCrFsKzVC4z0c/cpPXO8Xb8rGzvHR7Oa0i5Bo7i5wRiVXS87HT25iZmB78yjKnI -bVmWA3tVWInx6fixbZUO7L4D/Q1Ddfin/DiXyNpAhKii0QgpD61P7HJnrfnwUar5 -Vpwd2grnPNCbuILZxAZhtIXRnwKBgQDIH5hmyiIUAvrz+4UpE55ecxTMOkj0+Pgx -79KpSjXfEIk5V7UmCSk1SusQWq8Ri9d6QqPcTptVhxmC/geolp9bCW14JdORbjNv -5+3JfAwgZJtbDP4l3GKf168fLQXzSpWCW3vT1lCBz4x4nNs2EudTdDCn5aUVLGEJ -v15Iz0dQUwKBgHuZh8n55SXrx5FDCNSZwRi796Bo9rVhjhTWtgR87NhlHKTVOsZC -TFToL0Sb+776DHCh81kw6jC0JNv/yWkmpQ/LbcQbzrv/C6KuFLpa5Xy3wMcZJpPw -cSex5dI+TTqAOu1NUNsnS5IyCbw7mx8DsWfGHgweApovHa0hWbClGfwpAoGAfSt9 -6DTfkcK3cilMhX+2236BcKe4ADlFC/7jtW0sOsQeAFbCf/LU6ndchVMjEwdzlA3g -bahg8eLZaxw2cBUdwRQpey+1n83csE7RZOeIsi4bGZ0LzWSF71I5P3eqtBxfXTSZ -Q8tVeYv2YW5CkhTKyWDwGePCGHc0jqM6drHm+e8CgYEA+IkvplnK76zx3M579TpI -M2ffiC2b12FtJMpgnNrk6HZ19o2mhbte/7wf9SHVqsRw4V7/n6rzBJ5wzEHOWre7 -7PrkLgS0mY2SRfMmeT74m59dA8GpvhBUW/Xa4wlDtZkU2iIcDkKnYLjgrTKjlK86 -ER+evzmHeTqYJzuK8Mfq93I= +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDHuNl1ihybke3a +BU1+/c6xCn05Q9oY0SIn93RyiTUyTb2WudpiKB3pT+0VVLhToae2mQjS4SBMw8mT +m5fL8Dui9j1bubWwRBKDYsW6X4XPGSAhAblaNlAIZyRXDCbbr7awqvu8nqHMzP5P +54fBQc9lpy81rOAmbdbGuZJ2VxZgZrByULUCAur8e0M1XChjpQKLCBB0il+JyM+X +y4Fks6K9Rmsueo99T05Pqkb5T0DNmioi1p5S30RA+Mxyai3veIrbvJZT12+oPnC8 +cUSlKTKrRv9eXA3QWcL+NA42u25jX3tbuMNkAlS47x1WlaTV23EWsvzIZzNcOS8w +2ZlefG9fAgMBAAECggEAT1Tti/LASks8300b60WFxG0WMJjzGMh5eMaiSpyVtNWM +aUKJrFOjDfnhgoeUcCPWKoG/L4Sc/+EFQMydDzTte120IasysEFZ2TZytAUdcZXZ +XUMCDQNl5vCRTsJU7Q5u0t4YAGRCgMcsfTDKi8lISGiQKBHzN1CJ74Xm13rgOInd +lAc0wd5S89sL6RYmRTj1LvuZ95EHXHqQGdv0fIFEyP3pF1iPwcoTuIVEeICqnEvW +vd8CVO68eH3HFIwioqjp4qW3pxPZMhVq4161805uAMkoQlE+7MtEVenmP++1u1gM +FjvAs3j9CZqOHZKcLlOtcGSwDlD++fCMMT4slLgLgQKBgQDy58E5nuYXdxlFQQk4 +QccUKpyJ2aVXyp9xvTFBot/5Pik1SkuDzv2XU1OTxdxf3EongLy91nMJ2/6/39Je +lf0/2MjzCtJ/lSzZ/zpJAu86UkBkWBAA5loGIof6OKedbEIgqpJqtK59S+j3ExO9 +eqa+uFrtt1UfaJG4A7TT+dIvIwKBgQDSfSOdSM5Dh3KsQHVnIWcIkzwTtlJlO+rG +6rDEADxw6Kp8VIL/dq4Foe8yW4VqLVrWUuZsU6jzC9GdnyYi6VaqZ/iSUtGkBMOT +WTTYhqXlURaQ13jhqdwCZJRbVI72JbXn2OGEv8DgXnk//QKED/8VdKqAzCSr1t1f +3yfwei0AlQKBgD19KU66yKg7/+umEP1quUiDmOjUbaSRqFcUe3mQD356m9ffnMob +BdrevxNzTNv/Wc4yKpUryic+x3gu4oQLF/annAbaQHsHejkdANYmpgRvedls6XAw +360Z5K4U1WlmVD8Mrs/QOTOCmdChxad7euZgqLPwat3ujKS2W3oljW1dAoGBAM4/ +AB6lsDZLCfnuTxt2h1bHrh5CkAnR5AJ1BC+Ja6/WyvZ4eMOIroumWJKnStr3BgLr +yAxtDSbZddNUljGvIdRnfBEkRXbJlDlVN4rSpMtF4S6bcz7rCUDu/M9g05Qs70j2 +IkPJAFzZNUWVzFlKs096uXbqkSQvrUq7ho8DqAThAoGBAL7Nrbr5LWcBgvwEhEla +VRfYb0FUrDwLIrVWntJjW566/pVQQ4BmatsblLjlQYWk9MCIYXWZbnB+2fRx9yjQ +Adggez7Dws/Mrh/wVudKgayHCy5Lgd8rYjNgC+VZf8XGrWX3QXMJ6UWAyQLTeoO7 +hToW9o9CQMIhaR43G8di1kjF -----END PRIVATE KEY----- From 159598979df9abed12c28ebe7b63eed7deefeaa6 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Thu, 1 May 2025 13:53:40 -0700 Subject: [PATCH 5/9] fix: don't duplicate level key credits reward (#1940) Closes #1939 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1940 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- src/services/missionInventoryUpdateService.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/services/missionInventoryUpdateService.ts b/src/services/missionInventoryUpdateService.ts index dc670c59..86c414f5 100644 --- a/src/services/missionInventoryUpdateService.ts +++ b/src/services/missionInventoryUpdateService.ts @@ -858,8 +858,7 @@ export const addMissionRewards = async ( for (const reward of fixedLevelRewards.levelKeyRewards2) { //quest stage completion credit rewards if (reward.rewardType == "RT_CREDITS") { - inventory.RegularCredits += reward.amount; - missionCompletionCredits += reward.amount; + missionCompletionCredits += reward.amount; // will be added to inventory in addCredits continue; } MissionRewards.push({ From f7906c91e3daed1c437b921f1229183fe949a208 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Thu, 1 May 2025 13:54:04 -0700 Subject: [PATCH 6/9] fix: ignore purchaseQuantity for webui add items (#1944) Closes #1942 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1944 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- src/controllers/custom/addItemsController.ts | 2 +- src/services/inventoryService.ts | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/controllers/custom/addItemsController.ts b/src/controllers/custom/addItemsController.ts index 15837602..dc39ef64 100644 --- a/src/controllers/custom/addItemsController.ts +++ b/src/controllers/custom/addItemsController.ts @@ -7,7 +7,7 @@ export const addItemsController: RequestHandler = async (req, res) => { const requests = req.body as IAddItemRequest[]; const inventory = await getInventory(accountId); for (const request of requests) { - await addItem(inventory, request.ItemType, request.ItemCount, true); + await addItem(inventory, request.ItemType, request.ItemCount, true, undefined, undefined, true); } await inventory.save(); res.end(); diff --git a/src/services/inventoryService.ts b/src/services/inventoryService.ts index 089e2fbb..a241e796 100644 --- a/src/services/inventoryService.ts +++ b/src/services/inventoryService.ts @@ -332,7 +332,8 @@ export const addItem = async ( quantity: number = 1, premiumPurchase: boolean = false, seed?: bigint, - targetFingerprint?: string + targetFingerprint?: string, + exactQuantity: boolean = false ): Promise => { // Bundles are technically StoreItems but a) they don't have a normal counterpart, and b) they are used in non-StoreItem contexts, e.g. email attachments. if (typeName in ExportBundles) { @@ -490,7 +491,9 @@ export const addItem = async ( // Multipling by purchase quantity for gear because: // - The Saya's Vigil scanner message has it as a non-counted attachment. // - Blueprints for Ancient Protector Specter, Shield Osprey Specter, etc. have num=1 despite giving their purchaseQuantity. - quantity *= ExportGear[typeName].purchaseQuantity ?? 1; + if (!exactQuantity) { + quantity *= ExportGear[typeName].purchaseQuantity ?? 1; + } const consumablesChanges = [ { ItemType: typeName, From ec9dc2aa5fe6830d7aec21a5c71986dac839b12c Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Thu, 1 May 2025 13:54:27 -0700 Subject: [PATCH 7/9] fix: multiply standing cost by purchase quantity (#1948) Closes #1945 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1948 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- src/services/purchaseService.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/purchaseService.ts b/src/services/purchaseService.ts index 728f6570..38cfd3d1 100644 --- a/src/services/purchaseService.ts +++ b/src/services/purchaseService.ts @@ -223,10 +223,10 @@ export const handlePurchase = async ( purchaseResponse.Standing = [ { Tag: syndicateTag, - Standing: favour.standingCost + Standing: favour.standingCost * purchaseRequest.PurchaseParams.Quantity } ]; - affiliation.Standing -= favour.standingCost; + affiliation.Standing -= favour.standingCost * purchaseRequest.PurchaseParams.Quantity; } } } From a8227ce54cf1fb0f761f60a1a504705e4a62435f Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Thu, 1 May 2025 13:54:50 -0700 Subject: [PATCH 8/9] feat: cure vasca virus (#1949) Closes #1946 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1949 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- src/services/inventoryService.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/services/inventoryService.ts b/src/services/inventoryService.ts index a241e796..22106441 100644 --- a/src/services/inventoryService.ts +++ b/src/services/inventoryService.ts @@ -1509,7 +1509,9 @@ export const applyClientEquipmentUpdates = ( } if (InfestationDate) { - item.InfestationDate = fromMongoDate(InfestationDate); + // 2147483647000 means cured, otherwise became infected + item.InfestationDate = + InfestationDate.$date.$numberLong == "2147483647000" ? new Date(0) : fromMongoDate(InfestationDate); } }); }; From 8f8bc5b36430474ba76fb6972a7a27c7318d6777 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Thu, 1 May 2025 13:55:01 -0700 Subject: [PATCH 9/9] fix: don't set G3/Zanuka death marks by default (#1950) These should only be set to true after completing an invasion for the enemy faction. Re #1097 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1950 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- src/models/inventoryModels/inventoryModel.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/models/inventoryModels/inventoryModel.ts b/src/models/inventoryModels/inventoryModel.ts index 8c53d608..5525b500 100644 --- a/src/models/inventoryModels/inventoryModel.ts +++ b/src/models/inventoryModels/inventoryModel.ts @@ -1688,9 +1688,9 @@ const inventorySchema = new Schema( //Like BossAladV,BossCaptainVor come for you on missions % chance DeathMarks: { type: [String], default: [] }, //Zanuka - Harvestable: { type: Boolean, default: true }, + Harvestable: Boolean, //Grustag three - DeathSquadable: { type: Boolean, default: true }, + DeathSquadable: Boolean, EndlessXP: { type: [endlessXpProgressSchema], default: undefined },