Unstable 0.16.2.0

This commit is contained in:
Markus Isberg
2022-02-02 00:55:02 +09:00
parent b259af5911
commit 6814a11520
106 changed files with 1634 additions and 793 deletions
@@ -27,21 +27,85 @@ namespace Barotrauma
class SoldItem
{
public ItemPrefab ItemPrefab { get; }
public ushort ID { get; }
public ushort ID { get; private set; }
public bool Removed { get; set; }
public byte SellerID { get; }
public SellOrigin Origin { get; }
public SoldItem(ItemPrefab itemPrefab, ushort id, bool removed, byte sellerId)
public enum SellOrigin
{
Character,
Submarine
}
public SoldItem(ItemPrefab itemPrefab, ushort id, bool removed, byte sellerId, SellOrigin origin)
{
ItemPrefab = itemPrefab;
ID = id;
Removed = removed;
SellerID = sellerId;
Origin = origin;
}
public void SetItemId(ushort id)
{
if (ID != Entity.NullEntityID)
{
DebugConsole.ShowError("Error setting SoldItem.ID: ID has already been set and should not be changed.");
return;
}
ID = id;
}
}
partial class CargoManager
{
private class SoldEntity
{
public enum SellStatus
{
/// <summary>
/// Entity sold in SP. Or, entity sold by client and confirmed by server in MP.
/// </summary>
Confirmed,
/// <summary>
/// Entity sold by client in MP. Client has received at least one update from server after selling, but this entity wasn't yet confirmed.
/// </summary>
Unconfirmed,
/// <summary>
/// Entity sold by client in MP. Client hasn't yet received an update from server after selling.
/// </summary>
Local
}
public Item Item { get; private set; }
public ItemPrefab ItemPrefab { get; }
public SellStatus Status { get; set; }
public SoldEntity(Item item, SellStatus status)
{
Item = item;
ItemPrefab = item?.Prefab;
Status = status;
}
public SoldEntity(ItemPrefab itemPrefab, SellStatus status)
{
ItemPrefab = itemPrefab;
Status = status;
}
public void SetItem(Item item)
{
if (Item != null)
{
DebugConsole.ShowError($"Trying to set SoldEntity.Item, but it's already set!\n{Environment.StackTrace.CleanupStackTrace()}");
return;
}
Item = item;
}
}
public const int MaxQuantity = 100;
public List<PurchasedItem> ItemsInBuyCrate { get; } = new List<PurchasedItem>();
@@ -92,7 +156,7 @@ namespace Barotrauma
public void ModifyItemQuantityInBuyCrate(ItemPrefab itemPrefab, int changeInQuantity)
{
PurchasedItem itemInCrate = ItemsInBuyCrate.Find(i => i.ItemPrefab == itemPrefab);
var itemInCrate = ItemsInBuyCrate.Find(i => i.ItemPrefab == itemPrefab);
if (itemInCrate != null)
{
itemInCrate.Quantity += changeInQuantity;
@@ -109,6 +173,25 @@ namespace Barotrauma
OnItemsInBuyCrateChanged?.Invoke();
}
public void ModifyItemQuantityInSubSellCrate(ItemPrefab itemPrefab, int changeInQuantity)
{
var itemInCrate = ItemsInSellFromSubCrate.Find(i => i.ItemPrefab == itemPrefab);
if (itemInCrate != null)
{
itemInCrate.Quantity += changeInQuantity;
if (itemInCrate.Quantity < 1)
{
ItemsInSellFromSubCrate.Remove(itemInCrate);
}
}
else if (changeInQuantity > 0)
{
itemInCrate = new PurchasedItem(itemPrefab, changeInQuantity);
ItemsInSellFromSubCrate.Add(itemInCrate);
}
OnItemsInSellFromSubCrateChanged?.Invoke();
}
public void PurchaseItems(List<PurchasedItem> itemsToPurchase, bool removeFromCrate)
{
// Check all the prices before starting the transaction
@@ -185,6 +268,82 @@ namespace Barotrauma
OnPurchasedItemsChanged?.Invoke();
}
private Dictionary<ItemPrefab, int> UndeterminedSoldEntities { get; } = new Dictionary<ItemPrefab, int>();
public IEnumerable<Item> GetSellableItemsFromSub()
{
if (Submarine.MainSub == null) { return new List<Item>(); }
var confirmedSoldEntities = Enumerable.Empty<SoldEntity>();
UndeterminedSoldEntities.Clear();
#if CLIENT
confirmedSoldEntities = GetConfirmedSoldEntities();
foreach (var soldEntity in SoldEntities)
{
if (soldEntity.Item != null) { continue; }
if (UndeterminedSoldEntities.TryGetValue(soldEntity.ItemPrefab, out int count))
{
UndeterminedSoldEntities[soldEntity.ItemPrefab] = count + 1;
}
else
{
UndeterminedSoldEntities.Add(soldEntity.ItemPrefab, 1);
}
}
#endif
return Submarine.MainSub.GetItems(true).FindAll(item =>
{
if (!IsItemSellable(item, confirmedSoldEntities)) { return false; }
if (item.GetRootInventoryOwner() is Character) { return false; }
if (!item.Components.All(c => !(c is Holdable h) || !h.Attachable || !h.Attached)) { return false; }
if (!item.Components.All(c => !(c is Wire w) || w.Connections.All(c => c == null))) { return false; }
if (!ItemAndAllContainersInteractable(item)) { return false; }
if (item.GetRootContainer() is Item rootContainer && rootContainer.HasTag("donttakeitems")) { return false; }
return true;
}).Distinct();
static bool ItemAndAllContainersInteractable(Item item)
{
do
{
if (!item.IsPlayerTeamInteractable) { return false; }
item = item.Container;
} while (item != null);
return true;
}
}
private bool IsItemSellable(Item item, IEnumerable<SoldEntity> confirmedItems)
{
if (item.Removed) { return false; }
if (!item.Prefab.CanBeSold) { return false; }
if (item.SpawnedInCurrentOutpost) { return false; }
if (!item.Prefab.AllowSellingWhenBroken && item.ConditionPercentage < 90.0f) { return false; }
if (confirmedItems.Any(ci => ci.Item == item)) { return false; }
if (UndeterminedSoldEntities.TryGetValue(item.Prefab, out int count))
{
int newCount = count - 1;
if (newCount > 0)
{
UndeterminedSoldEntities[item.Prefab] = newCount;
}
else
{
UndeterminedSoldEntities.Remove(item.Prefab);
}
return false;
}
if (item.OwnInventory?.Container is ItemContainer itemContainer)
{
var containedItems = item.ContainedItems;
if (containedItems.None()) { return true; }
// Allow selling the item if contained items are unsellable and set to be removed on deconstruct
if (itemContainer.RemoveContainedItemsOnDeconstruct && containedItems.All(it => !it.Prefab.CanBeSold)) { return true; }
// Otherwise there must be no contained items or the contained items must be confirmed as sold
if (!containedItems.All(it => confirmedItems.Any(ci => ci.Item == it))) { return false; }
}
return true;
}
public static void CreateItems(List<PurchasedItem> itemsToSpawn, Submarine sub)
{
if (itemsToSpawn.Count == 0) { return; }