feat: gardening #1849
							
								
								
									
										84
									
								
								src/controllers/api/gardeningController.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								src/controllers/api/gardeningController.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,84 @@
 | 
				
			|||||||
 | 
					import { toMongoDate } from "@/src/helpers/inventoryHelpers";
 | 
				
			||||||
 | 
					import { getJSONfromString } from "@/src/helpers/stringHelpers";
 | 
				
			||||||
 | 
					import { addMiscItem, getInventory } from "@/src/services/inventoryService";
 | 
				
			||||||
 | 
					import { toStoreItem } from "@/src/services/itemDataService";
 | 
				
			||||||
 | 
					import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
				
			||||||
 | 
					import { createGarden, getPersonalRooms } from "@/src/services/personalRoomsService";
 | 
				
			||||||
 | 
					import { IMongoDate } from "@/src/types/commonTypes";
 | 
				
			||||||
 | 
					import { IMissionReward } from "@/src/types/missionTypes";
 | 
				
			||||||
 | 
					import { IPersonalRoomsClient } from "@/src/types/personalRoomsTypes";
 | 
				
			||||||
 | 
					import { IInventoryChanges } from "@/src/types/purchaseTypes";
 | 
				
			||||||
 | 
					import { IGardeningClient } from "@/src/types/shipTypes";
 | 
				
			||||||
 | 
					import { RequestHandler } from "express";
 | 
				
			||||||
 | 
					import { dict_en, ExportResources } from "warframe-public-export-plus";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const gardeningController: RequestHandler = async (req, res) => {
 | 
				
			||||||
 | 
					    const data = getJSONfromString<IGardeningRequest>(String(req.body));
 | 
				
			||||||
 | 
					    if (data.Mode != "HarvestAll") {
 | 
				
			||||||
 | 
					        throw new Error(`unexpected gardening mode: ${data.Mode}`);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const accountId = await getAccountIdForRequest(req);
 | 
				
			||||||
 | 
					    const [inventory, personalRooms] = await Promise.all([
 | 
				
			||||||
 | 
					        getInventory(accountId, "MiscItems"),
 | 
				
			||||||
 | 
					        getPersonalRooms(accountId, "Apartment")
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Harvest plants
 | 
				
			||||||
 | 
					    const inventoryChanges: IInventoryChanges = {};
 | 
				
			||||||
 | 
					    const rewards: Record<string, IMissionReward[][]> = {};
 | 
				
			||||||
 | 
					    for (const planter of personalRooms.Apartment.Gardening.Planters) {
 | 
				
			||||||
 | 
					        rewards[planter.Name] = [];
 | 
				
			||||||
 | 
					        for (const plant of planter.Plants) {
 | 
				
			||||||
 | 
					            const itemType =
 | 
				
			||||||
 | 
					                "/Lotus/Types/Gameplay/Duviri/Resource/DuviriPlantItem" +
 | 
				
			||||||
 | 
					                plant.PlantType.substring(plant.PlantType.length - 1);
 | 
				
			||||||
 | 
					            const itemCount = Math.random() < 0.775 ? 2 : 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            addMiscItem(inventory, itemType, itemCount, inventoryChanges);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            rewards[planter.Name].push([
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    StoreItem: toStoreItem(itemType),
 | 
				
			||||||
 | 
					                    TypeName: itemType,
 | 
				
			||||||
 | 
					                    ItemCount: itemCount,
 | 
				
			||||||
 | 
					                    DailyCooldown: false,
 | 
				
			||||||
 | 
					                    Rarity: itemCount == 2 ? 0.7743589743589744 : 0.22564102564102564,
 | 
				
			||||||
 | 
					                    TweetText: `${itemCount}x ${dict_en[ExportResources[itemType].name]} (Resource)`,
 | 
				
			||||||
 | 
					                    ProductCategory: "MiscItems"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Refresh garden
 | 
				
			||||||
 | 
					    personalRooms.Apartment.Gardening = createGarden();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await Promise.all([inventory.save(), personalRooms.save()]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const planter = personalRooms.Apartment.Gardening.Planters[personalRooms.Apartment.Gardening.Planters.length - 1];
 | 
				
			||||||
 | 
					    const plant = planter.Plants[planter.Plants.length - 1];
 | 
				
			||||||
 | 
					    res.json({
 | 
				
			||||||
 | 
					        GardenTagName: planter.Name,
 | 
				
			||||||
 | 
					        PlantType: plant.PlantType,
 | 
				
			||||||
 | 
					        PlotIndex: plant.PlotIndex,
 | 
				
			||||||
 | 
					        EndTime: toMongoDate(plant.EndTime),
 | 
				
			||||||
 | 
					        InventoryChanges: inventoryChanges,
 | 
				
			||||||
 | 
					        Gardening: personalRooms.toJSON<IPersonalRoomsClient>().Apartment.Gardening,
 | 
				
			||||||
 | 
					        Rewards: rewards
 | 
				
			||||||
 | 
					    } satisfies IGardeningResponse);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IGardeningRequest {
 | 
				
			||||||
 | 
					    Mode: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IGardeningResponse {
 | 
				
			||||||
 | 
					    GardenTagName: string;
 | 
				
			||||||
 | 
					    PlantType: string;
 | 
				
			||||||
 | 
					    PlotIndex: number;
 | 
				
			||||||
 | 
					    EndTime: IMongoDate;
 | 
				
			||||||
 | 
					    InventoryChanges: IInventoryChanges;
 | 
				
			||||||
 | 
					    Gardening: IGardeningClient;
 | 
				
			||||||
 | 
					    Rewards: Record<string, IMissionReward[][]>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -2,17 +2,24 @@ import { RequestHandler } from "express";
 | 
				
			|||||||
import { config } from "@/src/services/configService";
 | 
					import { config } from "@/src/services/configService";
 | 
				
			||||||
import allShipFeatures from "@/static/fixed_responses/allShipFeatures.json";
 | 
					import allShipFeatures from "@/static/fixed_responses/allShipFeatures.json";
 | 
				
			||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
					import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
				
			||||||
import { getPersonalRooms } from "@/src/services/personalRoomsService";
 | 
					import { createGarden, getPersonalRooms } from "@/src/services/personalRoomsService";
 | 
				
			||||||
import { getShip } from "@/src/services/shipService";
 | 
					import { getShip } from "@/src/services/shipService";
 | 
				
			||||||
import { toOid } from "@/src/helpers/inventoryHelpers";
 | 
					import { toOid } from "@/src/helpers/inventoryHelpers";
 | 
				
			||||||
import { IGetShipResponse } from "@/src/types/shipTypes";
 | 
					import { IGetShipResponse } from "@/src/types/shipTypes";
 | 
				
			||||||
import { IPersonalRooms } from "@/src/types/personalRoomsTypes";
 | 
					import { IPersonalRoomsClient } from "@/src/types/personalRoomsTypes";
 | 
				
			||||||
import { getLoadout } from "@/src/services/loadoutService";
 | 
					import { getLoadout } from "@/src/services/loadoutService";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const getShipController: RequestHandler = async (req, res) => {
 | 
					export const getShipController: RequestHandler = async (req, res) => {
 | 
				
			||||||
    const accountId = await getAccountIdForRequest(req);
 | 
					    const accountId = await getAccountIdForRequest(req);
 | 
				
			||||||
    const personalRoomsDb = await getPersonalRooms(accountId);
 | 
					    const personalRoomsDb = await getPersonalRooms(accountId);
 | 
				
			||||||
    const personalRooms = personalRoomsDb.toJSON<IPersonalRooms>();
 | 
					
 | 
				
			||||||
 | 
					    // Setup gardening if it's missing. Maybe should be done as part of some quest completion in the future.
 | 
				
			||||||
 | 
					    if (personalRoomsDb.Apartment.Gardening.Planters.length == 0) {
 | 
				
			||||||
 | 
					        personalRoomsDb.Apartment.Gardening = createGarden();
 | 
				
			||||||
 | 
					        await personalRoomsDb.save();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const personalRooms = personalRoomsDb.toJSON<IPersonalRoomsClient>();
 | 
				
			||||||
    const loadout = await getLoadout(accountId);
 | 
					    const loadout = await getLoadout(accountId);
 | 
				
			||||||
    const ship = await getShip(personalRoomsDb.activeShipId, "ShipAttachments SkinFlavourItem");
 | 
					    const ship = await getShip(personalRoomsDb.activeShipId, "ShipAttachments SkinFlavourItem");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,14 +1,17 @@
 | 
				
			|||||||
import { toOid } from "@/src/helpers/inventoryHelpers";
 | 
					import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
 | 
				
			||||||
import { colorSchema } from "@/src/models/inventoryModels/inventoryModel";
 | 
					import { colorSchema } from "@/src/models/inventoryModels/inventoryModel";
 | 
				
			||||||
import { IOrbiter, IPersonalRoomsDatabase, PersonalRoomsModelType } from "@/src/types/personalRoomsTypes";
 | 
					import { IOrbiter, IPersonalRoomsDatabase, PersonalRoomsModelType } from "@/src/types/personalRoomsTypes";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
    IFavouriteLoadoutDatabase,
 | 
					    IFavouriteLoadoutDatabase,
 | 
				
			||||||
    IGardening,
 | 
					    IGardeningDatabase,
 | 
				
			||||||
    IPlacedDecosDatabase,
 | 
					    IPlacedDecosDatabase,
 | 
				
			||||||
    IPictureFrameInfo,
 | 
					    IPictureFrameInfo,
 | 
				
			||||||
    IRoom,
 | 
					    IRoom,
 | 
				
			||||||
    ITailorShopDatabase,
 | 
					    ITailorShopDatabase,
 | 
				
			||||||
    IApartmentDatabase
 | 
					    IApartmentDatabase,
 | 
				
			||||||
 | 
					    IPlanterDatabase,
 | 
				
			||||||
 | 
					    IPlantDatabase,
 | 
				
			||||||
 | 
					    IPlantClient
 | 
				
			||||||
} from "@/src/types/shipTypes";
 | 
					} from "@/src/types/shipTypes";
 | 
				
			||||||
import { Schema, model } from "mongoose";
 | 
					import { Schema, model } from "mongoose";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -77,15 +80,45 @@ favouriteLoadoutSchema.set("toJSON", {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const gardeningSchema = new Schema<IGardening>({
 | 
					const plantSchema = new Schema<IPlantDatabase>(
 | 
				
			||||||
    Planters: [Schema.Types.Mixed] //TODO: add when implementing gardening
 | 
					    {
 | 
				
			||||||
 | 
					        PlantType: String,
 | 
				
			||||||
 | 
					        EndTime: Date,
 | 
				
			||||||
 | 
					        PlotIndex: Number
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    { _id: false }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					plantSchema.set("toJSON", {
 | 
				
			||||||
 | 
					    virtuals: true,
 | 
				
			||||||
 | 
					    transform(_doc, obj) {
 | 
				
			||||||
 | 
					        const client = obj as IPlantClient;
 | 
				
			||||||
 | 
					        const db = obj as IPlantDatabase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        client.EndTime = toMongoDate(db.EndTime);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const planterSchema = new Schema<IPlanterDatabase>(
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Name: { type: String, required: true },
 | 
				
			||||||
 | 
					        Plants: { type: [plantSchema], default: [] }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    { _id: false }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const gardeningSchema = new Schema<IGardeningDatabase>(
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Planters: { type: [planterSchema], default: [] }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    { _id: false }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const apartmentSchema = new Schema<IApartmentDatabase>(
 | 
					const apartmentSchema = new Schema<IApartmentDatabase>(
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        Rooms: [roomSchema],
 | 
					        Rooms: [roomSchema],
 | 
				
			||||||
        FavouriteLoadouts: [favouriteLoadoutSchema],
 | 
					        FavouriteLoadouts: [favouriteLoadoutSchema],
 | 
				
			||||||
        Gardening: gardeningSchema // TODO: ensure this is correct
 | 
					        Gardening: gardeningSchema
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    { _id: false }
 | 
					    { _id: false }
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
@ -98,7 +131,9 @@ const apartmentDefault: IApartmentDatabase = {
 | 
				
			|||||||
        { Name: "DuviriHallway", MaxCapacity: 1600 }
 | 
					        { Name: "DuviriHallway", MaxCapacity: 1600 }
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    FavouriteLoadouts: [],
 | 
					    FavouriteLoadouts: [],
 | 
				
			||||||
    Gardening: {}
 | 
					    Gardening: {
 | 
				
			||||||
 | 
					        Planters: []
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const orbiterSchema = new Schema<IOrbiter>(
 | 
					const orbiterSchema = new Schema<IOrbiter>(
 | 
				
			||||||
 | 
				
			|||||||
@ -48,6 +48,7 @@ import { findSessionsController } from "@/src/controllers/api/findSessionsContro
 | 
				
			|||||||
import { fishmongerController } from "@/src/controllers/api/fishmongerController";
 | 
					import { fishmongerController } from "@/src/controllers/api/fishmongerController";
 | 
				
			||||||
import { focusController } from "@/src/controllers/api/focusController";
 | 
					import { focusController } from "@/src/controllers/api/focusController";
 | 
				
			||||||
import { fusionTreasuresController } from "@/src/controllers/api/fusionTreasuresController";
 | 
					import { fusionTreasuresController } from "@/src/controllers/api/fusionTreasuresController";
 | 
				
			||||||
 | 
					import { gardeningController } from "@/src/controllers/api/gardeningController";
 | 
				
			||||||
import { genericUpdateController } from "@/src/controllers/api/genericUpdateController";
 | 
					import { genericUpdateController } from "@/src/controllers/api/genericUpdateController";
 | 
				
			||||||
import { getAllianceController } from "@/src/controllers/api/getAllianceController";
 | 
					import { getAllianceController } from "@/src/controllers/api/getAllianceController";
 | 
				
			||||||
import { getDailyDealStockLevelsController } from "@/src/controllers/api/getDailyDealStockLevelsController";
 | 
					import { getDailyDealStockLevelsController } from "@/src/controllers/api/getDailyDealStockLevelsController";
 | 
				
			||||||
@ -240,6 +241,7 @@ apiRouter.post("/findSessions.php", findSessionsController);
 | 
				
			|||||||
apiRouter.post("/fishmonger.php", fishmongerController);
 | 
					apiRouter.post("/fishmonger.php", fishmongerController);
 | 
				
			||||||
apiRouter.post("/focus.php", focusController);
 | 
					apiRouter.post("/focus.php", focusController);
 | 
				
			||||||
apiRouter.post("/fusionTreasures.php", fusionTreasuresController);
 | 
					apiRouter.post("/fusionTreasures.php", fusionTreasuresController);
 | 
				
			||||||
 | 
					apiRouter.post("/gardening.php", gardeningController);
 | 
				
			||||||
apiRouter.post("/genericUpdate.php", genericUpdateController);
 | 
					apiRouter.post("/genericUpdate.php", genericUpdateController);
 | 
				
			||||||
apiRouter.post("/getAlliance.php", getAllianceController);
 | 
					apiRouter.post("/getAlliance.php", getAllianceController);
 | 
				
			||||||
apiRouter.post("/getFriends.php", getFriendsController);
 | 
					apiRouter.post("/getFriends.php", getFriendsController);
 | 
				
			||||||
 | 
				
			|||||||
@ -213,6 +213,15 @@ export const combineInventoryChanges = (InventoryChanges: IInventoryChanges, del
 | 
				
			|||||||
    for (const key in delta) {
 | 
					    for (const key in delta) {
 | 
				
			||||||
        if (!(key in InventoryChanges)) {
 | 
					        if (!(key in InventoryChanges)) {
 | 
				
			||||||
            InventoryChanges[key] = delta[key];
 | 
					            InventoryChanges[key] = delta[key];
 | 
				
			||||||
 | 
					        } else if (key == "MiscItems") {
 | 
				
			||||||
 | 
					            for (const deltaItem of delta[key]!) {
 | 
				
			||||||
 | 
					                const existing = InventoryChanges[key]!.find(x => x.ItemType == deltaItem.ItemType);
 | 
				
			||||||
 | 
					                if (existing) {
 | 
				
			||||||
 | 
					                    existing.ItemCount += deltaItem.ItemCount;
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    InventoryChanges[key]!.push(deltaItem);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        } else if (Array.isArray(delta[key])) {
 | 
					        } else if (Array.isArray(delta[key])) {
 | 
				
			||||||
            const left = InventoryChanges[key] as object[];
 | 
					            const left = InventoryChanges[key] as object[];
 | 
				
			||||||
            const right: object[] = delta[key];
 | 
					            const right: object[] = delta[key];
 | 
				
			||||||
@ -1468,6 +1477,22 @@ export const addGearExpByCategory = (
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const addMiscItem = (
 | 
				
			||||||
 | 
					    inventory: TInventoryDatabaseDocument,
 | 
				
			||||||
 | 
					    type: string,
 | 
				
			||||||
 | 
					    count: number,
 | 
				
			||||||
 | 
					    inventoryChanges: IInventoryChanges
 | 
				
			||||||
 | 
					): void => {
 | 
				
			||||||
 | 
					    const miscItemChanges: IMiscItem[] = [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            ItemType: type,
 | 
				
			||||||
 | 
					            ItemCount: count
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					    addMiscItems(inventory, miscItemChanges);
 | 
				
			||||||
 | 
					    combineInventoryChanges(inventoryChanges, { MiscItems: miscItemChanges });
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const addMiscItems = (inventory: TInventoryDatabaseDocument, itemsArray: IMiscItem[]): void => {
 | 
					export const addMiscItems = (inventory: TInventoryDatabaseDocument, itemsArray: IMiscItem[]): void => {
 | 
				
			||||||
    const { MiscItems } = inventory;
 | 
					    const { MiscItems } = inventory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,9 +1,14 @@
 | 
				
			|||||||
import { PersonalRooms } from "@/src/models/personalRoomsModel";
 | 
					import { PersonalRooms } from "@/src/models/personalRoomsModel";
 | 
				
			||||||
import { addItem, getInventory } from "@/src/services/inventoryService";
 | 
					import { addItem, getInventory } from "@/src/services/inventoryService";
 | 
				
			||||||
import { TPersonalRoomsDatabaseDocument } from "../types/personalRoomsTypes";
 | 
					import { TPersonalRoomsDatabaseDocument } from "../types/personalRoomsTypes";
 | 
				
			||||||
 | 
					import { IGardeningDatabase } from "../types/shipTypes";
 | 
				
			||||||
 | 
					import { getRandomElement } from "./rngService";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const getPersonalRooms = async (accountId: string): Promise<TPersonalRoomsDatabaseDocument> => {
 | 
					export const getPersonalRooms = async (
 | 
				
			||||||
    const personalRooms = await PersonalRooms.findOne({ personalRoomsOwnerId: accountId });
 | 
					    accountId: string,
 | 
				
			||||||
 | 
					    projection?: string
 | 
				
			||||||
 | 
					): Promise<TPersonalRoomsDatabaseDocument> => {
 | 
				
			||||||
 | 
					    const personalRooms = await PersonalRooms.findOne({ personalRoomsOwnerId: accountId }, projection);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!personalRooms) {
 | 
					    if (!personalRooms) {
 | 
				
			||||||
        throw new Error(`personal rooms not found for account ${accountId}`);
 | 
					        throw new Error(`personal rooms not found for account ${accountId}`);
 | 
				
			||||||
@ -25,3 +30,64 @@ export const updateShipFeature = async (accountId: string, shipFeature: string):
 | 
				
			|||||||
    await addItem(inventory, shipFeature, -1);
 | 
					    await addItem(inventory, shipFeature, -1);
 | 
				
			||||||
    await inventory.save();
 | 
					    await inventory.save();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const createGarden = (): IGardeningDatabase => {
 | 
				
			||||||
 | 
					    const plantTypes = [
 | 
				
			||||||
 | 
					        "/Lotus/Types/Items/Plants/MiscItems/DuvxDuviriGrowingPlantA",
 | 
				
			||||||
 | 
					        "/Lotus/Types/Items/Plants/MiscItems/DuvxDuviriGrowingPlantB",
 | 
				
			||||||
 | 
					        "/Lotus/Types/Items/Plants/MiscItems/DuvxDuviriGrowingPlantC",
 | 
				
			||||||
 | 
					        "/Lotus/Types/Items/Plants/MiscItems/DuvxDuviriGrowingPlantD",
 | 
				
			||||||
 | 
					        "/Lotus/Types/Items/Plants/MiscItems/DuvxDuviriGrowingPlantE",
 | 
				
			||||||
 | 
					        "/Lotus/Types/Items/Plants/MiscItems/DuvxDuviriGrowingPlantF"
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					    const endTime = new Date((Math.trunc(Date.now() / 1000) + 79200) * 1000); // Plants will take 22 hours to grow
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        Planters: [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Name: "Garden0",
 | 
				
			||||||
 | 
					                Plants: [
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        PlantType: getRandomElement(plantTypes),
 | 
				
			||||||
 | 
					                        EndTime: endTime,
 | 
				
			||||||
 | 
					                        PlotIndex: 0
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        PlantType: getRandomElement(plantTypes),
 | 
				
			||||||
 | 
					                        EndTime: endTime,
 | 
				
			||||||
 | 
					                        PlotIndex: 1
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                ]
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Name: "Garden1",
 | 
				
			||||||
 | 
					                Plants: [
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        PlantType: getRandomElement(plantTypes),
 | 
				
			||||||
 | 
					                        EndTime: endTime,
 | 
				
			||||||
 | 
					                        PlotIndex: 0
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        PlantType: getRandomElement(plantTypes),
 | 
				
			||||||
 | 
					                        EndTime: endTime,
 | 
				
			||||||
 | 
					                        PlotIndex: 1
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                ]
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Name: "Garden2",
 | 
				
			||||||
 | 
					                Plants: [
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        PlantType: getRandomElement(plantTypes),
 | 
				
			||||||
 | 
					                        EndTime: endTime,
 | 
				
			||||||
 | 
					                        PlotIndex: 0
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        PlantType: getRandomElement(plantTypes),
 | 
				
			||||||
 | 
					                        EndTime: endTime,
 | 
				
			||||||
 | 
					                        PlotIndex: 1
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                ]
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,8 @@ export interface IMissionReward {
 | 
				
			|||||||
    TypeName?: string;
 | 
					    TypeName?: string;
 | 
				
			||||||
    UpgradeLevel?: number;
 | 
					    UpgradeLevel?: number;
 | 
				
			||||||
    ItemCount: number;
 | 
					    ItemCount: number;
 | 
				
			||||||
 | 
					    DailyCooldown?: boolean;
 | 
				
			||||||
 | 
					    Rarity?: number;
 | 
				
			||||||
    TweetText?: string;
 | 
					    TweetText?: string;
 | 
				
			||||||
    ProductCategory?: string;
 | 
					    ProductCategory?: string;
 | 
				
			||||||
    FromEnemyCache?: boolean;
 | 
					    FromEnemyCache?: boolean;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,12 +1,12 @@
 | 
				
			|||||||
import { IColor } from "@/src/types/inventoryTypes/commonInventoryTypes";
 | 
					import { IColor } from "@/src/types/inventoryTypes/commonInventoryTypes";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
    IApartment,
 | 
					 | 
				
			||||||
    IRoom,
 | 
					    IRoom,
 | 
				
			||||||
    IPlacedDecosDatabase,
 | 
					    IPlacedDecosDatabase,
 | 
				
			||||||
    ITailorShop,
 | 
					    ITailorShop,
 | 
				
			||||||
    ITailorShopDatabase,
 | 
					    ITailorShopDatabase,
 | 
				
			||||||
    TBootLocation,
 | 
					    TBootLocation,
 | 
				
			||||||
    IApartmentDatabase
 | 
					    IApartmentDatabase,
 | 
				
			||||||
 | 
					    IApartmentClient
 | 
				
			||||||
} from "@/src/types/shipTypes";
 | 
					} from "@/src/types/shipTypes";
 | 
				
			||||||
import { Document, Model, Types } from "mongoose";
 | 
					import { Document, Model, Types } from "mongoose";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -21,10 +21,10 @@ export interface IOrbiter {
 | 
				
			|||||||
    BootLocation?: TBootLocation;
 | 
					    BootLocation?: TBootLocation;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IPersonalRooms {
 | 
					export interface IPersonalRoomsClient {
 | 
				
			||||||
    ShipInteriorColors: IColor;
 | 
					    ShipInteriorColors: IColor;
 | 
				
			||||||
    Ship: IOrbiter;
 | 
					    Ship: IOrbiter;
 | 
				
			||||||
    Apartment: IApartment;
 | 
					    Apartment: IApartmentClient;
 | 
				
			||||||
    TailorShop: ITailorShop;
 | 
					    TailorShop: ITailorShop;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,12 +1,12 @@
 | 
				
			|||||||
import { Types } from "mongoose";
 | 
					import { Types } from "mongoose";
 | 
				
			||||||
import { IOid } from "@/src/types/commonTypes";
 | 
					import { IMongoDate, IOid } from "@/src/types/commonTypes";
 | 
				
			||||||
import { IColor } from "@/src/types/inventoryTypes/commonInventoryTypes";
 | 
					import { IColor } from "@/src/types/inventoryTypes/commonInventoryTypes";
 | 
				
			||||||
import { ILoadoutClient } from "./saveLoadoutTypes";
 | 
					import { ILoadoutClient } from "./saveLoadoutTypes";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IGetShipResponse {
 | 
					export interface IGetShipResponse {
 | 
				
			||||||
    ShipOwnerId: string;
 | 
					    ShipOwnerId: string;
 | 
				
			||||||
    Ship: IShip;
 | 
					    Ship: IShip;
 | 
				
			||||||
    Apartment: IApartment;
 | 
					    Apartment: IApartmentClient;
 | 
				
			||||||
    TailorShop: ITailorShop;
 | 
					    TailorShop: ITailorShop;
 | 
				
			||||||
    LoadOutInventory: { LoadOutPresets: ILoadoutClient };
 | 
					    LoadOutInventory: { LoadOutPresets: ILoadoutClient };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -51,28 +51,42 @@ export interface IRoom {
 | 
				
			|||||||
    PlacedDecos?: IPlacedDecosDatabase[];
 | 
					    PlacedDecos?: IPlacedDecosDatabase[];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IPlants {
 | 
					export interface IPlantClient {
 | 
				
			||||||
    PlantType: string;
 | 
					    PlantType: string;
 | 
				
			||||||
    EndTime: IOid;
 | 
					    EndTime: IMongoDate;
 | 
				
			||||||
    PlotIndex: number;
 | 
					    PlotIndex: number;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
export interface IPlanters {
 | 
					
 | 
				
			||||||
 | 
					export interface IPlantDatabase extends Omit<IPlantClient, "EndTime"> {
 | 
				
			||||||
 | 
					    EndTime: Date;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface IPlanterClient {
 | 
				
			||||||
    Name: string;
 | 
					    Name: string;
 | 
				
			||||||
    Plants: IPlants[];
 | 
					    Plants: IPlantClient[];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IGardening {
 | 
					export interface IPlanterDatabase {
 | 
				
			||||||
    Planters?: IPlanters[];
 | 
					    Name: string;
 | 
				
			||||||
 | 
					    Plants: IPlantDatabase[];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IApartment {
 | 
					export interface IGardeningClient {
 | 
				
			||||||
    Gardening: IGardening;
 | 
					    Planters: IPlanterClient[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface IGardeningDatabase {
 | 
				
			||||||
 | 
					    Planters: IPlanterDatabase[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface IApartmentClient {
 | 
				
			||||||
 | 
					    Gardening: IGardeningClient;
 | 
				
			||||||
    Rooms: IRoom[];
 | 
					    Rooms: IRoom[];
 | 
				
			||||||
    FavouriteLoadouts: IFavouriteLoadout[];
 | 
					    FavouriteLoadouts: IFavouriteLoadout[];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IApartmentDatabase {
 | 
					export interface IApartmentDatabase {
 | 
				
			||||||
    Gardening: IGardening;
 | 
					    Gardening: IGardeningDatabase;
 | 
				
			||||||
    Rooms: IRoom[];
 | 
					    Rooms: IRoom[];
 | 
				
			||||||
    FavouriteLoadouts: IFavouriteLoadoutDatabase[];
 | 
					    FavouriteLoadouts: IFavouriteLoadoutDatabase[];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user