ModernUO/Projects/UOContent/Engines/Khaldun/RaiseSwitch.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

225 lines
5.3 KiB
C#

using System;
using System.Linq;
using Server.Network;
namespace Server.Items
{
public class RaiseSwitch : Item
{
private ResetTimer m_ResetTimer;
[Constructible]
public RaiseSwitch(int itemID = 0x1093) : base(itemID) => Movable = false;
public RaiseSwitch(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public RaisableItem RaisableItem { get; set; }
public override void OnDoubleClick(Mobile m)
{
if (!m.InRange(this, 2))
{
m.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that.
return;
}
if (RaisableItem?.Deleted == true)
{
RaisableItem = null;
}
Flip();
if (RaisableItem == null)
{
return;
}
if (RaisableItem.IsRaisable)
{
RaisableItem.Raise();
m.LocalOverheadMessage(
MessageType.Regular,
0x5A,
true,
"You hear a grinding noise echoing in the distance."
);
}
else
{
m.LocalOverheadMessage(
MessageType.Regular,
0x5A,
true,
"You flip the switch again, but nothing happens."
);
}
}
protected virtual void Flip()
{
if (ItemID != 0x1093)
{
ItemID = 0x1093;
StopResetTimer();
}
else
{
ItemID = 0x1095;
StartResetTimer(
RaisableItem?.CloseDelay >= TimeSpan.Zero ? RaisableItem.CloseDelay : TimeSpan.FromMinutes(2.0)
);
}
Effects.PlaySound(Location, Map, 0x3E8);
}
protected void StartResetTimer(TimeSpan delay)
{
StopResetTimer();
m_ResetTimer = new ResetTimer(this, delay);
m_ResetTimer.Start();
}
protected void StopResetTimer()
{
if (m_ResetTimer != null)
{
m_ResetTimer.Stop();
m_ResetTimer = null;
}
}
protected virtual void Reset()
{
if (ItemID != 0x1093)
{
Flip();
}
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
writer.Write(RaisableItem);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadEncodedInt();
RaisableItem = (RaisableItem)reader.ReadEntity<Item>();
Reset();
}
private class ResetTimer : Timer
{
private readonly RaiseSwitch m_RaiseSwitch;
public ResetTimer(RaiseSwitch raiseSwitch, TimeSpan delay) : base(delay)
{
m_RaiseSwitch = raiseSwitch;
Priority = ComputePriority(delay);
}
protected override void OnTick()
{
if (m_RaiseSwitch.Deleted)
{
return;
}
m_RaiseSwitch.m_ResetTimer = null;
m_RaiseSwitch.Reset();
}
}
}
public class DisappearingRaiseSwitch : RaiseSwitch
{
[Constructible]
public DisappearingRaiseSwitch() : base(0x108F)
{
}
public DisappearingRaiseSwitch(Serial serial) : base(serial)
{
}
public int CurrentRange => Visible ? 3 : 2;
public override bool HandlesOnMovement => true;
protected override void Flip()
{
}
protected override void Reset()
{
}
public override void OnMovement(Mobile m, Point3D oldLocation)
{
if (Utility.InRange(m.Location, Location, CurrentRange) || Utility.InRange(oldLocation, Location, CurrentRange))
{
Refresh();
}
}
public override void OnMapChange()
{
if (!Deleted)
{
Refresh();
}
}
public override void OnLocationChange(Point3D oldLoc)
{
if (!Deleted)
{
Refresh();
}
}
public void Refresh()
{
Visible = GetMobilesInRange(CurrentRange).Any(mob => !mob.Hidden || mob.AccessLevel <= AccessLevel.Player);
}
public override void Serialize(IGenericWriter writer)
{
if (RaisableItem?.Deleted == true)
{
RaisableItem = null;
}
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadEncodedInt();
Timer.DelayCall(Refresh);
}
}
}