forked from OpenWF/SpaceNinjaServer
		
	fix: generate rewards based on RewardSeed to match what's show in client (#1628)
Reviewed-on: OpenWF/SpaceNinjaServer#1628 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									d28437b658
								
							
						
					
					
						commit
						3f0a2bec48
					
				@ -1,14 +1,12 @@
 | 
				
			|||||||
import { Inventory } from "@/src/models/inventoryModels/inventoryModel";
 | 
					import { Inventory } from "@/src/models/inventoryModels/inventoryModel";
 | 
				
			||||||
import { generateRewardSeed } from "@/src/services/inventoryService";
 | 
					import { generateRewardSeed } from "@/src/services/inventoryService";
 | 
				
			||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
					import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
				
			||||||
import { logger } from "@/src/utils/logger";
 | 
					 | 
				
			||||||
import { RequestHandler } from "express";
 | 
					import { RequestHandler } from "express";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const getNewRewardSeedController: RequestHandler = async (req, res) => {
 | 
					export const getNewRewardSeedController: RequestHandler = async (req, res) => {
 | 
				
			||||||
    const accountId = await getAccountIdForRequest(req);
 | 
					    const accountId = await getAccountIdForRequest(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const rewardSeed = generateRewardSeed();
 | 
					    const rewardSeed = generateRewardSeed();
 | 
				
			||||||
    logger.debug(`generated new reward seed: ${rewardSeed}`);
 | 
					 | 
				
			||||||
    await Inventory.updateOne(
 | 
					    await Inventory.updateOne(
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            accountOwnerId: accountId
 | 
					            accountOwnerId: accountId
 | 
				
			||||||
 | 
				
			|||||||
@ -1213,7 +1213,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
 | 
				
			|||||||
        accountOwnerId: Schema.Types.ObjectId,
 | 
					        accountOwnerId: Schema.Types.ObjectId,
 | 
				
			||||||
        SubscribedToEmails: { type: Number, default: 0 },
 | 
					        SubscribedToEmails: { type: Number, default: 0 },
 | 
				
			||||||
        SubscribedToEmailsPersonalized: { type: Number, default: 0 },
 | 
					        SubscribedToEmailsPersonalized: { type: Number, default: 0 },
 | 
				
			||||||
        RewardSeed: Number,
 | 
					        RewardSeed: BigInt,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //Credit
 | 
					        //Credit
 | 
				
			||||||
        RegularCredits: { type: Number, default: 0 },
 | 
					        RegularCredits: { type: Number, default: 0 },
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@ import {
 | 
				
			|||||||
} from "warframe-public-export-plus";
 | 
					} from "warframe-public-export-plus";
 | 
				
			||||||
import { IMissionInventoryUpdateRequest, IRewardInfo } from "../types/requestTypes";
 | 
					import { IMissionInventoryUpdateRequest, IRewardInfo } from "../types/requestTypes";
 | 
				
			||||||
import { logger } from "@/src/utils/logger";
 | 
					import { logger } from "@/src/utils/logger";
 | 
				
			||||||
import { IRngResult, getRandomElement, getRandomReward } from "@/src/services/rngService";
 | 
					import { IRngResult, SRng, getRandomElement, getRandomReward } from "@/src/services/rngService";
 | 
				
			||||||
import { equipmentKeys, TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
 | 
					import { equipmentKeys, TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
    addBooster,
 | 
					    addBooster,
 | 
				
			||||||
@ -31,6 +31,7 @@ import {
 | 
				
			|||||||
    addShipDecorations,
 | 
					    addShipDecorations,
 | 
				
			||||||
    addStanding,
 | 
					    addStanding,
 | 
				
			||||||
    combineInventoryChanges,
 | 
					    combineInventoryChanges,
 | 
				
			||||||
 | 
					    generateRewardSeed,
 | 
				
			||||||
    updateCurrency,
 | 
					    updateCurrency,
 | 
				
			||||||
    updateSyndicate
 | 
					    updateSyndicate
 | 
				
			||||||
} from "@/src/services/inventoryService";
 | 
					} from "@/src/services/inventoryService";
 | 
				
			||||||
@ -70,7 +71,12 @@ const getRotations = (rotationCount: number, tierOverride: number | undefined):
 | 
				
			|||||||
    return rotatedValues;
 | 
					    return rotatedValues;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getRandomRewardByChance = (pool: IReward[]): IRngResult | undefined => {
 | 
					const getRandomRewardByChance = (pool: IReward[], rng?: SRng): IRngResult | undefined => {
 | 
				
			||||||
 | 
					    if (rng) {
 | 
				
			||||||
 | 
					        const res = rng.randomReward(pool as IRngResult[]);
 | 
				
			||||||
 | 
					        rng.randomFloat(); // something related to rewards multiplier
 | 
				
			||||||
 | 
					        return res;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return getRandomReward(pool as IRngResult[]);
 | 
					    return getRandomReward(pool as IRngResult[]);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -548,6 +554,11 @@ export const addMissionRewards = async (
 | 
				
			|||||||
        return { MissionRewards: [] };
 | 
					        return { MissionRewards: [] };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (rewardInfo.rewardSeed) {
 | 
				
			||||||
 | 
					        // We're using a reward seed, so give the client a new one in the response. On live, missionInventoryUpdate seems to always provide a fresh one in the response.
 | 
				
			||||||
 | 
					        inventory.RewardSeed = generateRewardSeed();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //TODO: check double reward merging
 | 
					    //TODO: check double reward merging
 | 
				
			||||||
    const MissionRewards: IMissionReward[] = getRandomMissionDrops(rewardInfo, wagerTier);
 | 
					    const MissionRewards: IMissionReward[] = getRandomMissionDrops(rewardInfo, wagerTier);
 | 
				
			||||||
    logger.debug("random mission drops:", MissionRewards);
 | 
					    logger.debug("random mission drops:", MissionRewards);
 | 
				
			||||||
@ -1062,6 +1073,7 @@ function getRandomMissionDrops(RewardInfo: IRewardInfo, tierOverride: number | u
 | 
				
			|||||||
        if (rewardManifests.length != 0) {
 | 
					        if (rewardManifests.length != 0) {
 | 
				
			||||||
            logger.debug(`generating random mission rewards`, { rewardManifests, rotations });
 | 
					            logger.debug(`generating random mission rewards`, { rewardManifests, rotations });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        const rng = new SRng(BigInt(RewardInfo.rewardSeed ?? generateRewardSeed()) ^ 0xffffffffffffffffn);
 | 
				
			||||||
        rewardManifests.forEach(name => {
 | 
					        rewardManifests.forEach(name => {
 | 
				
			||||||
            const table = ExportRewards[name];
 | 
					            const table = ExportRewards[name];
 | 
				
			||||||
            if (!table) {
 | 
					            if (!table) {
 | 
				
			||||||
@ -1070,7 +1082,7 @@ function getRandomMissionDrops(RewardInfo: IRewardInfo, tierOverride: number | u
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            for (const rotation of rotations) {
 | 
					            for (const rotation of rotations) {
 | 
				
			||||||
                const rotationRewards = table[rotation];
 | 
					                const rotationRewards = table[rotation];
 | 
				
			||||||
                const drop = getRandomRewardByChance(rotationRewards);
 | 
					                const drop = getRandomRewardByChance(rotationRewards, rng);
 | 
				
			||||||
                if (drop) {
 | 
					                if (drop) {
 | 
				
			||||||
                    drops.push({ StoreItem: drop.type, ItemCount: drop.itemCount });
 | 
					                    drops.push({ StoreItem: drop.type, ItemCount: drop.itemCount });
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
				
			|||||||
@ -31,7 +31,7 @@ const getRewardAtPercentage = <T extends { probability: number }>(pool: T[], per
 | 
				
			|||||||
            return item;
 | 
					            return item;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    throw new Error("What the fuck?");
 | 
					    return pool[pool.length - 1];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const getRandomReward = <T extends { probability: number }>(pool: T[]): T | undefined => {
 | 
					export const getRandomReward = <T extends { probability: number }>(pool: T[]): T | undefined => {
 | 
				
			||||||
@ -142,4 +142,8 @@ export class SRng {
 | 
				
			|||||||
        this.state = (0x5851f42d4c957f2dn * this.state + 0x14057b7ef767814fn) & 0xffffffffffffffffn;
 | 
					        this.state = (0x5851f42d4c957f2dn * this.state + 0x14057b7ef767814fn) & 0xffffffffffffffffn;
 | 
				
			||||||
        return (Number(this.state >> 38n) & 0xffffff) * 0.000000059604645;
 | 
					        return (Number(this.state >> 38n) & 0xffffff) * 0.000000059604645;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    randomReward<T extends { probability: number }>(pool: T[]): T | undefined {
 | 
				
			||||||
 | 
					        return getRewardAtPercentage(pool, this.randomFloat());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -194,7 +194,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
 | 
				
			|||||||
    Mailbox?: IMailboxClient;
 | 
					    Mailbox?: IMailboxClient;
 | 
				
			||||||
    SubscribedToEmails: number;
 | 
					    SubscribedToEmails: number;
 | 
				
			||||||
    Created: IMongoDate;
 | 
					    Created: IMongoDate;
 | 
				
			||||||
    RewardSeed: number;
 | 
					    RewardSeed: number | bigint;
 | 
				
			||||||
    RegularCredits: number;
 | 
					    RegularCredits: number;
 | 
				
			||||||
    PremiumCredits: number;
 | 
					    PremiumCredits: number;
 | 
				
			||||||
    PremiumCreditsFree: number;
 | 
					    PremiumCreditsFree: number;
 | 
				
			||||||
 | 
				
			|||||||
@ -141,7 +141,7 @@ export interface IRewardInfo {
 | 
				
			|||||||
    EOM_AFK?: number;
 | 
					    EOM_AFK?: number;
 | 
				
			||||||
    rewardQualifications?: string; // did a Survival for 5 minutes and this was "1"
 | 
					    rewardQualifications?: string; // did a Survival for 5 minutes and this was "1"
 | 
				
			||||||
    PurgatoryRewardQualifications?: string;
 | 
					    PurgatoryRewardQualifications?: string;
 | 
				
			||||||
    rewardSeed?: number;
 | 
					    rewardSeed?: number | bigint;
 | 
				
			||||||
    periodicMissionTag?: string;
 | 
					    periodicMissionTag?: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // for bounties, only EOM_AFK and node are given from above, plus:
 | 
					    // for bounties, only EOM_AFK and node are given from above, plus:
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user