mirror of
https://github.com/SoDOff-Project/sodoff.git
synced 2025-10-11 08:18:49 -07:00
implement store, purchases; fix inventory
This only implements V2 purchases V1 purchases are used outside of the store
This commit is contained in:
parent
09553c9d4f
commit
0460746824
@ -51,7 +51,8 @@ methods = [
|
||||
'SaveMessage',
|
||||
'GetMMOServerInfoWithZone',
|
||||
'GetActiveChallenges',
|
||||
'GetAchievementsByUserID'
|
||||
'GetAchievementsByUserID',
|
||||
'PurchaseItems'
|
||||
]
|
||||
|
||||
def routable(path):
|
||||
|
@ -146,6 +146,7 @@ public class ContentController : Controller {
|
||||
List<InventoryItem> items = viking.Inventory.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);
|
||||
UserItemData uid = new UserItemData {
|
||||
UserInventoryID = viking.Inventory.Id,
|
||||
@ -175,17 +176,33 @@ public class ContentController : Controller {
|
||||
|
||||
// Set inventory items
|
||||
List<CommonInventoryResponseItem> responseItems = new();
|
||||
|
||||
// SetCommonInventory can remove any number of items from the inventory, this checks if it's possible
|
||||
foreach (var req in request) {
|
||||
if (req.Quantity >= 0) continue;
|
||||
InventoryItem? item = viking.Inventory.InventoryItems.FirstOrDefault(e => e.ItemId == req.ItemID);
|
||||
if (item is null || item.Quantity < req.Quantity)
|
||||
return Ok(new CommonInventoryResponse { Success = false });
|
||||
}
|
||||
|
||||
// Now that we know the request is valid, update the inventory
|
||||
foreach (var req in request) {
|
||||
InventoryItem? item = viking.Inventory.InventoryItems.FirstOrDefault(e => e.ItemId == req.ItemID);
|
||||
if (item is null) item = new InventoryItem { ItemId = (int)req.ItemID, Quantity = 0 };
|
||||
int origQuantity = item.Quantity;
|
||||
item.Quantity = request[0].Quantity;
|
||||
responseItems.Add(new CommonInventoryResponseItem {
|
||||
CommonInventoryID = viking.InventoryId,
|
||||
ItemID = item.ItemId,
|
||||
Quantity = origQuantity
|
||||
});
|
||||
viking.Inventory.InventoryItems.Add(item);
|
||||
if (item is null) {
|
||||
item = new InventoryItem { ItemId = (int)req.ItemID, Quantity = 0 };
|
||||
viking.Inventory.InventoryItems.Add(item);
|
||||
}
|
||||
int updateQuantity = 0; // The game expects 0 if quantity got updated by just 1
|
||||
if (req.Quantity > 1)
|
||||
updateQuantity = req.Quantity; // Otherwise it expects the quantity from the request
|
||||
item.Quantity += req.Quantity;
|
||||
ctx.SaveChanges(); // We need to get an ID of a newly created item
|
||||
if (req.Quantity > 0)
|
||||
responseItems.Add(new CommonInventoryResponseItem {
|
||||
CommonInventoryID = item.Id,
|
||||
ItemID = item.ItemId,
|
||||
Quantity = updateQuantity
|
||||
});
|
||||
}
|
||||
|
||||
CommonInventoryResponse response = new CommonInventoryResponse {
|
||||
@ -332,9 +349,7 @@ public class ContentController : Controller {
|
||||
ctx.Update(viking);
|
||||
ctx.SaveChanges();
|
||||
|
||||
return Ok(new SetRaisedPetResponse {
|
||||
RaisedPetSetResult = RaisedPetSetResult.Success
|
||||
});
|
||||
return Ok(true); // RaisedPetSetResult.Success doesn't work, this does
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
@ -512,6 +527,44 @@ public class ContentController : Controller {
|
||||
return Ok(new BuddyList[0]);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("V2/ContentWebService.asmx/PurchaseItems")]
|
||||
public IActionResult PurchaseItems([FromForm] string apiToken, [FromForm] string purchaseItemRequest) {
|
||||
Viking? viking = ctx.Sessions.FirstOrDefault(e => e.ApiToken == apiToken)?.Viking;
|
||||
if (viking is null)
|
||||
return Ok();
|
||||
|
||||
PurchaseStoreItemRequest request = XmlUtil.DeserializeXml<PurchaseStoreItemRequest>(purchaseItemRequest);
|
||||
CommonInventoryResponseItem[] items = new CommonInventoryResponseItem[request.Items.Length];
|
||||
for (int i = 0; i < request.Items.Length; i++) {
|
||||
InventoryItem? item = viking.Inventory.InventoryItems.FirstOrDefault(e => e.ItemId == request.Items[i]);
|
||||
if (item is null) {
|
||||
item = new InventoryItem { ItemId = request.Items[i], Quantity = 0 };
|
||||
viking.Inventory.InventoryItems.Add(item);
|
||||
}
|
||||
item.Quantity++;
|
||||
ctx.SaveChanges();
|
||||
items[i] = new CommonInventoryResponseItem {
|
||||
CommonInventoryID = item.Id,
|
||||
ItemID = request.Items[i],
|
||||
Quantity = 0 // The quantity of purchased items is always 0 and the items are instead duplicated in both the request and the response
|
||||
};
|
||||
}
|
||||
|
||||
CommonInventoryResponse response = new CommonInventoryResponse {
|
||||
Success = true,
|
||||
CommonInventoryIDs = items,
|
||||
UserGameCurrency = new UserGameCurrency {
|
||||
UserID = Guid.Parse(viking.Id),
|
||||
UserGameCurrencyID = 1, // TODO: user's wallet ID?
|
||||
CashCurrency = 1000,
|
||||
GameCurrency = 1000,
|
||||
}
|
||||
};
|
||||
return Ok(response);
|
||||
}
|
||||
|
||||
private RaisedPetData GetRaisedPetDataFromDragon (Dragon dragon) {
|
||||
RaisedPetData data = XmlUtil.DeserializeXml<RaisedPetData>(dragon.RaisedPetData);
|
||||
data.RaisedPetID = dragon.Id;
|
||||
|
@ -2,29 +2,36 @@
|
||||
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using sodoff.Model;
|
||||
using sodoff.Schema;
|
||||
using sodoff.Services;
|
||||
using sodoff.Util;
|
||||
|
||||
namespace sodoff.Controllers.Common;
|
||||
public class ItemStoreController : Controller {
|
||||
|
||||
private readonly DBContext ctx;
|
||||
public ItemStoreController(DBContext ctx) {
|
||||
private StoreService storeService;
|
||||
public ItemStoreController(DBContext ctx, StoreService storeService) {
|
||||
this.ctx = ctx;
|
||||
this.storeService = storeService;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
//[Produces("application/xml")]
|
||||
[Produces("application/xml")]
|
||||
[Route("ItemStoreWebService.asmx/GetStore")]
|
||||
public IActionResult GetStore() {
|
||||
// TODO, this may be implemented enough, but may not be
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
string resourceName = assembly.GetManifestResourceNames().Single(str => str.EndsWith("store.xml"));
|
||||
public IActionResult GetStore([FromForm] string getStoreRequest) {
|
||||
GetStoreRequest request = XmlUtil.DeserializeXml<GetStoreRequest>(getStoreRequest);
|
||||
|
||||
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
|
||||
using (StreamReader reader = new StreamReader(stream)) {
|
||||
string result = reader.ReadToEnd();
|
||||
return Ok(result);
|
||||
ItemsInStoreData[] stores = new ItemsInStoreData[request.StoreIDs.Length];
|
||||
for (int i = 0; i < request.StoreIDs.Length; i++) {
|
||||
stores[i] = storeService.GetStore(request.StoreIDs[i]);
|
||||
}
|
||||
|
||||
GetStoreResponse response = new GetStoreResponse {
|
||||
Stores = stores
|
||||
};
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
|
@ -156,8 +156,8 @@ public class ProfileController : Controller {
|
||||
AchievementCount = 0,
|
||||
MythieCount = 0,
|
||||
AnswerData = new UserAnswerData { UserID = viking.Id },
|
||||
GameCurrency = 300,
|
||||
CashCurrency = 75,
|
||||
GameCurrency = 1000,
|
||||
CashCurrency = 1000,
|
||||
ActivityCount = 0,
|
||||
UserGradeData = new UserGrade { UserGradeID = 0 }
|
||||
};
|
||||
|
@ -11,6 +11,6 @@ namespace sodoff.Model {
|
||||
|
||||
public virtual Inventory Inventory { get; set; }
|
||||
|
||||
public int Quantity;
|
||||
public int Quantity { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ builder.Services.AddScoped<KeyValueService>();
|
||||
builder.Services.AddSingleton<ItemService>();
|
||||
builder.Services.AddSingleton<MissionStoreSingleton>();
|
||||
builder.Services.AddScoped<MissionService>();
|
||||
builder.Services.AddSingleton<StoreService>();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
|
1844707
src/Resources/items.xml
1844707
src/Resources/items.xml
File diff suppressed because it is too large
Load Diff
1065311
src/Resources/store.xml
1065311
src/Resources/store.xml
File diff suppressed because it is too large
Load Diff
13
src/Schema/GetStoreRequest.cs
Normal file
13
src/Schema/GetStoreRequest.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace sodoff.Schema;
|
||||
|
||||
[XmlRoot(ElementName = "GetStoreRequest", Namespace = "")]
|
||||
[Serializable]
|
||||
public class GetStoreRequest {
|
||||
[XmlElement(ElementName = "StoreIDs")]
|
||||
public int[] StoreIDs;
|
||||
|
||||
[XmlElement(ElementName = "PIF")]
|
||||
public bool GetPopularItems = true;
|
||||
}
|
10
src/Schema/GetStoreResponse.cs
Normal file
10
src/Schema/GetStoreResponse.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace sodoff.Schema;
|
||||
|
||||
[XmlRoot(ElementName = "GetStoreResponse", Namespace = "", IsNullable = true)]
|
||||
[Serializable]
|
||||
public class GetStoreResponse {
|
||||
[XmlElement(ElementName = "Stores")]
|
||||
public ItemsInStoreData[] Stores;
|
||||
}
|
25
src/Schema/ItemsInStoreData.cs
Normal file
25
src/Schema/ItemsInStoreData.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace sodoff.Schema;
|
||||
|
||||
[XmlRoot(ElementName = "S", Namespace = "", IsNullable = true)]
|
||||
[Serializable]
|
||||
public class ItemsInStoreData {
|
||||
[XmlElement(ElementName = "i", IsNullable = true)]
|
||||
public int? ID;
|
||||
|
||||
[XmlElement(ElementName = "s")]
|
||||
public string StoreName;
|
||||
|
||||
[XmlElement(ElementName = "d")]
|
||||
public string Description;
|
||||
|
||||
[XmlElement(ElementName = "is")]
|
||||
public ItemData[] Items;
|
||||
|
||||
[XmlElement(ElementName = "ss")]
|
||||
public ItemsInStoreDataSale[] SalesAtStore;
|
||||
|
||||
[XmlElement(ElementName = "pitem")]
|
||||
public PopularStoreItem[] PopularItems;
|
||||
}
|
35
src/Schema/ItemsInStoreDataSale.cs
Normal file
35
src/Schema/ItemsInStoreDataSale.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace sodoff.Schema;
|
||||
|
||||
[XmlRoot(ElementName = "SL", Namespace = "", IsNullable = true)]
|
||||
[Serializable]
|
||||
public class ItemsInStoreDataSale {
|
||||
|
||||
[XmlElement(ElementName = "pcid")]
|
||||
public int PriceChangeId;
|
||||
|
||||
[XmlElement(ElementName = "m")]
|
||||
public float Modifier;
|
||||
|
||||
[XmlElement(ElementName = "ic")]
|
||||
public string Icon;
|
||||
|
||||
[XmlElement(ElementName = "rid", IsNullable = true)]
|
||||
public int? RankId;
|
||||
|
||||
[XmlElement(ElementName = "iids")]
|
||||
public int[] ItemIDs;
|
||||
|
||||
[XmlElement(ElementName = "cids")]
|
||||
public int[] CategoryIDs;
|
||||
|
||||
[XmlElement(ElementName = "ism", IsNullable = true)]
|
||||
public bool? ForMembers;
|
||||
|
||||
[XmlElement(ElementName = "sd", IsNullable = true)]
|
||||
public DateTime? StartDate;
|
||||
|
||||
[XmlElement(ElementName = "ed", IsNullable = true)]
|
||||
public DateTime? EndDate;
|
||||
}
|
12
src/Schema/PopularStoreItem.cs
Normal file
12
src/Schema/PopularStoreItem.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace sodoff.Schema;
|
||||
|
||||
[Serializable]
|
||||
public class PopularStoreItem {
|
||||
[XmlElement(ElementName = "id")]
|
||||
public int ItemID;
|
||||
|
||||
[XmlElement(ElementName = "c")]
|
||||
public int Rank;
|
||||
}
|
22
src/Schema/PurchaseStoreItemRequest.cs
Normal file
22
src/Schema/PurchaseStoreItemRequest.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace sodoff.Schema;
|
||||
|
||||
[XmlRoot(ElementName = "pireq", Namespace = "")]
|
||||
[Serializable]
|
||||
public class PurchaseStoreItemRequest {
|
||||
[XmlElement(ElementName = "cid")]
|
||||
public int ContainerId { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "sid")]
|
||||
public int? StoreID { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "i")]
|
||||
public int[] Items { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "ct")]
|
||||
public int CurrencyType { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "ambi")]
|
||||
public bool AddMysteryBoxToInventory { get; set; }
|
||||
}
|
21
src/Services/StoreService.cs
Normal file
21
src/Services/StoreService.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using sodoff.Schema;
|
||||
using sodoff.Util;
|
||||
|
||||
namespace sodoff.Services;
|
||||
|
||||
public class StoreService {
|
||||
|
||||
// NOTE: ANother memory waste (slow clap)
|
||||
Dictionary<int, ItemsInStoreData> stores = new();
|
||||
|
||||
public StoreService() {
|
||||
GetStoreResponse storeArray = XmlUtil.DeserializeXml<GetStoreResponse>(XmlUtil.ReadResourceXmlString("store"));
|
||||
foreach (var s in storeArray.Stores)
|
||||
if (s.ID != null)
|
||||
stores.Add((int)s.ID, s);
|
||||
}
|
||||
|
||||
public ItemsInStoreData GetStore(int id) {
|
||||
return stores[id];
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user