Adding Kenney UI and item management
Deploy Promiscuity Auth API / deploy (push) Successful in 48s
Deploy Promiscuity Character API / deploy (push) Successful in 47s
Deploy Promiscuity Inventory API / deploy (push) Successful in 59s
Deploy Promiscuity Locations API / deploy (push) Successful in 46s
k8s smoke test / test (push) Successful in 10s

This commit is contained in:
2026-03-20 13:11:47 -05:00
parent 038981d7b1
commit 525f9442c3
2631 changed files with 58336 additions and 142 deletions
@@ -313,114 +313,84 @@ public class InventoryStore
public async Task<InventoryMutationResult> TransferAsync(OwnerAccessResult fromOwner, OwnerAccessResult toOwner, TransferInventoryItemRequest req)
{
using var session = await _client.StartSessionAsync();
session.StartTransaction();
var item = await _items.Find(i => i.Id == req.ItemId).FirstOrDefaultAsync();
if (item is null)
return new InventoryMutationResult { Status = InventoryMutationStatus.ItemNotFound };
try
if (item.OwnerType != fromOwner.OwnerType || item.OwnerId != fromOwner.OwnerId || item.EquippedSlot is not null)
return new InventoryMutationResult { Status = InventoryMutationStatus.Invalid };
var quantity = req.Quantity ?? item.Quantity;
if (quantity <= 0 || quantity > item.Quantity)
return new InventoryMutationResult { Status = InventoryMutationStatus.Invalid };
var definition = await GetItemDefinitionAsync(item.ItemKey);
if (definition is null)
return new InventoryMutationResult { Status = InventoryMutationStatus.Invalid };
var toSlot = req.ToSlot ?? await FindFirstOpenSlotAsync(toOwner.OwnerType, toOwner.OwnerId);
if (toSlot is null)
return new InventoryMutationResult { Status = InventoryMutationStatus.Conflict };
var target = await FindItemBySlotAsync(toOwner.OwnerType, toOwner.OwnerId, toSlot.Value);
if (target is not null && !CanMerge(item, target, definition))
return new InventoryMutationResult { Status = InventoryMutationStatus.Conflict };
if (target is not null)
{
var item = await _items.Find(session, i => i.Id == req.ItemId).FirstOrDefaultAsync();
if (item is null)
var transferable = Math.Min(quantity, definition.MaxStackSize - target.Quantity);
if (transferable <= 0)
{
await session.AbortTransactionAsync();
return new InventoryMutationResult { Status = InventoryMutationStatus.ItemNotFound };
}
if (item.OwnerType != fromOwner.OwnerType || item.OwnerId != fromOwner.OwnerId || item.EquippedSlot is not null)
{
await session.AbortTransactionAsync();
return new InventoryMutationResult { Status = InventoryMutationStatus.Invalid };
}
var quantity = req.Quantity ?? item.Quantity;
if (quantity <= 0 || quantity > item.Quantity)
{
await session.AbortTransactionAsync();
return new InventoryMutationResult { Status = InventoryMutationStatus.Invalid };
}
var definition = await GetItemDefinitionAsync(item.ItemKey);
if (definition is null)
{
await session.AbortTransactionAsync();
return new InventoryMutationResult { Status = InventoryMutationStatus.Invalid };
}
var toSlot = req.ToSlot ?? await FindFirstOpenSlotAsync(toOwner.OwnerType, toOwner.OwnerId, session);
if (toSlot is null)
{
await session.AbortTransactionAsync();
return new InventoryMutationResult { Status = InventoryMutationStatus.Conflict };
}
var target = await FindItemBySlotAsync(toOwner.OwnerType, toOwner.OwnerId, toSlot.Value, session);
if (target is not null && !CanMerge(item, target, definition))
{
await session.AbortTransactionAsync();
return new InventoryMutationResult { Status = InventoryMutationStatus.Conflict };
}
if (target is not null)
{
var transferable = Math.Min(quantity, definition.MaxStackSize - target.Quantity);
if (transferable <= 0)
{
await session.AbortTransactionAsync();
return new InventoryMutationResult { Status = InventoryMutationStatus.Conflict };
}
target.Quantity += transferable;
target.UpdatedUtc = DateTime.UtcNow;
await ReplaceItemAsync(target);
target.Quantity += transferable;
target.UpdatedUtc = DateTime.UtcNow;
await ReplaceItemAsync(target, session);
if (transferable == item.Quantity)
await DeleteItemAsync(item.Id, session);
else
{
item.Quantity -= transferable;
item.UpdatedUtc = DateTime.UtcNow;
await ReplaceItemAsync(item, session);
}
}
else if (quantity == item.Quantity)
{
item.OwnerType = toOwner.OwnerType;
item.OwnerId = toOwner.OwnerId;
item.OwnerUserId = toOwner.OwnerUserId;
item.Slot = toSlot;
item.EquippedSlot = null;
item.UpdatedUtc = DateTime.UtcNow;
await ReplaceItemAsync(item, session);
}
if (transferable == item.Quantity)
await DeleteItemAsync(item.Id);
else
{
item.Quantity -= quantity;
item.Quantity -= transferable;
item.UpdatedUtc = DateTime.UtcNow;
await ReplaceItemAsync(item, session);
await InsertItemAsync(new InventoryItem
{
ItemKey = item.ItemKey,
Quantity = quantity,
OwnerType = toOwner.OwnerType,
OwnerId = toOwner.OwnerId,
OwnerUserId = toOwner.OwnerUserId,
Slot = toSlot
}, session);
await ReplaceItemAsync(item);
}
await session.CommitTransactionAsync();
var fromItems = await GetByOwnerAsync(fromOwner.OwnerType, fromOwner.OwnerId);
var toItems = await GetByOwnerAsync(toOwner.OwnerType, toOwner.OwnerId);
return new InventoryMutationResult
{
Status = InventoryMutationStatus.Ok,
Items = fromItems.Concat(toItems).ToList()
};
}
catch
else if (quantity == item.Quantity)
{
await session.AbortTransactionAsync();
throw;
item.OwnerType = toOwner.OwnerType;
item.OwnerId = toOwner.OwnerId;
item.OwnerUserId = toOwner.OwnerUserId;
item.Slot = toSlot;
item.EquippedSlot = null;
item.UpdatedUtc = DateTime.UtcNow;
await ReplaceItemAsync(item);
}
else
{
item.Quantity -= quantity;
item.UpdatedUtc = DateTime.UtcNow;
await ReplaceItemAsync(item);
await InsertItemAsync(new InventoryItem
{
ItemKey = item.ItemKey,
Quantity = quantity,
OwnerType = toOwner.OwnerType,
OwnerId = toOwner.OwnerId,
OwnerUserId = toOwner.OwnerUserId,
Slot = toSlot
});
}
var fromItems = await GetByOwnerAsync(fromOwner.OwnerType, fromOwner.OwnerId);
var toItems = await GetByOwnerAsync(toOwner.OwnerType, toOwner.OwnerId);
return new InventoryMutationResult
{
Status = InventoryMutationStatus.Ok,
Items = fromItems.Concat(toItems).ToList()
};
}
public async Task<InventoryMutationResult> ConsumeAsync(string itemId, int quantity, string userId, bool allowAnyOwner)