- [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
154 lines
3.4 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|