ModernUO/Projects/UOContent/Engines/Factions/Core/FactionItem.cs
Kamron Batman 4ddb3de026
fix(core): Fixes several serialization issues (#355)
- [X] Fixes an issue where a buffer smaller than 8 bytes would not double with enough space in some cases.
- [X] Fixes an issue with dupe copying the savebuffer reference (ugh).
- [X] Streamlines the IGenericWriter API to use better generics.
- [X] Streamlines the IGenericReader API to use better generics.
- [X] Forces `tidying` of a List/HashSet to be done externally since Writers/Readers should not have side effects.
- [X] Fixes an issue where Tidying a list didn't TrimExcess, causing memory leaks.
- [X] Reverted the meaning of `World.Running` to specifically refer to any world state post world loading.
  - NOTE: Do not use this if you want to block on world saves. Instead use checks against `WorldState.Saving` states.
- [X] Fixes an issue with serializing negative DateTime deltas.
- [X] Fixes a potential issue with serializing non-UTC DateTime.

Bumps release version
2020-12-23 07:11:41 -08:00

154 lines
3.4 KiB
C#

using System;
namespace Server.Factions
{
public interface IFactionItem
{
FactionItem FactionItemState { get; set; }
}
public class FactionItem
{
public static readonly TimeSpan ExpirationPeriod = TimeSpan.FromDays(21.0);
public FactionItem(Item item, Faction faction)
{
Item = item;
Faction = faction;
}
public FactionItem(IGenericReader reader, Faction faction)
{
var version = reader.ReadEncodedInt();
switch (version)
{
case 0:
{
Item = reader.ReadEntity<Item>();
Expiration = reader.ReadDateTime();
break;
}
}
Faction = faction;
}
public Item Item { get; }
public Faction Faction { get; }
public DateTime Expiration { get; private set; }
public bool HasExpired
{
get
{
if (Item?.Deleted != false)
{
return true;
}
return Expiration != DateTime.MinValue && DateTime.UtcNow >= Expiration;
}
}
public void StartExpiration()
{
Expiration = DateTime.UtcNow + ExpirationPeriod;
}
public void CheckAttach()
{
if (!HasExpired)
{
Attach();
}
else
{
Detach();
}
}
public void Attach()
{
if (Item is IFactionItem item)
{
item.FactionItemState = this;
}
Faction?.State.FactionItems.Add(this);
}
public void Detach()
{
if (Item is IFactionItem item)
{
item.FactionItemState = null;
}
if (Faction?.State.FactionItems.Contains(this) == true)
{
Faction.State.FactionItems.Remove(this);
}
}
public void Serialize(IGenericWriter writer)
{
writer.WriteEncodedInt(0);
writer.Write(Item);
writer.Write(Expiration);
}
public static int GetMaxWearables(Mobile mob)
{
var pl = PlayerState.Find(mob);
return pl == null ? 0 :
pl.Faction.IsCommander(mob) ? 9 : pl.Rank.MaxWearables;
}
public static FactionItem Find(Item item)
{
if (item is IFactionItem factionItem)
{
var state = factionItem.FactionItemState;
if (state?.HasExpired == true)
{
state.Detach();
state = null;
}
return state;
}
return null;
}
public static Item Imbue(Item item, Faction faction, bool expire, int hue)
{
if (!(item is IFactionItem))
{
return item;
}
var state = Find(item);
if (state == null)
{
state = new FactionItem(item, faction);
state.Attach();
}
if (expire)
{
state.StartExpiration();
}
item.Hue = hue;
return item;
}
}
}