sodoff/src/Services/InventoryService.cs
2025-10-19 11:19:15 +00:00

203 lines
8.5 KiB
C#

using sodoff.Model;
using sodoff.Schema;
using sodoff.Util;
using System.Threading.Tasks;
namespace sodoff.Services {
public class InventoryService {
private readonly DBContext ctx;
private ItemService itemService;
public const int Shards = 13711;
public InventoryService(DBContext ctx, ItemService itemService) {
this.ctx = ctx;
this.itemService = itemService;
}
public InventoryItem AddItemToInventory(Viking viking, int itemID, int quantity) {
InventoryItem? item = null;
if (!ItemNeedUniqueInventorySlot(itemID))
item = viking.InventoryItems.FirstOrDefault(e => e.ItemId == itemID);
if (item is null) {
ItemData itemData = itemService.GetItem(itemID);
item = new InventoryItem {
ItemId = itemID,
Quantity = 0
};
if (itemData.ItemStatsMap is null && itemData.PossibleStatsMap != null && !itemService.ItemHasCategory(itemData, 651)) {
// battle item without default stats, but not blueprints
Random random = new Random();
int itemTier = random.Next(1, 3);
item.StatsSerialized = XmlUtil.SerializeXml(new ItemStatsMap {
ItemID = itemID,
ItemTier = (ItemTier)itemTier,
ItemStats = itemService.CreateItemStats(itemData.PossibleStatsMap, (int)itemData.ItemRarity, itemTier).ToArray()
});
}
viking.InventoryItems.Add(item);
}
item.Quantity += quantity;
return item;
}
public CommonInventoryResponseItem AddItemToInventoryAndGetResponse(Viking viking, int itemID, int quantity) {
InventoryItem item = AddItemToInventory(viking, itemID, quantity);
ctx.SaveChanges(); // We need to get the ID of the newly created item
if (quantity == 1)
quantity = 0; // The game expects 0 if quantity got updated by just 1
// Otherwise it expects the quantity from the request
return new CommonInventoryResponseItem {
CommonInventoryID = item.Id,
ItemID = itemID,
Quantity = quantity
};
}
public Dictionary<int, int> AddItemsToInventoryBulk(Viking viking, Dictionary<int,int> itemsWithQuantity) {
List<InventoryItem> items = new();
Dictionary<int, int> itemsWithInventoryId = new();
List<CommonInventoryResponseItem> responses = new();
foreach (var i in itemsWithQuantity) {
items.Add(AddItemToInventory(viking, i.Key, i.Value));
}
ctx.SaveChanges();
foreach (var item in items) {
itemsWithInventoryId[item.ItemId] = item.Id;
}
return itemsWithInventoryId;
}
public CommonInventoryResponse AddItemsToInventoryBulkAndGetResponse(Viking viking, Dictionary<int,int> inventoryItemsToAdd, Dictionary<int,int> itemsToSendBack, UserGameCurrency gameCurrency) {
// add items to the inventory (database)
var addedItems = AddItemsToInventoryBulk(viking, inventoryItemsToAdd);
// build response
List<CommonInventoryResponseItem> items = new List<CommonInventoryResponseItem>();
foreach (var i in itemsToSendBack) {
items.AddRange(Enumerable.Repeat(
new CommonInventoryResponseItem {
CommonInventoryID = addedItems.ContainsKey(i.Key) ? addedItems[i.Key] : 0, // return inventory id if this item was added to the DB
ItemID = i.Key,
Quantity = 0
}, i.Value));
}
// NOTE: The quantity of purchased items can always be 0 and the items are instead duplicated in both the request and the response.
// Item quantities are used for non-store related requests/responses.
return new CommonInventoryResponse {
Success = true,
CommonInventoryIDs = items.ToArray(),
UserGameCurrency = gameCurrency
};
}
public InventoryItemStatsMap AddBattleItemToInventory(Viking viking, int itemId, int itemTier, ItemStat[] itemStat = null) {
// get item data
ItemData itemData = itemService.GetItem(itemId);
// create new item
InventoryItem item = new InventoryItem { ItemId = itemId, Quantity = 1 };
ItemStatsMap itemStatsMap = new ItemStatsMap {
ItemID = itemId,
ItemTier = (ItemTier)itemTier,
ItemStats = itemStat ?? itemService.CreateItemStats(itemData.PossibleStatsMap, (int)itemData.ItemRarity, itemTier).ToArray()
};
item.StatsSerialized = XmlUtil.SerializeXml(itemStatsMap);
// add to viking
viking.InventoryItems.Add(item);
ctx.SaveChanges(); // We need to get the ID of the newly created item
// return item with stats
return new InventoryItemStatsMap {
CommonInventoryID = item.Id,
Item = itemData,
ItemStatsMap = itemStatsMap
};
}
public void SellInventoryItem(Viking viking, int invItemID, ref int gold, ref int shard) {
// get item from inventory
InventoryItem? item = viking.InventoryItems.FirstOrDefault(e => e.Id == invItemID);
if (item is null)
return;
// get item data
ItemData? itemData = itemService.GetItem(item.ItemId);
// calculate shard price
switch (itemData.ItemRarity) {
case ItemRarity.Common:
shard += 1;
break;
case ItemRarity.Rare:
shard += 3;
break;
case ItemRarity.Epic:
shard += 5;
break;
case ItemRarity.Legendary:
shard += 10;
break;
}
// TODO: calculate cash (gold) rewards
// remove item
viking.InventoryItems.Remove(item);
}
public CommonInventoryData GetCommonInventoryData(Viking viking) {
List<InventoryItem> items = viking.InventoryItems.ToList();
List<UserItemData> userItemData = new();
foreach (InventoryItem item in items) {
if (item.Quantity == 0) continue; // Don't include an item that the viking doesn't have
ItemData itemData = itemService.GetItem(item.ItemId);
if (itemData is null) continue; // Don't include items removed from item database
UserItemData uid = new UserItemData {
UserInventoryID = item.Id,
ItemID = itemData.ItemID,
Quantity = item.Quantity,
Uses = itemData.Uses,
ModifiedDate = new DateTime(DateTime.Now.Ticks),
Item = itemData
};
if (item.StatsSerialized != null) {
ItemStatsMap itemStats = XmlUtil.DeserializeXml<ItemStatsMap>(item.StatsSerialized);
uid.ItemStats = itemStats.ItemStats;
uid.ItemTier = itemStats.ItemTier;
} else if (itemData.ItemStatsMap != null) {
uid.ItemStats = itemData.ItemStatsMap?.ItemStats;
uid.ItemTier = itemData.ItemStatsMap?.ItemTier;
}
if (item.AttributesSerialized != null) {
uid.UserItemAttributes = XmlUtil.DeserializeXml<Schema.PairData>(item.AttributesSerialized);
}
userItemData.Add(uid);
}
return new CommonInventoryData {
UserID = viking.Uid,
Item = userItemData.ToArray()
};
}
public bool ItemNeedUniqueInventorySlot(int itemId) {
ItemData itemData = itemService.GetItem(itemId);
if (itemData.PossibleStatsMap != null) // dragons tactics (battle) items
return true;
if (itemService.ItemHasCategory(itemData, new int[] {541, 657})) // farm expansion or customizable items
return true;
return false;
}
}
}