Overwrite

Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
Unstable Kitsune
2023-11-28 23:20:26 -05:00
parent 3cd54811de
commit b918192e4e
11608 changed files with 2644205 additions and 47 deletions

View File

@@ -0,0 +1,82 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System.Collections.Generic;
using System.IO;
using Server;
using VitaNex.IO;
#endregion
namespace VitaNex.Schedules
{
public class ScheduleDataStore : BinaryDataStore<string, Schedule>
{
public ScheduleDataStore(string root, string doc)
: base(root, doc)
{ }
public ScheduleDataStore(DirectoryInfo root, string doc)
: base(root, doc)
{ }
protected override void Serialize(GenericWriter writer)
{
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.WriteDictionary(
this,
(k, v) =>
{
writer.Write(k);
writer.WriteType(
v,
t =>
{
if (t != null)
{
v.Serialize(writer);
}
});
});
}
break;
}
}
protected override void Deserialize(GenericReader reader)
{
var version = reader.ReadInt();
switch (version)
{
case 0:
{
reader.ReadDictionary(
() =>
{
var key = reader.ReadString();
var val = reader.ReadTypeCreate<Schedule>(reader);
return new KeyValuePair<string, Schedule>(key, val);
},
this);
}
break;
}
}
}
}

View File

@@ -0,0 +1,32 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
#endregion
namespace VitaNex.Schedules
{
[Flags]
public enum ScheduleDays : short
{
None = 0x000,
Sunday = 0x001,
Monday = 0x002,
Tuesday = 0x004,
Wednesday = 0x008,
Thursday = 0x010,
Friday = 0x020,
Saturday = 0x040,
All = Int16.MaxValue
}
}

View File

@@ -0,0 +1,267 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Linq;
using Server;
#endregion
namespace VitaNex.Schedules
{
[PropertyObject]
public class ScheduleInfo : ICloneable
{
private static readonly TimeSpan _OneDay = TimeSpan.FromDays(1.0);
[CommandProperty(Schedules.Access)]
public ScheduleMonths Months { get; set; }
[CommandProperty(Schedules.Access)]
public ScheduleDays Days { get; set; }
[CommandProperty(Schedules.Access)]
public ScheduleTimes Times { get; set; }
[CommandProperty(Schedules.Access)]
public bool Local { get; set; }
public ScheduleInfo(
ScheduleMonths months = ScheduleMonths.All,
ScheduleDays days = ScheduleDays.All,
ScheduleTimes times = null)
{
Months = months;
Days = days;
Times = times ?? new ScheduleTimes();
}
public ScheduleInfo(GenericReader reader)
{
Deserialize(reader);
}
object ICloneable.Clone()
{
return Clone();
}
public virtual ScheduleInfo Clone()
{
return new ScheduleInfo(Months, Days, Times.Clone());
}
public override string ToString()
{
return "Schedule Info";
}
public virtual void Clear()
{
Months = ScheduleMonths.None;
Days = ScheduleDays.None;
Times.Clear();
}
public virtual bool HasMonth(ScheduleMonths month)
{
return Months.HasFlag(month);
}
public virtual bool HasDay(ScheduleDays day)
{
return Days.HasFlag(day);
}
public virtual bool HasTime(TimeSpan time)
{
Validate(ref time);
return Times.Contains(time);
}
public virtual void Validate(ref TimeSpan time)
{
time = new TimeSpan(0, time.Hours, time.Minutes, 0, 0);
}
public virtual void Validate(ref DateTime dt, out TimeSpan time)
{
Validate(ref dt);
time = new TimeSpan(0, dt.TimeOfDay.Hours, dt.TimeOfDay.Minutes, 0, 0);
}
public virtual void Validate(ref DateTime dt)
{
if (!Local && !dt.Kind.HasFlag(DateTimeKind.Utc))
{
dt = dt.ToUniversalTime();
}
else if (Local && !dt.Kind.HasFlag(DateTimeKind.Local))
{
dt = dt.ToLocalTime();
}
dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.TimeOfDay.Hours, dt.TimeOfDay.Minutes, 0, 0, dt.Kind);
}
public virtual DateTime? FindBefore(DateTime dt)
{
if (Months == ScheduleMonths.None || Days == ScheduleDays.None || Times.Count == 0)
{
return null;
}
Validate(ref dt, out var ts);
try
{
var past = false;
for (var year = dt.Year; year >= dt.Year - 1; year--)
{
for (var month = past ? 12 : dt.Month; month >= 1; month--)
{
if (!HasMonth(Schedules.ConvertMonth(month)))
{
past = true;
continue;
}
var start = new DateTime(year, month, past ? DateTime.DaysInMonth(year, month) : dt.Day, 0, 0, 0, dt.Kind);
var end = new DateTime(year, month, 1, 0, 0, 0, dt.Kind);
for (var date = start; date >= end; date -= _OneDay)
{
if (!HasDay(Schedules.ConvertDay(date.DayOfWeek)))
{
past = true;
continue;
}
foreach (var time in Times.Where(t => past || t < ts).OrderByDescending(t => t.Ticks))
{
return new DateTime(year, month, date.Day, time.Hours, time.Minutes, 0, dt.Kind);
}
past = true;
}
}
past = true;
}
}
catch (Exception e)
{
VitaNexCore.ToConsole(e);
}
return null;
}
public virtual DateTime? FindAfter(DateTime dt)
{
if (Months == ScheduleMonths.None || Days == ScheduleDays.None || Times.Count == 0)
{
return null;
}
Validate(ref dt, out var ts);
try
{
var future = false;
for (var year = dt.Year; year <= dt.Year + 1; year++)
{
for (var month = future ? 1 : dt.Month; month <= 12; month++)
{
if (!HasMonth(Schedules.ConvertMonth(month)))
{
future = true;
continue;
}
var start = new DateTime(year, month, future ? 1 : dt.Day, 0, 0, 0, dt.Kind);
var end = new DateTime(year, month, DateTime.DaysInMonth(year, month), 0, 0, 0, dt.Kind);
for (var date = start; date <= end; date += _OneDay)
{
if (!HasDay(Schedules.ConvertDay(date.DayOfWeek)))
{
future = true;
continue;
}
foreach (var time in Times.Where(t => future || t > ts).OrderBy(t => t.Ticks))
{
return new DateTime(year, month, date.Day, time.Hours, time.Minutes, 0, dt.Kind);
}
future = true;
}
}
future = true;
}
}
catch (Exception e)
{
VitaNexCore.ToConsole(e);
}
return null;
}
public virtual void Serialize(GenericWriter writer)
{
var version = writer.SetVersion(1);
switch (version)
{
case 1:
writer.Write(Local);
goto case 0;
case 0:
{
writer.WriteFlag(Months);
writer.WriteFlag(Days);
writer.WriteType(Times, t => Times.Serialize(writer));
}
break;
}
}
public virtual void Deserialize(GenericReader reader)
{
var version = reader.ReadInt();
switch (version)
{
case 1:
Local = reader.ReadBool();
goto case 0;
case 0:
{
Months = reader.ReadFlag<ScheduleMonths>();
Days = reader.ReadFlag<ScheduleDays>();
Times = reader.ReadTypeCreate<ScheduleTimes>(reader) ?? new ScheduleTimes();
}
break;
}
}
}
}

View File

@@ -0,0 +1,37 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
#endregion
namespace VitaNex.Schedules
{
[Flags]
public enum ScheduleMonths : short
{
None = 0x000,
January = 0x001,
February = 0x002,
March = 0x004,
April = 0x008,
May = 0x010,
June = 0x020,
July = 0x040,
August = 0x080,
September = 0x100,
October = 0x200,
November = 0x400,
December = 0x800,
All = ~None
}
}

View File

@@ -0,0 +1,500 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using Server;
using VitaNex.Crypto;
using VitaNex.SuperGumps;
#endregion
namespace VitaNex.Schedules
{
[PropertyObject]
public class Schedule : Timer, ICloneable
{
public static List<Schedule> Instances { get; private set; }
static Schedule()
{
Instances = new List<Schedule>(0x20);
}
private ScheduleInfo _Info;
private TimerPriority _DefaultPriority;
private bool _Enabled;
private string _Name;
private DateTime? _LastGlobalTick;
private DateTime? _CurrentGlobalTick;
private DateTime? _NextGlobalTick;
[CommandProperty(Schedules.Access, true)]
public CryptoHashCode UID { get; private set; }
[CommandProperty(Schedules.Access)]
public virtual string Name { get => _Name ?? (_Name = String.Empty); set => _Name = value ?? String.Empty; }
[CommandProperty(Schedules.Access)]
public virtual bool Enabled
{
get => _Enabled;
set
{
if (!_Enabled && value)
{
_Enabled = true;
InvalidateNextTick();
Priority = ComputePriority(Interval = TimeSpan.FromSeconds(1.0));
if (OnEnabled != null)
{
OnEnabled(this);
}
}
else if (_Enabled && !value)
{
_Enabled = false;
InvalidateNextTick();
Priority = ComputePriority(Interval = TimeSpan.FromMinutes(1.0));
if (OnDisabled != null)
{
OnDisabled(this);
}
}
}
}
[CommandProperty(Schedules.Access)]
public virtual ScheduleInfo Info
{
get => _Info ?? (_Info = new ScheduleInfo());
set
{
_Info = value ?? new ScheduleInfo();
InvalidateNextTick();
}
}
[CommandProperty(Schedules.Access)]
public virtual DateTime? LastGlobalTick => _LastGlobalTick;
[CommandProperty(Schedules.Access)]
public virtual DateTime? CurrentGlobalTick => _CurrentGlobalTick;
[CommandProperty(Schedules.Access)]
public virtual DateTime? NextGlobalTick => _NextGlobalTick;
[CommandProperty(Schedules.Access)]
public TimeSpan WaitGlobalTick
{
get
{
if (_NextGlobalTick != null)
{
return TimeSpan.FromTicks(Math.Max(0, (_NextGlobalTick.Value - Now).Ticks));
}
return TimeSpan.Zero;
}
}
[CommandProperty(Schedules.Access)]
public bool IsRegistered => Schedules.IsRegistered(this);
[CommandProperty(Schedules.Access)]
public bool IsLocal
{
get => _Info.Local;
set
{
_Info.Local = value;
InvalidateNextTick();
}
}
public DateTime Now => IsLocal ? DateTime.Now : DateTime.UtcNow;
public event Action<Schedule> OnGlobalTick;
public event Action<Schedule> OnEnabled;
public event Action<Schedule> OnDisabled;
public Schedule(
string name,
bool enabled,
ScheduleMonths months = ScheduleMonths.None,
ScheduleDays days = ScheduleDays.None,
ScheduleTimes times = null,
params Action<Schedule>[] onTick)
: this(name, enabled, new ScheduleInfo(months, days, times), onTick)
{ }
public Schedule(string name, bool enabled, ScheduleInfo info, params Action<Schedule>[] onTick)
: base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0))
{
UID = new CryptoHashCode(CryptoHashType.MD5, TimeStamp.Now + "+" + Utility.RandomDouble());
_Enabled = enabled;
_Name = name ?? String.Empty;
_Info = info ?? new ScheduleInfo();
Instances.Add(this);
UpdateTicks(Now);
if (onTick != null)
{
foreach (var a in onTick)
{
OnGlobalTick += a;
}
}
Start();
}
public Schedule(GenericReader reader)
: base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0))
{
Instances.Add(this);
Deserialize(reader);
}
~Schedule()
{
Free();
}
object ICloneable.Clone()
{
return Clone();
}
public virtual Schedule Clone()
{
return new Schedule(Name, Enabled, Info.Clone());
}
public void Free()
{
_LastGlobalTick = null;
_CurrentGlobalTick = null;
_NextGlobalTick = null;
OnGlobalTick = null;
OnEnabled = null;
OnDisabled = null;
Instances.Remove(this);
}
public void Register()
{
if (!IsRegistered)
{
Schedules.Register(this);
}
}
public void Unregister()
{
if (IsRegistered)
{
Schedules.Unregister(this);
}
}
private void UpdateTicks(DateTime dt)
{
_LastGlobalTick = dt;
InvalidateNextTick(dt);
}
public void InvalidateNextTick()
{
InvalidateNextTick(Now);
}
public void InvalidateNextTick(DateTime dt)
{
if (!_Enabled)
{
_NextGlobalTick = null;
return;
}
_NextGlobalTick = _Info.FindAfter(dt);
if (_NextGlobalTick != null && _NextGlobalTick < Now)
{
InvalidateNextTick(_NextGlobalTick.Value);
}
}
protected override void OnTick()
{
base.OnTick();
if (!_Enabled)
{
_LastGlobalTick = null;
_CurrentGlobalTick = null;
_NextGlobalTick = null;
return;
}
var now = Now;
if (_NextGlobalTick == null)
{
InvalidateNextTick(now);
}
if (_NextGlobalTick == null || now < _NextGlobalTick)
{
return;
}
_CurrentGlobalTick = now;
InvalidateNextTick(now);
if (OnGlobalTick != null)
{
OnGlobalTick(this);
}
_LastGlobalTick = now;
_CurrentGlobalTick = null;
}
public virtual void Serialize(GenericWriter writer)
{
var version = writer.SetVersion(3);
if (version > 2)
{
UID.Serialize(writer);
}
switch (version)
{
case 3:
case 2:
case 1:
case 0:
{
if (version < 2)
{
writer.WriteType(_Info, t => _Info.Serialize(writer));
}
else
{
writer.WriteBlock(w => w.WriteType(_Info, t => _Info.Serialize(w)));
}
writer.Write(_Enabled);
writer.Write(_Name);
writer.WriteFlag(_DefaultPriority);
if (_LastGlobalTick != null)
{
writer.Write(true);
writer.Write(_LastGlobalTick.Value);
}
else
{
writer.Write(false);
}
if (_NextGlobalTick != null)
{
writer.Write(true);
writer.Write(_NextGlobalTick.Value);
}
else
{
writer.Write(false);
}
writer.Write(Delay);
writer.Write(Interval);
}
break;
}
if (version > 0)
{
writer.Write(Running);
}
}
public virtual void Deserialize(GenericReader reader)
{
var version = reader.GetVersion();
if (version > 2)
{
UID = new CryptoHashCode(reader);
}
else
{
UID = new CryptoHashCode(CryptoHashType.MD5, TimeStamp.Now + "+" + Utility.RandomDouble());
}
switch (version)
{
case 3:
case 2:
case 1:
case 0:
{
if (version < 2)
{
_Info = reader.ReadTypeCreate<ScheduleInfo>(reader) ?? new ScheduleInfo();
}
else
{
_Info = reader.ReadBlock(r => r.ReadTypeCreate<ScheduleInfo>(r)) ?? new ScheduleInfo();
}
_Enabled = reader.ReadBool();
_Name = reader.ReadString();
_DefaultPriority = reader.ReadFlag<TimerPriority>();
if (reader.ReadBool())
{
_LastGlobalTick = reader.ReadDateTime();
}
if (reader.ReadBool())
{
_NextGlobalTick = reader.ReadDateTime();
}
Delay = reader.ReadTimeSpan();
Interval = reader.ReadTimeSpan();
}
break;
}
InvalidateNextTick();
if (version > 0)
{
Running = reader.ReadBool();
}
}
public override int GetHashCode()
{
return UID.ValueHash;
}
public override string ToString()
{
return _Name;
}
public virtual string ToHtmlString(bool big = true)
{
var now = Now;
var html = new StringBuilder();
html.AppendLine("Current Date: {0}", now.ToSimpleString("D, M d y"));
html.AppendLine("Current Time: {0}", now.ToSimpleString("t@h:m@ X"));
html.AppendLine();
html.AppendLine("Schedule Overview:");
html.AppendLine();
if (!_Enabled)
{
html.AppendLine("Schedule is currently disabled.".WrapUOHtmlColor(Color.IndianRed));
return html.ToString();
}
var print = false;
var months = String.Join(", ", _Info.Months.EnumerateValues<string>(true).Not("None".Equals));
var days = String.Join(", ", _Info.Days.EnumerateValues<string>(true).Not("None".Equals));
var times = _Info.Times.ToString(6);
if (months == "None" || String.IsNullOrWhiteSpace(months))
{
html.AppendLine("Schedule requires at least one Month to be set.".WrapUOHtmlColor(Color.IndianRed));
}
else if (days == "None" || String.IsNullOrWhiteSpace(days))
{
html.AppendLine("Schedule requires at least one Day to be set.".WrapUOHtmlColor(Color.IndianRed));
}
else if (times == "None" || String.IsNullOrWhiteSpace(times))
{
html.AppendLine("Schedule requires at least one Time to be set.".WrapUOHtmlColor(Color.IndianRed));
}
else
{
print = true;
}
if (print)
{
html.Append(String.Empty.WrapUOHtmlColor(Color.Cyan, false));
html.AppendLine("Schedule is set to perform an action:");
html.AppendLine();
html.AppendLine("<B>In...</B>");
html.AppendLine(months);
html.AppendLine();
html.AppendLine("<B>On...</B>");
html.AppendLine(days);
html.AppendLine();
html.AppendLine("<B>At...</B>");
html.AppendLine(times);
html.Append(String.Empty.WrapUOHtmlColor(SuperGump.DefaultHtmlColor, false));
if (_NextGlobalTick != null)
{
var today = _NextGlobalTick.Value.Day == now.Day;
var t = _NextGlobalTick.Value.ToSimpleString("t@h:m@ X");
var d = today ? "today" : ("on " + _NextGlobalTick.Value.ToSimpleString("D, M d y"));
var o = WaitGlobalTick.ToSimpleString(@"!<d\d ><h\h ><m\m >s\s");
html.AppendLine();
html.AppendLine("The next tick will be at {0} {1}, in {2}.", t, d, o);
}
}
var value = big ? String.Format("<big>{0}</big>", html) : html.ToString();
return value.WrapUOHtmlColor(SuperGump.DefaultHtmlColor, false);
}
}
}

View File

@@ -0,0 +1,309 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Server;
#endregion
namespace VitaNex.Schedules
{
public class ScheduleTimes : IEnumerable<TimeSpan>, ICloneable
{
private static readonly ScheduleTimes _None;
private static readonly ScheduleTimes _Noon;
private static readonly ScheduleTimes _Midnight;
private static readonly ScheduleTimes _EveryHour;
private static readonly ScheduleTimes _EveryHalfHour;
private static readonly ScheduleTimes _EveryQuarterHour;
private static readonly ScheduleTimes _EveryTenMinutes;
private static readonly ScheduleTimes _EveryFiveMinutes;
private static readonly ScheduleTimes _EveryMinute;
private static readonly ScheduleTimes _FourTwenty;
public static ScheduleTimes None => new ScheduleTimes(_None);
public static ScheduleTimes Noon => new ScheduleTimes(_Noon);
public static ScheduleTimes Midnight => new ScheduleTimes(_Midnight);
public static ScheduleTimes EveryHour => new ScheduleTimes(_EveryHour);
public static ScheduleTimes EveryHalfHour => new ScheduleTimes(_EveryHalfHour);
public static ScheduleTimes EveryQuarterHour => new ScheduleTimes(_EveryQuarterHour);
public static ScheduleTimes EveryTenMinutes => new ScheduleTimes(_EveryTenMinutes);
public static ScheduleTimes EveryFiveMinutes => new ScheduleTimes(_EveryFiveMinutes);
public static ScheduleTimes EveryMinute => new ScheduleTimes(_EveryMinute);
public static ScheduleTimes FourTwenty => new ScheduleTimes(_FourTwenty);
static ScheduleTimes()
{
_None = new ScheduleTimes();
_Noon = new ScheduleTimes(TimeSpan.FromHours(12));
_Midnight = new ScheduleTimes(TimeSpan.Zero);
_EveryHour = new ScheduleTimes();
_EveryHalfHour = new ScheduleTimes();
_EveryQuarterHour = new ScheduleTimes();
_EveryTenMinutes = new ScheduleTimes();
_EveryFiveMinutes = new ScheduleTimes();
_EveryMinute = new ScheduleTimes();
for (var hours = 0; hours < 24; hours++)
{
_EveryHour.Add(new TimeSpan(hours, 0, 0));
for (var minutes = 0; minutes < 60; minutes++)
{
_EveryMinute.Add(new TimeSpan(hours, minutes, 0));
if (minutes % 5 == 0)
{
_EveryFiveMinutes.Add(new TimeSpan(hours, minutes, 0));
}
if (minutes % 10 == 0)
{
_EveryTenMinutes.Add(new TimeSpan(hours, minutes, 0));
}
if (minutes % 15 == 0)
{
_EveryQuarterHour.Add(new TimeSpan(hours, minutes, 0));
}
if (minutes % 30 == 0)
{
_EveryHalfHour.Add(new TimeSpan(hours, minutes, 0));
}
}
}
_FourTwenty = new ScheduleTimes(new TimeSpan(4, 20, 0), new TimeSpan(16, 20, 0));
}
private static void Validate(ref TimeSpan time)
{
time = new TimeSpan(0, time.Hours, time.Minutes, 0, 0);
}
private List<TimeSpan> _List = new List<TimeSpan>();
public int Count => _List.Count;
public TimeSpan? this[int index]
{
get => index < 0 || index >= _List.Count ? default(TimeSpan?) : _List[index];
set
{
if (index < 0 || index >= _List.Count)
{
return;
}
if (value == null)
{
_List.RemoveAt(index);
}
else
{
_List[index] = (TimeSpan)value;
}
}
}
public ScheduleTimes(ScheduleTimes times)
{
Add(times);
}
public ScheduleTimes(IEnumerable<TimeSpan> times)
{
Add(times);
}
public ScheduleTimes(params TimeSpan[] times)
{
Add(times);
}
public ScheduleTimes(GenericReader reader)
{
Deserialize(reader);
}
object ICloneable.Clone()
{
return Clone();
}
public virtual ScheduleTimes Clone()
{
return new ScheduleTimes(this);
}
IEnumerator IEnumerable.GetEnumerator()
{
return _List.GetEnumerator();
}
public IEnumerator<TimeSpan> GetEnumerator()
{
return _List.GetEnumerator();
}
public bool Contains(TimeSpan time, bool validate = true)
{
if (validate)
{
Validate(ref time);
}
return _List.Contains(time);
}
public void Add(ScheduleTimes times)
{
foreach (var time in times)
{
InternalAdd(time);
}
_List.Sort();
}
public void Add(IEnumerable<TimeSpan> times)
{
foreach (var time in times)
{
InternalAdd(time);
}
_List.Sort();
}
public void Add(params TimeSpan[] times)
{
foreach (var time in times)
{
InternalAdd(time);
}
_List.Sort();
}
private void InternalAdd(TimeSpan time)
{
Validate(ref time);
if (Contains(time, false))
{
return;
}
_List.Add(time);
}
public void Remove(ScheduleTimes times)
{
foreach (var time in times)
{
InternalRemove(time);
}
_List.TrimExcess();
_List.Sort();
}
public void Remove(IEnumerable<TimeSpan> times)
{
foreach (var time in times)
{
InternalRemove(time);
}
_List.TrimExcess();
_List.Sort();
}
public void Remove(params TimeSpan[] times)
{
foreach (var time in times)
{
InternalRemove(time);
}
_List.TrimExcess();
_List.Sort();
}
private void InternalRemove(TimeSpan time)
{
Validate(ref time);
if (!Contains(time, false))
{
return;
}
_List.Remove(time);
}
public void Clear()
{
_List.Clear();
_List.TrimExcess();
}
public TimeSpan[] ToArray()
{
return _List.ToArray();
}
public string ToString(int cols)
{
if (!_List.IsNullOrEmpty())
{
return _List.Select(t => t.ToSimpleString("h:m")).ToWrappedString(", ", cols);
}
return "None";
}
public override string ToString()
{
return ToString(0);
}
public virtual void Serialize(GenericWriter writer)
{
var version = writer.SetVersion(0);
switch (version)
{
case 0:
writer.WriteList(_List, (w, t) => w.Write(t));
break;
}
}
public virtual void Deserialize(GenericReader reader)
{
var version = reader.GetVersion();
switch (version)
{
case 0:
_List = reader.ReadList(r => r.ReadTimeSpan());
break;
}
}
}
}

View File

@@ -0,0 +1,244 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using Server;
#endregion
namespace VitaNex.Schedules
{
public static partial class Schedules
{
public const AccessLevel Access = AccessLevel.Administrator;
public static List<Schedule> Registry { get; private set; }
public static Schedule CreateSchedule(
string name,
bool enabled = true,
bool register = true,
ScheduleMonths months = ScheduleMonths.None,
ScheduleDays days = ScheduleDays.None,
ScheduleTimes times = null,
Action<Schedule> handler = null)
{
return CreateSchedule<Schedule>(name, enabled, register, new ScheduleInfo(months, days, times), handler);
}
public static Schedule CreateSchedule(
string name,
bool enabled = true,
bool register = true,
ScheduleInfo info = null,
Action<Schedule> handler = null)
{
return CreateSchedule<Schedule>(name, enabled, register, info, handler);
}
public static TSchedule CreateSchedule<TSchedule>(
string name,
bool enabled = true,
bool register = true,
ScheduleMonths months = ScheduleMonths.None,
ScheduleDays days = ScheduleDays.None,
ScheduleTimes times = null,
Action<Schedule> handler = null)
where TSchedule : Schedule
{
return CreateSchedule<TSchedule>(name, enabled, register, new ScheduleInfo(months, days, times), handler);
}
public static TSchedule CreateSchedule<TSchedule>(
string name,
bool enabled = true,
bool register = true,
ScheduleInfo info = null,
Action<Schedule> handler = null)
where TSchedule : Schedule
{
var st = VitaNexCore.TryCatchGet(() => typeof(TSchedule).CreateInstance<TSchedule>(name, enabled, info, handler));
if (st != null && register)
{
st.Register();
}
return st;
}
public static bool IsRegistered(Schedule schedule)
{
return schedule != null && Registry.Contains(schedule);
}
public static void Register(Schedule schedule)
{
if (schedule != null)
{
Registry.Update(schedule);
}
}
public static void Unregister(Schedule schedule)
{
if (schedule != null)
{
Registry.Remove(schedule);
}
}
public static ScheduleDays ConvertDay(int day)
{
switch (day)
{
case 0:
return ScheduleDays.None;
case 1:
return ScheduleDays.Sunday;
case 2:
return ScheduleDays.Monday;
case 3:
return ScheduleDays.Tuesday;
case 4:
return ScheduleDays.Wednesday;
case 5:
return ScheduleDays.Thursday;
case 6:
return ScheduleDays.Friday;
case 7:
return ScheduleDays.Saturday;
}
return ScheduleDays.All;
}
public static int ConvertDay(ScheduleDays day)
{
switch (day)
{
case ScheduleDays.None:
return 0;
case ScheduleDays.Sunday:
return 1;
case ScheduleDays.Monday:
return 2;
case ScheduleDays.Tuesday:
return 3;
case ScheduleDays.Wednesday:
return 4;
case ScheduleDays.Thursday:
return 5;
case ScheduleDays.Friday:
return 6;
case ScheduleDays.Saturday:
return 7;
}
return 0;
}
public static ScheduleDays ConvertDay(DayOfWeek day)
{
switch (day)
{
case DayOfWeek.Sunday:
return ScheduleDays.Sunday;
case DayOfWeek.Monday:
return ScheduleDays.Monday;
case DayOfWeek.Tuesday:
return ScheduleDays.Tuesday;
case DayOfWeek.Wednesday:
return ScheduleDays.Wednesday;
case DayOfWeek.Thursday:
return ScheduleDays.Thursday;
case DayOfWeek.Friday:
return ScheduleDays.Friday;
case DayOfWeek.Saturday:
return ScheduleDays.Saturday;
}
return ScheduleDays.None;
}
public static ScheduleMonths ConvertMonth(int month)
{
switch (month)
{
case 0:
return ScheduleMonths.None;
case 1:
return ScheduleMonths.January;
case 2:
return ScheduleMonths.February;
case 3:
return ScheduleMonths.March;
case 4:
return ScheduleMonths.April;
case 5:
return ScheduleMonths.May;
case 6:
return ScheduleMonths.June;
case 7:
return ScheduleMonths.July;
case 8:
return ScheduleMonths.August;
case 9:
return ScheduleMonths.September;
case 10:
return ScheduleMonths.October;
case 11:
return ScheduleMonths.November;
case 12:
return ScheduleMonths.December;
}
return ScheduleMonths.All;
}
public static int ConvertMonth(ScheduleMonths month)
{
switch (month)
{
case ScheduleMonths.None:
return 0;
case ScheduleMonths.January:
return 1;
case ScheduleMonths.February:
return 2;
case ScheduleMonths.March:
return 3;
case ScheduleMonths.April:
return 4;
case ScheduleMonths.May:
return 5;
case ScheduleMonths.June:
return 6;
case ScheduleMonths.July:
return 7;
case ScheduleMonths.August:
return 8;
case ScheduleMonths.September:
return 9;
case ScheduleMonths.October:
return 10;
case ScheduleMonths.November:
return 11;
case ScheduleMonths.December:
return 12;
}
return 0;
}
}
}

View File

@@ -0,0 +1,31 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System.Collections.Generic;
#endregion
namespace VitaNex.Schedules
{
[CoreService("Schedules", "3.0.0.0", TaskPriority.High)]
public static partial class Schedules
{
static Schedules()
{
Registry = new List<Schedule>();
}
private static void CSConfig()
{
CommandUtility.Register("Schedules", Access, e => new ScheduleListGump(e.Mobile).Send());
}
}
}

View File

@@ -0,0 +1,113 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Gumps;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Schedules
{
public class ScheduleDaysMenuGump : MenuGump
{
public Schedule Schedule { get; set; }
public bool UseConfirmDialog { get; set; }
public ScheduleDaysMenuGump(
Mobile user,
Schedule schedule,
Gump parent = null,
GumpButton clicked = null,
bool useConfirm = true)
: base(user, parent, clicked: clicked)
{
Schedule = schedule;
UseConfirmDialog = useConfirm;
CanMove = false;
CanResize = false;
}
protected override void CompileOptions(MenuGumpOptions list)
{
list.AppendEntry(new ListGumpEntry("None", b => SetDay(b, ScheduleDays.None)));
list.AppendEntry(new ListGumpEntry("All", b => SetDay(b, ScheduleDays.All)));
list.AppendEntry(new ListGumpEntry("Monday", b => SetDay(b, ScheduleDays.Monday)));
list.AppendEntry(new ListGumpEntry("Tuesday", b => SetDay(b, ScheduleDays.Tuesday)));
list.AppendEntry(new ListGumpEntry("Wednesday", b => SetDay(b, ScheduleDays.Wednesday)));
list.AppendEntry(new ListGumpEntry("Thursday", b => SetDay(b, ScheduleDays.Thursday)));
list.AppendEntry(new ListGumpEntry("Friday", b => SetDay(b, ScheduleDays.Friday)));
list.AppendEntry(new ListGumpEntry("Saturday", b => SetDay(b, ScheduleDays.Saturday)));
list.AppendEntry(new ListGumpEntry("Sunday", b => SetDay(b, ScheduleDays.Sunday)));
base.CompileOptions(list);
list.Replace("Cancel", new ListGumpEntry("Done", Cancel));
}
protected override int GetLabelHue(int index, int pageIndex, ListGumpEntry entry)
{
if (Schedule == null)
{
return ErrorHue;
}
switch (entry.Label)
{
case "Monday":
return Schedule.Info.HasDay(ScheduleDays.Monday) ? HighlightHue : ErrorHue;
case "Tuesday":
return Schedule.Info.HasDay(ScheduleDays.Tuesday) ? HighlightHue : ErrorHue;
case "Wednesday":
return Schedule.Info.HasDay(ScheduleDays.Wednesday) ? HighlightHue : ErrorHue;
case "Thursday":
return Schedule.Info.HasDay(ScheduleDays.Thursday) ? HighlightHue : ErrorHue;
case "Friday":
return Schedule.Info.HasDay(ScheduleDays.Friday) ? HighlightHue : ErrorHue;
case "Saturday":
return Schedule.Info.HasDay(ScheduleDays.Saturday) ? HighlightHue : ErrorHue;
case "Sunday":
return Schedule.Info.HasDay(ScheduleDays.Sunday) ? HighlightHue : ErrorHue;
}
return base.GetLabelHue(index, pageIndex, entry);
}
protected virtual void SetDay(GumpButton button, ScheduleDays day)
{
if (Schedule == null)
{
Close();
return;
}
switch (day)
{
case ScheduleDays.None:
Schedule.Info.Days = ScheduleDays.None;
break;
case ScheduleDays.All:
Schedule.Info.Days = ScheduleDays.All;
break;
default:
Schedule.Info.Days ^= day;
break;
}
Schedule.InvalidateNextTick();
Refresh(true);
}
}
}

View File

@@ -0,0 +1,128 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Gumps;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Schedules
{
public class ScheduleMonthsMenuGump : MenuGump
{
public Schedule Schedule { get; set; }
public bool UseConfirmDialog { get; set; }
public ScheduleMonthsMenuGump(
Mobile user,
Schedule schedule,
Gump parent = null,
GumpButton clicked = null,
bool useConfirm = true)
: base(user, parent, clicked: clicked)
{
Schedule = schedule;
UseConfirmDialog = useConfirm;
CanMove = false;
CanResize = false;
}
protected override void CompileOptions(MenuGumpOptions list)
{
list.AppendEntry("None", b => SetMonth(b, ScheduleMonths.None));
list.AppendEntry("All", b => SetMonth(b, ScheduleMonths.All));
list.AppendEntry("January", b => SetMonth(b, ScheduleMonths.January));
list.AppendEntry("February", b => SetMonth(b, ScheduleMonths.February));
list.AppendEntry("March", b => SetMonth(b, ScheduleMonths.March));
list.AppendEntry("April", b => SetMonth(b, ScheduleMonths.April));
list.AppendEntry("May", b => SetMonth(b, ScheduleMonths.May));
list.AppendEntry("June", b => SetMonth(b, ScheduleMonths.June));
list.AppendEntry("July", b => SetMonth(b, ScheduleMonths.July));
list.AppendEntry("August", b => SetMonth(b, ScheduleMonths.August));
list.AppendEntry("September", b => SetMonth(b, ScheduleMonths.September));
list.AppendEntry("October", b => SetMonth(b, ScheduleMonths.October));
list.AppendEntry("November", b => SetMonth(b, ScheduleMonths.November));
list.AppendEntry("December", b => SetMonth(b, ScheduleMonths.December));
base.CompileOptions(list);
list.Replace("Cancel", "Done", Cancel);
}
protected override int GetLabelHue(int index, int pageIndex, ListGumpEntry entry)
{
if (Schedule == null)
{
return ErrorHue;
}
switch (entry.Label)
{
case "January":
return Schedule.Info.HasMonth(ScheduleMonths.January) ? HighlightHue : ErrorHue;
case "February":
return Schedule.Info.HasMonth(ScheduleMonths.February) ? HighlightHue : ErrorHue;
case "March":
return Schedule.Info.HasMonth(ScheduleMonths.March) ? HighlightHue : ErrorHue;
case "April":
return Schedule.Info.HasMonth(ScheduleMonths.April) ? HighlightHue : ErrorHue;
case "May":
return Schedule.Info.HasMonth(ScheduleMonths.May) ? HighlightHue : ErrorHue;
case "June":
return Schedule.Info.HasMonth(ScheduleMonths.June) ? HighlightHue : ErrorHue;
case "July":
return Schedule.Info.HasMonth(ScheduleMonths.July) ? HighlightHue : ErrorHue;
case "August":
return Schedule.Info.HasMonth(ScheduleMonths.August) ? HighlightHue : ErrorHue;
case "September":
return Schedule.Info.HasMonth(ScheduleMonths.September) ? HighlightHue : ErrorHue;
case "October":
return Schedule.Info.HasMonth(ScheduleMonths.October) ? HighlightHue : ErrorHue;
case "November":
return Schedule.Info.HasMonth(ScheduleMonths.November) ? HighlightHue : ErrorHue;
case "December":
return Schedule.Info.HasMonth(ScheduleMonths.December) ? HighlightHue : ErrorHue;
}
return base.GetLabelHue(index, pageIndex, entry);
}
protected virtual void SetMonth(GumpButton button, ScheduleMonths month)
{
if (Schedule == null)
{
Close();
return;
}
switch (month)
{
case ScheduleMonths.None:
Schedule.Info.Months = ScheduleMonths.None;
break;
case ScheduleMonths.All:
Schedule.Info.Months = ScheduleMonths.All;
break;
default:
Schedule.Info.Months ^= month;
break;
}
Schedule.InvalidateNextTick();
Refresh(true);
}
}
}

View File

@@ -0,0 +1,120 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using Server;
using Server.Gumps;
using VitaNex.SuperGumps;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Schedules
{
public class ScheduleListGump : ListGump<Schedule>
{
public static string HelpText = "Schedules: Schedules are timers that tick on specific dates at specific times.";
public bool UseConfirmDialog { get; set; }
public ScheduleListGump(Mobile user, Gump parent = null, bool useConfirm = true)
: base(user, parent, emptyText: "There are no schedules to display.", title: "Schedules")
{
UseConfirmDialog = useConfirm;
ForceRecompile = true;
CanMove = false;
CanResize = false;
AutoRefresh = true;
}
protected override string GetLabelText(int index, int pageIndex, Schedule entry)
{
return entry != null ? entry.Name : base.GetLabelText(index, pageIndex, null);
}
protected override int GetLabelHue(int index, int pageIndex, Schedule entry)
{
if (entry != null)
{
if (!entry.Enabled)
{
return ErrorHue;
}
if (!entry.Running || entry.NextGlobalTick == null)
{
return HighlightHue;
}
}
return base.GetLabelHue(index, pageIndex, null);
}
protected override void CompileMenuOptions(MenuGumpOptions list)
{
list.AppendEntry(new ListGumpEntry("Help", ShowHelp));
base.CompileMenuOptions(list);
}
protected virtual void ShowHelp(GumpButton button)
{
Send(new NoticeDialogGump(User, this, title: "Help", html: HelpText));
}
protected override void CompileList(List<Schedule> list)
{
list.Clear();
list.AddRange(Schedules.Registry);
base.CompileList(list);
}
public override string GetSearchKeyFor(Schedule key)
{
return key != null ? key.Name : base.GetSearchKeyFor(null);
}
protected override void CompileLayout(SuperGumpLayout layout)
{
base.CompileLayout(layout);
layout.Replace(
"label/header/title",
() => AddLabelCropped(90, 15, 185, 20, GetTitleHue(), String.IsNullOrEmpty(Title) ? DefaultTitle : Title));
layout.Replace(
"label/header/subtitle",
() =>
{
var loc = DateTime.Now.ToSimpleString("D t@h:m@ X");
var utc = DateTime.UtcNow.ToSimpleString("D t@h:m@ X");
AddLabelCropped(275, 15, 100, 20, HighlightHue, String.Format("[{0}] [{1}]", loc, utc));
});
}
protected override void SelectEntry(GumpButton button, Schedule entry)
{
base.SelectEntry(button, entry);
if (button != null && entry != null)
{
Send(new ScheduleOverviewGump(User, entry, Hide(true), UseConfirmDialog));
}
}
}
}

View File

@@ -0,0 +1,168 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Drawing;
using Server;
using Server.Gumps;
using VitaNex.SuperGumps;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Schedules
{
public class ScheduleOverviewGump : HtmlPanelGump<Schedule>
{
public bool UseConfirmDialog { get; set; }
public ScheduleOverviewGump(Mobile user, Schedule schedule, Gump parent = null, bool useConfirm = true)
: base(user, parent, emptyText: "Schedule Unavailable", title: "Schedule Overview", selected: schedule)
{
UseConfirmDialog = useConfirm;
HtmlColor = Color.GreenYellow;
ForceRecompile = true;
AutoRefresh = true;
}
protected override void Compile()
{
base.Compile();
if (Selected != null)
{
Html = Selected.ToHtmlString();
}
}
protected override void CompileLayout(SuperGumpLayout layout)
{
base.CompileLayout(layout);
layout.Replace(
"label/header/title",
() =>
{
var title = String.IsNullOrEmpty(Title) ? "Schedule Overview" : Title;
AddLabelCropped(90, 15, Width - 235, 20, GetTitleHue(), title);
});
layout.Replace(
"label/header/subtitle",
() =>
{
var time = Selected.Now.ToSimpleString("t@h:m@ X");
AddLabelCropped(90 + (Width - 235), 15, 100, 20, HighlightHue, time);
});
}
protected override void CompileMenuOptions(MenuGumpOptions list)
{
list.Clear();
if (Selected != null && User.AccessLevel >= Schedules.Access)
{
if (!Selected.Enabled)
{
list.AppendEntry(
"Enable",
b =>
{
Selected.Enabled = true;
Refresh(true);
},
HighlightHue);
}
else
{
list.AppendEntry(
"Disable",
b =>
{
Selected.Enabled = false;
Refresh(true);
},
HighlightHue);
}
if (Selected.IsLocal)
{
list.AppendEntry(
"Use Universal Time",
b =>
{
Selected.IsLocal = false;
Refresh(true);
},
HighlightHue);
}
else
{
list.AppendEntry(
"Use Local Time",
b =>
{
Selected.IsLocal = true;
Refresh(true);
},
HighlightHue);
}
list.AppendEntry("Edit Months", b => Send(new ScheduleMonthsMenuGump(User, Selected, Refresh(), b)), HighlightHue);
list.AppendEntry("Edit Days", b => Send(new ScheduleDaysMenuGump(User, Selected, Refresh(), b)), HighlightHue);
list.AppendEntry("Edit Times", b => Send(new SheduleTimeListGump(User, Selected, Hide(true))), HighlightHue);
list.AppendEntry(
"Clear Schedule",
b =>
{
if (UseConfirmDialog)
{
new ConfirmDialogGump(User, this)
{
Title = "Clear Schedule?",
Html = "The schedule will be cleared, erasing all data associated with its entries.\n" +
"This action can not be reversed.\n\nDo you want to continue?",
AcceptHandler = OnConfirmClearSchedule,
CancelHandler = Refresh
}.Send();
}
else
{
OnConfirmClearSchedule(b);
}
},
HighlightHue);
}
base.CompileMenuOptions(list);
}
protected virtual void OnConfirmClearSchedule(GumpButton button)
{
if (Selected == null)
{
Close();
return;
}
Selected.Info.Clear();
Selected.InvalidateNextTick();
Refresh(true);
}
}
}

View File

@@ -0,0 +1,217 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using Server;
using Server.Gumps;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Schedules
{
public class SheduleTimeListGump : ListGump<TimeSpan>
{
public static string HelpText = "Schedule Times: List specific times for this schedule.\n" +
"These times determine what time of day the schedule will tick.";
public Schedule Schedule { get; set; }
public bool UseConfirmDialog { get; set; }
public SheduleTimeListGump(Mobile user, Schedule schedule, Gump parent = null, bool useConfirm = true)
: base(user, parent, emptyText: "There are no times to display.", title: "Schedule Times")
{
Schedule = schedule;
UseConfirmDialog = useConfirm;
ForceRecompile = true;
CanMove = false;
CanResize = false;
Columns = 3;
EntriesPerPage = 24;
}
protected override void Compile()
{
var i = Title.IndexOf('(');
if (i > 0)
{
Title = Title.Substring(0, i);
}
Title += String.Concat(' ', '(', Schedule.Now.ToSimpleString("X"), ')');
base.Compile();
}
protected override string GetLabelText(int index, int pageIndex, TimeSpan entry)
{
return entry.ToSimpleString("h:m");
}
protected override void CompileMenuOptions(MenuGumpOptions list)
{
list.AppendEntry("Delete All", OnDeleteAll, HighlightHue);
list.AppendEntry("Add Time", OnAddTime, HighlightHue);
list.AppendEntry("Use Preset", OnPresetsMenu, HighlightHue);
list.AppendEntry("Help", ShowHelp);
base.CompileMenuOptions(list);
}
protected virtual void ShowHelp(GumpButton button)
{
if (User != null && !User.Deleted)
{
Send(new NoticeDialogGump(User, this, title: "Help", html: HelpText));
}
}
protected virtual void OnDeleteAll(GumpButton button)
{
if (UseConfirmDialog)
{
new ConfirmDialogGump(User, this)
{
Title = "Delete All Times?",
Html = "All times in the schedule will be deleted, erasing all data associated with them.\n" +
"This action can not be reversed.\n\nDo you want to continue?",
AcceptHandler = subButton =>
{
Schedule.Info.Times.Clear();
Schedule.InvalidateNextTick();
Refresh(true);
},
CancelHandler = Refresh
}.Send();
}
else
{
Schedule.Info.Times.Clear();
Schedule.InvalidateNextTick();
Refresh(true);
}
}
protected virtual void OnAddTime(GumpButton button)
{
var nowTime = Schedule.Now.TimeOfDay;
new InputDialogGump(User, this)
{
Title = "Add Schedule Time",
Html = "Enter the time of day " + String.Concat('(', nowTime.ToSimpleString("X"), ')') +
" to add to this schedule.\nFormat: HH:MM\nExample: " +
String.Format("{0:D2}:{1:D2}", nowTime.Hours, nowTime.Minutes) +
"\n\nYou can also load a preset list of times, but be aware that presets will " +
"overwrite any custom entries you have created.",
Callback = (b, text) =>
{
ParseTime(text, out var hh, out var mm);
if (hh == -1 || mm == -1)
{
OnAddTime(button);
return;
}
Schedule.Info.Times.Add(new TimeSpan(0, hh, mm, 0, 0));
Schedule.InvalidateNextTick();
OnAddTime(button);
},
CancelHandler = Refresh
}.Send();
}
protected virtual void OnPresetsMenu(GumpButton button)
{
var entries = new[]
{
new ListGumpEntry("Noon", b => UsePreset(b, ScheduleTimes.Noon), HighlightHue),
new ListGumpEntry("Midnight", b => UsePreset(b, ScheduleTimes.Midnight), HighlightHue),
new ListGumpEntry("Every Hour", b => UsePreset(b, ScheduleTimes.EveryHour), HighlightHue),
new ListGumpEntry("Every 30 Minutes", b => UsePreset(b, ScheduleTimes.EveryHalfHour), HighlightHue),
new ListGumpEntry("Every 15 Minutes", b => UsePreset(b, ScheduleTimes.EveryQuarterHour), HighlightHue),
new ListGumpEntry("Every 10 Minutes", b => UsePreset(b, ScheduleTimes.EveryTenMinutes), HighlightHue),
new ListGumpEntry("Every 5 Minutes", b => UsePreset(b, ScheduleTimes.EveryFiveMinutes), HighlightHue),
new ListGumpEntry("Every Minute", b => UsePreset(b, ScheduleTimes.EveryMinute), HighlightHue),
new ListGumpEntry("Four Twenty", b => UsePreset(b, ScheduleTimes.FourTwenty), HighlightHue)
};
Send(new MenuGump(User, this, entries, button));
}
protected virtual void UsePreset(GumpButton button, ScheduleTimes times)
{
Schedule.Info.Times.Clear();
Schedule.Info.Times.Add(times);
Schedule.InvalidateNextTick();
Refresh(true);
}
protected virtual void ParseTime(string text, out int hh, out int mm)
{
var parts = text.Split(':');
if (parts.Length >= 2)
{
if (!Int32.TryParse(parts[0], out hh))
{
hh = -1;
}
if (!Int32.TryParse(parts[1], out mm))
{
mm = -1;
}
hh = (hh < 0) ? 0 : (hh > 23) ? 23 : hh;
mm = (mm < 0) ? 0 : (mm > 59) ? 59 : mm;
}
else
{
hh = -1;
mm = -1;
}
}
protected override void CompileList(List<TimeSpan> list)
{
list.Clear();
list.AddRange(Schedule.Info.Times);
base.CompileList(list);
}
public override string GetSearchKeyFor(TimeSpan key)
{
return key.ToSimpleString("h:m");
}
protected override void SelectEntry(GumpButton button, TimeSpan entry)
{
base.SelectEntry(button, entry);
Send(new ScheduleTimeListEntryGump(User, Schedule, Refresh(), button, entry, UseConfirmDialog));
}
}
}

View File

@@ -0,0 +1,88 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Gumps;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Schedules
{
public class ScheduleTimeListEntryGump : MenuGump
{
public Schedule Schedule { get; set; }
public TimeSpan Time { get; set; }
public bool UseConfirmDialog { get; set; }
public ScheduleTimeListEntryGump(
Mobile user,
Schedule schedule,
Gump parent = null,
GumpButton clicked = null,
TimeSpan? time = null,
bool useConfirm = true)
: base(user, parent, clicked: clicked)
{
Schedule = schedule;
Time = time ?? TimeSpan.Zero;
UseConfirmDialog = useConfirm;
CanMove = false;
CanResize = false;
}
protected override void CompileOptions(MenuGumpOptions list)
{
base.CompileOptions(list);
list.PrependEntry(
"Delete",
button =>
{
if (UseConfirmDialog)
{
new ConfirmDialogGump(User, Refresh())
{
Title = "Delete Time?",
Html = "All data associated with this time will be deleted.\n" +
"This action can not be reversed!\nDo you want to continue?",
AcceptHandler = OnConfirmDelete
}.Send();
}
else
{
OnConfirmDelete(button);
}
},
HighlightHue);
}
protected virtual void OnConfirmDelete(GumpButton button)
{
if (Selected == null)
{
Close();
return;
}
Schedule.Info.Times.Remove(Time);
Schedule.InvalidateNextTick();
Close();
}
}
}