forked from OpenWF/SpaceNinjaServer
		
	feat: gardening (#1849)
Reviewed-on: OpenWF/SpaceNinjaServer#1849 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
							
								
									d0c9409a2d
								
							
						
					
					
						commit
						a90d3a5156
					
				
							
								
								
									
										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 allShipFeatures from "@/static/fixed_responses/allShipFeatures.json";
 | 
			
		||||
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 { toOid } from "@/src/helpers/inventoryHelpers";
 | 
			
		||||
import { IGetShipResponse } from "@/src/types/shipTypes";
 | 
			
		||||
import { IPersonalRooms } from "@/src/types/personalRoomsTypes";
 | 
			
		||||
import { IPersonalRoomsClient } from "@/src/types/personalRoomsTypes";
 | 
			
		||||
import { getLoadout } from "@/src/services/loadoutService";
 | 
			
		||||
 | 
			
		||||
export const getShipController: RequestHandler = async (req, res) => {
 | 
			
		||||
    const accountId = await getAccountIdForRequest(req);
 | 
			
		||||
    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 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 { IOrbiter, IPersonalRoomsDatabase, PersonalRoomsModelType } from "@/src/types/personalRoomsTypes";
 | 
			
		||||
import {
 | 
			
		||||
    IFavouriteLoadoutDatabase,
 | 
			
		||||
    IGardening,
 | 
			
		||||
    IGardeningDatabase,
 | 
			
		||||
    IPlacedDecosDatabase,
 | 
			
		||||
    IPictureFrameInfo,
 | 
			
		||||
    IRoom,
 | 
			
		||||
    ITailorShopDatabase,
 | 
			
		||||
    IApartmentDatabase
 | 
			
		||||
    IApartmentDatabase,
 | 
			
		||||
    IPlanterDatabase,
 | 
			
		||||
    IPlantDatabase,
 | 
			
		||||
    IPlantClient
 | 
			
		||||
} from "@/src/types/shipTypes";
 | 
			
		||||
import { Schema, model } from "mongoose";
 | 
			
		||||
 | 
			
		||||
@ -77,15 +80,45 @@ favouriteLoadoutSchema.set("toJSON", {
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const gardeningSchema = new Schema<IGardening>({
 | 
			
		||||
    Planters: [Schema.Types.Mixed] //TODO: add when implementing gardening
 | 
			
		||||
const plantSchema = new Schema<IPlantDatabase>(
 | 
			
		||||
    {
 | 
			
		||||
        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>(
 | 
			
		||||
    {
 | 
			
		||||
        Rooms: [roomSchema],
 | 
			
		||||
        FavouriteLoadouts: [favouriteLoadoutSchema],
 | 
			
		||||
        Gardening: gardeningSchema // TODO: ensure this is correct
 | 
			
		||||
        Gardening: gardeningSchema
 | 
			
		||||
    },
 | 
			
		||||
    { _id: false }
 | 
			
		||||
);
 | 
			
		||||
@ -98,7 +131,9 @@ const apartmentDefault: IApartmentDatabase = {
 | 
			
		||||
        { Name: "DuviriHallway", MaxCapacity: 1600 }
 | 
			
		||||
    ],
 | 
			
		||||
    FavouriteLoadouts: [],
 | 
			
		||||
    Gardening: {}
 | 
			
		||||
    Gardening: {
 | 
			
		||||
        Planters: []
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const orbiterSchema = new Schema<IOrbiter>(
 | 
			
		||||
 | 
			
		||||
@ -48,6 +48,7 @@ import { findSessionsController } from "@/src/controllers/api/findSessionsContro
 | 
			
		||||
import { fishmongerController } from "@/src/controllers/api/fishmongerController";
 | 
			
		||||
import { focusController } from "@/src/controllers/api/focusController";
 | 
			
		||||
import { fusionTreasuresController } from "@/src/controllers/api/fusionTreasuresController";
 | 
			
		||||
import { gardeningController } from "@/src/controllers/api/gardeningController";
 | 
			
		||||
import { genericUpdateController } from "@/src/controllers/api/genericUpdateController";
 | 
			
		||||
import { getAllianceController } from "@/src/controllers/api/getAllianceController";
 | 
			
		||||
import { getDailyDealStockLevelsController } from "@/src/controllers/api/getDailyDealStockLevelsController";
 | 
			
		||||
@ -240,6 +241,7 @@ apiRouter.post("/findSessions.php", findSessionsController);
 | 
			
		||||
apiRouter.post("/fishmonger.php", fishmongerController);
 | 
			
		||||
apiRouter.post("/focus.php", focusController);
 | 
			
		||||
apiRouter.post("/fusionTreasures.php", fusionTreasuresController);
 | 
			
		||||
apiRouter.post("/gardening.php", gardeningController);
 | 
			
		||||
apiRouter.post("/genericUpdate.php", genericUpdateController);
 | 
			
		||||
apiRouter.post("/getAlliance.php", getAllianceController);
 | 
			
		||||
apiRouter.post("/getFriends.php", getFriendsController);
 | 
			
		||||
 | 
			
		||||
@ -213,6 +213,15 @@ export const combineInventoryChanges = (InventoryChanges: IInventoryChanges, del
 | 
			
		||||
    for (const key in delta) {
 | 
			
		||||
        if (!(key in InventoryChanges)) {
 | 
			
		||||
            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])) {
 | 
			
		||||
            const left = InventoryChanges[key] as object[];
 | 
			
		||||
            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 => {
 | 
			
		||||
    const { MiscItems } = inventory;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,14 @@
 | 
			
		||||
import { PersonalRooms } from "@/src/models/personalRoomsModel";
 | 
			
		||||
import { addItem, getInventory } from "@/src/services/inventoryService";
 | 
			
		||||
import { TPersonalRoomsDatabaseDocument } from "../types/personalRoomsTypes";
 | 
			
		||||
import { IGardeningDatabase } from "../types/shipTypes";
 | 
			
		||||
import { getRandomElement } from "./rngService";
 | 
			
		||||
 | 
			
		||||
export const getPersonalRooms = async (accountId: string): Promise<TPersonalRoomsDatabaseDocument> => {
 | 
			
		||||
    const personalRooms = await PersonalRooms.findOne({ personalRoomsOwnerId: accountId });
 | 
			
		||||
export const getPersonalRooms = async (
 | 
			
		||||
    accountId: string,
 | 
			
		||||
    projection?: string
 | 
			
		||||
): Promise<TPersonalRoomsDatabaseDocument> => {
 | 
			
		||||
    const personalRooms = await PersonalRooms.findOne({ personalRoomsOwnerId: accountId }, projection);
 | 
			
		||||
 | 
			
		||||
    if (!personalRooms) {
 | 
			
		||||
        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 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;
 | 
			
		||||
    UpgradeLevel?: number;
 | 
			
		||||
    ItemCount: number;
 | 
			
		||||
    DailyCooldown?: boolean;
 | 
			
		||||
    Rarity?: number;
 | 
			
		||||
    TweetText?: string;
 | 
			
		||||
    ProductCategory?: string;
 | 
			
		||||
    FromEnemyCache?: boolean;
 | 
			
		||||
 | 
			
		||||
@ -1,12 +1,12 @@
 | 
			
		||||
import { IColor } from "@/src/types/inventoryTypes/commonInventoryTypes";
 | 
			
		||||
import {
 | 
			
		||||
    IApartment,
 | 
			
		||||
    IRoom,
 | 
			
		||||
    IPlacedDecosDatabase,
 | 
			
		||||
    ITailorShop,
 | 
			
		||||
    ITailorShopDatabase,
 | 
			
		||||
    TBootLocation,
 | 
			
		||||
    IApartmentDatabase
 | 
			
		||||
    IApartmentDatabase,
 | 
			
		||||
    IApartmentClient
 | 
			
		||||
} from "@/src/types/shipTypes";
 | 
			
		||||
import { Document, Model, Types } from "mongoose";
 | 
			
		||||
 | 
			
		||||
@ -21,10 +21,10 @@ export interface IOrbiter {
 | 
			
		||||
    BootLocation?: TBootLocation;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IPersonalRooms {
 | 
			
		||||
export interface IPersonalRoomsClient {
 | 
			
		||||
    ShipInteriorColors: IColor;
 | 
			
		||||
    Ship: IOrbiter;
 | 
			
		||||
    Apartment: IApartment;
 | 
			
		||||
    Apartment: IApartmentClient;
 | 
			
		||||
    TailorShop: ITailorShop;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,12 +1,12 @@
 | 
			
		||||
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 { ILoadoutClient } from "./saveLoadoutTypes";
 | 
			
		||||
 | 
			
		||||
export interface IGetShipResponse {
 | 
			
		||||
    ShipOwnerId: string;
 | 
			
		||||
    Ship: IShip;
 | 
			
		||||
    Apartment: IApartment;
 | 
			
		||||
    Apartment: IApartmentClient;
 | 
			
		||||
    TailorShop: ITailorShop;
 | 
			
		||||
    LoadOutInventory: { LoadOutPresets: ILoadoutClient };
 | 
			
		||||
}
 | 
			
		||||
@ -51,28 +51,42 @@ export interface IRoom {
 | 
			
		||||
    PlacedDecos?: IPlacedDecosDatabase[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IPlants {
 | 
			
		||||
export interface IPlantClient {
 | 
			
		||||
    PlantType: string;
 | 
			
		||||
    EndTime: IOid;
 | 
			
		||||
    EndTime: IMongoDate;
 | 
			
		||||
    PlotIndex: number;
 | 
			
		||||
}
 | 
			
		||||
export interface IPlanters {
 | 
			
		||||
 | 
			
		||||
export interface IPlantDatabase extends Omit<IPlantClient, "EndTime"> {
 | 
			
		||||
    EndTime: Date;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IPlanterClient {
 | 
			
		||||
    Name: string;
 | 
			
		||||
    Plants: IPlants[];
 | 
			
		||||
    Plants: IPlantClient[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IGardening {
 | 
			
		||||
    Planters?: IPlanters[];
 | 
			
		||||
export interface IPlanterDatabase {
 | 
			
		||||
    Name: string;
 | 
			
		||||
    Plants: IPlantDatabase[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IApartment {
 | 
			
		||||
    Gardening: IGardening;
 | 
			
		||||
export interface IGardeningClient {
 | 
			
		||||
    Planters: IPlanterClient[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IGardeningDatabase {
 | 
			
		||||
    Planters: IPlanterDatabase[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IApartmentClient {
 | 
			
		||||
    Gardening: IGardeningClient;
 | 
			
		||||
    Rooms: IRoom[];
 | 
			
		||||
    FavouriteLoadouts: IFavouriteLoadout[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IApartmentDatabase {
 | 
			
		||||
    Gardening: IGardening;
 | 
			
		||||
    Gardening: IGardeningDatabase;
 | 
			
		||||
    Rooms: IRoom[];
 | 
			
		||||
    FavouriteLoadouts: IFavouriteLoadoutDatabase[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user