Overwrite
Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
214
Server/AggressorInfo.cs
Normal file
214
Server/AggressorInfo.cs
Normal file
@@ -0,0 +1,214 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
#endregion
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class AggressorInfo
|
||||
{
|
||||
private Mobile m_Attacker, m_Defender;
|
||||
private DateTime m_LastCombatTime;
|
||||
private bool m_CanReportMurder;
|
||||
private bool m_Reported;
|
||||
private bool m_CriminalAggression;
|
||||
|
||||
private bool m_Queued;
|
||||
|
||||
private static readonly Queue<AggressorInfo> m_Pool = new Queue<AggressorInfo>();
|
||||
|
||||
public static AggressorInfo Create(Mobile attacker, Mobile defender, bool criminal)
|
||||
{
|
||||
AggressorInfo info;
|
||||
|
||||
if (m_Pool.Count > 0)
|
||||
{
|
||||
info = m_Pool.Dequeue();
|
||||
|
||||
info.m_Attacker = attacker;
|
||||
info.m_Defender = defender;
|
||||
|
||||
info.m_CanReportMurder = criminal;
|
||||
info.m_CriminalAggression = criminal;
|
||||
|
||||
info.m_Queued = false;
|
||||
|
||||
info.Refresh();
|
||||
}
|
||||
else
|
||||
{
|
||||
info = new AggressorInfo(attacker, defender, criminal);
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
public void Free()
|
||||
{
|
||||
if (m_Queued)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_Queued = true;
|
||||
m_Pool.Enqueue(this);
|
||||
}
|
||||
|
||||
private AggressorInfo(Mobile attacker, Mobile defender, bool criminal)
|
||||
{
|
||||
m_Attacker = attacker;
|
||||
m_Defender = defender;
|
||||
|
||||
m_CanReportMurder = criminal;
|
||||
m_CriminalAggression = criminal;
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
private static TimeSpan m_ExpireDelay = TimeSpan.FromMinutes(2.0);
|
||||
|
||||
public static TimeSpan ExpireDelay { get { return m_ExpireDelay; } set { m_ExpireDelay = value; } }
|
||||
|
||||
public static void DumpAccess()
|
||||
{
|
||||
using (StreamWriter op = new StreamWriter("warnings.log", true))
|
||||
{
|
||||
op.WriteLine("Warning: Access to queued AggressorInfo:");
|
||||
op.WriteLine(new StackTrace());
|
||||
op.WriteLine();
|
||||
op.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
public bool Expired
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_Queued)
|
||||
{
|
||||
DumpAccess();
|
||||
}
|
||||
|
||||
return (m_Attacker.Deleted || m_Defender.Deleted || DateTime.UtcNow >= (m_LastCombatTime + m_ExpireDelay));
|
||||
}
|
||||
}
|
||||
|
||||
public bool CriminalAggression
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_Queued)
|
||||
{
|
||||
DumpAccess();
|
||||
}
|
||||
|
||||
return m_CriminalAggression;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (m_Queued)
|
||||
{
|
||||
DumpAccess();
|
||||
}
|
||||
|
||||
m_CriminalAggression = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Mobile Attacker
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_Queued)
|
||||
{
|
||||
DumpAccess();
|
||||
}
|
||||
|
||||
return m_Attacker;
|
||||
}
|
||||
}
|
||||
|
||||
public Mobile Defender
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_Queued)
|
||||
{
|
||||
DumpAccess();
|
||||
}
|
||||
|
||||
return m_Defender;
|
||||
}
|
||||
}
|
||||
|
||||
public DateTime LastCombatTime
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_Queued)
|
||||
{
|
||||
DumpAccess();
|
||||
}
|
||||
|
||||
return m_LastCombatTime;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Reported
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_Queued)
|
||||
{
|
||||
DumpAccess();
|
||||
}
|
||||
|
||||
return m_Reported;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (m_Queued)
|
||||
{
|
||||
DumpAccess();
|
||||
}
|
||||
|
||||
m_Reported = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanReportMurder
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_Queued)
|
||||
{
|
||||
DumpAccess();
|
||||
}
|
||||
|
||||
return m_CanReportMurder;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (m_Queued)
|
||||
{
|
||||
DumpAccess();
|
||||
}
|
||||
|
||||
m_CanReportMurder = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
if (m_Queued)
|
||||
{
|
||||
DumpAccess();
|
||||
}
|
||||
|
||||
m_LastCombatTime = DateTime.UtcNow;
|
||||
m_Reported = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
63
Server/AssemblyInfo.cs
Normal file
63
Server/AssemblyInfo.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
#region References
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.InteropServices;
|
||||
#endregion
|
||||
|
||||
//
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
//
|
||||
|
||||
[assembly: AssemblyTitle("ServUO Server")]
|
||||
[assembly: AssemblyDescription("Ultima Online Server Emulator")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("The ServUO Team")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
//
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly: AssemblyVersion("0.5.*")]
|
||||
//
|
||||
// In order to sign your assembly you must specify a key to use. Refer to the
|
||||
// Microsoft .NET Framework documentation for more information on assembly signing.
|
||||
//
|
||||
// Use the attributes below to control which key is used for signing.
|
||||
//
|
||||
// Notes:
|
||||
// (*) If no key is specified, the assembly is not signed.
|
||||
// (*) KeyName refers to a key that has been installed in the Crypto Service
|
||||
// Provider (CSP) on your machine. KeyFile refers to a file which contains
|
||||
// a key.
|
||||
// (*) If the KeyFile and the KeyName values are both specified, the
|
||||
// following processing occurs:
|
||||
// (1) If the KeyName can be found in the CSP, that key is used.
|
||||
// (2) If the KeyName does not exist and the KeyFile does exist, the key
|
||||
// in the KeyFile is installed into the CSP and used.
|
||||
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
|
||||
// When specifying the KeyFile, the location of the KeyFile should be
|
||||
// relative to the project output directory which is
|
||||
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
|
||||
// located in the project directory, you would specify the AssemblyKeyFile
|
||||
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
|
||||
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
|
||||
// documentation for more information on this.
|
||||
//
|
||||
|
||||
[assembly: AssemblyDelaySign(false)]
|
||||
[assembly: AssemblyKeyFile("")]
|
||||
[assembly: AssemblyKeyName("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: NeutralResourcesLanguage("en")]
|
||||
206
Server/Attributes.cs
Normal file
206
Server/Attributes.cs
Normal file
@@ -0,0 +1,206 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
#endregion
|
||||
|
||||
namespace Server
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class HueAttribute : Attribute
|
||||
{ }
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class BodyAttribute : Attribute
|
||||
{ }
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface)]
|
||||
public class PropertyObjectAttribute : Attribute
|
||||
{ }
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
|
||||
public class NoSortAttribute : Attribute
|
||||
{ }
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class CallPriorityAttribute : Attribute
|
||||
{
|
||||
public int Priority { get; set; }
|
||||
|
||||
public CallPriorityAttribute(int priority)
|
||||
{
|
||||
Priority = priority;
|
||||
}
|
||||
}
|
||||
|
||||
public class CallPriorityComparer : IComparer<MethodInfo>
|
||||
{
|
||||
public int Compare(MethodInfo x, MethodInfo y)
|
||||
{
|
||||
if (x == null && y == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (x == null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (y == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
var xPriority = GetPriority(x);
|
||||
var yPriority = GetPriority(y);
|
||||
|
||||
if (xPriority > yPriority)
|
||||
return 1;
|
||||
|
||||
if (xPriority < yPriority)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int GetPriority(MethodInfo mi)
|
||||
{
|
||||
var objs = mi.GetCustomAttributes(typeof(CallPriorityAttribute), true);
|
||||
|
||||
if (objs == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (objs.Length == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
CallPriorityAttribute attr = objs[0] as CallPriorityAttribute;
|
||||
|
||||
if (attr == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return attr.Priority;
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class TypeAliasAttribute : Attribute
|
||||
{
|
||||
private readonly string[] m_Aliases;
|
||||
|
||||
public string[] Aliases { get { return m_Aliases; } }
|
||||
|
||||
public TypeAliasAttribute(params string[] aliases)
|
||||
{
|
||||
m_Aliases = aliases;
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
|
||||
public class ParsableAttribute : Attribute
|
||||
{ }
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum)]
|
||||
public class CustomEnumAttribute : Attribute
|
||||
{
|
||||
private readonly string[] m_Names;
|
||||
|
||||
public string[] Names { get { return m_Names; } }
|
||||
|
||||
public CustomEnumAttribute(string[] names)
|
||||
{
|
||||
m_Names = names;
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class DeleteConfirmAttribute : Attribute
|
||||
{
|
||||
public string Message { get; set; }
|
||||
|
||||
public DeleteConfirmAttribute()
|
||||
: this("Are you sure you wish to delete this item?")
|
||||
{ }
|
||||
|
||||
public DeleteConfirmAttribute(string message)
|
||||
{
|
||||
Message = message;
|
||||
}
|
||||
|
||||
public static bool Find<T>(out string message) where T : class
|
||||
{
|
||||
return Find(typeof(T), out message);
|
||||
}
|
||||
|
||||
public static bool Find(object o, out string message)
|
||||
{
|
||||
return Find(o.GetType(), out message);
|
||||
}
|
||||
|
||||
public static bool Find(Type t, out string message)
|
||||
{
|
||||
var attrs = t.GetCustomAttributes(typeof(DeleteConfirmAttribute), true);
|
||||
|
||||
if (attrs.Length > 0)
|
||||
{
|
||||
message = String.Join("\n", attrs.OfType<DeleteConfirmAttribute>().Select(a => a.Message));
|
||||
return true;
|
||||
}
|
||||
|
||||
message = String.Empty;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Constructor)]
|
||||
public class ConstructableAttribute : Attribute
|
||||
{
|
||||
public AccessLevel AccessLevel { get; set; }
|
||||
|
||||
public ConstructableAttribute()
|
||||
: this(AccessLevel.Player) //Lowest accesslevel for current functionality (Level determined by access to [add)
|
||||
{ }
|
||||
|
||||
public ConstructableAttribute(AccessLevel accessLevel)
|
||||
{
|
||||
AccessLevel = accessLevel;
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class CommandPropertyAttribute : Attribute
|
||||
{
|
||||
private readonly AccessLevel m_ReadLevel;
|
||||
private readonly AccessLevel m_WriteLevel;
|
||||
private readonly bool m_ReadOnly;
|
||||
|
||||
public AccessLevel ReadLevel { get { return m_ReadLevel; } }
|
||||
|
||||
public AccessLevel WriteLevel { get { return m_WriteLevel; } }
|
||||
|
||||
public bool ReadOnly { get { return m_ReadOnly; } }
|
||||
|
||||
public CommandPropertyAttribute(AccessLevel level, bool readOnly)
|
||||
{
|
||||
m_ReadLevel = level;
|
||||
m_ReadOnly = readOnly;
|
||||
}
|
||||
|
||||
public CommandPropertyAttribute(AccessLevel level)
|
||||
: this(level, level)
|
||||
{ }
|
||||
|
||||
public CommandPropertyAttribute(AccessLevel readLevel, AccessLevel writeLevel)
|
||||
{
|
||||
m_ReadLevel = readLevel;
|
||||
m_WriteLevel = writeLevel;
|
||||
}
|
||||
}
|
||||
}
|
||||
115
Server/BaseVendor.cs
Normal file
115
Server/BaseVendor.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
#region References
|
||||
using System.Collections.Generic;
|
||||
#endregion
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class BuyItemStateComparer : IComparer<BuyItemState>
|
||||
{
|
||||
public int Compare(BuyItemState l, BuyItemState r)
|
||||
{
|
||||
if (l == null && r == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (l == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (r == null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return l.MySerial.CompareTo(r.MySerial);
|
||||
}
|
||||
}
|
||||
|
||||
public class BuyItemResponse
|
||||
{
|
||||
private readonly Serial m_Serial;
|
||||
private readonly int m_Amount;
|
||||
|
||||
public BuyItemResponse(Serial serial, int amount)
|
||||
{
|
||||
m_Serial = serial;
|
||||
m_Amount = amount;
|
||||
}
|
||||
|
||||
public Serial Serial { get { return m_Serial; } }
|
||||
|
||||
public int Amount { get { return m_Amount; } }
|
||||
}
|
||||
|
||||
public class SellItemResponse
|
||||
{
|
||||
private readonly Item m_Item;
|
||||
private readonly int m_Amount;
|
||||
|
||||
public SellItemResponse(Item i, int amount)
|
||||
{
|
||||
m_Item = i;
|
||||
m_Amount = amount;
|
||||
}
|
||||
|
||||
public Item Item { get { return m_Item; } }
|
||||
|
||||
public int Amount { get { return m_Amount; } }
|
||||
}
|
||||
|
||||
public class SellItemState
|
||||
{
|
||||
private readonly Item m_Item;
|
||||
private readonly int m_Price;
|
||||
private readonly string m_Name;
|
||||
|
||||
public SellItemState(Item item, int price, string name)
|
||||
{
|
||||
m_Item = item;
|
||||
m_Price = price;
|
||||
m_Name = name;
|
||||
}
|
||||
|
||||
public Item Item { get { return m_Item; } }
|
||||
|
||||
public int Price { get { return m_Price; } }
|
||||
|
||||
public string Name { get { return m_Name; } }
|
||||
}
|
||||
|
||||
public class BuyItemState
|
||||
{
|
||||
private readonly Serial m_ContSer;
|
||||
private readonly Serial m_MySer;
|
||||
private readonly int m_ItemID;
|
||||
private readonly int m_Amount;
|
||||
private readonly int m_Hue;
|
||||
private readonly int m_Price;
|
||||
private readonly string m_Desc;
|
||||
|
||||
public BuyItemState(string name, Serial cont, Serial serial, int price, int amount, int itemID, int hue)
|
||||
{
|
||||
m_Desc = name;
|
||||
m_ContSer = cont;
|
||||
m_MySer = serial;
|
||||
m_Price = price;
|
||||
m_Amount = amount;
|
||||
m_ItemID = itemID;
|
||||
m_Hue = hue;
|
||||
}
|
||||
|
||||
public int Price { get { return m_Price; } }
|
||||
|
||||
public Serial MySerial { get { return m_MySer; } }
|
||||
|
||||
public Serial ContainerSerial { get { return m_ContSer; } }
|
||||
|
||||
public int ItemID { get { return m_ItemID; } }
|
||||
|
||||
public int Amount { get { return m_Amount; } }
|
||||
|
||||
public int Hue { get { return m_Hue; } }
|
||||
|
||||
public string Description { get { return m_Desc; } }
|
||||
}
|
||||
}
|
||||
226
Server/Body.cs
Normal file
226
Server/Body.cs
Normal file
@@ -0,0 +1,226 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.IO;
|
||||
#endregion
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public enum BodyType : byte
|
||||
{
|
||||
Empty,
|
||||
Monster,
|
||||
Sea,
|
||||
Animal,
|
||||
Human,
|
||||
Equipment
|
||||
}
|
||||
|
||||
public struct Body
|
||||
{
|
||||
private readonly int m_BodyID;
|
||||
|
||||
private static readonly BodyType[] m_Types;
|
||||
|
||||
static Body()
|
||||
{
|
||||
if (File.Exists("Data/bodyTable.cfg"))
|
||||
{
|
||||
using (StreamReader ip = new StreamReader("Data/bodyTable.cfg"))
|
||||
{
|
||||
m_Types = new BodyType[0x1000];
|
||||
|
||||
string line;
|
||||
|
||||
while ((line = ip.ReadLine()) != null)
|
||||
{
|
||||
if (line.Length == 0 || line.StartsWith("#"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var split = line.Split('\t');
|
||||
|
||||
BodyType type;
|
||||
int bodyID;
|
||||
|
||||
if (int.TryParse(split[0], out bodyID) && Enum.TryParse(split[1], true, out type) && bodyID >= 0 &&
|
||||
bodyID < m_Types.Length)
|
||||
{
|
||||
m_Types[bodyID] = type;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Warning: Invalid bodyTable entry:");
|
||||
Console.WriteLine(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Warning: Data/bodyTable.cfg does not exist");
|
||||
|
||||
m_Types = new BodyType[0];
|
||||
}
|
||||
}
|
||||
|
||||
public Body(int bodyID)
|
||||
{
|
||||
m_BodyID = bodyID;
|
||||
}
|
||||
|
||||
public BodyType Type
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_BodyID >= 0 && m_BodyID < m_Types.Length)
|
||||
{
|
||||
return m_Types[m_BodyID];
|
||||
}
|
||||
else
|
||||
{
|
||||
return BodyType.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsHuman
|
||||
{
|
||||
get
|
||||
{
|
||||
return (m_BodyID >= 0 && m_BodyID < m_Types.Length && m_Types[m_BodyID] == BodyType.Human && m_BodyID != 402 &&
|
||||
m_BodyID != 403 && m_BodyID != 607 && m_BodyID != 608 && m_BodyID != 970)
|
||||
|
||||
#region Stygian Abyss
|
||||
|| m_BodyID == 694 || m_BodyID == 695
|
||||
#endregion
|
||||
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsMale
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_BodyID == 183 || m_BodyID == 185 || m_BodyID == 400 || m_BodyID == 402 || m_BodyID == 605 ||
|
||||
m_BodyID == 607 || m_BodyID == 750
|
||||
|
||||
#region Stygian Abyss
|
||||
|| m_BodyID == 666 || m_BodyID == 694
|
||||
#endregion
|
||||
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsFemale
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_BodyID == 184 || m_BodyID == 186 || m_BodyID == 401 || m_BodyID == 403 || m_BodyID == 606 ||
|
||||
m_BodyID == 608 || m_BodyID == 751
|
||||
|
||||
#region Stygian Abyss
|
||||
|| m_BodyID == 667 || m_BodyID == 695
|
||||
#endregion
|
||||
|
||||
#region High Seas
|
||||
|| m_BodyID == 1253
|
||||
#endregion
|
||||
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsGhost
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_BodyID == 402 || m_BodyID == 403 || m_BodyID == 607 || m_BodyID == 608 || m_BodyID == 970
|
||||
|
||||
#region Stygian Abyss
|
||||
|| m_BodyID == 694 || m_BodyID == 695
|
||||
#endregion
|
||||
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsMonster { get { return m_BodyID >= 0 && m_BodyID < m_Types.Length && m_Types[m_BodyID] == BodyType.Monster; } }
|
||||
|
||||
public bool IsAnimal { get { return m_BodyID >= 0 && m_BodyID < m_Types.Length && m_Types[m_BodyID] == BodyType.Animal; } }
|
||||
|
||||
public bool IsEmpty { get { return m_BodyID >= 0 && m_BodyID < m_Types.Length && m_Types[m_BodyID] == BodyType.Empty; } }
|
||||
|
||||
public bool IsSea { get { return m_BodyID >= 0 && m_BodyID < m_Types.Length && m_Types[m_BodyID] == BodyType.Sea; } }
|
||||
|
||||
public bool IsEquipment { get { return m_BodyID >= 0 && m_BodyID < m_Types.Length && m_Types[m_BodyID] == BodyType.Equipment; } }
|
||||
|
||||
#region Stygian Abyss
|
||||
public bool IsGargoyle { get { return m_BodyID == 666 || m_BodyID == 667 || m_BodyID == 694 || m_BodyID == 695; } }
|
||||
#endregion
|
||||
|
||||
public int BodyID { get { return m_BodyID; } }
|
||||
|
||||
public static implicit operator int(Body a)
|
||||
{
|
||||
return a.m_BodyID;
|
||||
}
|
||||
|
||||
public static implicit operator Body(int a)
|
||||
{
|
||||
return new Body(a);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("0x{0:X}", m_BodyID);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return m_BodyID;
|
||||
}
|
||||
|
||||
public override bool Equals(object o)
|
||||
{
|
||||
if (o == null || !(o is Body))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((Body)o).m_BodyID == m_BodyID;
|
||||
}
|
||||
|
||||
public static bool operator ==(Body l, Body r)
|
||||
{
|
||||
return l.m_BodyID == r.m_BodyID;
|
||||
}
|
||||
|
||||
public static bool operator !=(Body l, Body r)
|
||||
{
|
||||
return l.m_BodyID != r.m_BodyID;
|
||||
}
|
||||
|
||||
public static bool operator >(Body l, Body r)
|
||||
{
|
||||
return l.m_BodyID > r.m_BodyID;
|
||||
}
|
||||
|
||||
public static bool operator >=(Body l, Body r)
|
||||
{
|
||||
return l.m_BodyID >= r.m_BodyID;
|
||||
}
|
||||
|
||||
public static bool operator <(Body l, Body r)
|
||||
{
|
||||
return l.m_BodyID < r.m_BodyID;
|
||||
}
|
||||
|
||||
public static bool operator <=(Body l, Body r)
|
||||
{
|
||||
return l.m_BodyID <= r.m_BodyID;
|
||||
}
|
||||
}
|
||||
}
|
||||
313
Server/ClientVersion.cs
Normal file
313
Server/ClientVersion.cs
Normal file
@@ -0,0 +1,313 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
#endregion
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public enum ClientType
|
||||
{
|
||||
Regular,
|
||||
UOTD,
|
||||
God,
|
||||
SA
|
||||
}
|
||||
|
||||
public class ClientVersion : IComparable, IComparer
|
||||
{
|
||||
private readonly int m_Major;
|
||||
private readonly int m_Minor;
|
||||
private readonly int m_Revision;
|
||||
private readonly int m_Patch;
|
||||
private readonly ClientType m_Type;
|
||||
private readonly string m_SourceString;
|
||||
|
||||
public int Major { get { return m_Major; } }
|
||||
|
||||
public int Minor { get { return m_Minor; } }
|
||||
|
||||
public int Revision { get { return m_Revision; } }
|
||||
|
||||
public int Patch { get { return m_Patch; } }
|
||||
|
||||
public ClientType Type { get { return m_Type; } }
|
||||
|
||||
public string SourceString { get { return m_SourceString; } }
|
||||
|
||||
public ClientVersion(int maj, int min, int rev, int pat)
|
||||
: this(maj, min, rev, pat, ClientType.Regular)
|
||||
{ }
|
||||
|
||||
public ClientVersion(int maj, int min, int rev, int pat, ClientType type)
|
||||
{
|
||||
m_Major = maj;
|
||||
m_Minor = min;
|
||||
m_Revision = rev;
|
||||
m_Patch = pat;
|
||||
m_Type = type;
|
||||
|
||||
if (m_Type != ClientType.SA && m_Major >= 67)
|
||||
{
|
||||
m_Type = ClientType.SA;
|
||||
}
|
||||
|
||||
m_SourceString = _ToStringImpl();
|
||||
}
|
||||
|
||||
public static bool operator ==(ClientVersion l, ClientVersion r)
|
||||
{
|
||||
return (Compare(l, r) == 0);
|
||||
}
|
||||
|
||||
public static bool operator !=(ClientVersion l, ClientVersion r)
|
||||
{
|
||||
return (Compare(l, r) != 0);
|
||||
}
|
||||
|
||||
public static bool operator >=(ClientVersion l, ClientVersion r)
|
||||
{
|
||||
return (Compare(l, r) >= 0);
|
||||
}
|
||||
|
||||
public static bool operator >(ClientVersion l, ClientVersion r)
|
||||
{
|
||||
return (Compare(l, r) > 0);
|
||||
}
|
||||
|
||||
public static bool operator <=(ClientVersion l, ClientVersion r)
|
||||
{
|
||||
return (Compare(l, r) <= 0);
|
||||
}
|
||||
|
||||
public static bool operator <(ClientVersion l, ClientVersion r)
|
||||
{
|
||||
return (Compare(l, r) < 0);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return m_Major ^ m_Minor ^ m_Revision ^ m_Patch ^ (int)m_Type;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ClientVersion v = obj as ClientVersion;
|
||||
|
||||
if (v == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_Major == v.m_Major && m_Minor == v.m_Minor && m_Revision == v.m_Revision && m_Patch == v.m_Patch &&
|
||||
m_Type == v.m_Type;
|
||||
}
|
||||
|
||||
private string _ToStringImpl()
|
||||
{
|
||||
StringBuilder builder = new StringBuilder(16);
|
||||
|
||||
builder.Append(m_Major);
|
||||
builder.Append('.');
|
||||
builder.Append(m_Minor);
|
||||
builder.Append('.');
|
||||
builder.Append(m_Revision);
|
||||
|
||||
if (m_Major <= 5 && m_Minor <= 0 && m_Revision <= 6) //Anything before 5.0.7
|
||||
{
|
||||
if (m_Patch > 0)
|
||||
{
|
||||
builder.Append((char)('a' + (m_Patch - 1)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Append('.');
|
||||
builder.Append(m_Patch);
|
||||
}
|
||||
|
||||
if (m_Type != ClientType.Regular)
|
||||
{
|
||||
builder.Append(' ');
|
||||
builder.Append(m_Type.ToString());
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return _ToStringImpl();
|
||||
}
|
||||
|
||||
public ClientVersion(string fmt)
|
||||
{
|
||||
m_SourceString = fmt;
|
||||
|
||||
try
|
||||
{
|
||||
fmt = fmt.ToLower();
|
||||
|
||||
int br1 = fmt.IndexOf('.');
|
||||
int br2 = fmt.IndexOf('.', br1 + 1);
|
||||
|
||||
int br3 = br2 + 1;
|
||||
while (br3 < fmt.Length && Char.IsDigit(fmt, br3))
|
||||
{
|
||||
br3++;
|
||||
}
|
||||
|
||||
m_Major = Utility.ToInt32(fmt.Substring(0, br1));
|
||||
m_Minor = Utility.ToInt32(fmt.Substring(br1 + 1, br2 - br1 - 1));
|
||||
m_Revision = Utility.ToInt32(fmt.Substring(br2 + 1, br3 - br2 - 1));
|
||||
|
||||
if (br3 < fmt.Length)
|
||||
{
|
||||
if (m_Major <= 5 && m_Minor <= 0 && m_Revision <= 6) //Anything before 5.0.7
|
||||
{
|
||||
if (!Char.IsWhiteSpace(fmt, br3))
|
||||
{
|
||||
m_Patch = (fmt[br3] - 'a') + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Patch = Utility.ToInt32(fmt.Substring(br3 + 1, fmt.Length - br3 - 1));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_Major >= 67)
|
||||
{
|
||||
m_Type = ClientType.SA;
|
||||
}
|
||||
else if(fmt.IndexOf("god") >= 0 || fmt.IndexOf("gq") >= 0)
|
||||
{
|
||||
m_Type = ClientType.God;
|
||||
}
|
||||
else if (fmt.IndexOf("third dawn") >= 0 || fmt.IndexOf("uo:td") >= 0 || fmt.IndexOf("uotd") >= 0 ||
|
||||
fmt.IndexOf("uo3d") >= 0 || fmt.IndexOf("uo:3d") >= 0)
|
||||
{
|
||||
m_Type = ClientType.UOTD;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Type = ClientType.Regular;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_Major = 0;
|
||||
m_Minor = 0;
|
||||
m_Revision = 0;
|
||||
m_Patch = 0;
|
||||
m_Type = ClientType.Regular;
|
||||
}
|
||||
}
|
||||
|
||||
public int CompareTo(object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ClientVersion o = obj as ClientVersion;
|
||||
|
||||
if (o == null)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
if (m_Major > o.m_Major)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (m_Major < o.m_Major)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (m_Minor > o.m_Minor)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (m_Minor < o.m_Minor)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (m_Revision > o.m_Revision)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (m_Revision < o.m_Revision)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (m_Patch > o.m_Patch)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (m_Patch < o.m_Patch)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsNull(object x)
|
||||
{
|
||||
return ReferenceEquals(x, null);
|
||||
}
|
||||
|
||||
public int Compare(object x, object y)
|
||||
{
|
||||
if (IsNull(x) && IsNull(y))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (IsNull(x))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (IsNull(y))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ClientVersion a = x as ClientVersion;
|
||||
ClientVersion b = y as ClientVersion;
|
||||
|
||||
if (IsNull(a) || IsNull(b))
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
return a.CompareTo(b);
|
||||
}
|
||||
|
||||
public static int Compare(ClientVersion a, ClientVersion b)
|
||||
{
|
||||
if (IsNull(a) && IsNull(b))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (IsNull(a))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (IsNull(b))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return a.CompareTo(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
288
Server/Commands.cs
Normal file
288
Server/Commands.cs
Normal file
@@ -0,0 +1,288 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Server.Network;
|
||||
#endregion
|
||||
|
||||
namespace Server.Commands
|
||||
{
|
||||
public delegate void CommandEventHandler(CommandEventArgs e);
|
||||
|
||||
public class CommandEventArgs : EventArgs
|
||||
{
|
||||
private readonly Mobile m_Mobile;
|
||||
private readonly string m_Command;
|
||||
private readonly string m_ArgString;
|
||||
private readonly string[] m_Arguments;
|
||||
|
||||
public Mobile Mobile { get { return m_Mobile; } }
|
||||
|
||||
public string Command { get { return m_Command; } }
|
||||
|
||||
public string ArgString { get { return m_ArgString; } }
|
||||
|
||||
public string[] Arguments { get { return m_Arguments; } }
|
||||
|
||||
public int Length { get { return m_Arguments.Length; } }
|
||||
|
||||
public string GetString(int index)
|
||||
{
|
||||
if (index < 0 || index >= m_Arguments.Length)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
return m_Arguments[index];
|
||||
}
|
||||
|
||||
public int GetInt32(int index)
|
||||
{
|
||||
if (index < 0 || index >= m_Arguments.Length)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Utility.ToInt32(m_Arguments[index]);
|
||||
}
|
||||
|
||||
public bool GetBoolean(int index)
|
||||
{
|
||||
if (index < 0 || index >= m_Arguments.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Utility.ToBoolean(m_Arguments[index]);
|
||||
}
|
||||
|
||||
public double GetDouble(int index)
|
||||
{
|
||||
if (index < 0 || index >= m_Arguments.Length)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return Utility.ToDouble(m_Arguments[index]);
|
||||
}
|
||||
|
||||
public TimeSpan GetTimeSpan(int index)
|
||||
{
|
||||
if (index < 0 || index >= m_Arguments.Length)
|
||||
{
|
||||
return TimeSpan.Zero;
|
||||
}
|
||||
|
||||
return Utility.ToTimeSpan(m_Arguments[index]);
|
||||
}
|
||||
|
||||
public CommandEventArgs(Mobile mobile, string command, string argString, string[] arguments)
|
||||
{
|
||||
m_Mobile = mobile;
|
||||
m_Command = command;
|
||||
m_ArgString = argString;
|
||||
m_Arguments = arguments;
|
||||
}
|
||||
}
|
||||
|
||||
public class CommandEntry : IComparable
|
||||
{
|
||||
private readonly string m_Command;
|
||||
private readonly CommandEventHandler m_Handler;
|
||||
private readonly AccessLevel m_AccessLevel;
|
||||
|
||||
public string Command { get { return m_Command; } }
|
||||
|
||||
public CommandEventHandler Handler { get { return m_Handler; } }
|
||||
|
||||
public AccessLevel AccessLevel { get { return m_AccessLevel; } }
|
||||
|
||||
public CommandEntry(string command, CommandEventHandler handler, AccessLevel accessLevel)
|
||||
{
|
||||
m_Command = command;
|
||||
m_Handler = handler;
|
||||
m_AccessLevel = accessLevel;
|
||||
}
|
||||
|
||||
public int CompareTo(object obj)
|
||||
{
|
||||
if (obj == this)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (obj == null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
CommandEntry e = obj as CommandEntry;
|
||||
|
||||
if (e == null)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
return m_Command.CompareTo(e.m_Command);
|
||||
}
|
||||
}
|
||||
|
||||
public static class CommandSystem
|
||||
{
|
||||
private static string m_Prefix = "[";
|
||||
|
||||
public static string Prefix { get { return m_Prefix; } set { m_Prefix = value; } }
|
||||
|
||||
public static string[] Split(string value)
|
||||
{
|
||||
var array = value.ToCharArray();
|
||||
var list = new List<string>();
|
||||
|
||||
int start = 0, end = 0;
|
||||
|
||||
while (start < array.Length)
|
||||
{
|
||||
char c = array[start];
|
||||
|
||||
if (c == '"')
|
||||
{
|
||||
++start;
|
||||
end = start;
|
||||
|
||||
while (end < array.Length)
|
||||
{
|
||||
if (array[end] != '"' || array[end - 1] == '\\')
|
||||
{
|
||||
++end;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
list.Add(value.Substring(start, end - start));
|
||||
|
||||
start = end + 2;
|
||||
}
|
||||
else if (c != ' ')
|
||||
{
|
||||
end = start;
|
||||
|
||||
while (end < array.Length)
|
||||
{
|
||||
if (array[end] != ' ')
|
||||
{
|
||||
++end;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
list.Add(value.Substring(start, end - start));
|
||||
|
||||
start = end + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
++start;
|
||||
}
|
||||
}
|
||||
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
private static readonly Dictionary<string, CommandEntry> m_Entries;
|
||||
|
||||
public static Dictionary<string, CommandEntry> Entries { get { return m_Entries; } }
|
||||
|
||||
static CommandSystem()
|
||||
{
|
||||
m_Entries = new Dictionary<string, CommandEntry>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public static void Register(string command, AccessLevel access, CommandEventHandler handler)
|
||||
{
|
||||
m_Entries[command] = new CommandEntry(command, handler, access);
|
||||
}
|
||||
|
||||
private static AccessLevel m_BadCommandIngoreLevel = AccessLevel.Player;
|
||||
|
||||
public static AccessLevel BadCommandIgnoreLevel { get { return m_BadCommandIngoreLevel; } set { m_BadCommandIngoreLevel = value; } }
|
||||
|
||||
public static bool Handle(Mobile from, string text)
|
||||
{
|
||||
return Handle(from, text, MessageType.Regular);
|
||||
}
|
||||
|
||||
public static bool Handle(Mobile from, string text, MessageType type)
|
||||
{
|
||||
if (text.StartsWith(m_Prefix) || type == MessageType.Command)
|
||||
{
|
||||
if (type != MessageType.Command)
|
||||
{
|
||||
text = text.Substring(m_Prefix.Length);
|
||||
}
|
||||
|
||||
int indexOf = text.IndexOf(' ');
|
||||
|
||||
string command;
|
||||
string[] args;
|
||||
string argString;
|
||||
|
||||
if (indexOf >= 0)
|
||||
{
|
||||
argString = text.Substring(indexOf + 1);
|
||||
|
||||
command = text.Substring(0, indexOf);
|
||||
args = Split(argString);
|
||||
}
|
||||
else
|
||||
{
|
||||
argString = "";
|
||||
command = text.ToLower();
|
||||
args = new string[0];
|
||||
}
|
||||
|
||||
CommandEntry entry = null;
|
||||
m_Entries.TryGetValue(command, out entry);
|
||||
|
||||
if (entry != null)
|
||||
{
|
||||
if (from.AccessLevel >= entry.AccessLevel)
|
||||
{
|
||||
if (entry.Handler != null)
|
||||
{
|
||||
CommandEventArgs e = new CommandEventArgs(from, command, argString, args);
|
||||
entry.Handler(e);
|
||||
EventSink.InvokeCommand(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (from.AccessLevel <= m_BadCommandIngoreLevel)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
from.SendMessage("You do not have access to that command.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (from.AccessLevel <= m_BadCommandIngoreLevel)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
from.SendMessage("That is not a valid command.");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
832
Server/Config.cs
Normal file
832
Server/Config.cs
Normal file
@@ -0,0 +1,832 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
#endregion
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public static class Config
|
||||
{
|
||||
public sealed class Entry : IEquatable<Entry>, IComparable<Entry>
|
||||
{
|
||||
public int FileIndex { get; private set; }
|
||||
|
||||
public string File { get; private set; }
|
||||
public string Scope { get; private set; }
|
||||
|
||||
public string Desc { get; set; }
|
||||
|
||||
public string Key { get; set; }
|
||||
public string Value { get; set; }
|
||||
|
||||
public bool UseDefault { get; set; }
|
||||
|
||||
public Entry(string file, int fileIndex, string scope, string desc, string key, string value, bool useDefault)
|
||||
{
|
||||
File = file;
|
||||
FileIndex = fileIndex;
|
||||
|
||||
Scope = scope;
|
||||
Desc = desc;
|
||||
|
||||
Key = key;
|
||||
Value = value;
|
||||
|
||||
UseDefault = useDefault;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("{0}.{1}{2}={3}", Scope, UseDefault ? "@" : "", Key, Value);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
var hash = -1;
|
||||
|
||||
hash = (hash * 397) ^ File.GetHashCode();
|
||||
hash = (hash * 397) ^ Scope.GetHashCode();
|
||||
hash = (hash * 397) ^ Key.GetHashCode();
|
||||
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is Entry && Equals((Entry)obj);
|
||||
}
|
||||
|
||||
public bool Equals(Entry other)
|
||||
{
|
||||
if (ReferenceEquals(other, null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ReferenceEquals(other, this))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return Insensitive.Equals(File, other.File) && //
|
||||
Insensitive.Equals(Scope, other.Scope) && //
|
||||
Insensitive.Equals(Key, other.Key);
|
||||
}
|
||||
|
||||
public int CompareTo(Entry other)
|
||||
{
|
||||
if (other == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!Insensitive.Equals(File, other.File))
|
||||
{
|
||||
return Insensitive.Compare(File, other.File);
|
||||
}
|
||||
|
||||
return FileIndex.CompareTo(other.FileIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool _Initialized;
|
||||
|
||||
private static readonly string _Path = Path.Combine(Core.BaseDirectory, "Config");
|
||||
|
||||
private static readonly IFormatProvider _NumFormatter = CultureInfo.InvariantCulture.NumberFormat;
|
||||
|
||||
private static readonly Dictionary<string, Entry> _Entries =
|
||||
new Dictionary<string, Entry>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public static IEnumerable<Entry> Entries { get { return _Entries.Values; } }
|
||||
|
||||
public static void Load()
|
||||
{
|
||||
if (_Initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_Initialized = true;
|
||||
|
||||
if (!Directory.Exists(_Path))
|
||||
{
|
||||
Directory.CreateDirectory(_Path);
|
||||
}
|
||||
|
||||
IEnumerable<string> files;
|
||||
|
||||
try
|
||||
{
|
||||
files = Directory.EnumerateFiles(_Path, "*.cfg", SearchOption.AllDirectories);
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
Console.WriteLine("Warning: No configuration files found!");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var path in files)
|
||||
{
|
||||
try
|
||||
{
|
||||
LoadFile(path);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Warning: Failed to load configuration file:");
|
||||
Console.WriteLine(path);
|
||||
Utility.PushColor(ConsoleColor.Red);
|
||||
Console.WriteLine(e.Message);
|
||||
Utility.PopColor();
|
||||
|
||||
ConsoleKey key;
|
||||
|
||||
do
|
||||
{
|
||||
Console.WriteLine("Ignore this warning? (y/n)");
|
||||
|
||||
key = Console.ReadKey(true).Key;
|
||||
}
|
||||
while (key != ConsoleKey.Y && key != ConsoleKey.N);
|
||||
|
||||
if (key != ConsoleKey.Y)
|
||||
{
|
||||
Console.WriteLine("Press any key to exit...");
|
||||
Console.ReadKey();
|
||||
|
||||
Core.Kill(false);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Core.Debug)
|
||||
{
|
||||
Console.WriteLine();
|
||||
|
||||
foreach (var e in _Entries.Values)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
private static void LoadFile(string path)
|
||||
{
|
||||
var info = new FileInfo(path);
|
||||
|
||||
if (!info.Exists)
|
||||
{
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
|
||||
path = info.Directory != null ? info.Directory.FullName : String.Empty;
|
||||
|
||||
var io = path.IndexOf(_Path, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (io > -1)
|
||||
{
|
||||
path = path.Substring(io + _Path.Length);
|
||||
}
|
||||
|
||||
var parts = path.Split(Path.DirectorySeparatorChar);
|
||||
|
||||
var scope = String.Join(".", parts.Where(p => !String.IsNullOrWhiteSpace(p)));
|
||||
|
||||
if (scope.Length > 0)
|
||||
{
|
||||
scope += ".";
|
||||
}
|
||||
|
||||
scope += Path.GetFileNameWithoutExtension(info.Name);
|
||||
|
||||
var lines = File.ReadAllLines(info.FullName);
|
||||
|
||||
var desc = new List<string>(0x10);
|
||||
|
||||
for (int i = 0, idx = 0; i < lines.Length; i++)
|
||||
{
|
||||
var line = lines[i].Trim();
|
||||
|
||||
if (String.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
desc.Clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.StartsWith("#"))
|
||||
{
|
||||
desc.Add(line.TrimStart('#').Trim());
|
||||
continue;
|
||||
}
|
||||
|
||||
var useDef = false;
|
||||
|
||||
if (line.StartsWith("@"))
|
||||
{
|
||||
useDef = true;
|
||||
line = line.TrimStart('@').Trim();
|
||||
}
|
||||
|
||||
io = line.IndexOf('=');
|
||||
|
||||
if (io < 0)
|
||||
{
|
||||
throw new FormatException(String.Format("Bad format at line {0}", i + 1));
|
||||
}
|
||||
|
||||
var key = line.Substring(0, io);
|
||||
var val = line.Substring(io + 1);
|
||||
|
||||
if (String.IsNullOrWhiteSpace(key))
|
||||
{
|
||||
throw new NullReferenceException(String.Format("Key can not be null at line {0}", i + 1));
|
||||
}
|
||||
|
||||
key = key.Trim();
|
||||
|
||||
if (String.IsNullOrEmpty(val))
|
||||
{
|
||||
val = null;
|
||||
}
|
||||
|
||||
var e = new Entry(info.FullName, idx++, scope, String.Join(String.Empty, desc), key, val, useDef);
|
||||
|
||||
_Entries[String.Format("{0}.{1}", e.Scope, e.Key)] = e;
|
||||
|
||||
desc.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static void Save()
|
||||
{
|
||||
if (!_Initialized)
|
||||
{
|
||||
Load();
|
||||
}
|
||||
|
||||
if (!Directory.Exists(_Path))
|
||||
{
|
||||
Directory.CreateDirectory(_Path);
|
||||
}
|
||||
|
||||
foreach (var g in _Entries.Values.ToLookup(e => e.File))
|
||||
{
|
||||
try
|
||||
{
|
||||
SaveFile(g.Key, g.OrderBy(e => e.FileIndex));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Warning: Failed to save configuration file:");
|
||||
Console.WriteLine(g.Key);
|
||||
Utility.PushColor(ConsoleColor.Red);
|
||||
Console.WriteLine(e.Message);
|
||||
Utility.PopColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void SaveFile(string path, IEnumerable<Entry> entries)
|
||||
{
|
||||
var content = new StringBuilder(0x1000);
|
||||
var line = new StringBuilder(0x80);
|
||||
|
||||
foreach (var e in entries)
|
||||
{
|
||||
content.AppendLine();
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(e.Desc))
|
||||
{
|
||||
line.Clear();
|
||||
|
||||
foreach (var word in e.Desc.Split(' '))
|
||||
{
|
||||
if ((line + word).Length > 100)
|
||||
{
|
||||
content.AppendLine(String.Format("# {0}", line));
|
||||
line.Clear();
|
||||
}
|
||||
|
||||
line.AppendFormat("{0} ", word);
|
||||
}
|
||||
|
||||
if (line.Length > 0)
|
||||
{
|
||||
content.AppendLine(String.Format("# {0}", line));
|
||||
line.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
content.AppendLine(String.Format("{0}{1}={2}", e.UseDefault ? "@" : String.Empty, e.Key, e.Value));
|
||||
}
|
||||
|
||||
File.WriteAllText(path, content.ToString());
|
||||
}
|
||||
|
||||
public static Entry Find(string key)
|
||||
{
|
||||
Entry e;
|
||||
_Entries.TryGetValue(key, out e);
|
||||
return e;
|
||||
}
|
||||
|
||||
private static void InternalSet(string key, string value)
|
||||
{
|
||||
var e = Find(key);
|
||||
|
||||
if (e != null)
|
||||
{
|
||||
e.Value = value;
|
||||
e.UseDefault = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var parts = key.Split('.');
|
||||
var realKey = parts.Last();
|
||||
|
||||
parts = parts.Take(parts.Length - 1).ToArray();
|
||||
|
||||
var file = new FileInfo(Path.Combine(_Path, Path.Combine(parts) + ".cfg"));
|
||||
var idx = _Entries.Values.Where(o => Insensitive.Equals(o.File, file.FullName)).Select(o => o.FileIndex).DefaultIfEmpty().Max();
|
||||
|
||||
_Entries[key] = new Entry(file.FullName, idx, String.Join(".", parts), String.Empty, realKey, value, false);
|
||||
}
|
||||
|
||||
public static void Set(string key, string value)
|
||||
{
|
||||
InternalSet(key, value);
|
||||
}
|
||||
|
||||
public static void Set(string key, char value)
|
||||
{
|
||||
InternalSet(key, value.ToString(_NumFormatter));
|
||||
}
|
||||
|
||||
public static void Set(string key, sbyte value)
|
||||
{
|
||||
InternalSet(key, value.ToString(_NumFormatter));
|
||||
}
|
||||
|
||||
public static void Set(string key, byte value)
|
||||
{
|
||||
InternalSet(key, value.ToString(_NumFormatter));
|
||||
}
|
||||
|
||||
public static void Set(string key, short value)
|
||||
{
|
||||
InternalSet(key, value.ToString(_NumFormatter));
|
||||
}
|
||||
|
||||
public static void Set(string key, ushort value)
|
||||
{
|
||||
InternalSet(key, value.ToString(_NumFormatter));
|
||||
}
|
||||
|
||||
public static void Set(string key, int value)
|
||||
{
|
||||
InternalSet(key, value.ToString(_NumFormatter));
|
||||
}
|
||||
|
||||
public static void Set(string key, uint value)
|
||||
{
|
||||
InternalSet(key, value.ToString(_NumFormatter));
|
||||
}
|
||||
|
||||
public static void Set(string key, long value)
|
||||
{
|
||||
InternalSet(key, value.ToString(_NumFormatter));
|
||||
}
|
||||
|
||||
public static void Set(string key, ulong value)
|
||||
{
|
||||
InternalSet(key, value.ToString(_NumFormatter));
|
||||
}
|
||||
|
||||
public static void Set(string key, float value)
|
||||
{
|
||||
InternalSet(key, value.ToString(_NumFormatter));
|
||||
}
|
||||
|
||||
public static void Set(string key, double value)
|
||||
{
|
||||
InternalSet(key, value.ToString(_NumFormatter));
|
||||
}
|
||||
|
||||
public static void Set(string key, decimal value)
|
||||
{
|
||||
InternalSet(key, value.ToString(_NumFormatter));
|
||||
}
|
||||
|
||||
public static void Set(string key, bool value)
|
||||
{
|
||||
InternalSet(key, value ? "true" : "false");
|
||||
}
|
||||
|
||||
public static void Set(string key, TimeSpan value)
|
||||
{
|
||||
InternalSet(key, value.ToString());
|
||||
}
|
||||
|
||||
public static void Set(string key, DateTime value)
|
||||
{
|
||||
InternalSet(key, value.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
public static void SetEnum<T>(string key, T value) where T : struct, IConvertible
|
||||
{
|
||||
var t = typeof(T);
|
||||
|
||||
if (!t.IsEnum)
|
||||
{
|
||||
throw new ArgumentException("T must be an enumerated type");
|
||||
}
|
||||
|
||||
var vals = Enum.GetValues(t).Cast<T>();
|
||||
|
||||
foreach (T o in vals.Where(o => o.Equals(value)))
|
||||
{
|
||||
InternalSet(key, o.ToString(CultureInfo.InvariantCulture));
|
||||
return;
|
||||
}
|
||||
|
||||
throw new ArgumentException("Enumerated value not found");
|
||||
}
|
||||
|
||||
private static void Warn<T>(string key)
|
||||
{
|
||||
Utility.PushColor(ConsoleColor.Yellow);
|
||||
Console.WriteLine("Config: Warning, '{0}' invalid value for '{1}'", typeof(T), key);
|
||||
Utility.PopColor();
|
||||
}
|
||||
|
||||
private static string InternalGet(string key)
|
||||
{
|
||||
if (!_Initialized)
|
||||
{
|
||||
Load();
|
||||
}
|
||||
|
||||
Entry e;
|
||||
|
||||
if (_Entries.TryGetValue(key, out e) && e != null)
|
||||
{
|
||||
return e.UseDefault ? null : e.Value;
|
||||
}
|
||||
|
||||
Utility.PushColor(ConsoleColor.Yellow);
|
||||
Console.WriteLine("Config: Warning, using default value for {0}", key);
|
||||
Utility.PopColor();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string Get(string key, string defaultValue)
|
||||
{
|
||||
return InternalGet(key) ?? defaultValue;
|
||||
}
|
||||
|
||||
public static sbyte Get(string key, sbyte defaultValue)
|
||||
{
|
||||
var ret = defaultValue;
|
||||
var value = InternalGet(key);
|
||||
|
||||
if (value == null || sbyte.TryParse(value, NumberStyles.Any, _NumFormatter, out ret))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
Warn<sbyte>(key);
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static byte Get(string key, byte defaultValue)
|
||||
{
|
||||
var ret = defaultValue;
|
||||
var value = InternalGet(key);
|
||||
|
||||
if (value == null || byte.TryParse(value, NumberStyles.Any & ~NumberStyles.AllowLeadingSign, _NumFormatter, out ret))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
Warn<byte>(key);
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static short Get(string key, short defaultValue)
|
||||
{
|
||||
var ret = defaultValue;
|
||||
var value = InternalGet(key);
|
||||
|
||||
if (value == null || short.TryParse(value, NumberStyles.Any, _NumFormatter, out ret))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
Warn<short>(key);
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static ushort Get(string key, ushort defaultValue)
|
||||
{
|
||||
var ret = defaultValue;
|
||||
var value = InternalGet(key);
|
||||
|
||||
if (value == null || ushort.TryParse(value, NumberStyles.Any & ~NumberStyles.AllowLeadingSign, _NumFormatter, out ret))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
Warn<ushort>(key);
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static int Get(string key, int defaultValue)
|
||||
{
|
||||
var ret = defaultValue;
|
||||
var value = InternalGet(key);
|
||||
|
||||
if (value == null || int.TryParse(value, NumberStyles.Any, _NumFormatter, out ret))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
Warn<int>(key);
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static uint Get(string key, uint defaultValue)
|
||||
{
|
||||
var ret = defaultValue;
|
||||
var value = InternalGet(key);
|
||||
|
||||
if (value == null || uint.TryParse(value, NumberStyles.Any & ~NumberStyles.AllowLeadingSign, _NumFormatter, out ret))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
Warn<uint>(key);
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static long Get(string key, long defaultValue)
|
||||
{
|
||||
var ret = defaultValue;
|
||||
var value = InternalGet(key);
|
||||
|
||||
if (value == null || long.TryParse(value, NumberStyles.Any, _NumFormatter, out ret))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
Warn<long>(key);
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static ulong Get(string key, ulong defaultValue)
|
||||
{
|
||||
var ret = defaultValue;
|
||||
var value = InternalGet(key);
|
||||
|
||||
if (value == null || ulong.TryParse(value, NumberStyles.Any & ~NumberStyles.AllowLeadingSign, _NumFormatter, out ret))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
Warn<ulong>(key);
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static float Get(string key, float defaultValue)
|
||||
{
|
||||
var ret = defaultValue;
|
||||
var value = InternalGet(key);
|
||||
|
||||
if (value == null || float.TryParse(value, NumberStyles.Any, _NumFormatter, out ret))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
Warn<float>(key);
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static double Get(string key, double defaultValue)
|
||||
{
|
||||
var ret = defaultValue;
|
||||
var value = InternalGet(key);
|
||||
|
||||
if (value == null || double.TryParse(value, NumberStyles.Any, _NumFormatter, out ret))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
Warn<double>(key);
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static decimal Get(string key, decimal defaultValue)
|
||||
{
|
||||
var ret = defaultValue;
|
||||
var value = InternalGet(key);
|
||||
|
||||
if (value == null || decimal.TryParse(value, NumberStyles.Any, _NumFormatter, out ret))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
Warn<decimal>(key);
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static bool Get(string key, bool defaultValue)
|
||||
{
|
||||
var value = InternalGet(key);
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
if (Regex.IsMatch(value, @"(true|yes|on|1|enabled)", RegexOptions.IgnoreCase))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Regex.IsMatch(value, @"(false|no|off|0|disabled)", RegexOptions.IgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Warn<bool>(key);
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static TimeSpan Get(string key, TimeSpan defaultValue)
|
||||
{
|
||||
var value = InternalGet(key);
|
||||
|
||||
TimeSpan ts;
|
||||
|
||||
if (TimeSpan.TryParse(value, out ts))
|
||||
{
|
||||
return ts;
|
||||
}
|
||||
|
||||
Warn<TimeSpan>(key);
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static DateTime Get(string key, DateTime defaultValue)
|
||||
{
|
||||
var value = InternalGet(key);
|
||||
|
||||
DateTime dt;
|
||||
|
||||
if (DateTime.TryParse(value, out dt))
|
||||
{
|
||||
return dt;
|
||||
}
|
||||
|
||||
Warn<DateTime>(key);
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static Type Get(string key, Type defaultValue)
|
||||
{
|
||||
var value = InternalGet(key);
|
||||
|
||||
var t = FindType(value);
|
||||
|
||||
if (t != null)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
Warn<Type>(key);
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static T GetEnum<T>(string key, T defaultValue) where T : struct, IConvertible
|
||||
{
|
||||
if (!typeof(T).IsEnum)
|
||||
{
|
||||
throw new ArgumentException("T must be an enumerated type");
|
||||
}
|
||||
|
||||
var value = InternalGet(key);
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
value = value.Trim();
|
||||
|
||||
var vals = Enum.GetValues(typeof(T)).Cast<T>();
|
||||
|
||||
foreach (var o in vals.Where(o => Insensitive.Equals(value, o.ToString(CultureInfo.InvariantCulture))))
|
||||
{
|
||||
return o;
|
||||
}
|
||||
|
||||
Warn<T>(key);
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static T GetDelegate<T>(string key, T defaultValue)
|
||||
{
|
||||
if (!typeof(MulticastDelegate).IsAssignableFrom(typeof(T).BaseType))
|
||||
{
|
||||
throw new ArgumentException("T must be a delegate type");
|
||||
}
|
||||
|
||||
var value = InternalGet(key);
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
value = value.Trim();
|
||||
|
||||
var i = value.LastIndexOf('.');
|
||||
|
||||
if (i <= 0)
|
||||
{
|
||||
Warn<T>(key);
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var method = value.Substring(i + 1);
|
||||
var target = FindType(value.Remove(i));
|
||||
|
||||
if (target != null)
|
||||
{
|
||||
var info = target.GetMethod(method, (BindingFlags)0x38);
|
||||
|
||||
if (info != null)
|
||||
{
|
||||
return (T)(object)Delegate.CreateDelegate(typeof(T), info);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
|
||||
Warn<T>(key);
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private static Type FindType(string value)
|
||||
{
|
||||
var type = Type.GetType(value, false);
|
||||
|
||||
if (type != null)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
if (value.IndexOf('.') < 0)
|
||||
{
|
||||
return ScriptCompiler.FindTypeByName(value);
|
||||
}
|
||||
|
||||
return ScriptCompiler.FindTypeByFullName(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
275
Server/ContextMenus/ContextMenu.cs
Normal file
275
Server/ContextMenus/ContextMenu.cs
Normal file
@@ -0,0 +1,275 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
#endregion
|
||||
|
||||
namespace Server.ContextMenus
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the state of an active context menu. This includes who opened the menu, the menu's focus object, and a list of
|
||||
/// <see
|
||||
/// cref="ContextMenuEntry">
|
||||
/// entries
|
||||
/// </see>
|
||||
/// that the menu is composed of.
|
||||
/// <seealso cref="ContextMenuEntry" />
|
||||
/// </summary>
|
||||
public class ContextMenu : IDisposable
|
||||
{
|
||||
public bool IsDisposed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Mobile" /> who opened this ContextMenu.
|
||||
/// </summary>
|
||||
public Mobile From { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets an object of the <see cref="Mobile" /> or <see cref="Item" /> for which this ContextMenu is on.
|
||||
/// </summary>
|
||||
public IEntity Target { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of <see cref="ContextMenuEntry">entries</see> contained in this ContextMenu.
|
||||
/// </summary>
|
||||
public ContextMenuEntry[] Entries { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new ContextMenu instance.
|
||||
/// </summary>
|
||||
/// <param name="from">
|
||||
/// The <see cref="Mobile" /> who opened this ContextMenu.
|
||||
/// <seealso cref="From" />
|
||||
/// </param>
|
||||
/// <param name="target">
|
||||
/// The <see cref="Mobile" /> or <see cref="Item" /> for which this ContextMenu is on.
|
||||
/// <seealso cref="Target" />
|
||||
/// </param>
|
||||
public ContextMenu(Mobile from, IEntity target)
|
||||
{
|
||||
From = from;
|
||||
Target = target;
|
||||
|
||||
var list = new List<ContextMenuEntry>();
|
||||
|
||||
if (target is Mobile)
|
||||
{
|
||||
((Mobile)target).GetContextMenuEntries(from, list);
|
||||
}
|
||||
else if (target is Item)
|
||||
{
|
||||
((Item)target).GetContextMenuEntries(from, list);
|
||||
}
|
||||
|
||||
EventSink.InvokeContextMenu(new ContextMenuEventArgs(From, Target, list));
|
||||
|
||||
foreach (var e in list)
|
||||
{
|
||||
e.Owner = this;
|
||||
}
|
||||
|
||||
Entries = list.ToArray();
|
||||
|
||||
list.Clear();
|
||||
list.TrimExcess();
|
||||
}
|
||||
|
||||
~ContextMenu()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this ContextMenu requires packet version 2.
|
||||
/// </summary>
|
||||
public bool RequiresNewPacket { get { return Entries.Any(t => t.Number < 3000000 || t.Number > 3032767); } }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (IsDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IsDisposed = true;
|
||||
|
||||
if (Entries != null)
|
||||
{
|
||||
foreach (var e in Entries.Where(e => e != null))
|
||||
{
|
||||
e.Dispose();
|
||||
}
|
||||
|
||||
Entries = null;
|
||||
}
|
||||
|
||||
if (From != null)
|
||||
{
|
||||
if (From.ContextMenu == this)
|
||||
{
|
||||
From.ContextMenu = null;
|
||||
}
|
||||
|
||||
From = null;
|
||||
}
|
||||
|
||||
Target = null;
|
||||
}
|
||||
|
||||
public static bool Display(Mobile m, IEntity target)
|
||||
{
|
||||
if (m == null || target == null || m.Map != target.Map)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (target is Mobile && !Utility.InUpdateRange(m, target.Location))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (target is Item && !Utility.InUpdateRange(m, ((Item)target).GetWorldLocation()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m.CheckContextMenuDisplay(target))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var c = new ContextMenu(m, target);
|
||||
|
||||
if (c.Entries.Length <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (target is Item)
|
||||
{
|
||||
var root = ((Item)target).RootParent;
|
||||
|
||||
if (root is Mobile && root != m && ((Mobile)root).AccessLevel >= m.AccessLevel)
|
||||
{
|
||||
foreach (var e in c.Entries.Where(e => !e.NonLocalUse))
|
||||
{
|
||||
e.Enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m.ContextMenu = c;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the proper index of Enhanced Client Context Menu when sent from the icon on
|
||||
/// the vendors status bar. Only known are Bank, Bulk Order Info and Bribe
|
||||
/// </summary>
|
||||
/// <param name="index">pre-described index sent by client. Must be 0x64 or higher</param>
|
||||
/// <returns>actual index of pre-desribed index from client</returns>
|
||||
public int GetIndexEC(int index)
|
||||
{
|
||||
int number = index;
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case 0x0078:
|
||||
number = 3006105;
|
||||
break; // Bank
|
||||
case 0x0193:
|
||||
number = 3006152;
|
||||
break; // Bulk Order Info
|
||||
case 0x01A3:
|
||||
number = 1152294;
|
||||
break; // Bribe
|
||||
case 0x032A:
|
||||
number = 3000197;
|
||||
break; // Add Party Member
|
||||
case 0x032B:
|
||||
number = 3000198;
|
||||
break; // Remove Party Member
|
||||
case 0x012D:
|
||||
number = 3006130;
|
||||
break; // Tame
|
||||
case 0x082:
|
||||
number = 3006107;
|
||||
break; // Command: Guard
|
||||
case 0x083:
|
||||
number = 3006108;
|
||||
break; // Command: Follow
|
||||
case 0x086:
|
||||
number = 3006111;
|
||||
break; // Command: Kill
|
||||
case 0x087:
|
||||
number = 3006114;
|
||||
break; // Command: Stay
|
||||
case 0x089:
|
||||
number = 3006112;
|
||||
break; // Command: Stop
|
||||
case 0x0140:
|
||||
number = 1113797;
|
||||
break; // Enable PVP Warning TODO: Not Enabled
|
||||
case 0x025A:
|
||||
number = 3006205;
|
||||
break; // Release Co-Ownership TODO: Not Enabled
|
||||
case 0x025C:
|
||||
number = 3006207;
|
||||
break; // Leave House
|
||||
case 0x0196:
|
||||
number = 3006156;
|
||||
break; // Quest Conversation
|
||||
case 0x0194:
|
||||
number = 3006154;
|
||||
break; // View Quest Log
|
||||
case 0x0195:
|
||||
number = 3006155;
|
||||
break; // Cancel Quest
|
||||
case 0x0321:
|
||||
number = 3006169;
|
||||
break; // Toggle Quest Item
|
||||
case 0x01A0:
|
||||
number = 1114299;
|
||||
break; // Open Item Insurance Menu
|
||||
case 0x01A2:
|
||||
number = 3006201;
|
||||
break; // Toggle Item Insurance
|
||||
case 0x0396:
|
||||
number = 1115022;
|
||||
break; // Open Titles Menu
|
||||
case 0x0393:
|
||||
number = 1049594;
|
||||
break; // Loyalty Rating
|
||||
case 0x0134:
|
||||
number = 3006157;
|
||||
break; // Cancel Protection
|
||||
case 0x03F2:
|
||||
number = 1152531;
|
||||
break; // Void Pool
|
||||
case 0x03F5:
|
||||
number = 1154112;
|
||||
break; // Allow Trades
|
||||
case 0x03F6:
|
||||
number = 1154113;
|
||||
break; // Refuse Trades
|
||||
case 0x0334:
|
||||
number = 3006168;
|
||||
break; // Siege Bless Item
|
||||
}
|
||||
|
||||
if (index >= 0x64)
|
||||
{
|
||||
for (int i = 0; i < Entries.Length; i++)
|
||||
{
|
||||
if (Entries[i].Number == number)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
||||
141
Server/ContextMenus/ContextMenuEntry.cs
Normal file
141
Server/ContextMenus/ContextMenuEntry.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
#region References
|
||||
using System;
|
||||
|
||||
using Server.Network;
|
||||
#endregion
|
||||
|
||||
namespace Server.ContextMenus
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single entry of a <see cref="ContextMenu">context menu</see>.
|
||||
/// <seealso cref="ContextMenu" />
|
||||
/// </summary>
|
||||
public class ContextMenuEntry : IDisposable
|
||||
{
|
||||
public bool IsDisposed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets additional <see cref="CMEFlags">flags</see> used in client communication.
|
||||
/// </summary>
|
||||
public CMEFlags Flags { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="ContextMenu" /> that owns this entry.
|
||||
/// </summary>
|
||||
public ContextMenu Owner { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the localization number containing the name of this entry.
|
||||
/// </summary>
|
||||
public int Number { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum range at which this entry may be used, in tiles. A value of -1 signifies no maximum range.
|
||||
/// </summary>
|
||||
public int Range { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the color for this entry. Format is A1-R5-G5-B5.
|
||||
/// </summary>
|
||||
public int Color { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether this entry is enabled. When false, the entry will appear in a gray hue and <see cref="OnClick" /> will never be invoked.
|
||||
/// </summary>
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating if non local use of this entry is permitted.
|
||||
/// </summary>
|
||||
public virtual bool NonLocalUse { get { return false; } }
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new ContextMenuEntry with a given <see cref="Number">localization number</see> (
|
||||
/// <paramref
|
||||
/// name="number" />
|
||||
/// ). No <see cref="Range">maximum range</see> is used.
|
||||
/// </summary>
|
||||
/// <param name="number">
|
||||
/// The localization number containing the name of this entry.
|
||||
/// <seealso cref="Number" />
|
||||
/// </param>
|
||||
public ContextMenuEntry(int number)
|
||||
: this(number, -1)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new ContextMenuEntry with a given <see cref="Number">localization number</see> (
|
||||
/// <paramref
|
||||
/// name="number" />
|
||||
/// ) and <see cref="Range">maximum range</see> (<paramref name="range" />).
|
||||
/// </summary>
|
||||
/// <param name="number">
|
||||
/// The localization number containing the name of this entry.
|
||||
/// <seealso cref="Number" />
|
||||
/// </param>
|
||||
/// <param name="range">
|
||||
/// The maximum range at which this entry can be used.
|
||||
/// <seealso cref="Range" />
|
||||
/// </param>
|
||||
public ContextMenuEntry(int number, int range)
|
||||
{
|
||||
if (number <= 0x7FFF) // Legacy code support
|
||||
{
|
||||
Number = 3000000 + number;
|
||||
}
|
||||
else
|
||||
{
|
||||
Number = number;
|
||||
}
|
||||
|
||||
Range = range;
|
||||
Enabled = true;
|
||||
Color = 0xFFFF;
|
||||
}
|
||||
|
||||
~ContextMenuEntry()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overridable. Virtual event invoked when the entry is clicked.
|
||||
/// </summary>
|
||||
public virtual void OnClick()
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Overridable. Virtual event invoked when the entry is clicked and the entry is disabled.
|
||||
/// </summary>
|
||||
public virtual void OnClickDisabled()
|
||||
{ }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (IsDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IsDisposed = true;
|
||||
|
||||
OnDispose();
|
||||
|
||||
if (Owner != null && Owner.Entries != null)
|
||||
{
|
||||
for (var i = 0; i < Owner.Entries.Length; i++)
|
||||
{
|
||||
if (Owner.Entries[i] == this)
|
||||
{
|
||||
Owner.Entries[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Owner = null;
|
||||
}
|
||||
|
||||
protected virtual void OnDispose()
|
||||
{ }
|
||||
}
|
||||
}
|
||||
18
Server/ContextMenus/OpenBackpackEntry.cs
Normal file
18
Server/ContextMenus/OpenBackpackEntry.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace Server.ContextMenus
|
||||
{
|
||||
public class OpenBackpackEntry : ContextMenuEntry
|
||||
{
|
||||
private readonly Mobile m_Mobile;
|
||||
|
||||
public OpenBackpackEntry(Mobile m)
|
||||
: base(6145)
|
||||
{
|
||||
m_Mobile = m;
|
||||
}
|
||||
|
||||
public override void OnClick()
|
||||
{
|
||||
m_Mobile.Use(m_Mobile.Backpack);
|
||||
}
|
||||
}
|
||||
}
|
||||
21
Server/ContextMenus/PaperdollEntry.cs
Normal file
21
Server/ContextMenus/PaperdollEntry.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
namespace Server.ContextMenus
|
||||
{
|
||||
public class PaperdollEntry : ContextMenuEntry
|
||||
{
|
||||
private readonly Mobile m_Mobile;
|
||||
|
||||
public PaperdollEntry(Mobile m)
|
||||
: base(6123, 18)
|
||||
{
|
||||
m_Mobile = m;
|
||||
}
|
||||
|
||||
public override void OnClick()
|
||||
{
|
||||
if (m_Mobile.CanPaperdollBeOpenedBy(Owner.From))
|
||||
{
|
||||
m_Mobile.DisplayPaperdollTo(Owner.From);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
80
Server/Customs Framework/Central Core/Base Types/BaseCore.cs
Normal file
80
Server/Customs Framework/Central Core/Base Types/BaseCore.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
#region References
|
||||
using Server;
|
||||
using Server.Gumps;
|
||||
#endregion
|
||||
|
||||
namespace CustomsFramework
|
||||
{
|
||||
public class BaseCore : SaveData, ICustomsEntity, ISerializable
|
||||
{
|
||||
public static event BaseCoreEventHandler OnEnabledChanged;
|
||||
|
||||
private bool _Enabled;
|
||||
|
||||
public BaseCore()
|
||||
{ }
|
||||
|
||||
public BaseCore(CustomSerial serial)
|
||||
: base(serial)
|
||||
{ }
|
||||
|
||||
[CommandProperty(AccessLevel.Developer)]
|
||||
public bool Enabled
|
||||
{
|
||||
get { return _Enabled; }
|
||||
set
|
||||
{
|
||||
if (value != _Enabled)
|
||||
{
|
||||
_Enabled = value;
|
||||
|
||||
if (OnEnabledChanged != null)
|
||||
{
|
||||
OnEnabledChanged(new BaseCoreEventArgs(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string Name { get { return @"Base Core"; } }
|
||||
public virtual string Description { get { return @"Base Core, inherit from this class and override the interface items."; } }
|
||||
public virtual string Version { get { return "1.0"; } }
|
||||
public virtual AccessLevel EditLevel { get { return AccessLevel.Developer; } }
|
||||
// TODO: Implement Custom Systems Control
|
||||
public virtual Gump SettingsGump { get { return null; } }
|
||||
public virtual bool ShardControlEnabled { get { return false; } }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
|
||||
public override void Prep()
|
||||
{ }
|
||||
|
||||
public override void Delete()
|
||||
{ }
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
writer.WriteVersion(0);
|
||||
|
||||
// Version 0
|
||||
writer.Write(_Enabled);
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
int version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
_Enabled = reader.ReadBool();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
188
Server/Customs Framework/Central Core/Base Types/BaseModule.cs
Normal file
188
Server/Customs Framework/Central Core/Base Types/BaseModule.cs
Normal file
@@ -0,0 +1,188 @@
|
||||
#region References
|
||||
using System;
|
||||
|
||||
using Server;
|
||||
using Server.Gumps;
|
||||
#endregion
|
||||
|
||||
namespace CustomsFramework
|
||||
{
|
||||
public class BaseModule : SaveData, ICustomsEntity, ISerializable
|
||||
{
|
||||
private Mobile _LinkedMobile;
|
||||
private Item _LinkedItem;
|
||||
private DateTime _CreatedTime;
|
||||
private DateTime _LastEditedTime;
|
||||
|
||||
public BaseModule()
|
||||
{ }
|
||||
|
||||
public BaseModule(Mobile from)
|
||||
{
|
||||
LinkMobile(from);
|
||||
}
|
||||
|
||||
public BaseModule(Item item)
|
||||
{
|
||||
LinkItem(item);
|
||||
}
|
||||
|
||||
public BaseModule(CustomSerial serial)
|
||||
: base(serial)
|
||||
{ }
|
||||
|
||||
public override string Name { get { return @"Base Module"; } }
|
||||
|
||||
public virtual string Description { get { return "Base Module, inherit from this class and override all interface items."; } }
|
||||
|
||||
public virtual string Version { get { return "1.0"; } }
|
||||
|
||||
public virtual AccessLevel EditLevel { get { return AccessLevel.Developer; } }
|
||||
|
||||
public virtual Gump SettingsGump { get { return null; } }
|
||||
|
||||
[CommandProperty(AccessLevel.Administrator)]
|
||||
public Mobile LinkedMobile { get { return _LinkedMobile; } set { LinkMobile(value); } }
|
||||
|
||||
[CommandProperty(AccessLevel.Administrator)]
|
||||
public Item LinkedItem { get { return _LinkedItem; } set { LinkItem(value); } }
|
||||
|
||||
[CommandProperty(AccessLevel.Administrator)]
|
||||
public DateTime CreatedTime { get { return _CreatedTime; } }
|
||||
|
||||
[CommandProperty(AccessLevel.Administrator)]
|
||||
public DateTime LastEditedTime { get { return _LastEditedTime; } }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
|
||||
public override void Prep()
|
||||
{ }
|
||||
|
||||
public override void Delete()
|
||||
{
|
||||
if (_LinkedMobile != null)
|
||||
{
|
||||
_LinkedMobile.Modules.Remove(this);
|
||||
_LinkedMobile = null;
|
||||
}
|
||||
|
||||
if (_LinkedItem != null)
|
||||
{
|
||||
_LinkedItem.Modules.Remove(this);
|
||||
_LinkedItem = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
_LastEditedTime = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
public bool LinkMobile(Mobile from)
|
||||
{
|
||||
if (_LinkedMobile != null || _LinkedMobile == from)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!from.Modules.Contains(this))
|
||||
{
|
||||
from.Modules.Add(this);
|
||||
}
|
||||
|
||||
_LinkedMobile = from;
|
||||
Update();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool LinkItem(Item item)
|
||||
{
|
||||
if (_LinkedItem != null || _LinkedItem == item)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!item.Modules.Contains(this))
|
||||
{
|
||||
item.Modules.Add(this);
|
||||
}
|
||||
|
||||
_LinkedItem = item;
|
||||
Update();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool UnlinkMobile()
|
||||
{
|
||||
if (_LinkedMobile == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_LinkedMobile.Modules.Contains(this))
|
||||
{
|
||||
_LinkedMobile.Modules.Remove(this);
|
||||
}
|
||||
|
||||
_LinkedMobile = null;
|
||||
Update();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool UnlinkItem()
|
||||
{
|
||||
if (_LinkedItem == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_LinkedItem.Modules.Contains(this))
|
||||
{
|
||||
_LinkedItem.Modules.Remove(this);
|
||||
}
|
||||
|
||||
_LinkedItem = null;
|
||||
Update();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
writer.WriteVersion(0);
|
||||
|
||||
// Version 0
|
||||
writer.Write(_LinkedMobile);
|
||||
writer.Write(_LinkedItem);
|
||||
writer.Write(_CreatedTime);
|
||||
writer.Write(_LastEditedTime);
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
int version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
LinkedMobile = reader.ReadMobile();
|
||||
LinkedItem = reader.ReadItem();
|
||||
_CreatedTime = reader.ReadDateTime();
|
||||
_LastEditedTime = reader.ReadDateTime();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
#region References
|
||||
using Server;
|
||||
using Server.Gumps;
|
||||
#endregion
|
||||
|
||||
namespace CustomsFramework
|
||||
{
|
||||
public class BaseService : SaveData, ICustomsEntity, ISerializable
|
||||
{
|
||||
public BaseService()
|
||||
{ }
|
||||
|
||||
public BaseService(CustomSerial serial)
|
||||
: base(serial)
|
||||
{ }
|
||||
|
||||
public override string Name { get { return @"Base Service"; } }
|
||||
public virtual string Description { get { return @"Base Service, inherit from this class and override the interface items."; } }
|
||||
public virtual string Version { get { return "1.0"; } }
|
||||
public virtual AccessLevel EditLevel { get { return AccessLevel.Developer; } }
|
||||
public virtual Gump SettingsGump { get { return null; } }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
|
||||
public override void Prep()
|
||||
{ }
|
||||
|
||||
public override void Delete()
|
||||
{ }
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
writer.WriteVersion(0);
|
||||
//Version 0
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
int version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Server/Customs Framework/Central Core/Base Types/Events.cs
Normal file
34
Server/Customs Framework/Central Core/Base Types/Events.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
#region References
|
||||
using System;
|
||||
#endregion
|
||||
|
||||
namespace CustomsFramework
|
||||
{
|
||||
public delegate void BaseCoreEventHandler(BaseCoreEventArgs e);
|
||||
|
||||
public delegate void BaseModuleEventHandler(BaseModuleEventArgs e);
|
||||
|
||||
public class BaseCoreEventArgs : EventArgs
|
||||
{
|
||||
private readonly BaseCore m_Core;
|
||||
|
||||
public BaseCoreEventArgs(BaseCore core)
|
||||
{
|
||||
m_Core = core;
|
||||
}
|
||||
|
||||
public BaseCore Core { get { return m_Core; } }
|
||||
}
|
||||
|
||||
public class BaseModuleEventArgs : EventArgs
|
||||
{
|
||||
private readonly BaseModule m_Module;
|
||||
|
||||
public BaseModuleEventArgs(BaseModule module)
|
||||
{
|
||||
m_Module = module;
|
||||
}
|
||||
|
||||
public BaseModule Module { get { return m_Module; } }
|
||||
}
|
||||
}
|
||||
113
Server/Customs Framework/Central Core/Base Types/SaveData.cs
Normal file
113
Server/Customs Framework/Central Core/Base Types/SaveData.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
#region References
|
||||
using System;
|
||||
|
||||
using Server;
|
||||
#endregion
|
||||
|
||||
namespace CustomsFramework
|
||||
{
|
||||
public class SaveData : ICustomsEntity, IComparable<SaveData>, ISerializable
|
||||
{
|
||||
#region CompareTo
|
||||
public int CompareTo(ICustomsEntity other)
|
||||
{
|
||||
if (other == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _Serial.CompareTo(other.Serial);
|
||||
}
|
||||
|
||||
public int CompareTo(SaveData other)
|
||||
{
|
||||
return CompareTo((ICustomsEntity)other);
|
||||
}
|
||||
|
||||
public int CompareTo(object other)
|
||||
{
|
||||
if (other == null || other is ICustomsEntity)
|
||||
{
|
||||
return CompareTo((ICustomsEntity)other);
|
||||
}
|
||||
|
||||
throw new ArgumentException();
|
||||
}
|
||||
#endregion
|
||||
|
||||
internal int _TypeID;
|
||||
|
||||
int ISerializable.TypeReference { get { return _TypeID; } }
|
||||
|
||||
int ISerializable.SerialIdentity { get { return _Serial; } }
|
||||
|
||||
private bool _Deleted;
|
||||
private CustomSerial _Serial;
|
||||
|
||||
[CommandProperty(AccessLevel.Developer)]
|
||||
public bool Deleted { get { return _Deleted; } set { _Deleted = value; } }
|
||||
|
||||
[CommandProperty(AccessLevel.Developer)]
|
||||
public CustomSerial Serial { get { return _Serial; } set { _Serial = value; } }
|
||||
|
||||
public virtual string Name { get { return @"Save Data"; } }
|
||||
|
||||
public SaveData(CustomSerial serial)
|
||||
{
|
||||
_Serial = serial;
|
||||
|
||||
Type dataType = GetType();
|
||||
_TypeID = World._DataTypes.IndexOf(dataType);
|
||||
|
||||
if (_TypeID == -1)
|
||||
{
|
||||
World._DataTypes.Add(dataType);
|
||||
_TypeID = World._DataTypes.Count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
public SaveData()
|
||||
{
|
||||
_Serial = CustomSerial.NewCustom;
|
||||
|
||||
World.AddData(this);
|
||||
|
||||
Type dataType = GetType();
|
||||
_TypeID = World._DataTypes.IndexOf(dataType);
|
||||
|
||||
if (_TypeID == -1)
|
||||
{
|
||||
World._DataTypes.Add(dataType);
|
||||
_TypeID = World._DataTypes.Count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Prep()
|
||||
{ }
|
||||
|
||||
public virtual void Delete()
|
||||
{ }
|
||||
|
||||
public virtual void Serialize(GenericWriter writer)
|
||||
{
|
||||
writer.WriteVersion(0);
|
||||
|
||||
// Version 0
|
||||
writer.Write(_Deleted);
|
||||
}
|
||||
|
||||
public virtual void Deserialize(GenericReader reader)
|
||||
{
|
||||
int version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
_Deleted = reader.ReadBool();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
116
Server/Customs Framework/Central Core/CustomSerial.cs
Normal file
116
Server/Customs Framework/Central Core/CustomSerial.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
#region References
|
||||
using System;
|
||||
|
||||
using Server;
|
||||
#endregion
|
||||
|
||||
namespace CustomsFramework
|
||||
{
|
||||
public struct CustomSerial : IComparable, IComparable<CustomSerial>
|
||||
{
|
||||
public static readonly CustomSerial MinusOne = new CustomSerial(-1);
|
||||
public static readonly CustomSerial Zero = new CustomSerial(0);
|
||||
private static CustomSerial _LastCustom = Zero;
|
||||
private readonly int _Serial;
|
||||
|
||||
private CustomSerial(int serial)
|
||||
{
|
||||
_Serial = serial;
|
||||
}
|
||||
|
||||
public static CustomSerial LastCore { get { return _LastCustom; } }
|
||||
|
||||
public static CustomSerial NewCustom
|
||||
{
|
||||
get
|
||||
{
|
||||
while (World.GetData(_LastCustom = (_LastCustom + 1)) != null)
|
||||
{ }
|
||||
|
||||
return _LastCustom;
|
||||
}
|
||||
}
|
||||
|
||||
public int Value { get { return _Serial; } }
|
||||
public bool IsValid { get { return (_Serial > 0); } }
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _Serial;
|
||||
}
|
||||
|
||||
public int CompareTo(CustomSerial other)
|
||||
{
|
||||
return _Serial.CompareTo(other._Serial);
|
||||
}
|
||||
|
||||
public int CompareTo(object other)
|
||||
{
|
||||
if (other is CustomSerial)
|
||||
{
|
||||
return CompareTo((CustomSerial)other);
|
||||
}
|
||||
else if (other == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == null || !(obj is CustomSerial))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((CustomSerial)obj)._Serial == _Serial;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("0x{0:X8}", _Serial);
|
||||
}
|
||||
|
||||
public static bool operator ==(CustomSerial first, CustomSerial second)
|
||||
{
|
||||
return first._Serial == second._Serial;
|
||||
}
|
||||
|
||||
public static bool operator !=(CustomSerial first, CustomSerial second)
|
||||
{
|
||||
return first._Serial != second._Serial;
|
||||
}
|
||||
|
||||
public static bool operator >(CustomSerial first, CustomSerial second)
|
||||
{
|
||||
return first._Serial > second._Serial;
|
||||
}
|
||||
|
||||
public static bool operator <(CustomSerial first, CustomSerial second)
|
||||
{
|
||||
return first._Serial < second._Serial;
|
||||
}
|
||||
|
||||
public static bool operator >=(CustomSerial first, CustomSerial second)
|
||||
{
|
||||
return first._Serial >= second._Serial;
|
||||
}
|
||||
|
||||
public static bool operator <=(CustomSerial first, CustomSerial second)
|
||||
{
|
||||
return first._Serial <= second._Serial;
|
||||
}
|
||||
|
||||
public static implicit operator int(CustomSerial serial)
|
||||
{
|
||||
return serial._Serial;
|
||||
}
|
||||
|
||||
public static implicit operator CustomSerial(int serial)
|
||||
{
|
||||
return new CustomSerial(serial);
|
||||
}
|
||||
}
|
||||
}
|
||||
23
Server/Customs Framework/Central Core/Interfaces.cs
Normal file
23
Server/Customs Framework/Central Core/Interfaces.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
#region References
|
||||
using System;
|
||||
#endregion
|
||||
|
||||
namespace CustomsFramework
|
||||
{
|
||||
public interface ICustomsEntry
|
||||
{
|
||||
CustomSerial Serial { get; }
|
||||
int TypeID { get; }
|
||||
long Position { get; }
|
||||
int Length { get; }
|
||||
}
|
||||
|
||||
public interface ICustomsEntity : IComparable, IComparable<ICustomsEntity>
|
||||
{
|
||||
CustomSerial Serial { get; }
|
||||
string Name { get; }
|
||||
void Delete();
|
||||
|
||||
void Prep();
|
||||
}
|
||||
}
|
||||
55
Server/Customs Framework/Custom Types/LastEditedBy.cs
Normal file
55
Server/Customs Framework/Custom Types/LastEditedBy.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
#region References
|
||||
using System;
|
||||
|
||||
using CustomsFramework;
|
||||
#endregion
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class LastEditedBy
|
||||
{
|
||||
private Mobile _Mobile;
|
||||
private DateTime _Time;
|
||||
|
||||
public LastEditedBy(Mobile mobile)
|
||||
{
|
||||
_Mobile = mobile;
|
||||
_Time = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
public LastEditedBy(GenericReader reader)
|
||||
{
|
||||
Deserialize(reader);
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.Decorator)]
|
||||
public Mobile Mobile { get { return _Mobile; } set { _Mobile = value; } }
|
||||
|
||||
[CommandProperty(AccessLevel.Decorator)]
|
||||
public DateTime Time { get { return _Time; } set { _Time = value; } }
|
||||
|
||||
public void Serialize(GenericWriter writer)
|
||||
{
|
||||
writer.WriteVersion(0);
|
||||
|
||||
// Version 0
|
||||
writer.Write(_Mobile);
|
||||
writer.Write(_Time);
|
||||
}
|
||||
|
||||
private void Deserialize(GenericReader reader)
|
||||
{
|
||||
int version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
_Mobile = reader.ReadMobile();
|
||||
_Time = reader.ReadDateTime();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
59
Server/Customs Framework/Custom Types/Place.cs
Normal file
59
Server/Customs Framework/Custom Types/Place.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
#region References
|
||||
using CustomsFramework;
|
||||
#endregion
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class Place
|
||||
{
|
||||
private Map _Map;
|
||||
private Point3D _Location;
|
||||
|
||||
public Place()
|
||||
{
|
||||
_Map = Map.Internal;
|
||||
_Location = new Point3D(0, 0, 0);
|
||||
}
|
||||
|
||||
public Place(Map map, Point3D location)
|
||||
{
|
||||
_Map = map;
|
||||
_Location = location;
|
||||
}
|
||||
|
||||
public Place(GenericReader reader)
|
||||
{
|
||||
Deserialize(reader);
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.Decorator)]
|
||||
public Map Map { get { return _Map; } set { _Map = value; } }
|
||||
|
||||
[CommandProperty(AccessLevel.Decorator)]
|
||||
public Point3D Location { get { return _Location; } set { _Location = value; } }
|
||||
|
||||
public void Serialize(GenericWriter writer)
|
||||
{
|
||||
writer.WriteVersion(0);
|
||||
|
||||
// Version 0
|
||||
writer.Write(_Map);
|
||||
writer.Write(_Location);
|
||||
}
|
||||
|
||||
private void Deserialize(GenericReader reader)
|
||||
{
|
||||
int version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
_Map = reader.ReadMap();
|
||||
_Location = reader.ReadPoint3D();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
209
Server/Customs Framework/Utilities/Decompressor.cs
Normal file
209
Server/Customs Framework/Utilities/Decompressor.cs
Normal file
@@ -0,0 +1,209 @@
|
||||
#region References
|
||||
using System;
|
||||
#endregion
|
||||
|
||||
namespace CustomsFramework
|
||||
{
|
||||
internal class Decompressor
|
||||
{
|
||||
#region Decompression Tree
|
||||
private static readonly int[,] _huffmanTree = new int[256,2]
|
||||
{
|
||||
/*node*/ /*leaf0 leaf1*/
|
||||
/* 0*/ {2, 1}, /* 1*/ {4, 3}, /* 2*/ {0, 5}, /* 3*/ {7, 6}, /* 4*/ {9, 8}, /* 5*/ {11, 10}, /* 6*/ {13, 12}, /* 7*/
|
||||
{14, -256}, /* 8*/ {16, 15}, /* 9*/ {18, 17}, /* 10*/ {20, 19}, /* 11*/ {22, 21}, /* 12*/ {23, -1}, /* 13*/ {25, 24},
|
||||
/* 14*/ {27, 26}, /* 15*/ {29, 28}, /* 16*/ {31, 30}, /* 17*/ {33, 32}, /* 18*/ {35, 34}, /* 19*/ {37, 36}, /* 20*/
|
||||
{39, 38}, /* 21*/ {-64, 40}, /* 22*/ {42, 41}, /* 23*/ {44, 43}, /* 24*/ {45, -6}, /* 25*/ {47, 46}, /* 26*/ {49, 48}
|
||||
, /* 27*/ {51, 50}, /* 28*/ {52, -119}, /* 29*/ {53, -32}, /* 30*/ {-14, 54}, /* 31*/ {-5, 55}, /* 32*/ {57, 56},
|
||||
/* 33*/ {59, 58}, /* 34*/ {-2, 60}, /* 35*/ {62, 61}, /* 36*/ {64, 63}, /* 37*/ {66, 65}, /* 38*/ {68, 67}, /* 39*/
|
||||
{70, 69}, /* 40*/ {72, 71}, /* 41*/ {73, -51}, /* 42*/ {75, 74}, /* 43*/ {77, 76}, /* 44*/ {-111, -101}, /* 45*/
|
||||
{-97, -4}, /* 46*/ {79, 78}, /* 47*/ {80, -110}, /* 48*/ {-116, 81}, /* 49*/ {83, 82}, /* 50*/ {-255, 84}, /* 51*/
|
||||
{86, 85}, /* 52*/ {88, 87}, /* 53*/ {90, 89}, /* 54*/ {-10, -15}, /* 55*/ {92, 91}, /* 56*/ {93, -21}, /* 57*/
|
||||
{94, -117}, /* 58*/ {96, 95}, /* 59*/ {98, 97}, /* 60*/ {100, 99}, /* 61*/ {101, -114}, /* 62*/ {102, -105}, /* 63*/
|
||||
{103, -26}, /* 64*/ {105, 104}, /* 65*/ {107, 106}, /* 66*/ {109, 108}, /* 67*/ {111, 110}, /* 68*/ {-3, 112},
|
||||
/* 69*/ {-7, 113}, /* 70*/ {-131, 114}, /* 71*/ {-144, 115}, /* 72*/ {117, 116}, /* 73*/ {118, -20}, /* 74*/
|
||||
{120, 119}, /* 75*/ {122, 121}, /* 76*/ {124, 123}, /* 77*/ {126, 125}, /* 78*/ {128, 127}, /* 79*/ {-100, 129},
|
||||
/* 80*/ {-8, 130}, /* 81*/ {132, 131}, /* 82*/ {134, 133}, /* 83*/ {135, -120}, /* 84*/ {-31, 136}, /* 85*/
|
||||
{138, 137}, /* 86*/ {-234, -109}, /* 87*/ {140, 139}, /* 88*/ {142, 141}, /* 89*/ {144, 143}, /* 90*/ {145, -112},
|
||||
/* 91*/ {146, -19}, /* 92*/ {148, 147}, /* 93*/ {-66, 149}, /* 94*/ {-145, 150}, /* 95*/ {-65, -13}, /* 96*/
|
||||
{152, 151}, /* 97*/ {154, 153}, /* 98*/ {155, -30}, /* 99*/ {157, 156}, /* 100*/ {158, -99}, /* 101*/ {160, 159},
|
||||
/* 102*/ {162, 161}, /* 103*/ {163, -23}, /* 104*/ {164, -29}, /* 105*/ {165, -11}, /* 106*/ {-115, 166}, /* 107*/
|
||||
{168, 167}, /* 108*/ {170, 169}, /* 109*/ {171, -16}, /* 110*/ {172, -34}, /* 111*/ {-132, 173}, /* 112*/ {-108, 174}
|
||||
, /* 113*/ {-22, 175}, /* 114*/ {-9, 176}, /* 115*/ {-84, 177}, /* 116*/ {-37, -17}, /* 117*/ {178, -28}, /* 118*/
|
||||
{180, 179}, /* 119*/ {182, 181}, /* 120*/ {184, 183}, /* 121*/ {186, 185}, /* 122*/ {-104, 187}, /* 123*/ {-78, 188},
|
||||
/* 124*/ {-61, 189}, /* 125*/ {-178, -79}, /* 126*/ {-134, -59}, /* 127*/ {-25, 190}, /* 128*/ {-18, -83}, /* 129*/
|
||||
{-57, 191}, /* 130*/ {192, -67}, /* 131*/ {193, -98}, /* 132*/ {-68, -12}, /* 133*/ {195, 194}, /* 134*/ {-128, -55},
|
||||
/* 135*/ {-50, -24}, /* 136*/ {196, -70}, /* 137*/ {-33, -94}, /* 138*/ {-129, 197}, /* 139*/ {198, -74}, /* 140*/
|
||||
{199, -82}, /* 141*/ {-87, -56}, /* 142*/ {200, -44}, /* 143*/ {201, -248}, /* 144*/ {-81, -163}, /* 145*/
|
||||
{-123, -52}, /* 146*/ {-113, 202}, /* 147*/ {-41, -48}, /* 148*/ {-40, -122}, /* 149*/ {-90, 203}, /* 150*/
|
||||
{204, -54}, /* 151*/ {-192, -86}, /* 152*/ {206, 205}, /* 153*/ {-130, 207}, /* 154*/ {208, -53}, /* 155*/
|
||||
{-45, -133}, /* 156*/ {210, 209}, /* 157*/ {-91, 211}, /* 158*/ {213, 212}, /* 159*/ {-88, -106}, /* 160*/ {215, 214}
|
||||
, /* 161*/ {217, 216}, /* 162*/ {-49, 218}, /* 163*/ {220, 219}, /* 164*/ {222, 221}, /* 165*/ {224, 223}, /* 166*/
|
||||
{226, 225}, /* 167*/ {-102, 227}, /* 168*/ {228, -160}, /* 169*/ {229, -46}, /* 170*/ {230, -127}, /* 171*/
|
||||
{231, -103}, /* 172*/ {233, 232}, /* 173*/ {234, -60}, /* 174*/ {-76, 235}, /* 175*/ {-121, 236}, /* 176*/ {-73, 237}
|
||||
, /* 177*/ {238, -149}, /* 178*/ {-107, 239}, /* 179*/ {240, -35}, /* 180*/ {-27, -71}, /* 181*/ {241, -69}, /* 182*/
|
||||
{-77, -89}, /* 183*/ {-118, -62}, /* 184*/ {-85, -75}, /* 185*/ {-58, -72}, /* 186*/ {-80, -63}, /* 187*/ {-42, 242},
|
||||
/* 188*/ {-157, -150}, /* 189*/ {-236, -139}, /* 190*/ {-243, -126}, /* 191*/ {-214, -142}, /* 192*/ {-206, -138},
|
||||
/* 193*/ {-146, -240}, /* 194*/ {-147, -204}, /* 195*/ {-201, -152}, /* 196*/ {-207, -227}, /* 197*/ {-209, -154},
|
||||
/* 198*/ {-254, -153}, /* 199*/ {-156, -176}, /* 200*/ {-210, -165}, /* 201*/ {-185, -172}, /* 202*/ {-170, -195},
|
||||
/* 203*/ {-211, -232}, /* 204*/ {-239, -219}, /* 205*/ {-177, -200}, /* 206*/ {-212, -175}, /* 207*/ {-143, -244},
|
||||
/* 208*/ {-171, -246}, /* 209*/ {-221, -203}, /* 210*/ {-181, -202}, /* 211*/ {-250, -173}, /* 212*/ {-164, -184},
|
||||
/* 213*/ {-218, -193}, /* 214*/ {-220, -199}, /* 215*/ {-249, -190}, /* 216*/ {-217, -230}, /* 217*/ {-216, -169},
|
||||
/* 218*/ {-197, -191}, /* 219*/ {243, -47}, /* 220*/ {245, 244}, /* 221*/ {247, 246}, /* 222*/ {-159, -148}, /* 223*/
|
||||
{249, 248}, /* 224*/ {-93, -92}, /* 225*/ {-225, -96}, /* 226*/ {-95, -151}, /* 227*/ {251, 250}, /* 228*/
|
||||
{252, -241}, /* 229*/ {-36, -161}, /* 230*/ {254, 253}, /* 231*/ {-39, -135}, /* 232*/ {-124, -187}, /* 233*/
|
||||
{-251, 255}, /* 234*/ {-238, -162}, /* 235*/ {-38, -242}, /* 236*/ {-125, -43}, /* 237*/ {-253, -215}, /* 238*/
|
||||
{-208, -140}, /* 239*/ {-235, -137}, /* 240*/ {-237, -158}, /* 241*/ {-205, -136}, /* 242*/ {-141, -155}, /* 243*/
|
||||
{-229, -228}, /* 244*/ {-168, -213}, /* 245*/ {-194, -224}, /* 246*/ {-226, -196}, /* 247*/ {-233, -183}, /* 248*/
|
||||
{-167, -231}, /* 249*/ {-189, -174}, /* 250*/ {-166, -252}, /* 251*/ {-222, -198}, /* 252*/ {-179, -188}, /* 253*/
|
||||
{-182, -223}, /* 254*/ {-186, -180}, /* 255*/ {-247, -245}
|
||||
};
|
||||
#endregion
|
||||
|
||||
private static int GetBit(int buf, int bit)
|
||||
{
|
||||
return (buf >> (bit - 1)) & 1;
|
||||
}
|
||||
|
||||
public static bool Decompress(byte[] source, int sourceLength, byte[] destination, ref int destinationLength)
|
||||
{
|
||||
Array.Clear(destination, 0, destination.Length);
|
||||
destinationLength = 0;
|
||||
int node = 0, leaf = 0, leaf_value = 0, dest_pos = 0, bit_num = 8, src_pos = 0;
|
||||
|
||||
while (src_pos < sourceLength)
|
||||
{
|
||||
leaf = GetBit(source[src_pos], bit_num);
|
||||
leaf_value = _huffmanTree[node, leaf];
|
||||
|
||||
// all numbers below 1 (0..-256) are codewords
|
||||
// if the halt codeword has been found, skip this byte
|
||||
if (leaf_value == -256)
|
||||
{
|
||||
bit_num = 8;
|
||||
node = 0;
|
||||
src_pos++;
|
||||
var newsource = new byte[sourceLength - src_pos];
|
||||
Array.Copy(source, src_pos, newsource, 0, sourceLength - src_pos);
|
||||
source = newsource;
|
||||
destinationLength = dest_pos;
|
||||
return true;
|
||||
}
|
||||
else if (leaf_value < 1)
|
||||
{
|
||||
destination[dest_pos] = (byte)-leaf_value;
|
||||
leaf_value = 0;
|
||||
dest_pos++;
|
||||
}
|
||||
|
||||
bit_num--;
|
||||
node = leaf_value;
|
||||
/* if its the end of the byte, go to the next byte */
|
||||
if (bit_num < 1)
|
||||
{
|
||||
bit_num = 8;
|
||||
src_pos++;
|
||||
}
|
||||
|
||||
// check to see if the current codeword has no end
|
||||
// if not, make it an incomplete byte
|
||||
if (src_pos == sourceLength)
|
||||
{
|
||||
if (node != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/*if(obj != NULL && src_pos == *src_size && node)
|
||||
{
|
||||
obj->incomplete_byte = src[src_pos-1];
|
||||
obj->has_incomplete = 1;
|
||||
}*/
|
||||
}
|
||||
|
||||
destinationLength = dest_pos;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static byte? DecompressFirstByte(byte[] source, int sourceLength)
|
||||
{
|
||||
int node = 0, leaf = 0, value = 0, bit = 8, index = 0;
|
||||
|
||||
while (index < sourceLength)
|
||||
{
|
||||
leaf = GetBit(source[index], bit);
|
||||
value = _huffmanTree[node, leaf];
|
||||
|
||||
if (value == -256)
|
||||
{
|
||||
bit = 8;
|
||||
node = 0;
|
||||
index++;
|
||||
|
||||
continue;
|
||||
}
|
||||
else if (value < 1)
|
||||
{
|
||||
return (byte)-value;
|
||||
}
|
||||
|
||||
bit--;
|
||||
node = value;
|
||||
|
||||
if (bit < 1)
|
||||
{
|
||||
bit = 8;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void DecompressAll(byte[] src, int src_size, byte[] dest, ref int dest_size)
|
||||
{
|
||||
int node = 0, leaf = 0, leaf_value = 0, dest_pos = 0, bit_num = 8, src_pos = 0;
|
||||
|
||||
while (src_pos < src_size)
|
||||
{
|
||||
leaf = GetBit(src[src_pos], bit_num);
|
||||
leaf_value = _huffmanTree[node, leaf];
|
||||
|
||||
// all numbers below 1 (0..-256) are codewords
|
||||
// if the halt codeword has been found, skip this byte
|
||||
if (leaf_value == -256)
|
||||
{
|
||||
bit_num = 8;
|
||||
node = 0;
|
||||
src_pos++;
|
||||
continue;
|
||||
}
|
||||
else if (leaf_value < 1)
|
||||
{
|
||||
dest[dest_pos] = (byte)-leaf_value;
|
||||
leaf_value = 0;
|
||||
dest_pos++;
|
||||
}
|
||||
|
||||
bit_num--;
|
||||
node = leaf_value;
|
||||
/* if its the end of the byte, go to the next byte */
|
||||
if (bit_num < 1)
|
||||
{
|
||||
bit_num = 8;
|
||||
src_pos++;
|
||||
}
|
||||
// check to see if the current codeword has no end
|
||||
// if not, make it an incomplete byte
|
||||
/*if(obj != NULL && src_pos == *src_size && node)
|
||||
{
|
||||
obj->incomplete_byte = src[src_pos-1];
|
||||
obj->has_incomplete = 1;
|
||||
}*/
|
||||
}
|
||||
|
||||
dest_size = dest_pos;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
180
Server/Customs Framework/Utilities/ObjectDumper.cs
Normal file
180
Server/Customs Framework/Utilities/ObjectDumper.cs
Normal file
@@ -0,0 +1,180 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
#endregion
|
||||
|
||||
namespace CustomsFramework
|
||||
{
|
||||
public class ObjectDumper
|
||||
{
|
||||
private int _level;
|
||||
private readonly int _indentSize;
|
||||
private readonly StringBuilder _stringBuilder;
|
||||
private readonly List<int> _hashListOfFoundElements;
|
||||
|
||||
private ObjectDumper(int indentSize)
|
||||
{
|
||||
_indentSize = indentSize;
|
||||
_stringBuilder = new StringBuilder();
|
||||
_hashListOfFoundElements = new List<int>();
|
||||
}
|
||||
|
||||
public static string Dump(object element)
|
||||
{
|
||||
return Dump(element, 2);
|
||||
}
|
||||
|
||||
public static string Dump(object element, int indentSize)
|
||||
{
|
||||
var instance = new ObjectDumper(indentSize);
|
||||
return instance.DumpElement(element);
|
||||
}
|
||||
|
||||
private string DumpElement(object element)
|
||||
{
|
||||
if (element == null || element is ValueType || element is string)
|
||||
{
|
||||
Write(FormatValue(element));
|
||||
}
|
||||
else
|
||||
{
|
||||
var objectType = element.GetType();
|
||||
if (!typeof(IEnumerable).IsAssignableFrom(objectType))
|
||||
{
|
||||
Write("{{{0}}}", objectType.FullName);
|
||||
_hashListOfFoundElements.Add(element.GetHashCode());
|
||||
_level++;
|
||||
}
|
||||
|
||||
var enumerableElement = element as IEnumerable;
|
||||
if (enumerableElement != null)
|
||||
{
|
||||
foreach (object item in enumerableElement)
|
||||
{
|
||||
if (item is IEnumerable && !(item is string))
|
||||
{
|
||||
_level++;
|
||||
DumpElement(item);
|
||||
_level--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!AlreadyTouched(item))
|
||||
{
|
||||
DumpElement(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
Write("{{{0}}} <-- bidirectional reference found", item.GetType().FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var members = element.GetType().GetMembers(BindingFlags.Public | BindingFlags.Instance);
|
||||
foreach (var memberInfo in members)
|
||||
{
|
||||
var fieldInfo = memberInfo as FieldInfo;
|
||||
var propertyInfo = memberInfo as PropertyInfo;
|
||||
|
||||
if (fieldInfo == null && propertyInfo == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var type = fieldInfo != null ? fieldInfo.FieldType : propertyInfo.PropertyType;
|
||||
object value = fieldInfo != null ? fieldInfo.GetValue(element) : propertyInfo.GetValue(element, null);
|
||||
|
||||
if (type.IsValueType || type == typeof(string))
|
||||
{
|
||||
Write("{0}: {1}", memberInfo.Name, FormatValue(value));
|
||||
}
|
||||
else
|
||||
{
|
||||
var isEnumerable = typeof(IEnumerable).IsAssignableFrom(type);
|
||||
Write("{0}: {1}", memberInfo.Name, isEnumerable ? "..." : "{ }");
|
||||
|
||||
var alreadyTouched = !isEnumerable && AlreadyTouched(value);
|
||||
_level++;
|
||||
if (!alreadyTouched)
|
||||
{
|
||||
DumpElement(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Write("{{{0}}} <-- bidirectional reference found", value.GetType().FullName);
|
||||
}
|
||||
_level--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!typeof(IEnumerable).IsAssignableFrom(objectType))
|
||||
{
|
||||
_level--;
|
||||
}
|
||||
}
|
||||
|
||||
return _stringBuilder.ToString();
|
||||
}
|
||||
|
||||
private bool AlreadyTouched(object value)
|
||||
{
|
||||
var hash = value.GetHashCode();
|
||||
for (var i = 0; i < _hashListOfFoundElements.Count; i++)
|
||||
{
|
||||
if (_hashListOfFoundElements[i] == hash)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void Write(string value, params object[] args)
|
||||
{
|
||||
var space = new string(' ', _level * _indentSize);
|
||||
|
||||
if (args != null)
|
||||
{
|
||||
value = string.Format(value, args);
|
||||
}
|
||||
|
||||
_stringBuilder.AppendLine(space + value);
|
||||
}
|
||||
|
||||
private string FormatValue(object o)
|
||||
{
|
||||
if (o == null)
|
||||
{
|
||||
return ("null");
|
||||
}
|
||||
|
||||
if (o is DateTime)
|
||||
{
|
||||
return (((DateTime)o).ToShortDateString());
|
||||
}
|
||||
|
||||
if (o is string)
|
||||
{
|
||||
return string.Format("\"{0}\"", o);
|
||||
}
|
||||
|
||||
if (o is ValueType)
|
||||
{
|
||||
return (o.ToString());
|
||||
}
|
||||
|
||||
if (o is IEnumerable)
|
||||
{
|
||||
return ("...");
|
||||
}
|
||||
|
||||
return ("{ }");
|
||||
}
|
||||
}
|
||||
}
|
||||
148
Server/Customs Framework/Utilities/OutgoingPacketOverride.cs
Normal file
148
Server/Customs Framework/Utilities/OutgoingPacketOverride.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Server;
|
||||
using Server.Network;
|
||||
#endregion
|
||||
|
||||
namespace CustomsFramework
|
||||
{
|
||||
public delegate void OutgoingPacketOverrideHandler(
|
||||
NetState to, PacketReader reader, ref byte[] packetBuffer, ref int packetLength);
|
||||
|
||||
public static class OutgoingPacketOverrides
|
||||
{
|
||||
public const int CallPriority = ((byte)'r') << 16 + ((byte)'a') << 8 + ((byte)'d');
|
||||
|
||||
private static readonly OutgoingPacketOverrideHandler[] _Handlers;
|
||||
private static readonly OutgoingPacketOverrideHandler[] _ExtendedHandlersLow;
|
||||
private static readonly Dictionary<int, OutgoingPacketOverrideHandler> _ExtendedHandlersHigh;
|
||||
|
||||
static OutgoingPacketOverrides()
|
||||
{
|
||||
_Handlers = new OutgoingPacketOverrideHandler[0x100];
|
||||
_ExtendedHandlersLow = new OutgoingPacketOverrideHandler[0x100];
|
||||
_ExtendedHandlersHigh = new Dictionary<int, OutgoingPacketOverrideHandler>();
|
||||
}
|
||||
|
||||
[CallPriority(CallPriority)]
|
||||
public static void Configure()
|
||||
{
|
||||
NetState.CreatedCallback += OnNetStateCreated;
|
||||
}
|
||||
|
||||
public static void Register(int packetID, bool compressed, OutgoingPacketOverrideHandler handler)
|
||||
{
|
||||
_Handlers[packetID] = handler;
|
||||
}
|
||||
|
||||
public static OutgoingPacketOverrideHandler GetHandler(int packetID)
|
||||
{
|
||||
return _Handlers[packetID];
|
||||
}
|
||||
|
||||
public static void RegisterExtended(int packetID, OutgoingPacketOverrideHandler handler)
|
||||
{
|
||||
if (packetID >= 0 && packetID < 0x100)
|
||||
{
|
||||
_ExtendedHandlersLow[packetID] = handler;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ExtendedHandlersHigh[packetID] = handler;
|
||||
}
|
||||
}
|
||||
|
||||
public static OutgoingPacketOverrideHandler GetExtendedHandler(int packetID)
|
||||
{
|
||||
if (packetID >= 0 && packetID < 0x100)
|
||||
{
|
||||
return _ExtendedHandlersLow[packetID];
|
||||
}
|
||||
else
|
||||
{
|
||||
OutgoingPacketOverrideHandler handler;
|
||||
_ExtendedHandlersHigh.TryGetValue(packetID, out handler);
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnNetStateCreated(NetState n)
|
||||
{
|
||||
n.PacketEncoder = new PacketOverrideRegistryEncoder(n.PacketEncoder);
|
||||
}
|
||||
|
||||
private class PacketOverrideRegistryEncoder : IPacketEncoder
|
||||
{
|
||||
private static readonly byte[] _UnpackBuffer = new byte[65535];
|
||||
private readonly IPacketEncoder _Successor;
|
||||
|
||||
public PacketOverrideRegistryEncoder(IPacketEncoder successor)
|
||||
{
|
||||
_Successor = successor;
|
||||
}
|
||||
|
||||
public void EncodeOutgoingPacket(NetState to, ref byte[] packetBuffer, ref int packetLength)
|
||||
{
|
||||
byte[] buffer;
|
||||
int bufferLength = 0;
|
||||
|
||||
byte packetID;
|
||||
|
||||
if (to.CompressionEnabled)
|
||||
{
|
||||
var firstByte = Decompressor.DecompressFirstByte(packetBuffer, packetLength);
|
||||
|
||||
if (!firstByte.HasValue)
|
||||
{
|
||||
Utility.PushColor(ConsoleColor.Yellow);
|
||||
Console.WriteLine("Outgoing Packet Override: Unable to decompress packet!");
|
||||
Utility.PopColor();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
packetID = firstByte.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
packetID = packetBuffer[0];
|
||||
}
|
||||
|
||||
OutgoingPacketOverrideHandler handler = GetHandler(packetID) ?? GetExtendedHandler(packetID);
|
||||
|
||||
if (handler != null)
|
||||
{
|
||||
if (to.CompressionEnabled)
|
||||
{
|
||||
Decompressor.DecompressAll(packetBuffer, packetLength, _UnpackBuffer, ref bufferLength);
|
||||
|
||||
buffer = new byte[bufferLength];
|
||||
Buffer.BlockCopy(_UnpackBuffer, 0, buffer, 0, bufferLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = packetBuffer;
|
||||
bufferLength = packetLength;
|
||||
}
|
||||
|
||||
handler(to, new PacketReader(buffer, packetLength, true), ref packetBuffer, ref packetLength);
|
||||
}
|
||||
|
||||
if (_Successor != null)
|
||||
{
|
||||
_Successor.EncodeOutgoingPacket(to, ref packetBuffer, ref packetLength);
|
||||
}
|
||||
}
|
||||
|
||||
public void DecodeIncomingPacket(NetState from, ref byte[] buffer, ref int length)
|
||||
{
|
||||
if (_Successor != null)
|
||||
{
|
||||
_Successor.DecodeIncomingPacket(from, ref buffer, ref length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
160
Server/Customs Framework/Utilities/Utilities.cs
Normal file
160
Server/Customs Framework/Utilities/Utilities.cs
Normal file
@@ -0,0 +1,160 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using Server;
|
||||
using Server.Items;
|
||||
#endregion
|
||||
|
||||
namespace CustomsFramework
|
||||
{
|
||||
public enum SaveStrategyTypes
|
||||
{
|
||||
StandardSaveStrategy,
|
||||
DualSaveStrategy,
|
||||
DynamicSaveStrategy,
|
||||
ParallelSaveStrategy
|
||||
}
|
||||
|
||||
public enum OldClientResponse
|
||||
{
|
||||
Ignore,
|
||||
Warn,
|
||||
Annoy,
|
||||
LenientKick,
|
||||
Kick
|
||||
}
|
||||
|
||||
public static class Utilities
|
||||
{
|
||||
public static int WriteVersion(this GenericWriter writer, int version)
|
||||
{
|
||||
writer.Write(version);
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
public static int ReaderVersion(this GenericReader reader, int version)
|
||||
{
|
||||
return reader.ReadInt();
|
||||
}
|
||||
|
||||
public static void CheckFileStructure(string path)
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Make this factor-in GeneralSettings AccessLevel options?
|
||||
public static bool IsPlayer(this Mobile from)
|
||||
{
|
||||
return from.AccessLevel <= AccessLevel.VIP;
|
||||
}
|
||||
|
||||
// TODO: Make this factor-in GeneralSettings AccessLevel options?
|
||||
public static bool IsStaff(this Mobile from)
|
||||
{
|
||||
return from.AccessLevel >= AccessLevel.Counselor;
|
||||
}
|
||||
|
||||
// TODO: Make this factor-in GeneralSettings AccessLevel options?
|
||||
public static bool IsOwner(this Mobile from)
|
||||
{
|
||||
return from.AccessLevel >= AccessLevel.CoOwner;
|
||||
}
|
||||
|
||||
public static bool IsDigit(this string text)
|
||||
{
|
||||
int value;
|
||||
return IsDigit(text, out value);
|
||||
}
|
||||
|
||||
public static bool IsDigit(this string text, out int value)
|
||||
{
|
||||
return Int32.TryParse(text, out value);
|
||||
}
|
||||
|
||||
public static SaveStrategy GetSaveStrategy(this SaveStrategyTypes saveStrategyTypes)
|
||||
{
|
||||
switch (saveStrategyTypes)
|
||||
{
|
||||
case SaveStrategyTypes.StandardSaveStrategy:
|
||||
return new StandardSaveStrategy();
|
||||
case SaveStrategyTypes.DualSaveStrategy:
|
||||
return new DualSaveStrategy();
|
||||
case SaveStrategyTypes.DynamicSaveStrategy:
|
||||
return new DynamicSaveStrategy();
|
||||
case SaveStrategyTypes.ParallelSaveStrategy:
|
||||
return new ParallelSaveStrategy(Core.ProcessorCount);
|
||||
default:
|
||||
return new StandardSaveStrategy();
|
||||
}
|
||||
}
|
||||
|
||||
public static SaveStrategyTypes GetSaveType(this SaveStrategy saveStrategy)
|
||||
{
|
||||
if (saveStrategy is DualSaveStrategy)
|
||||
{
|
||||
return SaveStrategyTypes.StandardSaveStrategy;
|
||||
}
|
||||
|
||||
if (saveStrategy is StandardSaveStrategy)
|
||||
{
|
||||
return SaveStrategyTypes.StandardSaveStrategy;
|
||||
}
|
||||
|
||||
if (saveStrategy is DynamicSaveStrategy)
|
||||
{
|
||||
return SaveStrategyTypes.DynamicSaveStrategy;
|
||||
}
|
||||
|
||||
if (saveStrategy is ParallelSaveStrategy)
|
||||
{
|
||||
return SaveStrategyTypes.ParallelSaveStrategy;
|
||||
}
|
||||
|
||||
return SaveStrategyTypes.StandardSaveStrategy;
|
||||
}
|
||||
|
||||
public static void PlaceItemIn(this Container container, Item item, Point3D location)
|
||||
{
|
||||
container.AddItem(item);
|
||||
item.Location = location;
|
||||
}
|
||||
|
||||
public static void PlaceItemIn(this Container container, Item item, int x = 0, int y = 0, int z = 0)
|
||||
{
|
||||
PlaceItemIn(container, item, new Point3D(x, y, z));
|
||||
}
|
||||
|
||||
public static Item BlessItem(this Item item)
|
||||
{
|
||||
item.LootType = LootType.Blessed;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
public static Item MakeNewbie(this Item item)
|
||||
{
|
||||
if (!Core.AOS)
|
||||
{
|
||||
item.LootType = LootType.Newbied;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
public static void DumpToConsole(params object[] elements)
|
||||
{
|
||||
Console.WriteLine();
|
||||
|
||||
foreach (var element in elements)
|
||||
{
|
||||
Console.WriteLine(ObjectDumper.Dump(element));
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
88
Server/Diagnostics/BaseProfile.cs
Normal file
88
Server/Diagnostics/BaseProfile.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
#endregion
|
||||
|
||||
namespace Server.Diagnostics
|
||||
{
|
||||
public abstract class BaseProfile
|
||||
{
|
||||
public static void WriteAll<T>(TextWriter op, IEnumerable<T> profiles) where T : BaseProfile
|
||||
{
|
||||
var list = new List<T>(profiles);
|
||||
|
||||
list.Sort(delegate(T a, T b) { return -a.TotalTime.CompareTo(b.TotalTime); });
|
||||
|
||||
foreach (T prof in list)
|
||||
{
|
||||
prof.WriteTo(op);
|
||||
op.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
private readonly string _name;
|
||||
|
||||
private long _count;
|
||||
|
||||
private TimeSpan _totalTime;
|
||||
private TimeSpan _peakTime;
|
||||
|
||||
private readonly Stopwatch _stopwatch;
|
||||
|
||||
public string Name { get { return _name; } }
|
||||
|
||||
public long Count { get { return _count; } }
|
||||
|
||||
public TimeSpan AverageTime { get { return TimeSpan.FromTicks(_totalTime.Ticks / Math.Max(1, _count)); } }
|
||||
|
||||
public TimeSpan PeakTime { get { return _peakTime; } }
|
||||
|
||||
public TimeSpan TotalTime { get { return _totalTime; } }
|
||||
|
||||
protected BaseProfile(string name)
|
||||
{
|
||||
_name = name;
|
||||
|
||||
_stopwatch = new Stopwatch();
|
||||
}
|
||||
|
||||
public virtual void Start()
|
||||
{
|
||||
if (_stopwatch.IsRunning)
|
||||
{
|
||||
_stopwatch.Reset();
|
||||
}
|
||||
|
||||
_stopwatch.Start();
|
||||
}
|
||||
|
||||
public virtual void Finish()
|
||||
{
|
||||
TimeSpan elapsed = _stopwatch.Elapsed;
|
||||
|
||||
_totalTime += elapsed;
|
||||
|
||||
if (elapsed > _peakTime)
|
||||
{
|
||||
_peakTime = elapsed;
|
||||
}
|
||||
|
||||
_count++;
|
||||
|
||||
_stopwatch.Reset();
|
||||
}
|
||||
|
||||
public virtual void WriteTo(TextWriter op)
|
||||
{
|
||||
op.Write(
|
||||
"{0,-100} {1,12:N0} {2,12:F5} {3,-12:F5} {4,12:F5}",
|
||||
Name,
|
||||
Count,
|
||||
AverageTime.TotalSeconds,
|
||||
PeakTime.TotalSeconds,
|
||||
TotalTime.TotalSeconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
35
Server/Diagnostics/GumpProfile.cs
Normal file
35
Server/Diagnostics/GumpProfile.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#endregion
|
||||
|
||||
namespace Server.Diagnostics
|
||||
{
|
||||
public class GumpProfile : BaseProfile
|
||||
{
|
||||
private static readonly Dictionary<Type, GumpProfile> _profiles = new Dictionary<Type, GumpProfile>();
|
||||
|
||||
public static IEnumerable<GumpProfile> Profiles { get { return _profiles.Values; } }
|
||||
|
||||
public static GumpProfile Acquire(Type type)
|
||||
{
|
||||
if (!Core.Profiling)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
GumpProfile prof;
|
||||
|
||||
if (!_profiles.TryGetValue(type, out prof))
|
||||
{
|
||||
_profiles.Add(type, prof = new GumpProfile(type));
|
||||
}
|
||||
|
||||
return prof;
|
||||
}
|
||||
|
||||
public GumpProfile(Type type)
|
||||
: base(type.FullName)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
99
Server/Diagnostics/PacketProfile.cs
Normal file
99
Server/Diagnostics/PacketProfile.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
#endregion
|
||||
|
||||
namespace Server.Diagnostics
|
||||
{
|
||||
public abstract class BasePacketProfile : BaseProfile
|
||||
{
|
||||
private long _totalLength;
|
||||
|
||||
public long TotalLength { get { return _totalLength; } }
|
||||
|
||||
public double AverageLength { get { return (double)_totalLength / Math.Max(1, Count); } }
|
||||
|
||||
protected BasePacketProfile(string name)
|
||||
: base(name)
|
||||
{ }
|
||||
|
||||
public void Finish(int length)
|
||||
{
|
||||
Finish();
|
||||
|
||||
_totalLength += length;
|
||||
}
|
||||
|
||||
public override void WriteTo(TextWriter op)
|
||||
{
|
||||
base.WriteTo(op);
|
||||
|
||||
op.Write("\t{0,12:F2} {1,-12:N0}", AverageLength, TotalLength);
|
||||
}
|
||||
}
|
||||
|
||||
public class PacketSendProfile : BasePacketProfile
|
||||
{
|
||||
private static readonly Dictionary<Type, PacketSendProfile> _profiles = new Dictionary<Type, PacketSendProfile>();
|
||||
|
||||
public static IEnumerable<PacketSendProfile> Profiles { get { return _profiles.Values; } }
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
public static PacketSendProfile Acquire(Type type)
|
||||
{
|
||||
PacketSendProfile prof;
|
||||
|
||||
if (!_profiles.TryGetValue(type, out prof))
|
||||
{
|
||||
_profiles.Add(type, prof = new PacketSendProfile(type));
|
||||
}
|
||||
|
||||
return prof;
|
||||
}
|
||||
|
||||
private long _created;
|
||||
|
||||
public void Increment()
|
||||
{
|
||||
Interlocked.Increment(ref _created);
|
||||
}
|
||||
|
||||
public PacketSendProfile(Type type)
|
||||
: base(type.FullName)
|
||||
{ }
|
||||
|
||||
public override void WriteTo(TextWriter op)
|
||||
{
|
||||
base.WriteTo(op);
|
||||
|
||||
op.Write("\t{0,12:N0}", _created);
|
||||
}
|
||||
}
|
||||
|
||||
public class PacketReceiveProfile : BasePacketProfile
|
||||
{
|
||||
private static readonly Dictionary<int, PacketReceiveProfile> _profiles = new Dictionary<int, PacketReceiveProfile>();
|
||||
|
||||
public static IEnumerable<PacketReceiveProfile> Profiles { get { return _profiles.Values; } }
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
public static PacketReceiveProfile Acquire(int packetId)
|
||||
{
|
||||
PacketReceiveProfile prof;
|
||||
|
||||
if (!_profiles.TryGetValue(packetId, out prof))
|
||||
{
|
||||
_profiles.Add(packetId, prof = new PacketReceiveProfile(packetId));
|
||||
}
|
||||
|
||||
return prof;
|
||||
}
|
||||
|
||||
public PacketReceiveProfile(int packetId)
|
||||
: base(String.Format("0x{0:X2}", packetId))
|
||||
{ }
|
||||
}
|
||||
}
|
||||
35
Server/Diagnostics/TargetProfile.cs
Normal file
35
Server/Diagnostics/TargetProfile.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#endregion
|
||||
|
||||
namespace Server.Diagnostics
|
||||
{
|
||||
public class TargetProfile : BaseProfile
|
||||
{
|
||||
private static readonly Dictionary<Type, TargetProfile> _profiles = new Dictionary<Type, TargetProfile>();
|
||||
|
||||
public static IEnumerable<TargetProfile> Profiles { get { return _profiles.Values; } }
|
||||
|
||||
public static TargetProfile Acquire(Type type)
|
||||
{
|
||||
if (!Core.Profiling)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
TargetProfile prof;
|
||||
|
||||
if (!_profiles.TryGetValue(type, out prof))
|
||||
{
|
||||
_profiles.Add(type, prof = new TargetProfile(type));
|
||||
}
|
||||
|
||||
return prof;
|
||||
}
|
||||
|
||||
public TargetProfile(Type type)
|
||||
: base(type.FullName)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
50
Server/Diagnostics/TimerProfile.cs
Normal file
50
Server/Diagnostics/TimerProfile.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
#region References
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
#endregion
|
||||
|
||||
namespace Server.Diagnostics
|
||||
{
|
||||
public class TimerProfile : BaseProfile
|
||||
{
|
||||
private static readonly Dictionary<string, TimerProfile> _profiles = new Dictionary<string, TimerProfile>();
|
||||
|
||||
public static IEnumerable<TimerProfile> Profiles { get { return _profiles.Values; } }
|
||||
|
||||
public static TimerProfile Acquire(string name)
|
||||
{
|
||||
if (!Core.Profiling)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
TimerProfile prof;
|
||||
|
||||
if (!_profiles.TryGetValue(name, out prof))
|
||||
{
|
||||
_profiles.Add(name, prof = new TimerProfile(name));
|
||||
}
|
||||
|
||||
return prof;
|
||||
}
|
||||
|
||||
private long _created, _started, _stopped;
|
||||
|
||||
public long Created { get { return _created; } set { _created = value; } }
|
||||
|
||||
public long Started { get { return _started; } set { _started = value; } }
|
||||
|
||||
public long Stopped { get { return _stopped; } set { _stopped = value; } }
|
||||
|
||||
public TimerProfile(string name)
|
||||
: base(name)
|
||||
{ }
|
||||
|
||||
public override void WriteTo(TextWriter op)
|
||||
{
|
||||
base.WriteTo(op);
|
||||
|
||||
op.Write("\t{0,12:N0} {1,12:N0} {2,-12:N0}", _created, _started, _stopped);
|
||||
}
|
||||
}
|
||||
}
|
||||
563
Server/Effects.cs
Normal file
563
Server/Effects.cs
Normal file
@@ -0,0 +1,563 @@
|
||||
#region References
|
||||
using Server.Network;
|
||||
#endregion
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public enum EffectLayer
|
||||
{
|
||||
Head = 0,
|
||||
RightHand = 1,
|
||||
LeftHand = 2,
|
||||
Waist = 3,
|
||||
LeftFoot = 4,
|
||||
RightFoot = 5,
|
||||
CenterFeet = 7
|
||||
}
|
||||
|
||||
public enum ParticleSupportType
|
||||
{
|
||||
Full,
|
||||
Detect,
|
||||
None
|
||||
}
|
||||
|
||||
public static class Effects
|
||||
{
|
||||
private static ParticleSupportType m_ParticleSupportType = ParticleSupportType.Detect;
|
||||
|
||||
public static ParticleSupportType ParticleSupportType { get { return m_ParticleSupportType; } set { m_ParticleSupportType = value; } }
|
||||
|
||||
public static bool SendParticlesTo(NetState state)
|
||||
{
|
||||
return (m_ParticleSupportType == ParticleSupportType.Full ||
|
||||
(m_ParticleSupportType == ParticleSupportType.Detect && (state.IsUOTDClient || state.IsEnhancedClient)));
|
||||
}
|
||||
|
||||
public static void PlayExplodeSound(IPoint3D p, Map map)
|
||||
{
|
||||
PlaySound(p, map, Utility.RandomList(283, 284, 285, 286, 519, 773, 774, 775, 776, 777, 1231));
|
||||
}
|
||||
|
||||
public static void PlaySound(IPoint3D p, Map map, int soundID)
|
||||
{
|
||||
if (soundID <= -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (map != null)
|
||||
{
|
||||
Packet playSound = null;
|
||||
|
||||
var eable = map.GetClientsInRange(new Point3D(p));
|
||||
|
||||
foreach (NetState state in eable)
|
||||
{
|
||||
state.Mobile.ProcessDelta();
|
||||
|
||||
if (playSound == null)
|
||||
{
|
||||
playSound = Packet.Acquire(new PlaySound(soundID, p));
|
||||
}
|
||||
|
||||
state.Send(playSound);
|
||||
}
|
||||
|
||||
Packet.Release(playSound);
|
||||
|
||||
eable.Free();
|
||||
}
|
||||
}
|
||||
|
||||
public static void SendBoltEffect(IEntity e)
|
||||
{
|
||||
SendBoltEffect(e, true, 0);
|
||||
}
|
||||
|
||||
public static void SendBoltEffect(IEntity e, bool sound)
|
||||
{
|
||||
SendBoltEffect(e, sound, 0);
|
||||
}
|
||||
|
||||
public static void SendBoltEffect(IEntity e, bool sound, int hue, bool delay)
|
||||
{
|
||||
if (delay)
|
||||
{
|
||||
Timer.DelayCall(() => SendBoltEffect(e, sound, hue));
|
||||
}
|
||||
else
|
||||
{
|
||||
SendBoltEffect(e, sound, hue);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SendBoltEffect(IEntity e, bool sound, int hue)
|
||||
{
|
||||
Map map = e.Map;
|
||||
|
||||
if (map == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
e.ProcessDelta();
|
||||
|
||||
Packet preEffect = null, postEffect = null, boltEffect = null, playSound = null;
|
||||
|
||||
var eable = map.GetClientsInRange(e.Location);
|
||||
|
||||
foreach (NetState state in eable)
|
||||
{
|
||||
if (state.Mobile.CanSee(e))
|
||||
{
|
||||
bool sendParticles = SendParticlesTo(state);
|
||||
|
||||
if (sendParticles)
|
||||
{
|
||||
if (preEffect == null)
|
||||
{
|
||||
preEffect = Packet.Acquire(new TargetParticleEffect(e, 0, 10, 5, 0, 0, 5031, 3, 0));
|
||||
}
|
||||
|
||||
state.Send(preEffect);
|
||||
}
|
||||
|
||||
if (boltEffect == null)
|
||||
{
|
||||
if (Core.SA && hue == 0)
|
||||
{
|
||||
boltEffect = Packet.Acquire(new BoltEffectNew(e));
|
||||
}
|
||||
else
|
||||
{
|
||||
boltEffect = Packet.Acquire(new BoltEffect(e, hue));
|
||||
}
|
||||
}
|
||||
|
||||
state.Send(boltEffect);
|
||||
|
||||
if (sendParticles)
|
||||
{
|
||||
if (postEffect == null)
|
||||
{
|
||||
postEffect = Packet.Acquire(new GraphicalEffect(EffectType.FixedFrom, e.Serial, Serial.Zero, 0, e.Location, e.Location, 0, 0, false, 0));
|
||||
}
|
||||
|
||||
state.Send(postEffect);
|
||||
}
|
||||
|
||||
if (sound)
|
||||
{
|
||||
if (playSound == null)
|
||||
{
|
||||
playSound = Packet.Acquire(new PlaySound(0x29, e));
|
||||
}
|
||||
|
||||
state.Send(playSound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Packet.Release(preEffect);
|
||||
Packet.Release(postEffect);
|
||||
Packet.Release(boltEffect);
|
||||
Packet.Release(playSound);
|
||||
|
||||
eable.Free();
|
||||
}
|
||||
|
||||
public static void SendLocationEffect(IPoint3D p, Map map, int itemID, int duration)
|
||||
{
|
||||
SendLocationEffect(p, map, itemID, duration, 10, 0, 0);
|
||||
}
|
||||
|
||||
public static void SendLocationEffect(IPoint3D p, Map map, int itemID, int duration, int speed)
|
||||
{
|
||||
SendLocationEffect(p, map, itemID, duration, speed, 0, 0);
|
||||
}
|
||||
|
||||
public static void SendLocationEffect(IPoint3D p, Map map, int itemID, int duration, int hue, int renderMode)
|
||||
{
|
||||
SendLocationEffect(p, map, itemID, duration, 10, hue, renderMode);
|
||||
}
|
||||
|
||||
public static void SendLocationEffect(
|
||||
IPoint3D p, Map map, int itemID, int duration, int speed, int hue, int renderMode)
|
||||
{
|
||||
SendPacket(p, map, new LocationEffect(p, itemID, speed, duration, hue, renderMode));
|
||||
}
|
||||
|
||||
public static void SendLocationParticles(IEntity e, int itemID, int speed, int duration, int effect)
|
||||
{
|
||||
SendLocationParticles(e, itemID, speed, duration, 0, 0, effect, 0);
|
||||
}
|
||||
|
||||
public static void SendLocationParticles(IEntity e, int itemID, int speed, int duration, int effect, int unknown)
|
||||
{
|
||||
SendLocationParticles(e, itemID, speed, duration, 0, 0, effect, unknown);
|
||||
}
|
||||
|
||||
public static void SendLocationParticles(
|
||||
IEntity e, int itemID, int speed, int duration, int hue, int renderMode, int effect, int unknown)
|
||||
{
|
||||
Map map = e.Map;
|
||||
|
||||
if (map != null)
|
||||
{
|
||||
Packet particles = null, regular = null;
|
||||
|
||||
var eable = map.GetClientsInRange(e.Location);
|
||||
|
||||
foreach (NetState state in eable)
|
||||
{
|
||||
state.Mobile.ProcessDelta();
|
||||
|
||||
if (SendParticlesTo(state))
|
||||
{
|
||||
if (particles == null)
|
||||
{
|
||||
particles =
|
||||
Packet.Acquire(new LocationParticleEffect(e, itemID, speed, duration, hue, renderMode, effect, unknown));
|
||||
}
|
||||
|
||||
state.Send(particles);
|
||||
}
|
||||
else if (itemID != 0)
|
||||
{
|
||||
if (regular == null)
|
||||
{
|
||||
regular = Packet.Acquire(new LocationEffect(e, itemID, speed, duration, hue, renderMode));
|
||||
}
|
||||
|
||||
state.Send(regular);
|
||||
}
|
||||
}
|
||||
|
||||
Packet.Release(particles);
|
||||
Packet.Release(regular);
|
||||
|
||||
eable.Free();
|
||||
}
|
||||
//SendPacket( e.Location, e.Map, new LocationParticleEffect( e, itemID, speed, duration, hue, renderMode, effect, unknown ) );
|
||||
}
|
||||
|
||||
public static void SendTargetEffect(IEntity target, int itemID, int duration)
|
||||
{
|
||||
SendTargetEffect(target, itemID, duration, 0, 0);
|
||||
}
|
||||
|
||||
public static void SendTargetEffect(IEntity target, int itemID, int speed, int duration)
|
||||
{
|
||||
SendTargetEffect(target, itemID, speed, duration, 0, 0);
|
||||
}
|
||||
|
||||
public static void SendTargetEffect(IEntity target, int itemID, int duration, int hue, int renderMode)
|
||||
{
|
||||
SendTargetEffect(target, itemID, 10, duration, hue, renderMode);
|
||||
}
|
||||
|
||||
public static void SendTargetEffect(IEntity target, int itemID, int speed, int duration, int hue, int renderMode)
|
||||
{
|
||||
if (target is Mobile)
|
||||
{
|
||||
((Mobile)target).ProcessDelta();
|
||||
}
|
||||
|
||||
SendPacket(target.Location, target.Map, new TargetEffect(target, itemID, speed, duration, hue, renderMode));
|
||||
}
|
||||
|
||||
public static void SendTargetParticles(
|
||||
IEntity target, int itemID, int speed, int duration, int effect, EffectLayer layer)
|
||||
{
|
||||
SendTargetParticles(target, itemID, speed, duration, 0, 0, effect, layer, 0);
|
||||
}
|
||||
|
||||
public static void SendTargetParticles(
|
||||
IEntity target, int itemID, int speed, int duration, int effect, EffectLayer layer, int unknown)
|
||||
{
|
||||
SendTargetParticles(target, itemID, speed, duration, 0, 0, effect, layer, unknown);
|
||||
}
|
||||
|
||||
public static void SendTargetParticles(
|
||||
IEntity target,
|
||||
int itemID,
|
||||
int speed,
|
||||
int duration,
|
||||
int hue,
|
||||
int renderMode,
|
||||
int effect,
|
||||
EffectLayer layer,
|
||||
int unknown)
|
||||
{
|
||||
if (target is Mobile)
|
||||
{
|
||||
((Mobile)target).ProcessDelta();
|
||||
}
|
||||
|
||||
Map map = target.Map;
|
||||
|
||||
if (map != null)
|
||||
{
|
||||
Packet particles = null, regular = null;
|
||||
|
||||
var eable = map.GetClientsInRange(target.Location);
|
||||
|
||||
foreach (NetState state in eable)
|
||||
{
|
||||
state.Mobile.ProcessDelta();
|
||||
|
||||
if (SendParticlesTo(state))
|
||||
{
|
||||
if (particles == null)
|
||||
{
|
||||
particles =
|
||||
Packet.Acquire(
|
||||
new TargetParticleEffect(target, itemID, speed, duration, hue, renderMode, effect, (int)layer, unknown));
|
||||
}
|
||||
|
||||
state.Send(particles);
|
||||
}
|
||||
else if (itemID != 0)
|
||||
{
|
||||
if (regular == null)
|
||||
{
|
||||
regular = Packet.Acquire(new TargetEffect(target, itemID, speed, duration, hue, renderMode));
|
||||
}
|
||||
|
||||
state.Send(regular);
|
||||
}
|
||||
}
|
||||
|
||||
Packet.Release(particles);
|
||||
Packet.Release(regular);
|
||||
|
||||
eable.Free();
|
||||
}
|
||||
|
||||
//SendPacket( target.Location, target.Map, new TargetParticleEffect( target, itemID, speed, duration, hue, renderMode, effect, (int)layer, unknown ) );
|
||||
}
|
||||
|
||||
public static void SendMovingEffect(
|
||||
IEntity from, IEntity to, int itemID, int speed, int duration, bool fixedDirection, bool explodes)
|
||||
{
|
||||
SendMovingEffect(from, to, itemID, speed, duration, fixedDirection, explodes, 0, 0);
|
||||
}
|
||||
|
||||
public static void SendMovingEffect(
|
||||
IEntity from,
|
||||
IEntity to,
|
||||
int itemID,
|
||||
int speed,
|
||||
int duration,
|
||||
bool fixedDirection,
|
||||
bool explodes,
|
||||
int hue,
|
||||
int renderMode)
|
||||
{
|
||||
if (from is Mobile)
|
||||
{
|
||||
((Mobile)from).ProcessDelta();
|
||||
}
|
||||
|
||||
if (to is Mobile)
|
||||
{
|
||||
((Mobile)to).ProcessDelta();
|
||||
}
|
||||
|
||||
SendPacket(
|
||||
from.Location,
|
||||
from.Map,
|
||||
new MovingEffect(from, to, itemID, speed, duration, fixedDirection, explodes, hue, renderMode));
|
||||
}
|
||||
|
||||
public static void SendMovingParticles(
|
||||
IEntity from,
|
||||
IEntity to,
|
||||
int itemID,
|
||||
int speed,
|
||||
int duration,
|
||||
bool fixedDirection,
|
||||
bool explodes,
|
||||
int effect,
|
||||
int explodeEffect,
|
||||
int explodeSound)
|
||||
{
|
||||
SendMovingParticles(
|
||||
from, to, itemID, speed, duration, fixedDirection, explodes, 0, 0, effect, explodeEffect, explodeSound, 0);
|
||||
}
|
||||
|
||||
public static void SendMovingParticles(
|
||||
IEntity from,
|
||||
IEntity to,
|
||||
int itemID,
|
||||
int speed,
|
||||
int duration,
|
||||
bool fixedDirection,
|
||||
bool explodes,
|
||||
int effect,
|
||||
int explodeEffect,
|
||||
int explodeSound,
|
||||
int unknown)
|
||||
{
|
||||
SendMovingParticles(
|
||||
from, to, itemID, speed, duration, fixedDirection, explodes, 0, 0, effect, explodeEffect, explodeSound, unknown);
|
||||
}
|
||||
|
||||
public static void SendMovingParticles(
|
||||
IEntity from,
|
||||
IEntity to,
|
||||
int itemID,
|
||||
int speed,
|
||||
int duration,
|
||||
bool fixedDirection,
|
||||
bool explodes,
|
||||
int hue,
|
||||
int renderMode,
|
||||
int effect,
|
||||
int explodeEffect,
|
||||
int explodeSound,
|
||||
int unknown)
|
||||
{
|
||||
SendMovingParticles(
|
||||
from,
|
||||
to,
|
||||
itemID,
|
||||
speed,
|
||||
duration,
|
||||
fixedDirection,
|
||||
explodes,
|
||||
hue,
|
||||
renderMode,
|
||||
effect,
|
||||
explodeEffect,
|
||||
explodeSound,
|
||||
(EffectLayer)255,
|
||||
unknown);
|
||||
}
|
||||
|
||||
public static void SendMovingParticles(
|
||||
IEntity from,
|
||||
IEntity to,
|
||||
int itemID,
|
||||
int speed,
|
||||
int duration,
|
||||
bool fixedDirection,
|
||||
bool explodes,
|
||||
int hue,
|
||||
int renderMode,
|
||||
int effect,
|
||||
int explodeEffect,
|
||||
int explodeSound,
|
||||
EffectLayer layer,
|
||||
int unknown)
|
||||
{
|
||||
if (from is Mobile)
|
||||
{
|
||||
((Mobile)from).ProcessDelta();
|
||||
}
|
||||
|
||||
if (to is Mobile)
|
||||
{
|
||||
((Mobile)to).ProcessDelta();
|
||||
}
|
||||
|
||||
Map map = from.Map;
|
||||
|
||||
if (map != null)
|
||||
{
|
||||
Packet particles = null, regular = null;
|
||||
|
||||
var eable = map.GetClientsInRange(from.Location);
|
||||
|
||||
foreach (NetState state in eable)
|
||||
{
|
||||
state.Mobile.ProcessDelta();
|
||||
|
||||
if (SendParticlesTo(state))
|
||||
{
|
||||
if (particles == null)
|
||||
{
|
||||
particles =
|
||||
Packet.Acquire(
|
||||
new MovingParticleEffect(
|
||||
from,
|
||||
to,
|
||||
itemID,
|
||||
speed,
|
||||
duration,
|
||||
fixedDirection,
|
||||
explodes,
|
||||
hue,
|
||||
renderMode,
|
||||
effect,
|
||||
explodeEffect,
|
||||
explodeSound,
|
||||
layer,
|
||||
unknown));
|
||||
}
|
||||
|
||||
state.Send(particles);
|
||||
}
|
||||
else if (itemID > 1)
|
||||
{
|
||||
if (regular == null)
|
||||
{
|
||||
regular =
|
||||
Packet.Acquire(new MovingEffect(from, to, itemID, speed, duration, fixedDirection, explodes, hue, renderMode));
|
||||
}
|
||||
|
||||
state.Send(regular);
|
||||
}
|
||||
}
|
||||
|
||||
Packet.Release(particles);
|
||||
Packet.Release(regular);
|
||||
|
||||
eable.Free();
|
||||
}
|
||||
|
||||
//SendPacket( from.Location, from.Map, new MovingParticleEffect( from, to, itemID, speed, duration, fixedDirection, explodes, hue, renderMode, effect, explodeEffect, explodeSound, unknown ) );
|
||||
}
|
||||
|
||||
public static void SendPacket(Point3D origin, Map map, Packet p)
|
||||
{
|
||||
if (map != null)
|
||||
{
|
||||
var eable = map.GetClientsInRange(origin);
|
||||
|
||||
p.Acquire();
|
||||
|
||||
foreach (NetState state in eable)
|
||||
{
|
||||
state.Mobile.ProcessDelta();
|
||||
state.Send(p);
|
||||
}
|
||||
|
||||
p.Release();
|
||||
|
||||
eable.Free();
|
||||
}
|
||||
}
|
||||
|
||||
public static void SendPacket(IPoint3D origin, Map map, Packet p)
|
||||
{
|
||||
if (map != null)
|
||||
{
|
||||
var eable = map.GetClientsInRange(new Point3D(origin));
|
||||
|
||||
p.Acquire();
|
||||
|
||||
foreach (NetState state in eable)
|
||||
{
|
||||
state.Mobile.ProcessDelta();
|
||||
state.Send(p);
|
||||
}
|
||||
|
||||
p.Release();
|
||||
|
||||
eable.Free();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
50
Server/EventLog.cs
Normal file
50
Server/EventLog.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
using DiagELog = System.Diagnostics.EventLog;
|
||||
#endregion
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public static class EventLog
|
||||
{
|
||||
static EventLog()
|
||||
{
|
||||
if (!DiagELog.SourceExists("ServUO"))
|
||||
{
|
||||
DiagELog.CreateEventSource("ServUO", "Application");
|
||||
}
|
||||
}
|
||||
|
||||
public static void Error(int eventID, string text)
|
||||
{
|
||||
DiagELog.WriteEntry("ServUO", text, EventLogEntryType.Error, eventID);
|
||||
}
|
||||
|
||||
public static void Error(int eventID, string format, params object[] args)
|
||||
{
|
||||
Error(eventID, String.Format(format, args));
|
||||
}
|
||||
|
||||
public static void Warning(int eventID, string text)
|
||||
{
|
||||
DiagELog.WriteEntry("ServUO", text, EventLogEntryType.Warning, eventID);
|
||||
}
|
||||
|
||||
public static void Warning(int eventID, string format, params object[] args)
|
||||
{
|
||||
Warning(eventID, String.Format(format, args));
|
||||
}
|
||||
|
||||
public static void Inform(int eventID, string text)
|
||||
{
|
||||
DiagELog.WriteEntry("ServUO", text, EventLogEntryType.Information, eventID);
|
||||
}
|
||||
|
||||
public static void Inform(int eventID, string format, params object[] args)
|
||||
{
|
||||
Inform(eventID, String.Format(format, args));
|
||||
}
|
||||
}
|
||||
}
|
||||
2601
Server/EventSink.cs
Normal file
2601
Server/EventSink.cs
Normal file
File diff suppressed because it is too large
Load Diff
358
Server/ExpansionInfo.cs
Normal file
358
Server/ExpansionInfo.cs
Normal file
@@ -0,0 +1,358 @@
|
||||
#region References
|
||||
using System;
|
||||
#endregion
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public enum Expansion
|
||||
{
|
||||
None = 0,
|
||||
T2A,
|
||||
UOR,
|
||||
UOTD,
|
||||
LBR,
|
||||
AOS,
|
||||
SE,
|
||||
ML,
|
||||
SA,
|
||||
HS,
|
||||
TOL,
|
||||
EJ
|
||||
}
|
||||
|
||||
public enum ThemePack
|
||||
{
|
||||
None = 0,
|
||||
Kings,
|
||||
Rustic,
|
||||
Gothic
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ClientFlags
|
||||
{
|
||||
None = 0x00000000,
|
||||
Felucca = 0x00000001,
|
||||
Trammel = 0x00000002,
|
||||
Ilshenar = 0x00000004,
|
||||
Malas = 0x00000008,
|
||||
Tokuno = 0x00000010,
|
||||
TerMur = 0x00000020,
|
||||
Unk1 = 0x00000040,
|
||||
Unk2 = 0x00000080,
|
||||
UOTD = 0x00000100
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum FeatureFlags
|
||||
{
|
||||
None = 0x00000000,
|
||||
T2A = 0x00000001,
|
||||
UOR = 0x00000002,
|
||||
UOTD = 0x00000004,
|
||||
LBR = 0x00000008,
|
||||
AOS = 0x00000010,
|
||||
SixthCharacterSlot = 0x00000020,
|
||||
SE = 0x00000040,
|
||||
ML = 0x00000080,
|
||||
EigthAge = 0x00000100,
|
||||
NinthAge = 0x00000200, /* Crystal/Shadow Custom House Tiles */
|
||||
TenthAge = 0x00000400,
|
||||
IncreasedStorage = 0x00000800, /* Increased Housing/Bank Storage */
|
||||
SeventhCharacterSlot = 0x00001000,
|
||||
RoleplayFaces = 0x00002000,
|
||||
TrialAccount = 0x00004000,
|
||||
LiveAccount = 0x00008000,
|
||||
SA = 0x00010000,
|
||||
HS = 0x00020000,
|
||||
Gothic = 0x00040000,
|
||||
Rustic = 0x00080000,
|
||||
Jungle = 0x00100000,
|
||||
Shadowguard = 0x00200000,
|
||||
TOL = 0x00400000,
|
||||
EJ = 0x00800000, // TODO: Verify value
|
||||
|
||||
ExpansionNone = None,
|
||||
ExpansionT2A = T2A,
|
||||
ExpansionUOR = ExpansionT2A | UOR,
|
||||
ExpansionUOTD = ExpansionUOR | UOTD,
|
||||
ExpansionLBR = ExpansionUOTD | LBR,
|
||||
ExpansionAOS = ExpansionLBR | AOS | LiveAccount,
|
||||
ExpansionSE = ExpansionAOS | SE,
|
||||
ExpansionML = ExpansionSE | ML | NinthAge,
|
||||
ExpansionSA = ExpansionML | SA | Gothic | Rustic,
|
||||
ExpansionHS = ExpansionSA | HS,
|
||||
ExpansionTOL = ExpansionHS | TOL | Jungle | Shadowguard,
|
||||
ExpansionEJ = ExpansionTOL | EJ
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum CharacterListFlags
|
||||
{
|
||||
None = 0x00000000,
|
||||
Unk1 = 0x00000001,
|
||||
OverwriteConfigButton = 0x00000002,
|
||||
OneCharacterSlot = 0x00000004,
|
||||
ContextMenus = 0x00000008,
|
||||
SlotLimit = 0x00000010,
|
||||
AOS = 0x00000020,
|
||||
SixthCharacterSlot = 0x00000040,
|
||||
SE = 0x00000080,
|
||||
ML = 0x00000100,
|
||||
Unk2 = 0x00000200,
|
||||
UO3DClientType = 0x00000400,
|
||||
KR = 0x00000600, // uo:kr support flags
|
||||
Unk3 = 0x00000800,
|
||||
SeventhCharacterSlot = 0x00001000,
|
||||
Unk4 = 0x00002000,
|
||||
NewMovementSystem = 0x00004000,
|
||||
NewFeluccaAreas = 0x00008000,
|
||||
|
||||
ExpansionNone = ContextMenus, //
|
||||
ExpansionT2A = ContextMenus, //
|
||||
ExpansionUOR = ContextMenus, // None
|
||||
ExpansionUOTD = ContextMenus, //
|
||||
ExpansionLBR = ContextMenus, //
|
||||
ExpansionAOS = ContextMenus | AOS,
|
||||
ExpansionSE = ExpansionAOS | SE,
|
||||
ExpansionML = ExpansionSE | ML,
|
||||
ExpansionSA = ExpansionML,
|
||||
ExpansionHS = ExpansionSA,
|
||||
ExpansionTOL = ExpansionHS,
|
||||
ExpansionEJ = ExpansionTOL
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum HousingFlags
|
||||
{
|
||||
None = 0x0,
|
||||
AOS = 0x10,
|
||||
SE = 0x40,
|
||||
ML = 0x80,
|
||||
Crystal = 0x200,
|
||||
SA = 0x10000,
|
||||
HS = 0x20000,
|
||||
Gothic = 0x40000,
|
||||
Rustic = 0x80000,
|
||||
Jungle = 0x100000,
|
||||
Shadowguard = 0x200000,
|
||||
TOL = 0x400000,
|
||||
EJ = 0x800000, // TODO: Verify value
|
||||
|
||||
HousingAOS = AOS,
|
||||
HousingSE = HousingAOS | SE,
|
||||
HousingML = HousingSE | ML | Crystal,
|
||||
HousingSA = HousingML | SA | Gothic | Rustic,
|
||||
HousingHS = HousingSA | HS,
|
||||
HousingTOL = HousingHS | TOL | Jungle | Shadowguard,
|
||||
HousingEJ = HousingTOL | EJ
|
||||
}
|
||||
|
||||
public class ExpansionInfo
|
||||
{
|
||||
public static ExpansionInfo CoreExpansion { get { return GetInfo(Core.Expansion); } }
|
||||
|
||||
public static ExpansionInfo[] Table { get; private set; }
|
||||
|
||||
static ExpansionInfo()
|
||||
{
|
||||
Table = new[]
|
||||
{
|
||||
new ExpansionInfo(
|
||||
0,
|
||||
"None",
|
||||
ClientFlags.None,
|
||||
FeatureFlags.ExpansionNone,
|
||||
CharacterListFlags.ExpansionNone,
|
||||
HousingFlags.None),
|
||||
new ExpansionInfo(
|
||||
1,
|
||||
"The Second Age",
|
||||
ClientFlags.Felucca,
|
||||
FeatureFlags.ExpansionT2A,
|
||||
CharacterListFlags.ExpansionT2A,
|
||||
HousingFlags.None),
|
||||
new ExpansionInfo(
|
||||
2,
|
||||
"Renaissance",
|
||||
ClientFlags.Trammel,
|
||||
FeatureFlags.ExpansionUOR,
|
||||
CharacterListFlags.ExpansionUOR,
|
||||
HousingFlags.None),
|
||||
new ExpansionInfo(
|
||||
3,
|
||||
"Third Dawn",
|
||||
ClientFlags.Ilshenar,
|
||||
FeatureFlags.ExpansionUOTD,
|
||||
CharacterListFlags.ExpansionUOTD,
|
||||
HousingFlags.None),
|
||||
new ExpansionInfo(
|
||||
4,
|
||||
"Blackthorn's Revenge",
|
||||
ClientFlags.Ilshenar,
|
||||
FeatureFlags.ExpansionLBR,
|
||||
CharacterListFlags.ExpansionLBR,
|
||||
HousingFlags.None),
|
||||
new ExpansionInfo(
|
||||
5,
|
||||
"Age of Shadows",
|
||||
ClientFlags.Malas,
|
||||
FeatureFlags.ExpansionAOS,
|
||||
CharacterListFlags.ExpansionAOS,
|
||||
HousingFlags.HousingAOS),
|
||||
new ExpansionInfo(
|
||||
6,
|
||||
"Samurai Empire",
|
||||
ClientFlags.Tokuno,
|
||||
FeatureFlags.ExpansionSE,
|
||||
CharacterListFlags.ExpansionSE,
|
||||
HousingFlags.HousingSE),
|
||||
new ExpansionInfo(
|
||||
7,
|
||||
"Mondain's Legacy",
|
||||
new ClientVersion("5.0.0a"),
|
||||
FeatureFlags.ExpansionML,
|
||||
CharacterListFlags.ExpansionML,
|
||||
HousingFlags.HousingML),
|
||||
new ExpansionInfo(
|
||||
8,
|
||||
"Stygian Abyss",
|
||||
ClientFlags.TerMur,
|
||||
FeatureFlags.ExpansionSA,
|
||||
CharacterListFlags.ExpansionSA,
|
||||
HousingFlags.HousingSA),
|
||||
new ExpansionInfo(
|
||||
9,
|
||||
"High Seas",
|
||||
new ClientVersion("7.0.9.0"),
|
||||
FeatureFlags.ExpansionHS,
|
||||
CharacterListFlags.ExpansionHS,
|
||||
HousingFlags.HousingHS),
|
||||
new ExpansionInfo(
|
||||
10,
|
||||
"Time of Legends",
|
||||
new ClientVersion("7.0.45.65"),
|
||||
FeatureFlags.ExpansionTOL,
|
||||
CharacterListFlags.ExpansionTOL,
|
||||
HousingFlags.HousingTOL),
|
||||
new ExpansionInfo(
|
||||
11,
|
||||
"Endless Journey",
|
||||
new ClientVersion("7.0.61.0"),
|
||||
FeatureFlags.ExpansionEJ,
|
||||
CharacterListFlags.ExpansionEJ,
|
||||
HousingFlags.HousingEJ)
|
||||
};
|
||||
}
|
||||
|
||||
public static FeatureFlags GetFeatures(Expansion ex)
|
||||
{
|
||||
var info = GetInfo(ex);
|
||||
|
||||
if (info != null)
|
||||
{
|
||||
return info.SupportedFeatures;
|
||||
}
|
||||
|
||||
switch (ex)
|
||||
{
|
||||
case Expansion.None:
|
||||
return FeatureFlags.ExpansionNone;
|
||||
case Expansion.T2A:
|
||||
return FeatureFlags.ExpansionT2A;
|
||||
case Expansion.UOR:
|
||||
return FeatureFlags.ExpansionUOR;
|
||||
case Expansion.UOTD:
|
||||
return FeatureFlags.ExpansionUOTD;
|
||||
case Expansion.LBR:
|
||||
return FeatureFlags.ExpansionLBR;
|
||||
case Expansion.AOS:
|
||||
return FeatureFlags.ExpansionAOS;
|
||||
case Expansion.SE:
|
||||
return FeatureFlags.ExpansionSE;
|
||||
case Expansion.ML:
|
||||
return FeatureFlags.ExpansionML;
|
||||
case Expansion.SA:
|
||||
return FeatureFlags.ExpansionSA;
|
||||
case Expansion.HS:
|
||||
return FeatureFlags.ExpansionHS;
|
||||
case Expansion.TOL:
|
||||
return FeatureFlags.ExpansionTOL;
|
||||
case Expansion.EJ:
|
||||
return FeatureFlags.ExpansionEJ;
|
||||
}
|
||||
|
||||
return FeatureFlags.ExpansionNone;
|
||||
}
|
||||
|
||||
public static ExpansionInfo GetInfo(Expansion ex)
|
||||
{
|
||||
return GetInfo((int)ex);
|
||||
}
|
||||
|
||||
public static ExpansionInfo GetInfo(int ex)
|
||||
{
|
||||
var v = ex;
|
||||
|
||||
if (v < 0 || v >= Table.Length)
|
||||
{
|
||||
v = 0;
|
||||
}
|
||||
|
||||
return Table[v];
|
||||
}
|
||||
|
||||
public int ID { get; private set; }
|
||||
public string Name { get; set; }
|
||||
|
||||
public ClientFlags ClientFlags { get; set; }
|
||||
public FeatureFlags SupportedFeatures { get; set; }
|
||||
public CharacterListFlags CharacterListFlags { get; set; }
|
||||
public ClientVersion RequiredClient { get; set; }
|
||||
public HousingFlags CustomHousingFlag { get; set; }
|
||||
|
||||
public ExpansionInfo(
|
||||
int id,
|
||||
string name,
|
||||
ClientFlags clientFlags,
|
||||
FeatureFlags supportedFeatures,
|
||||
CharacterListFlags charListFlags,
|
||||
HousingFlags customHousingFlag)
|
||||
: this(id, name, supportedFeatures, charListFlags, customHousingFlag)
|
||||
{
|
||||
ClientFlags = clientFlags;
|
||||
}
|
||||
|
||||
public ExpansionInfo(
|
||||
int id,
|
||||
string name,
|
||||
ClientVersion requiredClient,
|
||||
FeatureFlags supportedFeatures,
|
||||
CharacterListFlags charListFlags,
|
||||
HousingFlags customHousingFlag)
|
||||
: this(id, name, supportedFeatures, charListFlags, customHousingFlag)
|
||||
{
|
||||
RequiredClient = requiredClient;
|
||||
}
|
||||
|
||||
private ExpansionInfo(
|
||||
int id,
|
||||
string name,
|
||||
FeatureFlags supportedFeatures,
|
||||
CharacterListFlags charListFlags,
|
||||
HousingFlags customHousingFlag)
|
||||
{
|
||||
ID = id;
|
||||
Name = name;
|
||||
|
||||
SupportedFeatures = supportedFeatures;
|
||||
CharacterListFlags = charListFlags;
|
||||
CustomHousingFlag = customHousingFlag;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
604
Server/Geometry.cs
Normal file
604
Server/Geometry.cs
Normal file
@@ -0,0 +1,604 @@
|
||||
#region References
|
||||
using System;
|
||||
#endregion
|
||||
|
||||
namespace Server
|
||||
{
|
||||
[Parsable]
|
||||
public struct Point2D : IPoint2D, IComparable, IComparable<Point2D>
|
||||
{
|
||||
internal int m_X;
|
||||
internal int m_Y;
|
||||
|
||||
public static readonly Point2D Zero = new Point2D(0, 0);
|
||||
|
||||
public Point2D(int x, int y)
|
||||
{
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
}
|
||||
|
||||
public Point2D(IPoint2D p)
|
||||
: this(p.X, p.Y)
|
||||
{ }
|
||||
|
||||
[CommandProperty(AccessLevel.Counselor)]
|
||||
public int X { get { return m_X; } set { m_X = value; } }
|
||||
|
||||
[CommandProperty(AccessLevel.Counselor)]
|
||||
public int Y { get { return m_Y; } set { m_Y = value; } }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("({0}, {1})", m_X, m_Y);
|
||||
}
|
||||
|
||||
public static Point2D Parse(string value)
|
||||
{
|
||||
int start = value.IndexOf('(');
|
||||
int end = value.IndexOf(',', start + 1);
|
||||
|
||||
string param1 = value.Substring(start + 1, end - (start + 1)).Trim();
|
||||
|
||||
start = end;
|
||||
end = value.IndexOf(')', start + 1);
|
||||
|
||||
string param2 = value.Substring(start + 1, end - (start + 1)).Trim();
|
||||
|
||||
return new Point2D(Convert.ToInt32(param1), Convert.ToInt32(param2));
|
||||
}
|
||||
|
||||
public int CompareTo(Point2D other)
|
||||
{
|
||||
int v = (m_X.CompareTo(other.m_X));
|
||||
|
||||
if (v == 0)
|
||||
{
|
||||
v = (m_Y.CompareTo(other.m_Y));
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public int CompareTo(object other)
|
||||
{
|
||||
if (other is Point2D)
|
||||
{
|
||||
return CompareTo((Point2D)other);
|
||||
}
|
||||
|
||||
if (other == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
public override bool Equals(object o)
|
||||
{
|
||||
if (!(o is IPoint2D))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
IPoint2D p = (IPoint2D)o;
|
||||
|
||||
return m_X == p.X && m_Y == p.Y;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
var hash = 1 + Math.Abs(X) + Math.Abs(Y);
|
||||
|
||||
hash = (hash * 397) ^ X;
|
||||
hash = (hash * 397) ^ Y;
|
||||
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool operator ==(Point2D l, Point2D r)
|
||||
{
|
||||
return l.m_X == r.m_X && l.m_Y == r.m_Y;
|
||||
}
|
||||
|
||||
public static bool operator !=(Point2D l, Point2D r)
|
||||
{
|
||||
return l.m_X != r.m_X || l.m_Y != r.m_Y;
|
||||
}
|
||||
|
||||
public static bool operator ==(Point2D l, IPoint2D r)
|
||||
{
|
||||
if (ReferenceEquals(r, null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return l.m_X == r.X && l.m_Y == r.Y;
|
||||
}
|
||||
|
||||
public static bool operator !=(Point2D l, IPoint2D r)
|
||||
{
|
||||
if (ReferenceEquals(r, null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return l.m_X != r.X || l.m_Y != r.Y;
|
||||
}
|
||||
|
||||
public static bool operator >(Point2D l, Point2D r)
|
||||
{
|
||||
return l.m_X > r.m_X && l.m_Y > r.m_Y;
|
||||
}
|
||||
|
||||
public static bool operator >(Point2D l, Point3D r)
|
||||
{
|
||||
return l.m_X > r.m_X && l.m_Y > r.m_Y;
|
||||
}
|
||||
|
||||
public static bool operator >(Point2D l, IPoint2D r)
|
||||
{
|
||||
if (ReferenceEquals(r, null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return l.m_X > r.X && l.m_Y > r.Y;
|
||||
}
|
||||
|
||||
public static bool operator <(Point2D l, Point2D r)
|
||||
{
|
||||
return l.m_X < r.m_X && l.m_Y < r.m_Y;
|
||||
}
|
||||
|
||||
public static bool operator <(Point2D l, Point3D r)
|
||||
{
|
||||
return l.m_X < r.m_X && l.m_Y < r.m_Y;
|
||||
}
|
||||
|
||||
public static bool operator <(Point2D l, IPoint2D r)
|
||||
{
|
||||
if (ReferenceEquals(r, null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return l.m_X < r.X && l.m_Y < r.Y;
|
||||
}
|
||||
|
||||
public static bool operator >=(Point2D l, Point2D r)
|
||||
{
|
||||
return l.m_X >= r.m_X && l.m_Y >= r.m_Y;
|
||||
}
|
||||
|
||||
public static bool operator >=(Point2D l, Point3D r)
|
||||
{
|
||||
return l.m_X >= r.m_X && l.m_Y >= r.m_Y;
|
||||
}
|
||||
|
||||
public static bool operator >=(Point2D l, IPoint2D r)
|
||||
{
|
||||
if (ReferenceEquals(r, null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return l.m_X >= r.X && l.m_Y >= r.Y;
|
||||
}
|
||||
|
||||
public static bool operator <=(Point2D l, Point2D r)
|
||||
{
|
||||
return l.m_X <= r.m_X && l.m_Y <= r.m_Y;
|
||||
}
|
||||
|
||||
public static bool operator <=(Point2D l, Point3D r)
|
||||
{
|
||||
return l.m_X <= r.m_X && l.m_Y <= r.m_Y;
|
||||
}
|
||||
|
||||
public static bool operator <=(Point2D l, IPoint2D r)
|
||||
{
|
||||
if (ReferenceEquals(r, null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return l.m_X <= r.X && l.m_Y <= r.Y;
|
||||
}
|
||||
}
|
||||
|
||||
[Parsable]
|
||||
public struct Point3D : IPoint3D, IComparable, IComparable<Point3D>
|
||||
{
|
||||
internal int m_X;
|
||||
internal int m_Y;
|
||||
internal int m_Z;
|
||||
|
||||
public static readonly Point3D Zero = new Point3D(0, 0, 0);
|
||||
|
||||
public Point3D(int x, int y, int z)
|
||||
{
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_Z = z;
|
||||
}
|
||||
|
||||
public Point3D(IPoint3D p)
|
||||
: this(p.X, p.Y, p.Z)
|
||||
{ }
|
||||
|
||||
public Point3D(IPoint2D p, int z)
|
||||
: this(p.X, p.Y, z)
|
||||
{ }
|
||||
|
||||
[CommandProperty(AccessLevel.Counselor)]
|
||||
public int X { get { return m_X; } set { m_X = value; } }
|
||||
|
||||
[CommandProperty(AccessLevel.Counselor)]
|
||||
public int Y { get { return m_Y; } set { m_Y = value; } }
|
||||
|
||||
[CommandProperty(AccessLevel.Counselor)]
|
||||
public int Z { get { return m_Z; } set { m_Z = value; } }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("({0}, {1}, {2})", m_X, m_Y, m_Z);
|
||||
}
|
||||
|
||||
public override bool Equals(object o)
|
||||
{
|
||||
if (!(o is IPoint3D))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
IPoint3D p = (IPoint3D)o;
|
||||
|
||||
return m_X == p.X && m_Y == p.Y && m_Z == p.Z;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
var hash = 1 + Math.Abs(X) + Math.Abs(Y) + Math.Abs(Z);
|
||||
|
||||
hash = (hash * 397) ^ X;
|
||||
hash = (hash * 397) ^ Y;
|
||||
hash = (hash * 397) ^ Z;
|
||||
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
public static Point3D Parse(string value)
|
||||
{
|
||||
int start = value.IndexOf('(');
|
||||
int end = value.IndexOf(',', start + 1);
|
||||
|
||||
string param1 = value.Substring(start + 1, end - (start + 1)).Trim();
|
||||
|
||||
start = end;
|
||||
end = value.IndexOf(',', start + 1);
|
||||
|
||||
string param2 = value.Substring(start + 1, end - (start + 1)).Trim();
|
||||
|
||||
start = end;
|
||||
end = value.IndexOf(')', start + 1);
|
||||
|
||||
string param3 = value.Substring(start + 1, end - (start + 1)).Trim();
|
||||
|
||||
return new Point3D(Convert.ToInt32(param1), Convert.ToInt32(param2), Convert.ToInt32(param3));
|
||||
}
|
||||
|
||||
public static bool operator ==(Point3D l, Point3D r)
|
||||
{
|
||||
return l.m_X == r.m_X && l.m_Y == r.m_Y && l.m_Z == r.m_Z;
|
||||
}
|
||||
|
||||
public static bool operator !=(Point3D l, Point3D r)
|
||||
{
|
||||
return l.m_X != r.m_X || l.m_Y != r.m_Y || l.m_Z != r.m_Z;
|
||||
}
|
||||
|
||||
public static bool operator ==(Point3D l, IPoint3D r)
|
||||
{
|
||||
if (ReferenceEquals(r, null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return l.m_X == r.X && l.m_Y == r.Y && l.m_Z == r.Z;
|
||||
}
|
||||
|
||||
public static bool operator !=(Point3D l, IPoint3D r)
|
||||
{
|
||||
if (ReferenceEquals(r, null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return l.m_X != r.X || l.m_Y != r.Y || l.m_Z != r.Z;
|
||||
}
|
||||
|
||||
public int CompareTo(Point3D other)
|
||||
{
|
||||
int v = (m_X.CompareTo(other.m_X));
|
||||
|
||||
if (v == 0)
|
||||
{
|
||||
v = (m_Y.CompareTo(other.m_Y));
|
||||
|
||||
if (v == 0)
|
||||
{
|
||||
v = (m_Z.CompareTo(other.m_Z));
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public int CompareTo(object other)
|
||||
{
|
||||
if (other is Point3D)
|
||||
{
|
||||
return CompareTo((Point3D)other);
|
||||
}
|
||||
|
||||
if (other == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
throw new ArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
[NoSort]
|
||||
[Parsable]
|
||||
[PropertyObject]
|
||||
public struct Rectangle2D
|
||||
{
|
||||
private Point2D m_Start;
|
||||
private Point2D m_End;
|
||||
|
||||
public Rectangle2D(IPoint2D start, IPoint2D end)
|
||||
{
|
||||
m_Start = new Point2D(start);
|
||||
m_End = new Point2D(end);
|
||||
}
|
||||
|
||||
public Rectangle2D(int x, int y, int width, int height)
|
||||
{
|
||||
m_Start = new Point2D(x, y);
|
||||
m_End = new Point2D(x + width, y + height);
|
||||
}
|
||||
|
||||
public void Set(int x, int y, int width, int height)
|
||||
{
|
||||
m_Start = new Point2D(x, y);
|
||||
m_End = new Point2D(x + width, y + height);
|
||||
}
|
||||
|
||||
public static Rectangle2D Parse(string value)
|
||||
{
|
||||
int start = value.IndexOf('(');
|
||||
int end = value.IndexOf(',', start + 1);
|
||||
|
||||
string param1 = value.Substring(start + 1, end - (start + 1)).Trim();
|
||||
|
||||
start = end;
|
||||
end = value.IndexOf(',', start + 1);
|
||||
|
||||
string param2 = value.Substring(start + 1, end - (start + 1)).Trim();
|
||||
|
||||
start = end;
|
||||
end = value.IndexOf(',', start + 1);
|
||||
|
||||
string param3 = value.Substring(start + 1, end - (start + 1)).Trim();
|
||||
|
||||
start = end;
|
||||
end = value.IndexOf(')', start + 1);
|
||||
|
||||
string param4 = value.Substring(start + 1, end - (start + 1)).Trim();
|
||||
|
||||
return new Rectangle2D(
|
||||
Convert.ToInt32(param1),
|
||||
Convert.ToInt32(param2),
|
||||
Convert.ToInt32(param3),
|
||||
Convert.ToInt32(param4));
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.Counselor)]
|
||||
public Point2D Start { get { return m_Start; } set { m_Start = value; } }
|
||||
|
||||
[CommandProperty(AccessLevel.Counselor)]
|
||||
public Point2D End { get { return m_End; } set { m_End = value; } }
|
||||
|
||||
[CommandProperty(AccessLevel.Counselor)]
|
||||
public int X { get { return m_Start.m_X; } set { m_Start.m_X = value; } }
|
||||
|
||||
[CommandProperty(AccessLevel.Counselor)]
|
||||
public int Y { get { return m_Start.m_Y; } set { m_Start.m_Y = value; } }
|
||||
|
||||
[CommandProperty(AccessLevel.Counselor)]
|
||||
public int Width { get { return m_End.m_X - m_Start.m_X; } set { m_End.m_X = m_Start.m_X + value; } }
|
||||
|
||||
[CommandProperty(AccessLevel.Counselor)]
|
||||
public int Height { get { return m_End.m_Y - m_Start.m_Y; } set { m_End.m_Y = m_Start.m_Y + value; } }
|
||||
|
||||
public void MakeHold(Rectangle2D r)
|
||||
{
|
||||
if (r.m_Start.m_X < m_Start.m_X)
|
||||
{
|
||||
m_Start.m_X = r.m_Start.m_X;
|
||||
}
|
||||
|
||||
if (r.m_Start.m_Y < m_Start.m_Y)
|
||||
{
|
||||
m_Start.m_Y = r.m_Start.m_Y;
|
||||
}
|
||||
|
||||
if (r.m_End.m_X > m_End.m_X)
|
||||
{
|
||||
m_End.m_X = r.m_End.m_X;
|
||||
}
|
||||
|
||||
if (r.m_End.m_Y > m_End.m_Y)
|
||||
{
|
||||
m_End.m_Y = r.m_End.m_Y;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Contains(Point3D p)
|
||||
{
|
||||
return (m_Start.m_X <= p.m_X && m_Start.m_Y <= p.m_Y && m_End.m_X > p.m_X && m_End.m_Y > p.m_Y);
|
||||
//return ( m_Start <= p && m_End > p );
|
||||
}
|
||||
|
||||
public bool Contains(Point2D p)
|
||||
{
|
||||
return (m_Start.m_X <= p.m_X && m_Start.m_Y <= p.m_Y && m_End.m_X > p.m_X && m_End.m_Y > p.m_Y);
|
||||
//return ( m_Start <= p && m_End > p );
|
||||
}
|
||||
|
||||
public bool Contains(IPoint2D p)
|
||||
{
|
||||
return (m_Start <= p && m_End > p);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("({0}, {1})+({2}, {3})", X, Y, Width, Height);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
var hash = 1 + Math.Abs(Start.X + Start.Y) + Math.Abs(End.X + End.Y);
|
||||
|
||||
hash = (hash * 397) ^ Start.GetHashCode();
|
||||
hash = (hash * 397) ^ End.GetHashCode();
|
||||
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[NoSort]
|
||||
[PropertyObject]
|
||||
public struct Rectangle3D
|
||||
{
|
||||
private Point3D m_Start;
|
||||
private Point3D m_End;
|
||||
|
||||
public Rectangle3D(Point3D start, Point3D end)
|
||||
{
|
||||
m_Start = start;
|
||||
m_End = end;
|
||||
}
|
||||
|
||||
public Rectangle3D(int x, int y, int z, int width, int height, int depth)
|
||||
{
|
||||
m_Start = new Point3D(x, y, z);
|
||||
m_End = new Point3D(x + width, y + height, z + depth);
|
||||
}
|
||||
|
||||
public void Set(int x, int y, int z, int width, int height, int depth)
|
||||
{
|
||||
m_Start = new Point3D(x, y, z);
|
||||
m_End = new Point3D(x + width, y + height, z + depth);
|
||||
}
|
||||
|
||||
public static Rectangle3D Parse(string value)
|
||||
{
|
||||
int start = value.IndexOf('(');
|
||||
int end = value.IndexOf(',', start + 1);
|
||||
|
||||
string param1 = value.Substring(start + 1, end - (start + 1)).Trim();
|
||||
|
||||
start = end;
|
||||
end = value.IndexOf(',', start + 1);
|
||||
|
||||
string param2 = value.Substring(start + 1, end - (start + 1)).Trim();
|
||||
|
||||
start = end;
|
||||
end = value.IndexOf(',', start + 1);
|
||||
|
||||
string param3 = value.Substring(start + 1, end - (start + 1)).Trim();
|
||||
|
||||
start = end;
|
||||
end = value.IndexOf(',', start + 1);
|
||||
|
||||
string param4 = value.Substring(start + 1, end - (start + 1)).Trim();
|
||||
|
||||
start = end;
|
||||
end = value.IndexOf(',', start + 1);
|
||||
|
||||
string param5 = value.Substring(start + 1, end - (start + 1)).Trim();
|
||||
|
||||
start = end;
|
||||
end = value.IndexOf(')', start + 1);
|
||||
|
||||
string param6 = value.Substring(start + 1, end - (start + 1)).Trim();
|
||||
|
||||
return new Rectangle3D(
|
||||
Convert.ToInt32(param1),
|
||||
Convert.ToInt32(param2),
|
||||
Convert.ToInt32(param3),
|
||||
Convert.ToInt32(param4),
|
||||
Convert.ToInt32(param5),
|
||||
Convert.ToInt32(param6));
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.Counselor)]
|
||||
public Point3D Start { get { return m_Start; } set { m_Start = value; } }
|
||||
|
||||
[CommandProperty(AccessLevel.Counselor)]
|
||||
public Point3D End { get { return m_End; } set { m_End = value; } }
|
||||
|
||||
[CommandProperty(AccessLevel.Counselor)]
|
||||
public int Width { get { return m_End.X - m_Start.X; } }
|
||||
|
||||
[CommandProperty(AccessLevel.Counselor)]
|
||||
public int Height { get { return m_End.Y - m_Start.Y; } }
|
||||
|
||||
[CommandProperty(AccessLevel.Counselor)]
|
||||
public int Depth { get { return m_End.Z - m_Start.Z; } }
|
||||
|
||||
public bool Contains(Point3D p)
|
||||
{
|
||||
return (p.m_X >= m_Start.m_X) && (p.m_X < m_End.m_X) && (p.m_Y >= m_Start.m_Y) && (p.m_Y < m_End.m_Y) &&
|
||||
(p.m_Z >= m_Start.m_Z) && (p.m_Z < m_End.m_Z);
|
||||
}
|
||||
|
||||
public bool Contains(IPoint3D p)
|
||||
{
|
||||
return (p.X >= m_Start.m_X) && (p.X < m_End.m_X) && (p.Y >= m_Start.m_Y) && (p.Y < m_End.m_Y) && (p.Z >= m_Start.m_Z) &&
|
||||
(p.Z < m_End.m_Z);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("({0}, {1}, {2})+({3}, {4}, {5})", Start.X, Start.Y, Start.Z, Width, Height, Depth);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
var hash = 1 + Math.Abs(Start.X + Start.Y + Start.Z) + Math.Abs(End.X + End.Y + End.Z);
|
||||
|
||||
hash = (hash * 397) ^ Start.GetHashCode();
|
||||
hash = (hash * 397) ^ End.GetHashCode();
|
||||
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
123
Server/Guild.cs
Normal file
123
Server/Guild.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#endregion
|
||||
|
||||
namespace Server.Guilds
|
||||
{
|
||||
public enum GuildType
|
||||
{
|
||||
Regular,
|
||||
Chaos,
|
||||
Order
|
||||
}
|
||||
|
||||
public abstract class BaseGuild : ISerializable
|
||||
{
|
||||
private readonly int m_Id;
|
||||
|
||||
protected BaseGuild(int Id) //serialization ctor
|
||||
{
|
||||
m_Id = Id;
|
||||
m_GuildList.Add(m_Id, this);
|
||||
if (m_Id + 1 > m_NextID)
|
||||
{
|
||||
m_NextID = m_Id + 1;
|
||||
}
|
||||
}
|
||||
|
||||
protected BaseGuild()
|
||||
{
|
||||
m_Id = m_NextID++;
|
||||
m_GuildList.Add(m_Id, this);
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.Counselor)]
|
||||
public int Id { get { return m_Id; } }
|
||||
|
||||
int ISerializable.TypeReference { get { return 0; } }
|
||||
|
||||
int ISerializable.SerialIdentity { get { return m_Id; } }
|
||||
|
||||
public abstract void Deserialize(GenericReader reader);
|
||||
public abstract void Serialize(GenericWriter writer);
|
||||
|
||||
public abstract string Abbreviation { get; set; }
|
||||
public abstract string Name { get; set; }
|
||||
public abstract GuildType Type { get; set; }
|
||||
public abstract bool Disbanded { get; }
|
||||
public abstract void OnDelete(Mobile mob);
|
||||
|
||||
private static readonly Dictionary<int, BaseGuild> m_GuildList = new Dictionary<int, BaseGuild>();
|
||||
private static int m_NextID = 1;
|
||||
|
||||
public static Dictionary<int, BaseGuild> List { get { return m_GuildList; } }
|
||||
|
||||
public static BaseGuild Find(int id)
|
||||
{
|
||||
BaseGuild g;
|
||||
|
||||
m_GuildList.TryGetValue(id, out g);
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
public static BaseGuild FindByName(string name)
|
||||
{
|
||||
foreach (BaseGuild g in m_GuildList.Values)
|
||||
{
|
||||
if (g.Name == name)
|
||||
{
|
||||
return g;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static BaseGuild FindByAbbrev(string abbr)
|
||||
{
|
||||
foreach (BaseGuild g in m_GuildList.Values)
|
||||
{
|
||||
if (g.Abbreviation == abbr)
|
||||
{
|
||||
return g;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<BaseGuild> Search(string find)
|
||||
{
|
||||
var words = find.ToLower().Split(' ');
|
||||
var results = new List<BaseGuild>();
|
||||
|
||||
foreach (BaseGuild g in m_GuildList.Values)
|
||||
{
|
||||
bool match = true;
|
||||
string name = g.Name.ToLower();
|
||||
for (int i = 0; i < words.Length; i++)
|
||||
{
|
||||
if (name.IndexOf(words[i]) == -1)
|
||||
{
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (match)
|
||||
{
|
||||
results.Add(g);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("0x{0:X} \"{1} [{2}]\"", m_Id, Name, Abbreviation);
|
||||
}
|
||||
}
|
||||
}
|
||||
24
Server/Gumps/ECHandleInput.cs
Normal file
24
Server/Gumps/ECHandleInput.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public class ECHandleInput : GumpEntry
|
||||
{
|
||||
public ECHandleInput()
|
||||
{
|
||||
}
|
||||
|
||||
public override string Compile()
|
||||
{
|
||||
return String.Format("{{ echandleinput }}");
|
||||
}
|
||||
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer("echandleinput");
|
||||
|
||||
public override void AppendTo(IGumpWriter disp)
|
||||
{
|
||||
disp.AppendLayout(m_LayoutName);
|
||||
}
|
||||
}
|
||||
}
|
||||
493
Server/Gumps/Gump.cs
Normal file
493
Server/Gumps/Gump.cs
Normal file
@@ -0,0 +1,493 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
using Server.Network;
|
||||
#endregion
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public class Gump
|
||||
{
|
||||
private List<GumpEntry> m_Entries;
|
||||
private List<string> m_Strings;
|
||||
|
||||
internal int m_TextEntries, m_Switches;
|
||||
|
||||
private static int m_NextSerial = 1;
|
||||
|
||||
private int m_Serial;
|
||||
private int m_X, m_Y;
|
||||
|
||||
private bool m_Dragable = true;
|
||||
private bool m_Closable = true;
|
||||
private bool m_Resizable = true;
|
||||
private bool m_Disposable = true;
|
||||
|
||||
public virtual int GetTypeID()
|
||||
{
|
||||
return this.GetType().FullName.GetHashCode();
|
||||
}
|
||||
|
||||
public Gump(int x, int y)
|
||||
{
|
||||
do
|
||||
{
|
||||
m_Serial = m_NextSerial++;
|
||||
}
|
||||
while (m_Serial == 0); // standard client apparently doesn't send a gump response packet if serial == 0
|
||||
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
|
||||
TypeID = GetTypeID();
|
||||
|
||||
m_Entries = new List<GumpEntry>();
|
||||
m_Strings = new List<string>();
|
||||
}
|
||||
|
||||
public void Invalidate()
|
||||
{
|
||||
//if ( m_Strings.Count > 0 )
|
||||
// m_Strings.Clear();
|
||||
}
|
||||
|
||||
public int TypeID { get; set; }
|
||||
|
||||
public List<GumpEntry> Entries { get { return m_Entries; } }
|
||||
|
||||
public int Serial
|
||||
{
|
||||
get { return m_Serial; }
|
||||
set
|
||||
{
|
||||
if (m_Serial != value)
|
||||
{
|
||||
m_Serial = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int X
|
||||
{
|
||||
get { return m_X; }
|
||||
set
|
||||
{
|
||||
if (m_X != value)
|
||||
{
|
||||
m_X = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get { return m_Y; }
|
||||
set
|
||||
{
|
||||
if (m_Y != value)
|
||||
{
|
||||
m_Y = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Disposable
|
||||
{
|
||||
get { return m_Disposable; }
|
||||
set
|
||||
{
|
||||
if (m_Disposable != value)
|
||||
{
|
||||
m_Disposable = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Resizable
|
||||
{
|
||||
get { return m_Resizable; }
|
||||
set
|
||||
{
|
||||
if (m_Resizable != value)
|
||||
{
|
||||
m_Resizable = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Dragable
|
||||
{
|
||||
get { return m_Dragable; }
|
||||
set
|
||||
{
|
||||
if (m_Dragable != value)
|
||||
{
|
||||
m_Dragable = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Closable
|
||||
{
|
||||
get { return m_Closable; }
|
||||
set
|
||||
{
|
||||
if (m_Closable != value)
|
||||
{
|
||||
m_Closable = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddPage(int page)
|
||||
{
|
||||
Add(new GumpPage(page));
|
||||
}
|
||||
|
||||
public void AddAlphaRegion(int x, int y, int width, int height)
|
||||
{
|
||||
Add(new GumpAlphaRegion(x, y, width, height));
|
||||
}
|
||||
|
||||
public void AddBackground(int x, int y, int width, int height, int gumpID)
|
||||
{
|
||||
Add(new GumpBackground(x, y, width, height, gumpID));
|
||||
}
|
||||
|
||||
public void AddButton(int x, int y, int normalID, int pressedID, int buttonID, GumpButtonType type, int param)
|
||||
{
|
||||
Add(new GumpButton(x, y, normalID, pressedID, buttonID, type, param));
|
||||
}
|
||||
|
||||
public void AddCheck(int x, int y, int inactiveID, int activeID, bool initialState, int switchID)
|
||||
{
|
||||
Add(new GumpCheck(x, y, inactiveID, activeID, initialState, switchID));
|
||||
}
|
||||
|
||||
public void AddGroup(int group)
|
||||
{
|
||||
Add(new GumpGroup(group));
|
||||
}
|
||||
|
||||
public void AddTooltip(int number)
|
||||
{
|
||||
Add(new GumpTooltip(number));
|
||||
}
|
||||
|
||||
public void AddHtml(int x, int y, int width, int height, string text, bool background, bool scrollbar)
|
||||
{
|
||||
Add(new GumpHtml(x, y, width, height, text, background, scrollbar));
|
||||
}
|
||||
|
||||
public void AddHtmlIntern(int x, int y, int width, int height, int textid, bool background, bool scrollbar)
|
||||
{
|
||||
Add(new GumpHtml(x, y, width, height, textid, background, scrollbar));
|
||||
}
|
||||
|
||||
public void AddHtmlLocalized(int x, int y, int width, int height, int number, bool background, bool scrollbar)
|
||||
{
|
||||
Add(new GumpHtmlLocalized(x, y, width, height, number, background, scrollbar));
|
||||
}
|
||||
|
||||
public void AddHtmlLocalized(
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
int number,
|
||||
int color,
|
||||
bool background,
|
||||
bool scrollbar)
|
||||
{
|
||||
Add(new GumpHtmlLocalized(x, y, width, height, number, color, background, scrollbar));
|
||||
}
|
||||
|
||||
public void AddHtmlLocalized(
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
int number,
|
||||
string args,
|
||||
int color,
|
||||
bool background,
|
||||
bool scrollbar)
|
||||
{
|
||||
Add(new GumpHtmlLocalized(x, y, width, height, number, args, color, background, scrollbar));
|
||||
}
|
||||
|
||||
public void AddImage(int x, int y, int gumpID)
|
||||
{
|
||||
Add(new GumpImage(x, y, gumpID));
|
||||
}
|
||||
|
||||
public void AddSpriteImage(int x, int y, int gumpID, int width, int height, int sx, int sy)
|
||||
{
|
||||
Add(new GumpSpriteImage(x, y, gumpID, width, height, sx, sy));
|
||||
}
|
||||
|
||||
public void AddImage(int x, int y, int gumpID, int hue)
|
||||
{
|
||||
Add(new GumpImage(x, y, gumpID, hue));
|
||||
}
|
||||
|
||||
public void AddImageTiled(int x, int y, int width, int height, int gumpID)
|
||||
{
|
||||
Add(new GumpImageTiled(x, y, width, height, gumpID));
|
||||
}
|
||||
|
||||
public void AddImageTiledButton(
|
||||
int x,
|
||||
int y,
|
||||
int normalID,
|
||||
int pressedID,
|
||||
int buttonID,
|
||||
GumpButtonType type,
|
||||
int param,
|
||||
int itemID,
|
||||
int hue,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
Add(new GumpImageTileButton(x, y, normalID, pressedID, buttonID, type, param, itemID, hue, width, height));
|
||||
}
|
||||
|
||||
public void AddImageTiledButton(
|
||||
int x,
|
||||
int y,
|
||||
int normalID,
|
||||
int pressedID,
|
||||
int buttonID,
|
||||
GumpButtonType type,
|
||||
int param,
|
||||
int itemID,
|
||||
int hue,
|
||||
int width,
|
||||
int height,
|
||||
int localizedTooltip)
|
||||
{
|
||||
Add(
|
||||
new GumpImageTileButton(
|
||||
x,
|
||||
y,
|
||||
normalID,
|
||||
pressedID,
|
||||
buttonID,
|
||||
type,
|
||||
param,
|
||||
itemID,
|
||||
hue,
|
||||
width,
|
||||
height,
|
||||
localizedTooltip));
|
||||
}
|
||||
|
||||
public void AddItem(int x, int y, int itemID)
|
||||
{
|
||||
Add(new GumpItem(x, y, itemID));
|
||||
}
|
||||
|
||||
public void AddItem(int x, int y, int itemID, int hue)
|
||||
{
|
||||
Add(new GumpItem(x, y, itemID, hue));
|
||||
}
|
||||
|
||||
public void AddLabelIntern(int x, int y, int hue, int textid)
|
||||
{
|
||||
Add(new GumpLabel(x, y, hue, textid));
|
||||
}
|
||||
|
||||
public void AddLabel(int x, int y, int hue, string text)
|
||||
{
|
||||
Add(new GumpLabel(x, y, hue, text));
|
||||
}
|
||||
|
||||
public void AddLabelCropped(int x, int y, int width, int height, int hue, string text)
|
||||
{
|
||||
Add(new GumpLabelCropped(x, y, width, height, hue, text));
|
||||
}
|
||||
|
||||
public void AddLabelCroppedIntern(int x, int y, int width, int height, int hue, int textid)
|
||||
{
|
||||
Add(new GumpLabelCropped(x, y, width, height, hue, textid));
|
||||
}
|
||||
|
||||
public void AddRadio(int x, int y, int inactiveID, int activeID, bool initialState, int switchID)
|
||||
{
|
||||
Add(new GumpRadio(x, y, inactiveID, activeID, initialState, switchID));
|
||||
}
|
||||
|
||||
public void AddTextEntry(int x, int y, int width, int height, int hue, int entryID, string initialText)
|
||||
{
|
||||
Add(new GumpTextEntry(x, y, width, height, hue, entryID, initialText));
|
||||
}
|
||||
|
||||
public void AddTextEntry(int x, int y, int width, int height, int hue, int entryID, string initialText, int size)
|
||||
{
|
||||
Add(new GumpTextEntryLimited(x, y, width, height, hue, entryID, initialText, size));
|
||||
}
|
||||
|
||||
public void AddTextEntryIntern(int x, int y, int width, int height, int hue, int entryID, int initialTextID)
|
||||
{
|
||||
Add(new GumpTextEntry(x, y, width, height, hue, entryID, initialTextID));
|
||||
}
|
||||
|
||||
/*public void AddTooltip(int number, string args)
|
||||
{
|
||||
Add(new GumpTooltip(number, args));
|
||||
}*/
|
||||
|
||||
public void AddItemProperty(Item item)
|
||||
{
|
||||
Add(new GumpItemProperty(item.Serial.Value));
|
||||
}
|
||||
|
||||
public void AddItemProperty(int serial)
|
||||
{
|
||||
Add(new GumpItemProperty(serial));
|
||||
}
|
||||
|
||||
public void AddECHandleInput()
|
||||
{
|
||||
Add(new ECHandleInput());
|
||||
}
|
||||
|
||||
public void Add(GumpEntry g)
|
||||
{
|
||||
if (g.Parent != this)
|
||||
{
|
||||
g.Parent = this;
|
||||
}
|
||||
else if (!m_Entries.Contains(g))
|
||||
{
|
||||
Invalidate();
|
||||
m_Entries.Add(g);
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove(GumpEntry g)
|
||||
{
|
||||
if (g == null || !m_Entries.Contains(g))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Invalidate();
|
||||
m_Entries.Remove(g);
|
||||
g.Parent = null;
|
||||
}
|
||||
|
||||
public int Intern(string value)
|
||||
{
|
||||
return Intern(value, false);
|
||||
}
|
||||
|
||||
public int Intern(string value, bool enforceUnique)
|
||||
{
|
||||
if (enforceUnique)
|
||||
{
|
||||
int indexOf = m_Strings.IndexOf(value);
|
||||
|
||||
if (indexOf >= 0)
|
||||
return indexOf;
|
||||
}
|
||||
|
||||
m_Strings.Add(value);
|
||||
return m_Strings.Count - 1;
|
||||
}
|
||||
|
||||
public void SendTo(NetState state)
|
||||
{
|
||||
state.AddGump(this);
|
||||
state.Send(Compile(state));
|
||||
}
|
||||
|
||||
public static byte[] StringToBuffer(string str)
|
||||
{
|
||||
return Encoding.ASCII.GetBytes(str);
|
||||
}
|
||||
|
||||
private static readonly byte[] m_BeginLayout = StringToBuffer("{ ");
|
||||
private static readonly byte[] m_EndLayout = StringToBuffer(" }");
|
||||
|
||||
private static readonly byte[] m_NoMove = StringToBuffer("{ nomove }");
|
||||
private static readonly byte[] m_NoClose = StringToBuffer("{ noclose }");
|
||||
private static readonly byte[] m_NoDispose = StringToBuffer("{ nodispose }");
|
||||
private static readonly byte[] m_NoResize = StringToBuffer("{ noresize }");
|
||||
|
||||
protected virtual Packet GetPacketFor(NetState ns)
|
||||
{
|
||||
return Compile(ns);
|
||||
}
|
||||
|
||||
private Packet Compile(NetState ns)
|
||||
{
|
||||
IGumpWriter disp;
|
||||
|
||||
if (ns == null || ns.Unpack)
|
||||
{
|
||||
disp = new DisplayGumpPacked(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
disp = new DisplayGumpFast(this);
|
||||
}
|
||||
|
||||
if (!m_Dragable)
|
||||
{
|
||||
disp.AppendLayout(m_NoMove);
|
||||
}
|
||||
|
||||
if (!m_Closable)
|
||||
{
|
||||
disp.AppendLayout(m_NoClose);
|
||||
}
|
||||
|
||||
if (!m_Disposable)
|
||||
{
|
||||
disp.AppendLayout(m_NoDispose);
|
||||
}
|
||||
|
||||
if (!m_Resizable)
|
||||
{
|
||||
disp.AppendLayout(m_NoResize);
|
||||
}
|
||||
|
||||
var count = m_Entries.Count;
|
||||
GumpEntry e;
|
||||
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
e = m_Entries[i];
|
||||
|
||||
disp.AppendLayout(m_BeginLayout);
|
||||
e.AppendTo(disp);
|
||||
disp.AppendLayout(m_EndLayout);
|
||||
}
|
||||
|
||||
disp.WriteStrings(m_Strings);
|
||||
|
||||
disp.Flush();
|
||||
|
||||
m_TextEntries = disp.TextEntries;
|
||||
m_Switches = disp.Switches;
|
||||
|
||||
return (Packet)disp;
|
||||
}
|
||||
|
||||
public virtual void OnResponse(NetState sender, RelayInfo info)
|
||||
{ }
|
||||
|
||||
public virtual void OnServerClose(NetState owner)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
103
Server/Gumps/GumpAlphaRegion.cs
Normal file
103
Server/Gumps/GumpAlphaRegion.cs
Normal file
@@ -0,0 +1,103 @@
|
||||
/***************************************************************************
|
||||
* GumpAlphaRegion.cs
|
||||
* -------------------
|
||||
* begin : May 1, 2002
|
||||
* copyright : (C) The RunUO Software Team
|
||||
* email : info@runuo.com
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public class GumpAlphaRegion : GumpEntry
|
||||
{
|
||||
private int m_X, m_Y;
|
||||
private int m_Width, m_Height;
|
||||
|
||||
public int X
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_X;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_X, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Y;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Y, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Width;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Width, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Height;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Height, value );
|
||||
}
|
||||
}
|
||||
|
||||
public GumpAlphaRegion( int x, int y, int width, int height )
|
||||
{
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_Width = width;
|
||||
m_Height = height;
|
||||
}
|
||||
|
||||
public override string Compile()
|
||||
{
|
||||
return String.Format( "{{ checkertrans {0} {1} {2} {3} }}", m_X, m_Y, m_Width, m_Height );
|
||||
}
|
||||
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer( "checkertrans" );
|
||||
|
||||
public override void AppendTo( IGumpWriter disp )
|
||||
{
|
||||
disp.AppendLayout( m_LayoutName );
|
||||
disp.AppendLayout( m_X );
|
||||
disp.AppendLayout( m_Y );
|
||||
disp.AppendLayout( m_Width );
|
||||
disp.AppendLayout( m_Height );
|
||||
}
|
||||
}
|
||||
}
|
||||
118
Server/Gumps/GumpBackground.cs
Normal file
118
Server/Gumps/GumpBackground.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
/***************************************************************************
|
||||
* GumpBackground.cs
|
||||
* -------------------
|
||||
* begin : May 1, 2002
|
||||
* copyright : (C) The RunUO Software Team
|
||||
* email : info@runuo.com
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public class GumpBackground : GumpEntry
|
||||
{
|
||||
private int m_X, m_Y;
|
||||
private int m_Width, m_Height;
|
||||
private int m_GumpID;
|
||||
|
||||
public int X
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_X;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_X, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Y;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Y, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Width;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Width, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Height;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Height, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int GumpID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_GumpID;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_GumpID, value );
|
||||
}
|
||||
}
|
||||
|
||||
public GumpBackground( int x, int y, int width, int height, int gumpID )
|
||||
{
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_Width = width;
|
||||
m_Height = height;
|
||||
m_GumpID = gumpID;
|
||||
}
|
||||
|
||||
public override string Compile()
|
||||
{
|
||||
return String.Format( "{{ resizepic {0} {1} {2} {3} {4} }}", m_X, m_Y, m_GumpID, m_Width, m_Height );
|
||||
}
|
||||
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer( "resizepic" );
|
||||
|
||||
public override void AppendTo( IGumpWriter disp )
|
||||
{
|
||||
disp.AppendLayout( m_LayoutName );
|
||||
disp.AppendLayout( m_X );
|
||||
disp.AppendLayout( m_Y );
|
||||
disp.AppendLayout( m_GumpID );
|
||||
disp.AppendLayout( m_Width );
|
||||
disp.AppendLayout( m_Height );
|
||||
}
|
||||
}
|
||||
}
|
||||
164
Server/Gumps/GumpButton.cs
Normal file
164
Server/Gumps/GumpButton.cs
Normal file
@@ -0,0 +1,164 @@
|
||||
/***************************************************************************
|
||||
* GumpButton.cs
|
||||
* -------------------
|
||||
* begin : May 1, 2002
|
||||
* copyright : (C) The RunUO Software Team
|
||||
* email : info@runuo.com
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public enum GumpButtonType
|
||||
{
|
||||
Page = 0,
|
||||
Reply = 1
|
||||
}
|
||||
|
||||
public class GumpButton : GumpEntry
|
||||
{
|
||||
private int m_X, m_Y;
|
||||
private int m_ID1, m_ID2;
|
||||
private int m_ButtonID;
|
||||
private GumpButtonType m_Type;
|
||||
private int m_Param;
|
||||
|
||||
public GumpButton( int x, int y, int normalID, int pressedID, int buttonID, GumpButtonType type, int param )
|
||||
{
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_ID1 = normalID;
|
||||
m_ID2 = pressedID;
|
||||
m_ButtonID = buttonID;
|
||||
m_Type = type;
|
||||
m_Param = param;
|
||||
}
|
||||
|
||||
public int X
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_X;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_X, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Y;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Y, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int NormalID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_ID1;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_ID1, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int PressedID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_ID2;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_ID2, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int ButtonID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_ButtonID;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_ButtonID, value );
|
||||
}
|
||||
}
|
||||
|
||||
public GumpButtonType Type
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Type;
|
||||
}
|
||||
set
|
||||
{
|
||||
if ( m_Type != value )
|
||||
{
|
||||
m_Type = value;
|
||||
|
||||
Gump parent = Parent;
|
||||
|
||||
if ( parent != null )
|
||||
{
|
||||
parent.Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int Param
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Param;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Param, value );
|
||||
}
|
||||
}
|
||||
|
||||
public override string Compile()
|
||||
{
|
||||
return String.Format( "{{ button {0} {1} {2} {3} {4} {5} {6} }}", m_X, m_Y, m_ID1, m_ID2, (int)m_Type, m_Param, m_ButtonID );
|
||||
}
|
||||
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer( "button" );
|
||||
|
||||
public override void AppendTo( IGumpWriter disp )
|
||||
{
|
||||
disp.AppendLayout( m_LayoutName );
|
||||
disp.AppendLayout( m_X );
|
||||
disp.AppendLayout( m_Y );
|
||||
disp.AppendLayout( m_ID1 );
|
||||
disp.AppendLayout( m_ID2 );
|
||||
disp.AppendLayout( (int)m_Type );
|
||||
disp.AppendLayout( m_Param );
|
||||
disp.AppendLayout( m_ButtonID );
|
||||
}
|
||||
}
|
||||
}
|
||||
135
Server/Gumps/GumpCheck.cs
Normal file
135
Server/Gumps/GumpCheck.cs
Normal file
@@ -0,0 +1,135 @@
|
||||
/***************************************************************************
|
||||
* GumpCheck.cs
|
||||
* -------------------
|
||||
* begin : May 1, 2002
|
||||
* copyright : (C) The RunUO Software Team
|
||||
* email : info@runuo.com
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public class GumpCheck : GumpEntry
|
||||
{
|
||||
private int m_X, m_Y;
|
||||
private int m_ID1, m_ID2;
|
||||
private bool m_InitialState;
|
||||
private int m_SwitchID;
|
||||
|
||||
public int X
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_X;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_X, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Y;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Y, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int InactiveID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_ID1;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_ID1, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int ActiveID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_ID2;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_ID2, value );
|
||||
}
|
||||
}
|
||||
|
||||
public bool InitialState
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_InitialState;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_InitialState, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int SwitchID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_SwitchID;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_SwitchID, value );
|
||||
}
|
||||
}
|
||||
|
||||
public GumpCheck( int x, int y, int inactiveID, int activeID, bool initialState, int switchID )
|
||||
{
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_ID1 = inactiveID;
|
||||
m_ID2 = activeID;
|
||||
m_InitialState = initialState;
|
||||
m_SwitchID = switchID;
|
||||
}
|
||||
|
||||
public override string Compile()
|
||||
{
|
||||
return String.Format( "{{ checkbox {0} {1} {2} {3} {4} {5} }}", m_X, m_Y, m_ID1, m_ID2, m_InitialState ? 1 : 0, m_SwitchID );
|
||||
}
|
||||
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer( "checkbox" );
|
||||
|
||||
public override void AppendTo( IGumpWriter disp )
|
||||
{
|
||||
disp.AppendLayout( m_LayoutName );
|
||||
disp.AppendLayout( m_X );
|
||||
disp.AppendLayout( m_Y );
|
||||
disp.AppendLayout( m_ID1 );
|
||||
disp.AppendLayout( m_ID2 );
|
||||
disp.AppendLayout( m_InitialState );
|
||||
disp.AppendLayout( m_SwitchID );
|
||||
|
||||
disp.Switches++;
|
||||
}
|
||||
}
|
||||
}
|
||||
83
Server/Gumps/GumpEntry.cs
Normal file
83
Server/Gumps/GumpEntry.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
#region References
|
||||
using Server.Network;
|
||||
#endregion
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public abstract class GumpEntry
|
||||
{
|
||||
private Gump _Parent;
|
||||
|
||||
public Gump Parent
|
||||
{
|
||||
get { return _Parent; }
|
||||
set
|
||||
{
|
||||
if (_Parent == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_Parent != null)
|
||||
{
|
||||
_Parent.Remove(this);
|
||||
}
|
||||
|
||||
_Parent = value;
|
||||
|
||||
if (_Parent != null)
|
||||
{
|
||||
_Parent.Add(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void Delta(ref int var, int val)
|
||||
{
|
||||
if (var == val)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var = val;
|
||||
|
||||
if (_Parent != null)
|
||||
{
|
||||
_Parent.Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
protected void Delta(ref bool var, bool val)
|
||||
{
|
||||
if (var == val)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var = val;
|
||||
|
||||
if (_Parent != null)
|
||||
{
|
||||
_Parent.Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
protected void Delta(ref string var, string val)
|
||||
{
|
||||
if (var == val)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var = val;
|
||||
|
||||
if (_Parent != null)
|
||||
{
|
||||
_Parent.Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract string Compile();
|
||||
public abstract void AppendTo(IGumpWriter disp);
|
||||
}
|
||||
}
|
||||
60
Server/Gumps/GumpGroup.cs
Normal file
60
Server/Gumps/GumpGroup.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
/***************************************************************************
|
||||
* GumpGroup.cs
|
||||
* -------------------
|
||||
* begin : May 1, 2002
|
||||
* copyright : (C) The RunUO Software Team
|
||||
* email : info@runuo.com
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public class GumpGroup : GumpEntry
|
||||
{
|
||||
private int m_Group;
|
||||
|
||||
public GumpGroup( int group )
|
||||
{
|
||||
m_Group = group;
|
||||
}
|
||||
|
||||
public int Group
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Group;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Group, value );
|
||||
}
|
||||
}
|
||||
|
||||
public override string Compile()
|
||||
{
|
||||
return String.Format( "{{ group {0} }}", m_Group );
|
||||
}
|
||||
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer( "group" );
|
||||
|
||||
public override void AppendTo( IGumpWriter disp )
|
||||
{
|
||||
disp.AppendLayout( m_LayoutName );
|
||||
disp.AppendLayout( m_Group );
|
||||
}
|
||||
}
|
||||
}
|
||||
159
Server/Gumps/GumpHtml.cs
Normal file
159
Server/Gumps/GumpHtml.cs
Normal file
@@ -0,0 +1,159 @@
|
||||
/***************************************************************************
|
||||
* GumpHtml.cs
|
||||
* -------------------
|
||||
* begin : May 1, 2002
|
||||
* copyright : (C) The RunUO Software Team
|
||||
* email : info@runuo.com
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public class GumpHtml : GumpEntry
|
||||
{
|
||||
private int m_X, m_Y;
|
||||
private int m_Width, m_Height;
|
||||
private string m_Text;
|
||||
private readonly int m_TextID;
|
||||
private bool m_Background, m_Scrollbar;
|
||||
|
||||
public int X
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_X;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta(ref m_X, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Y;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta(ref m_Y, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Width;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta(ref m_Width, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Height;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta(ref m_Height, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string Text
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Text;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta(ref m_Text, value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Background
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Background;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta(ref m_Background, value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Scrollbar
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Scrollbar;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta(ref m_Scrollbar, value);
|
||||
}
|
||||
}
|
||||
|
||||
public GumpHtml(int x, int y, int width, int height, string text, bool background, bool scrollbar)
|
||||
{
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_Width = width;
|
||||
m_Height = height;
|
||||
m_Text = text;
|
||||
m_Background = background;
|
||||
m_Scrollbar = scrollbar;
|
||||
}
|
||||
|
||||
public GumpHtml(int x, int y, int width, int height, int textid, bool background, bool scrollbar)
|
||||
{
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_Width = width;
|
||||
m_Height = height;
|
||||
m_TextID = textid;
|
||||
m_Background = background;
|
||||
m_Scrollbar = scrollbar;
|
||||
}
|
||||
|
||||
public override string Compile()
|
||||
{
|
||||
return String.Format("{{ htmlgump {0} {1} {2} {3} {4} {5} {6} }}", m_X, m_Y, m_Width, m_Height, m_Text == null ? m_TextID : Parent.Intern(m_Text), m_Background ? 1 : 0, m_Scrollbar ? 1 : 0);
|
||||
}
|
||||
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer("htmlgump");
|
||||
|
||||
public override void AppendTo(IGumpWriter disp)
|
||||
{
|
||||
disp.AppendLayout(m_LayoutName);
|
||||
disp.AppendLayout(m_X);
|
||||
disp.AppendLayout(m_Y);
|
||||
disp.AppendLayout(m_Width);
|
||||
disp.AppendLayout(m_Height);
|
||||
disp.AppendLayout(m_Text == null ? m_TextID : Parent.Intern(m_Text));
|
||||
disp.AppendLayout(m_Background);
|
||||
disp.AppendLayout(m_Scrollbar);
|
||||
}
|
||||
}
|
||||
}
|
||||
287
Server/Gumps/GumpHtmlLocalized.cs
Normal file
287
Server/Gumps/GumpHtmlLocalized.cs
Normal file
@@ -0,0 +1,287 @@
|
||||
/***************************************************************************
|
||||
* GumpHtmlLocalized.cs
|
||||
* -------------------
|
||||
* begin : May 1, 2002
|
||||
* copyright : (C) The RunUO Software Team
|
||||
* email : info@runuo.com
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public enum GumpHtmlLocalizedType
|
||||
{
|
||||
Plain,
|
||||
Color,
|
||||
Args
|
||||
}
|
||||
|
||||
public class GumpHtmlLocalized : GumpEntry
|
||||
{
|
||||
private int m_X, m_Y;
|
||||
private int m_Width, m_Height;
|
||||
private int m_Number;
|
||||
private string m_Args;
|
||||
private int m_Color;
|
||||
private bool m_Background, m_Scrollbar;
|
||||
|
||||
private GumpHtmlLocalizedType m_Type;
|
||||
|
||||
public int X
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_X;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_X, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Y;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Y, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Width;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Width, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Height;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Height, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Number
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Number;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Number, value );
|
||||
}
|
||||
}
|
||||
|
||||
public string Args
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Args;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Args, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Color
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Color;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Color, value );
|
||||
}
|
||||
}
|
||||
|
||||
public bool Background
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Background;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Background, value );
|
||||
}
|
||||
}
|
||||
|
||||
public bool Scrollbar
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Scrollbar;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Scrollbar, value );
|
||||
}
|
||||
}
|
||||
|
||||
public GumpHtmlLocalizedType Type
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Type;
|
||||
}
|
||||
set
|
||||
{
|
||||
if ( m_Type != value )
|
||||
{
|
||||
m_Type = value;
|
||||
|
||||
if ( Parent != null )
|
||||
Parent.Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public GumpHtmlLocalized( int x, int y, int width, int height, int number, bool background, bool scrollbar )
|
||||
{
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_Width = width;
|
||||
m_Height = height;
|
||||
m_Number = number;
|
||||
m_Background = background;
|
||||
m_Scrollbar = scrollbar;
|
||||
|
||||
m_Type = GumpHtmlLocalizedType.Plain;
|
||||
}
|
||||
|
||||
public GumpHtmlLocalized( int x, int y, int width, int height, int number, int color, bool background, bool scrollbar )
|
||||
{
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_Width = width;
|
||||
m_Height = height;
|
||||
m_Number = number;
|
||||
m_Color = color;
|
||||
m_Background = background;
|
||||
m_Scrollbar = scrollbar;
|
||||
|
||||
m_Type = GumpHtmlLocalizedType.Color;
|
||||
}
|
||||
|
||||
public GumpHtmlLocalized( int x, int y, int width, int height, int number, string args, int color, bool background, bool scrollbar )
|
||||
{
|
||||
// Are multiple arguments unsupported? And what about non ASCII arguments?
|
||||
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_Width = width;
|
||||
m_Height = height;
|
||||
m_Number = number;
|
||||
m_Args = args;
|
||||
m_Color = color;
|
||||
m_Background = background;
|
||||
m_Scrollbar = scrollbar;
|
||||
|
||||
m_Type = GumpHtmlLocalizedType.Args;
|
||||
}
|
||||
|
||||
public override string Compile()
|
||||
{
|
||||
switch ( m_Type )
|
||||
{
|
||||
case GumpHtmlLocalizedType.Plain:
|
||||
return String.Format( "{{ xmfhtmlgump {0} {1} {2} {3} {4} {5} {6} }}", m_X, m_Y, m_Width, m_Height, m_Number, m_Background ? 1 : 0, m_Scrollbar ? 1 : 0 );
|
||||
|
||||
case GumpHtmlLocalizedType.Color:
|
||||
return String.Format( "{{ xmfhtmlgumpcolor {0} {1} {2} {3} {4} {5} {6} {7} }}", m_X, m_Y, m_Width, m_Height, m_Number, m_Background ? 1 : 0, m_Scrollbar ? 1 : 0, m_Color );
|
||||
|
||||
default: // GumpHtmlLocalizedType.Args
|
||||
return String.Format( "{{ xmfhtmltok {0} {1} {2} {3} {4} {5} {6} {7} @{8}@ }}", m_X, m_Y, m_Width, m_Height, m_Background ? 1 : 0, m_Scrollbar ? 1 : 0, m_Color, m_Number, m_Args );
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] m_LayoutNamePlain = Gump.StringToBuffer( "xmfhtmlgump" );
|
||||
private static byte[] m_LayoutNameColor = Gump.StringToBuffer( "xmfhtmlgumpcolor" );
|
||||
private static byte[] m_LayoutNameArgs = Gump.StringToBuffer( "xmfhtmltok" );
|
||||
|
||||
public override void AppendTo( IGumpWriter disp )
|
||||
{
|
||||
switch ( m_Type )
|
||||
{
|
||||
case GumpHtmlLocalizedType.Plain:
|
||||
{
|
||||
disp.AppendLayout( m_LayoutNamePlain );
|
||||
|
||||
disp.AppendLayout( m_X );
|
||||
disp.AppendLayout( m_Y );
|
||||
disp.AppendLayout( m_Width );
|
||||
disp.AppendLayout( m_Height );
|
||||
disp.AppendLayout( m_Number );
|
||||
disp.AppendLayout( m_Background );
|
||||
disp.AppendLayout( m_Scrollbar );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case GumpHtmlLocalizedType.Color:
|
||||
{
|
||||
disp.AppendLayout( m_LayoutNameColor );
|
||||
|
||||
disp.AppendLayout( m_X );
|
||||
disp.AppendLayout( m_Y );
|
||||
disp.AppendLayout( m_Width );
|
||||
disp.AppendLayout( m_Height );
|
||||
disp.AppendLayout( m_Number );
|
||||
disp.AppendLayout( m_Background );
|
||||
disp.AppendLayout( m_Scrollbar );
|
||||
disp.AppendLayout( m_Color );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case GumpHtmlLocalizedType.Args:
|
||||
{
|
||||
disp.AppendLayout( m_LayoutNameArgs );
|
||||
|
||||
disp.AppendLayout( m_X );
|
||||
disp.AppendLayout( m_Y );
|
||||
disp.AppendLayout( m_Width );
|
||||
disp.AppendLayout( m_Height );
|
||||
disp.AppendLayout( m_Background );
|
||||
disp.AppendLayout( m_Scrollbar );
|
||||
disp.AppendLayout( m_Color );
|
||||
disp.AppendLayout( m_Number );
|
||||
disp.AppendLayout( m_Args );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
117
Server/Gumps/GumpImage.cs
Normal file
117
Server/Gumps/GumpImage.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
/***************************************************************************
|
||||
* GumpImage.cs
|
||||
* -------------------
|
||||
* begin : May 1, 2002
|
||||
* copyright : (C) The RunUO Software Team
|
||||
* email : info@runuo.com
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public class GumpImage : GumpEntry
|
||||
{
|
||||
private int m_X, m_Y;
|
||||
private int m_GumpID;
|
||||
private int m_Hue;
|
||||
|
||||
public GumpImage( int x, int y, int gumpID ) : this( x, y, gumpID, 0 )
|
||||
{
|
||||
}
|
||||
|
||||
public GumpImage( int x, int y, int gumpID, int hue )
|
||||
{
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_GumpID = gumpID;
|
||||
m_Hue = hue;
|
||||
}
|
||||
|
||||
public int X
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_X;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_X, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Y;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Y, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int GumpID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_GumpID;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_GumpID, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Hue
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Hue;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Hue, value );
|
||||
}
|
||||
}
|
||||
|
||||
public override string Compile()
|
||||
{
|
||||
if ( m_Hue == 0 )
|
||||
return String.Format( "{{ gumppic {0} {1} {2} }}", m_X, m_Y, m_GumpID );
|
||||
else
|
||||
return String.Format( "{{ gumppic {0} {1} {2} hue={3} }}", m_X, m_Y, m_GumpID, m_Hue );
|
||||
}
|
||||
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer( "gumppic" );
|
||||
private static byte[] m_HueEquals = Gump.StringToBuffer( " hue=" );
|
||||
|
||||
public override void AppendTo( IGumpWriter disp )
|
||||
{
|
||||
disp.AppendLayout( m_LayoutName );
|
||||
disp.AppendLayout( m_X );
|
||||
disp.AppendLayout( m_Y );
|
||||
disp.AppendLayout( m_GumpID );
|
||||
|
||||
if ( m_Hue != 0 )
|
||||
{
|
||||
disp.AppendLayout( m_HueEquals );
|
||||
disp.AppendLayoutNS( m_Hue );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
252
Server/Gumps/GumpImageTileButton.cs
Normal file
252
Server/Gumps/GumpImageTileButton.cs
Normal file
@@ -0,0 +1,252 @@
|
||||
/***************************************************************************
|
||||
* GumpImageTileButton.cs
|
||||
* -------------------
|
||||
* begin : April 26, 2005
|
||||
* copyright : (C) The RunUO Software Team
|
||||
* email : info@runuo.com
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public class GumpImageTileButton : GumpEntry
|
||||
{
|
||||
//Note, on OSI, The tooltip supports ONLY clilocs as far as I can figure out, and the tooltip ONLY works after the buttonTileArt (as far as I can tell from testing)
|
||||
private int m_X, m_Y;
|
||||
private int m_ID1, m_ID2;
|
||||
private int m_ButtonID;
|
||||
private GumpButtonType m_Type;
|
||||
private int m_Param;
|
||||
|
||||
private int m_ItemID;
|
||||
private int m_Hue;
|
||||
private int m_Width;
|
||||
private int m_Height;
|
||||
|
||||
private int m_LocalizedTooltip;
|
||||
|
||||
public GumpImageTileButton( int x, int y, int normalID, int pressedID, int buttonID, GumpButtonType type, int param, int itemID, int hue, int width, int height ) : this(x, y, normalID, pressedID, buttonID, type, param, itemID, hue, width, height, -1 )
|
||||
{
|
||||
}
|
||||
|
||||
public GumpImageTileButton( int x, int y, int normalID, int pressedID, int buttonID, GumpButtonType type, int param, int itemID, int hue, int width, int height, int localizedTooltip )
|
||||
{
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_ID1 = normalID;
|
||||
m_ID2 = pressedID;
|
||||
m_ButtonID = buttonID;
|
||||
m_Type = type;
|
||||
m_Param = param;
|
||||
|
||||
m_ItemID = itemID;
|
||||
m_Hue = hue;
|
||||
m_Width = width;
|
||||
m_Height = height;
|
||||
|
||||
m_LocalizedTooltip = localizedTooltip;
|
||||
}
|
||||
|
||||
public int X
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_X;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_X, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Y;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Y, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int NormalID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_ID1;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_ID1, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int PressedID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_ID2;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_ID2, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int ButtonID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_ButtonID;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_ButtonID, value );
|
||||
}
|
||||
}
|
||||
|
||||
public GumpButtonType Type
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Type;
|
||||
}
|
||||
set
|
||||
{
|
||||
if( m_Type != value )
|
||||
{
|
||||
m_Type = value;
|
||||
|
||||
Gump parent = Parent;
|
||||
|
||||
if( parent != null )
|
||||
{
|
||||
parent.Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int Param
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Param;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Param, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int ItemID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_ItemID;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_ItemID, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Hue
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Hue;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Hue, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Width;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Width, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Height;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Height, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int LocalizedTooltip
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_LocalizedTooltip;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_LocalizedTooltip = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override string Compile()
|
||||
{
|
||||
if( m_LocalizedTooltip > 0 )
|
||||
return String.Format( "{{ buttontileart {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} }}{{ tooltip {11} }}", m_X, m_Y, m_ID1, m_ID2, (int)m_Type, m_Param, m_ButtonID, m_ItemID, m_Hue, m_Width, m_Height, m_LocalizedTooltip );
|
||||
else
|
||||
return String.Format( "{{ buttontileart {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} }}", m_X, m_Y, m_ID1, m_ID2, (int)m_Type, m_Param, m_ButtonID, m_ItemID, m_Hue, m_Width, m_Height );
|
||||
}
|
||||
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer( "buttontileart" );
|
||||
private static byte[] m_LayoutTooltip = Gump.StringToBuffer( " }{ tooltip" );
|
||||
|
||||
public override void AppendTo( IGumpWriter disp )
|
||||
{
|
||||
disp.AppendLayout( m_LayoutName );
|
||||
disp.AppendLayout( m_X );
|
||||
disp.AppendLayout( m_Y );
|
||||
disp.AppendLayout( m_ID1 );
|
||||
disp.AppendLayout( m_ID2 );
|
||||
disp.AppendLayout( (int)m_Type );
|
||||
disp.AppendLayout( m_Param );
|
||||
disp.AppendLayout( m_ButtonID );
|
||||
|
||||
disp.AppendLayout( m_ItemID );
|
||||
disp.AppendLayout( m_Hue );
|
||||
disp.AppendLayout( m_Width );
|
||||
disp.AppendLayout( m_Height );
|
||||
|
||||
if( m_LocalizedTooltip > 0 )
|
||||
{
|
||||
disp.AppendLayout( m_LayoutTooltip );
|
||||
disp.AppendLayout( m_LocalizedTooltip );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
118
Server/Gumps/GumpImageTiled.cs
Normal file
118
Server/Gumps/GumpImageTiled.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
/***************************************************************************
|
||||
* GumpImageTiled.cs
|
||||
* -------------------
|
||||
* begin : May 1, 2002
|
||||
* copyright : (C) The RunUO Software Team
|
||||
* email : info@runuo.com
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public class GumpImageTiled : GumpEntry
|
||||
{
|
||||
private int m_X, m_Y;
|
||||
private int m_Width, m_Height;
|
||||
private int m_GumpID;
|
||||
|
||||
public GumpImageTiled( int x, int y, int width, int height, int gumpID )
|
||||
{
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_Width = width;
|
||||
m_Height = height;
|
||||
m_GumpID = gumpID;
|
||||
}
|
||||
|
||||
public int X
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_X;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_X, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Y;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Y, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Width;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Width, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Height;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Height, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int GumpID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_GumpID;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_GumpID, value );
|
||||
}
|
||||
}
|
||||
|
||||
public override string Compile()
|
||||
{
|
||||
return String.Format( "{{ gumppictiled {0} {1} {2} {3} {4} }}", m_X, m_Y, m_Width, m_Height, m_GumpID );
|
||||
}
|
||||
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer( "gumppictiled" );
|
||||
|
||||
public override void AppendTo( IGumpWriter disp )
|
||||
{
|
||||
disp.AppendLayout( m_LayoutName );
|
||||
disp.AppendLayout( m_X );
|
||||
disp.AppendLayout( m_Y );
|
||||
disp.AppendLayout( m_Width );
|
||||
disp.AppendLayout( m_Height );
|
||||
disp.AppendLayout( m_GumpID );
|
||||
}
|
||||
}
|
||||
}
|
||||
114
Server/Gumps/GumpItem.cs
Normal file
114
Server/Gumps/GumpItem.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
/***************************************************************************
|
||||
* GumpItem.cs
|
||||
* -------------------
|
||||
* begin : May 1, 2002
|
||||
* copyright : (C) The RunUO Software Team
|
||||
* email : info@runuo.com
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public class GumpItem : GumpEntry
|
||||
{
|
||||
private int m_X, m_Y;
|
||||
private int m_ItemID;
|
||||
private int m_Hue;
|
||||
|
||||
public GumpItem( int x, int y, int itemID ) : this( x, y, itemID, 0 )
|
||||
{
|
||||
}
|
||||
|
||||
public GumpItem( int x, int y, int itemID, int hue )
|
||||
{
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_ItemID = itemID;
|
||||
m_Hue = hue;
|
||||
}
|
||||
|
||||
public int X
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_X;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_X, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Y;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Y, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int ItemID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_ItemID;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_ItemID, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Hue
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Hue;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Hue, value );
|
||||
}
|
||||
}
|
||||
|
||||
public override string Compile()
|
||||
{
|
||||
if ( m_Hue == 0 )
|
||||
return String.Format( "{{ tilepic {0} {1} {2} }}", m_X, m_Y, m_ItemID );
|
||||
else
|
||||
return String.Format( "{{ tilepichue {0} {1} {2} {3} }}", m_X, m_Y, m_ItemID, m_Hue );
|
||||
}
|
||||
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer( "tilepic" );
|
||||
private static byte[] m_LayoutNameHue = Gump.StringToBuffer( "tilepichue" );
|
||||
|
||||
public override void AppendTo( IGumpWriter disp )
|
||||
{
|
||||
disp.AppendLayout( m_Hue == 0 ? m_LayoutName : m_LayoutNameHue );
|
||||
disp.AppendLayout( m_X );
|
||||
disp.AppendLayout( m_Y );
|
||||
disp.AppendLayout( m_ItemID );
|
||||
|
||||
if ( m_Hue != 0 )
|
||||
disp.AppendLayout( m_Hue );
|
||||
}
|
||||
}
|
||||
}
|
||||
60
Server/Gumps/GumpItemProperty.cs
Normal file
60
Server/Gumps/GumpItemProperty.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
/***************************************************************************
|
||||
* GumpItemProperty.cs
|
||||
* -------------------
|
||||
* begin : May 26, 2013
|
||||
* copyright : (C) The RunUO Software Team
|
||||
* email : info@runuo.com
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public class GumpItemProperty : GumpEntry
|
||||
{
|
||||
private int m_Serial;
|
||||
|
||||
public GumpItemProperty( int serial )
|
||||
{
|
||||
m_Serial = serial;
|
||||
}
|
||||
|
||||
public int Serial
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Serial;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Serial, value );
|
||||
}
|
||||
}
|
||||
|
||||
public override string Compile()
|
||||
{
|
||||
return String.Format( "{{ itemproperty {0} }}", m_Serial );
|
||||
}
|
||||
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer( "itemproperty" );
|
||||
|
||||
public override void AppendTo( IGumpWriter disp )
|
||||
{
|
||||
disp.AppendLayout( m_LayoutName );
|
||||
disp.AppendLayout( m_Serial );
|
||||
}
|
||||
}
|
||||
}
|
||||
113
Server/Gumps/GumpLabel.cs
Normal file
113
Server/Gumps/GumpLabel.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
/***************************************************************************
|
||||
* GumpLabel.cs
|
||||
* -------------------
|
||||
* begin : May 1, 2002
|
||||
* copyright : (C) The RunUO Software Team
|
||||
* email : info@runuo.com
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public class GumpLabel : GumpEntry
|
||||
{
|
||||
private int m_X, m_Y;
|
||||
private int m_Hue;
|
||||
private string m_Text;
|
||||
private int m_TextID;
|
||||
|
||||
public GumpLabel( int x, int y, int hue, string text )
|
||||
{
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_Hue = hue;
|
||||
m_Text = text;
|
||||
}
|
||||
|
||||
public GumpLabel(int x, int y, int hue, int textid)
|
||||
{
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_Hue = hue;
|
||||
m_TextID = textid;
|
||||
}
|
||||
|
||||
public int X
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_X;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_X, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Y;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Y, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Hue
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Hue;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Hue, value );
|
||||
}
|
||||
}
|
||||
|
||||
public string Text
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Text;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Text, value );
|
||||
}
|
||||
}
|
||||
|
||||
public override string Compile()
|
||||
{
|
||||
return String.Format( "{{ text {0} {1} {2} {3} }}", m_X, m_Y, m_Hue, m_Text == null ? m_TextID : Parent.Intern(m_Text));
|
||||
}
|
||||
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer( "text" );
|
||||
|
||||
public override void AppendTo( IGumpWriter disp )
|
||||
{
|
||||
disp.AppendLayout( m_LayoutName );
|
||||
disp.AppendLayout( m_X );
|
||||
disp.AppendLayout( m_Y );
|
||||
disp.AppendLayout( m_Hue );
|
||||
disp.AppendLayout(m_Text == null ? m_TextID : Parent.Intern(m_Text));
|
||||
}
|
||||
}
|
||||
}
|
||||
144
Server/Gumps/GumpLabelCropped.cs
Normal file
144
Server/Gumps/GumpLabelCropped.cs
Normal file
@@ -0,0 +1,144 @@
|
||||
/***************************************************************************
|
||||
* GumpLabelCropped.cs
|
||||
* -------------------
|
||||
* begin : May 1, 2002
|
||||
* copyright : (C) The RunUO Software Team
|
||||
* email : info@runuo.com
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public class GumpLabelCropped : GumpEntry
|
||||
{
|
||||
private int m_X, m_Y;
|
||||
private int m_Width, m_Height;
|
||||
private int m_Hue;
|
||||
private string m_Text;
|
||||
private int m_TextID;
|
||||
|
||||
public int X
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_X;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_X, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Y;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Y, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Width;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Width, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Height;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Height, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Hue
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Hue;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Hue, value );
|
||||
}
|
||||
}
|
||||
|
||||
public string Text
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Text;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Text, value );
|
||||
}
|
||||
}
|
||||
|
||||
public GumpLabelCropped( int x, int y, int width, int height, int hue, string text )
|
||||
{
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_Width = width;
|
||||
m_Height = height;
|
||||
m_Hue = hue;
|
||||
m_Text = text;
|
||||
}
|
||||
|
||||
public GumpLabelCropped(int x, int y, int width, int height, int hue, int textid)
|
||||
{
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_Width = width;
|
||||
m_Height = height;
|
||||
m_Hue = hue;
|
||||
m_TextID = textid;
|
||||
}
|
||||
|
||||
public override string Compile()
|
||||
{
|
||||
return String.Format( "{{ croppedtext {0} {1} {2} {3} {4} {5} }}", m_X, m_Y, m_Width, m_Height, m_Hue, m_Text == null ? m_TextID : Parent.Intern(m_Text));
|
||||
}
|
||||
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer( "croppedtext" );
|
||||
|
||||
public override void AppendTo( IGumpWriter disp )
|
||||
{
|
||||
disp.AppendLayout( m_LayoutName );
|
||||
disp.AppendLayout( m_X );
|
||||
disp.AppendLayout( m_Y );
|
||||
disp.AppendLayout( m_Width );
|
||||
disp.AppendLayout( m_Height );
|
||||
disp.AppendLayout( m_Hue );
|
||||
disp.AppendLayout( m_Text == null ? m_TextID : Parent.Intern(m_Text) );
|
||||
}
|
||||
}
|
||||
}
|
||||
60
Server/Gumps/GumpPage.cs
Normal file
60
Server/Gumps/GumpPage.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
/***************************************************************************
|
||||
* GumpPage.cs
|
||||
* -------------------
|
||||
* begin : May 1, 2002
|
||||
* copyright : (C) The RunUO Software Team
|
||||
* email : info@runuo.com
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public class GumpPage : GumpEntry
|
||||
{
|
||||
private int m_Page;
|
||||
|
||||
public GumpPage( int page )
|
||||
{
|
||||
m_Page = page;
|
||||
}
|
||||
|
||||
public int Page
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Page;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Page, value );
|
||||
}
|
||||
}
|
||||
|
||||
public override string Compile()
|
||||
{
|
||||
return String.Format( "{{ page {0} }}", m_Page );
|
||||
}
|
||||
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer( "page" );
|
||||
|
||||
public override void AppendTo( IGumpWriter disp )
|
||||
{
|
||||
disp.AppendLayout( m_LayoutName );
|
||||
disp.AppendLayout( m_Page );
|
||||
}
|
||||
}
|
||||
}
|
||||
135
Server/Gumps/GumpRadio.cs
Normal file
135
Server/Gumps/GumpRadio.cs
Normal file
@@ -0,0 +1,135 @@
|
||||
/***************************************************************************
|
||||
* GumpRadio.cs
|
||||
* -------------------
|
||||
* begin : May 1, 2002
|
||||
* copyright : (C) The RunUO Software Team
|
||||
* email : info@runuo.com
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public class GumpRadio : GumpEntry
|
||||
{
|
||||
private int m_X, m_Y;
|
||||
private int m_ID1, m_ID2;
|
||||
private bool m_InitialState;
|
||||
private int m_SwitchID;
|
||||
|
||||
public int X
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_X;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_X, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Y;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Y, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int InactiveID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_ID1;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_ID1, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int ActiveID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_ID2;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_ID2, value );
|
||||
}
|
||||
}
|
||||
|
||||
public bool InitialState
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_InitialState;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_InitialState, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int SwitchID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_SwitchID;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_SwitchID, value );
|
||||
}
|
||||
}
|
||||
|
||||
public GumpRadio( int x, int y, int inactiveID, int activeID, bool initialState, int switchID )
|
||||
{
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_ID1 = inactiveID;
|
||||
m_ID2 = activeID;
|
||||
m_InitialState = initialState;
|
||||
m_SwitchID = switchID;
|
||||
}
|
||||
|
||||
public override string Compile()
|
||||
{
|
||||
return String.Format( "{{ radio {0} {1} {2} {3} {4} {5} }}", m_X, m_Y, m_ID1, m_ID2, m_InitialState ? 1 : 0, m_SwitchID );
|
||||
}
|
||||
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer( "radio" );
|
||||
|
||||
public override void AppendTo( IGumpWriter disp )
|
||||
{
|
||||
disp.AppendLayout( m_LayoutName );
|
||||
disp.AppendLayout( m_X );
|
||||
disp.AppendLayout( m_Y );
|
||||
disp.AppendLayout( m_ID1 );
|
||||
disp.AppendLayout( m_ID2 );
|
||||
disp.AppendLayout( m_InitialState );
|
||||
disp.AppendLayout( m_SwitchID );
|
||||
|
||||
disp.Switches++;
|
||||
}
|
||||
}
|
||||
}
|
||||
126
Server/Gumps/GumpSpriteImage.cs
Normal file
126
Server/Gumps/GumpSpriteImage.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public class GumpSpriteImage : GumpEntry
|
||||
{
|
||||
private int m_X, m_Y, m_SX, m_SY;
|
||||
private int m_Width, m_Height;
|
||||
private int m_GumpID;
|
||||
|
||||
public GumpSpriteImage(int x, int y, int gumpID, int width, int height, int sx, int sy)
|
||||
{
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_GumpID = gumpID;
|
||||
m_Width = width;
|
||||
m_Height = height;
|
||||
m_SX = sx;
|
||||
m_SY = sy;
|
||||
}
|
||||
|
||||
public int X
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_X;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta(ref m_X, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Y;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta(ref m_Y, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Width;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta(ref m_Width, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Height;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta(ref m_Height, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int GumpID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_GumpID;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta(ref m_GumpID, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int SX
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_SX;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta(ref m_SX, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int SY
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_SY;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta(ref m_SY, value);
|
||||
}
|
||||
}
|
||||
|
||||
public override string Compile()
|
||||
{
|
||||
return String.Format("{{ picinpic {0} {1} {2} {3} {4} {5} {6} }}", m_X, m_Y, m_GumpID, m_Width, m_Height, m_SX, m_SY);
|
||||
}
|
||||
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer("picinpic");
|
||||
|
||||
public override void AppendTo(IGumpWriter disp)
|
||||
{
|
||||
disp.AppendLayout(m_LayoutName);
|
||||
disp.AppendLayout(m_X);
|
||||
disp.AppendLayout(m_Y);
|
||||
disp.AppendLayout(m_GumpID);
|
||||
disp.AppendLayout(m_Width);
|
||||
disp.AppendLayout(m_Height);
|
||||
disp.AppendLayout(m_SX);
|
||||
disp.AppendLayout(m_SY);
|
||||
}
|
||||
}
|
||||
}
|
||||
162
Server/Gumps/GumpTextEntry.cs
Normal file
162
Server/Gumps/GumpTextEntry.cs
Normal file
@@ -0,0 +1,162 @@
|
||||
/***************************************************************************
|
||||
* GumpTextEntry.cs
|
||||
* -------------------
|
||||
* begin : May 1, 2002
|
||||
* copyright : (C) The RunUO Software Team
|
||||
* email : info@runuo.com
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public class GumpTextEntry : GumpEntry
|
||||
{
|
||||
private int m_X, m_Y;
|
||||
private int m_Width, m_Height;
|
||||
private int m_Hue;
|
||||
private int m_EntryID;
|
||||
private string m_InitialText;
|
||||
private int m_InitialTextID = -1;
|
||||
|
||||
public int X
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_X;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_X, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Y;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Y, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Width;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Width, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Height;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Height, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Hue
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Hue;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Hue, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int EntryID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_EntryID;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_EntryID, value );
|
||||
}
|
||||
}
|
||||
|
||||
public string InitialText
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_InitialText;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_InitialText, value );
|
||||
}
|
||||
}
|
||||
|
||||
public GumpTextEntry( int x, int y, int width, int height, int hue, int entryID, string initialText )
|
||||
{
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_Width = width;
|
||||
m_Height = height;
|
||||
m_Hue = hue;
|
||||
m_EntryID = entryID;
|
||||
m_InitialText = initialText;
|
||||
}
|
||||
|
||||
public GumpTextEntry(int x, int y, int width, int height, int hue, int entryID, int initialTextID)
|
||||
{
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_Width = width;
|
||||
m_Height = height;
|
||||
m_Hue = hue;
|
||||
m_EntryID = entryID;
|
||||
m_InitialTextID = initialTextID;
|
||||
}
|
||||
|
||||
public override string Compile()
|
||||
{
|
||||
return String.Format( "{{ textentry {0} {1} {2} {3} {4} {5} {6} }}", m_X, m_Y, m_Width, m_Height, m_Hue, m_EntryID, m_InitialTextID == -1 ? Parent.Intern(m_InitialText) : m_InitialTextID);
|
||||
}
|
||||
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer( "textentry" );
|
||||
|
||||
public override void AppendTo( IGumpWriter disp )
|
||||
{
|
||||
disp.AppendLayout( m_LayoutName );
|
||||
disp.AppendLayout( m_X );
|
||||
disp.AppendLayout( m_Y );
|
||||
disp.AppendLayout( m_Width );
|
||||
disp.AppendLayout( m_Height );
|
||||
disp.AppendLayout( m_Hue );
|
||||
disp.AppendLayout( m_EntryID );
|
||||
disp.AppendLayout(m_InitialTextID == -1 ? Parent.Intern(m_InitialText) : m_InitialTextID);
|
||||
|
||||
disp.TextEntries++;
|
||||
}
|
||||
}
|
||||
}
|
||||
136
Server/Gumps/GumpTextEntryLimited.cs
Normal file
136
Server/Gumps/GumpTextEntryLimited.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
/***************************************************************************
|
||||
* GumpTextEntryLimited.cs
|
||||
* -------------------
|
||||
* begin : May 1, 2002
|
||||
* copyright : (C) The RunUO Software Team
|
||||
* email : info@runuo.com
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Gumps {
|
||||
public class GumpTextEntryLimited : GumpEntry {
|
||||
private int m_X, m_Y;
|
||||
private int m_Width, m_Height;
|
||||
private int m_Hue;
|
||||
private int m_EntryID;
|
||||
private string m_InitialText;
|
||||
private int m_Size;
|
||||
|
||||
public int X {
|
||||
get {
|
||||
return m_X;
|
||||
}
|
||||
set {
|
||||
Delta( ref m_X, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Y {
|
||||
get {
|
||||
return m_Y;
|
||||
}
|
||||
set {
|
||||
Delta( ref m_Y, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Width {
|
||||
get {
|
||||
return m_Width;
|
||||
}
|
||||
set {
|
||||
Delta( ref m_Width, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Height {
|
||||
get {
|
||||
return m_Height;
|
||||
}
|
||||
set {
|
||||
Delta( ref m_Height, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Hue {
|
||||
get {
|
||||
return m_Hue;
|
||||
}
|
||||
set {
|
||||
Delta( ref m_Hue, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int EntryID {
|
||||
get {
|
||||
return m_EntryID;
|
||||
}
|
||||
set {
|
||||
Delta( ref m_EntryID, value );
|
||||
}
|
||||
}
|
||||
|
||||
public string InitialText {
|
||||
get {
|
||||
return m_InitialText;
|
||||
}
|
||||
set {
|
||||
Delta( ref m_InitialText, value );
|
||||
}
|
||||
}
|
||||
|
||||
public int Size {
|
||||
get {
|
||||
return m_Size;
|
||||
}
|
||||
set {
|
||||
Delta( ref m_Size, value );
|
||||
}
|
||||
}
|
||||
|
||||
public GumpTextEntryLimited( int x, int y, int width, int height, int hue, int entryID, string initialText, int size ) {
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_Width = width;
|
||||
m_Height = height;
|
||||
m_Hue = hue;
|
||||
m_EntryID = entryID;
|
||||
m_InitialText = initialText;
|
||||
m_Size = size;
|
||||
}
|
||||
|
||||
public override string Compile() {
|
||||
return String.Format( "{{ textentrylimited {0} {1} {2} {3} {4} {5} {6} {7} }}", m_X, m_Y, m_Width, m_Height, m_Hue, m_EntryID, Parent.Intern( m_InitialText ), m_Size );
|
||||
}
|
||||
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer( "textentrylimited" );
|
||||
|
||||
public override void AppendTo( IGumpWriter disp ) {
|
||||
disp.AppendLayout( m_LayoutName );
|
||||
disp.AppendLayout( m_X );
|
||||
disp.AppendLayout( m_Y );
|
||||
disp.AppendLayout( m_Width );
|
||||
disp.AppendLayout( m_Height );
|
||||
disp.AppendLayout( m_Hue );
|
||||
disp.AppendLayout( m_EntryID );
|
||||
disp.AppendLayout( Parent.Intern( m_InitialText ) );
|
||||
disp.AppendLayout( m_Size );
|
||||
|
||||
disp.TextEntries++;
|
||||
}
|
||||
}
|
||||
}
|
||||
59
Server/Gumps/GumpTooltip.cs
Normal file
59
Server/Gumps/GumpTooltip.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
/***************************************************************************
|
||||
* GumpTooltip.cs
|
||||
* -------------------
|
||||
* begin : May 1, 2002
|
||||
* copyright : (C) The RunUO Software Team
|
||||
* email : info@runuo.com
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public class GumpTooltip : GumpEntry
|
||||
{
|
||||
private int m_Number;
|
||||
public GumpTooltip( int number )
|
||||
{
|
||||
m_Number = number;
|
||||
}
|
||||
|
||||
public int Number
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Number;
|
||||
}
|
||||
set
|
||||
{
|
||||
Delta( ref m_Number, value );
|
||||
}
|
||||
}
|
||||
|
||||
public override string Compile()
|
||||
{
|
||||
return string.Format("{{ tooltip {0} }}", m_Number);
|
||||
}
|
||||
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer( "tooltip" );
|
||||
|
||||
public override void AppendTo( IGumpWriter disp )
|
||||
{
|
||||
disp.AppendLayout( m_LayoutName );
|
||||
disp.AppendLayout( m_Number );
|
||||
}
|
||||
}
|
||||
}
|
||||
116
Server/Gumps/RelayInfo.cs
Normal file
116
Server/Gumps/RelayInfo.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
/***************************************************************************
|
||||
* RelayInfo.cs
|
||||
* -------------------
|
||||
* begin : May 1, 2002
|
||||
* copyright : (C) The RunUO Software Team
|
||||
* email : info@runuo.com
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
using System;
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public class TextRelay
|
||||
{
|
||||
private int m_EntryID;
|
||||
private string m_Text;
|
||||
|
||||
public TextRelay( int entryID, string text )
|
||||
{
|
||||
m_EntryID = entryID;
|
||||
m_Text = text;
|
||||
}
|
||||
|
||||
public int EntryID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_EntryID;
|
||||
}
|
||||
}
|
||||
|
||||
public string Text
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class RelayInfo
|
||||
{
|
||||
private int m_ButtonID;
|
||||
private int[] m_Switches;
|
||||
private TextRelay[] m_TextEntries;
|
||||
|
||||
public RelayInfo( int buttonID, int[] switches, TextRelay[] textEntries )
|
||||
{
|
||||
m_ButtonID = buttonID;
|
||||
m_Switches = switches;
|
||||
m_TextEntries = textEntries;
|
||||
}
|
||||
|
||||
public int ButtonID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_ButtonID;
|
||||
}
|
||||
}
|
||||
|
||||
public int[] Switches
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Switches;
|
||||
}
|
||||
}
|
||||
|
||||
public TextRelay[] TextEntries
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_TextEntries;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSwitched( int switchID )
|
||||
{
|
||||
for ( int i = 0; i < m_Switches.Length; ++i )
|
||||
{
|
||||
if ( m_Switches[i] == switchID )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public TextRelay GetTextEntry( int entryID )
|
||||
{
|
||||
for ( int i = 0; i < m_TextEntries.Length; ++i )
|
||||
{
|
||||
if ( m_TextEntries[i].EntryID == entryID )
|
||||
{
|
||||
return m_TextEntries[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
38
Server/HuePicker.cs
Normal file
38
Server/HuePicker.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
#region References
|
||||
using Server.Network;
|
||||
#endregion
|
||||
|
||||
namespace Server.HuePickers
|
||||
{
|
||||
public class HuePicker
|
||||
{
|
||||
private static int m_NextSerial = 1;
|
||||
|
||||
private readonly int m_Serial;
|
||||
private readonly int m_ItemID;
|
||||
|
||||
public int Serial { get { return m_Serial; } }
|
||||
|
||||
public int ItemID { get { return m_ItemID; } }
|
||||
|
||||
public HuePicker(int itemID)
|
||||
{
|
||||
do
|
||||
{
|
||||
m_Serial = m_NextSerial++;
|
||||
}
|
||||
while (m_Serial == 0);
|
||||
|
||||
m_ItemID = itemID;
|
||||
}
|
||||
|
||||
public virtual void OnResponse(int hue)
|
||||
{ }
|
||||
|
||||
public void SendTo(NetState state)
|
||||
{
|
||||
state.Send(new DisplayHuePicker(this));
|
||||
state.AddHuePicker(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
285
Server/IAccount.cs
Normal file
285
Server/IAccount.cs
Normal file
@@ -0,0 +1,285 @@
|
||||
#region References
|
||||
using System;
|
||||
#endregion
|
||||
|
||||
namespace Server.Accounting
|
||||
{
|
||||
public static class AccountGold
|
||||
{
|
||||
public static bool Enabled = false;
|
||||
|
||||
/// <summary>
|
||||
/// This amount specifies the value at which point Gold turns to Platinum.
|
||||
/// By default, when 1,000,000,000 Gold is accumulated, it will transform
|
||||
/// into 1 Platinum.
|
||||
/// !!! WARNING !!!
|
||||
/// The client is designed to perceive the currency threashold at 1,000,000,000
|
||||
/// if you change this, it may cause unexpected results when using secure trading.
|
||||
/// </summary>
|
||||
public static int CurrencyThreshold = 1000000000;
|
||||
|
||||
/// <summary>
|
||||
/// Enables or Disables automatic conversion of Gold and Checks to Bank Currency
|
||||
/// when they are added to a bank box container.
|
||||
/// </summary>
|
||||
public static bool ConvertOnBank = true;
|
||||
|
||||
/// <summary>
|
||||
/// Enables or Disables automatic conversion of Gold and Checks to Bank Currency
|
||||
/// when they are added to a secure trade container.
|
||||
/// </summary>
|
||||
public static bool ConvertOnTrade = false;
|
||||
|
||||
public static double GetGoldTotal(Mobile m)
|
||||
{
|
||||
if (m == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return GetGoldTotal(m.Account);
|
||||
}
|
||||
|
||||
public static double GetGoldTotal(IGoldAccount a)
|
||||
{
|
||||
if (a == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gold;
|
||||
double totalGold;
|
||||
|
||||
a.GetGoldBalance(out gold, out totalGold);
|
||||
|
||||
return totalGold;
|
||||
}
|
||||
|
||||
public static double GetPlatTotal(Mobile m)
|
||||
{
|
||||
if (m == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return GetPlatTotal(m.Account);
|
||||
}
|
||||
|
||||
public static double GetPlatTotal(IGoldAccount a)
|
||||
{
|
||||
if (a == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plat;
|
||||
double totalPlat;
|
||||
|
||||
a.GetPlatBalance(out plat, out totalPlat);
|
||||
|
||||
return totalPlat;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IGoldAccount
|
||||
{
|
||||
/// <summary>
|
||||
/// This amount represents the total amount of currency owned by the player.
|
||||
/// It is cumulative of both Gold and Platinum, the absolute total amount of
|
||||
/// Gold owned by the player can be found by multiplying this value by the
|
||||
/// CurrencyThreshold value.
|
||||
/// </summary>
|
||||
[CommandProperty(AccessLevel.Administrator)]
|
||||
double TotalCurrency { get; }
|
||||
|
||||
/// <summary>
|
||||
/// This amount represents the current amount of Gold owned by the player.
|
||||
/// The value does not include the value of Platinum and ranges from
|
||||
/// 0 to 999,999,999 by default.
|
||||
/// </summary>
|
||||
[CommandProperty(AccessLevel.Administrator)]
|
||||
int TotalGold { get; }
|
||||
|
||||
/// <summary>
|
||||
/// This amount represents the current amount of Platinum owned by the player.
|
||||
/// The value does not include the value of Gold and ranges from
|
||||
/// 0 to 2,147,483,647 by default.
|
||||
/// One Platinum represents the value of CurrencyThreshold in Gold.
|
||||
/// </summary>
|
||||
[CommandProperty(AccessLevel.Administrator)]
|
||||
int TotalPlat { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to deposit the given amount of Gold and Platinum into this account.
|
||||
/// </summary>
|
||||
/// <param name="amount">Amount to deposit.</param>
|
||||
/// <returns>True if successful, false if amount given is less than or equal to zero.</returns>
|
||||
bool DepositCurrency(double amount);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to deposit the given amount of Gold into this account.
|
||||
/// If the given amount is greater than the CurrencyThreshold,
|
||||
/// Platinum will be deposited to offset the difference.
|
||||
/// </summary>
|
||||
/// <param name="amount">Amount to deposit.</param>
|
||||
/// <returns>True if successful, false if amount given is less than or equal to zero.</returns>
|
||||
bool DepositGold(int amount);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to deposit the given amount of Gold into this account.
|
||||
/// If the given amount is greater than the CurrencyThreshold,
|
||||
/// Platinum will be deposited to offset the difference.
|
||||
/// </summary>
|
||||
/// <param name="amount">Amount to deposit.</param>
|
||||
/// <returns>True if successful, false if amount given is less than or equal to zero.</returns>
|
||||
bool DepositGold(long amount);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to deposit the given amount of Platinum into this account.
|
||||
/// </summary>
|
||||
/// <param name="amount">Amount to deposit.</param>
|
||||
/// <returns>True if successful, false if amount given is less than or equal to zero.</returns>
|
||||
bool DepositPlat(int amount);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to deposit the given amount of Platinum into this account.
|
||||
/// </summary>
|
||||
/// <param name="amount">Amount to deposit.</param>
|
||||
/// <returns>True if successful, false if amount given is less than or equal to zero.</returns>
|
||||
bool DepositPlat(long amount);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to withdraw the given amount of Platinum and Gold from this account.
|
||||
/// </summary>
|
||||
/// <param name="amount">Amount to withdraw.</param>
|
||||
/// <returns>True if successful, false if balance was too low.</returns>
|
||||
bool WithdrawCurrency(double amount);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to withdraw the given amount of Gold from this account.
|
||||
/// If the given amount is greater than the CurrencyThreshold,
|
||||
/// Platinum will be withdrawn to offset the difference.
|
||||
/// </summary>
|
||||
/// <param name="amount">Amount to withdraw.</param>
|
||||
/// <returns>True if successful, false if balance was too low.</returns>
|
||||
bool WithdrawGold(int amount);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to withdraw the given amount of Gold from this account.
|
||||
/// If the given amount is greater than the CurrencyThreshold,
|
||||
/// Platinum will be withdrawn to offset the difference.
|
||||
/// </summary>
|
||||
/// <param name="amount">Amount to withdraw.</param>
|
||||
/// <returns>True if successful, false if balance was too low.</returns>
|
||||
bool WithdrawGold(long amount);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to withdraw the given amount of Platinum from this account.
|
||||
/// </summary>
|
||||
/// <param name="amount">Amount to withdraw.</param>
|
||||
/// <returns>True if successful, false if balance was too low.</returns>
|
||||
bool WithdrawPlat(int amount);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to withdraw the given amount of Platinum from this account.
|
||||
/// </summary>
|
||||
/// <param name="amount">Amount to withdraw.</param>
|
||||
/// <returns>True if successful, false if balance was too low.</returns>
|
||||
bool WithdrawPlat(long amount);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total balance of Gold for this account.
|
||||
/// </summary>
|
||||
/// <param name="gold">Gold value, Platinum exclusive</param>
|
||||
/// <param name="totalGold">Gold value, Platinum inclusive</param>
|
||||
void GetGoldBalance(out int gold, out double totalGold);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total balance of Gold for this account.
|
||||
/// </summary>
|
||||
/// <param name="gold">Gold value, Platinum exclusive</param>
|
||||
/// <param name="totalGold">Gold value, Platinum inclusive</param>
|
||||
void GetGoldBalance(out long gold, out double totalGold);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total balance of Platinum for this account.
|
||||
/// </summary>
|
||||
/// <param name="plat">Platinum value, Gold exclusive</param>
|
||||
/// <param name="totalPlat">Platinum value, Gold inclusive</param>
|
||||
void GetPlatBalance(out int plat, out double totalPlat);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total balance of Platinum for this account.
|
||||
/// </summary>
|
||||
/// <param name="plat">Platinum value, Gold exclusive</param>
|
||||
/// <param name="totalPlat">Platinum value, Gold inclusive</param>
|
||||
void GetPlatBalance(out long plat, out double totalPlat);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total balance of Gold and Platinum for this account.
|
||||
/// </summary>
|
||||
/// <param name="gold">Gold value, Platinum exclusive</param>
|
||||
/// <param name="totalGold">Gold value, Platinum inclusive</param>
|
||||
/// <param name="plat">Platinum value, Gold exclusive</param>
|
||||
/// <param name="totalPlat">Platinum value, Gold inclusive</param>
|
||||
void GetBalance(out int gold, out double totalGold, out int plat, out double totalPlat);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total balance of Gold and Platinum for this account.
|
||||
/// </summary>
|
||||
/// <param name="gold">Gold value, Platinum exclusive</param>
|
||||
/// <param name="totalGold">Gold value, Platinum inclusive</param>
|
||||
/// <param name="plat">Platinum value, Gold exclusive</param>
|
||||
/// <param name="totalPlat">Platinum value, Gold inclusive</param>
|
||||
void GetBalance(out long gold, out double totalGold, out long plat, out double totalPlat);
|
||||
|
||||
bool HasGoldBalance(double amount);
|
||||
bool HasPlatBalance(double amount);
|
||||
}
|
||||
|
||||
public interface IAccount : IGoldAccount, IComparable<IAccount>
|
||||
{
|
||||
[CommandProperty(AccessLevel.Administrator, true)]
|
||||
string Username { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.Administrator, true)]
|
||||
string Email { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.Administrator, AccessLevel.Owner)]
|
||||
AccessLevel AccessLevel { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.Administrator)]
|
||||
int Length { get; }
|
||||
|
||||
[CommandProperty(AccessLevel.Administrator)]
|
||||
int Limit { get; }
|
||||
|
||||
[CommandProperty(AccessLevel.Administrator)]
|
||||
int Count { get; }
|
||||
|
||||
[CommandProperty(AccessLevel.Administrator, true)]
|
||||
DateTime Created { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.Administrator, true)]
|
||||
DateTime LastLogin { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.Administrator)]
|
||||
TimeSpan Age { get; }
|
||||
|
||||
[CommandProperty(AccessLevel.Administrator)]
|
||||
TimeSpan TotalGameTime { get; }
|
||||
|
||||
[CommandProperty(AccessLevel.Administrator)]
|
||||
bool Banned { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.Administrator)]
|
||||
bool Young { get; set; }
|
||||
|
||||
Mobile this[int index] { get; set; }
|
||||
|
||||
void Delete();
|
||||
|
||||
void SetPassword(string password);
|
||||
bool CheckPassword(string password);
|
||||
}
|
||||
}
|
||||
105
Server/IEntity.cs
Normal file
105
Server/IEntity.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
#region References
|
||||
using System;
|
||||
#endregion
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public interface IEntity : IPoint3D, IComparable, IComparable<IEntity>
|
||||
{
|
||||
Serial Serial { get; }
|
||||
|
||||
Point3D Location { get; set; }
|
||||
Map Map { get; set; }
|
||||
|
||||
bool NoMoveHS { get; set; }
|
||||
|
||||
Direction Direction { get; set; }
|
||||
|
||||
string Name { get; set; }
|
||||
|
||||
int Hue { get; set; }
|
||||
|
||||
bool Deleted { get; }
|
||||
|
||||
void Delete();
|
||||
void ProcessDelta();
|
||||
void InvalidateProperties();
|
||||
void OnStatsQuery(Mobile m);
|
||||
}
|
||||
|
||||
public class Entity : IEntity, IComparable<Entity>
|
||||
{
|
||||
public Serial Serial { get; private set; }
|
||||
|
||||
public Point3D Location { get; set; }
|
||||
public Map Map { get; set; }
|
||||
|
||||
public int X { get { return Location.X; } }
|
||||
public int Y { get { return Location.Y; } }
|
||||
public int Z { get { return Location.Z; } }
|
||||
|
||||
public bool Deleted { get; private set; }
|
||||
|
||||
public bool NoMoveHS { get; set; }
|
||||
|
||||
Direction IEntity.Direction { get; set; }
|
||||
|
||||
string IEntity.Name { get; set; }
|
||||
|
||||
int IEntity.Hue { get; set; }
|
||||
|
||||
public Entity(Serial serial, Point3D loc, Map map)
|
||||
{
|
||||
Serial = serial;
|
||||
Location = loc;
|
||||
Map = map;
|
||||
}
|
||||
|
||||
public int CompareTo(IEntity other)
|
||||
{
|
||||
if (other == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return Serial.CompareTo(other.Serial);
|
||||
}
|
||||
|
||||
public int CompareTo(Entity other)
|
||||
{
|
||||
return CompareTo((IEntity)other);
|
||||
}
|
||||
|
||||
public int CompareTo(object other)
|
||||
{
|
||||
if (other == null || other is IEntity)
|
||||
{
|
||||
return CompareTo((IEntity)other);
|
||||
}
|
||||
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
if (Deleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Deleted = true;
|
||||
|
||||
Location = Point3D.Zero;
|
||||
Map = null;
|
||||
}
|
||||
|
||||
void IEntity.ProcessDelta()
|
||||
{ }
|
||||
|
||||
void IEntity.InvalidateProperties()
|
||||
{ }
|
||||
|
||||
void IEntity.OnStatsQuery(Mobile m)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
65
Server/Insensitive.cs
Normal file
65
Server/Insensitive.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
#region References
|
||||
using System.Collections;
|
||||
#endregion
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public static class Insensitive
|
||||
{
|
||||
private static readonly IComparer m_Comparer = CaseInsensitiveComparer.Default;
|
||||
|
||||
public static IComparer Comparer { get { return m_Comparer; } }
|
||||
|
||||
public static int Compare(string a, string b)
|
||||
{
|
||||
return m_Comparer.Compare(a, b);
|
||||
}
|
||||
|
||||
public static bool Equals(string a, string b)
|
||||
{
|
||||
if (a == null && b == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (a == null || b == null || a.Length != b.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (m_Comparer.Compare(a, b) == 0);
|
||||
}
|
||||
|
||||
public static bool StartsWith(string a, string b)
|
||||
{
|
||||
if (a == null || b == null || a.Length < b.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (m_Comparer.Compare(a.Substring(0, b.Length), b) == 0);
|
||||
}
|
||||
|
||||
public static bool EndsWith(string a, string b)
|
||||
{
|
||||
if (a == null || b == null || a.Length < b.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (m_Comparer.Compare(a.Substring(a.Length - b.Length), b) == 0);
|
||||
}
|
||||
|
||||
public static bool Contains(string a, string b)
|
||||
{
|
||||
if (a == null || b == null || a.Length < b.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
a = a.ToLower();
|
||||
b = b.ToLower();
|
||||
|
||||
return (a.IndexOf(b) >= 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
145
Server/Interfaces.cs
Normal file
145
Server/Interfaces.cs
Normal file
@@ -0,0 +1,145 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Server.ContextMenus;
|
||||
using Server.Mobiles;
|
||||
#endregion
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public interface IMount
|
||||
{
|
||||
Mobile Rider { get; set; }
|
||||
void OnRiderDamaged(Mobile from, ref int amount, bool willKill);
|
||||
}
|
||||
|
||||
public interface IMountItem
|
||||
{
|
||||
IMount Mount { get; }
|
||||
}
|
||||
}
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public interface IVendor
|
||||
{
|
||||
bool OnBuyItems(Mobile from, List<BuyItemResponse> list);
|
||||
bool OnSellItems(Mobile from, List<SellItemResponse> list);
|
||||
|
||||
DateTime LastRestock { get; set; }
|
||||
TimeSpan RestockDelay { get; }
|
||||
void Restock();
|
||||
}
|
||||
|
||||
public interface IPoint2D
|
||||
{
|
||||
int X { get; }
|
||||
int Y { get; }
|
||||
}
|
||||
|
||||
public interface IPoint3D : IPoint2D
|
||||
{
|
||||
int Z { get; }
|
||||
}
|
||||
|
||||
public interface ICarvable
|
||||
{
|
||||
bool Carve(Mobile from, Item item);
|
||||
}
|
||||
|
||||
public interface IWeapon
|
||||
{
|
||||
int MaxRange { get; }
|
||||
void OnBeforeSwing(Mobile attacker, IDamageable damageable);
|
||||
TimeSpan OnSwing(Mobile attacker, IDamageable damageable);
|
||||
void GetStatusDamage(Mobile from, out int min, out int max);
|
||||
TimeSpan GetDelay(Mobile attacker);
|
||||
}
|
||||
|
||||
public interface IHued
|
||||
{
|
||||
int HuedItemID { get; }
|
||||
}
|
||||
|
||||
public interface ISpell
|
||||
{
|
||||
int ID { get; }
|
||||
bool IsCasting { get; }
|
||||
void OnCasterHurt();
|
||||
void OnCasterKilled();
|
||||
void OnConnectionChanged();
|
||||
bool OnCasterMoving(Direction d);
|
||||
bool CheckMovement(Mobile caster);
|
||||
bool OnCasterEquiping(Item item);
|
||||
bool OnCasterUsingObject(object o);
|
||||
bool OnCastInTown(Region r);
|
||||
}
|
||||
|
||||
public interface IParty
|
||||
{
|
||||
void OnStamChanged(Mobile m);
|
||||
void OnManaChanged(Mobile m);
|
||||
void OnStatsQuery(Mobile beholder, Mobile beheld);
|
||||
}
|
||||
|
||||
public interface ISpawner
|
||||
{
|
||||
bool UnlinkOnTaming { get; }
|
||||
Point3D HomeLocation { get; }
|
||||
int HomeRange { get; }
|
||||
|
||||
void Remove(ISpawnable spawn);
|
||||
|
||||
void GetSpawnProperties(ISpawnable spawn, ObjectPropertyList list);
|
||||
void GetSpawnContextEntries(ISpawnable spawn, Mobile m, List<ContextMenuEntry> list);
|
||||
}
|
||||
|
||||
public interface ISpawnable : IEntity
|
||||
{
|
||||
void OnBeforeSpawn(Point3D location, Map map);
|
||||
void MoveToWorld(Point3D location, Map map);
|
||||
void OnAfterSpawn();
|
||||
|
||||
ISpawner Spawner { get; set; }
|
||||
}
|
||||
|
||||
public interface IDamageable : IEntity
|
||||
{
|
||||
int Hits { get; set; }
|
||||
int HitsMax { get; }
|
||||
bool Alive { get; }
|
||||
|
||||
int PhysicalResistance { get; }
|
||||
int FireResistance { get; }
|
||||
int ColdResistance { get; }
|
||||
int PoisonResistance { get; }
|
||||
int EnergyResistance { get; }
|
||||
|
||||
int Damage(int amount, Mobile attacker);
|
||||
|
||||
void PlaySound(int soundID);
|
||||
|
||||
void MovingEffect(IEntity to, int itemID, int speed, int duration, bool fixedDirection, bool explodes, int hue, int renderMode);
|
||||
void MovingEffect(IEntity to, int itemID, int speed, int duration, bool fixedDirection, bool explodes);
|
||||
|
||||
void MovingParticles(IEntity to, int itemID, int speed, int duration, bool fixedDirection, bool explodes, int hue, int renderMode, int effect, int explodeEffect, int explodeSound, EffectLayer layer, int unknown);
|
||||
void MovingParticles(IEntity to, int itemID, int speed, int duration, bool fixedDirection, bool explodes, int hue, int renderMode, int effect, int explodeEffect, int explodeSound, int unknown);
|
||||
void MovingParticles(IEntity to, int itemID, int speed, int duration, bool fixedDirection, bool explodes, int effect, int explodeEffect, int explodeSound, int unknown);
|
||||
void MovingParticles(IEntity to, int itemID, int speed, int duration, bool fixedDirection, bool explodes, int effect, int explodeEffect, int explodeSound);
|
||||
|
||||
void FixedEffect(int itemID, int speed, int duration, int hue, int renderMode);
|
||||
void FixedEffect(int itemID, int speed, int duration);
|
||||
|
||||
void FixedParticles(int itemID, int speed, int duration, int effect, int hue, int renderMode, EffectLayer layer, int unknown);
|
||||
void FixedParticles(int itemID, int speed, int duration, int effect, int hue, int renderMode, EffectLayer layer);
|
||||
void FixedParticles(int itemID, int speed, int duration, int effect, EffectLayer layer, int unknown);
|
||||
void FixedParticles(int itemID, int speed, int duration, int effect, EffectLayer layer);
|
||||
void BoltEffect(int hue);
|
||||
}
|
||||
|
||||
public interface IArtifact
|
||||
{
|
||||
int ArtifactRarity { get; }
|
||||
}
|
||||
}
|
||||
6496
Server/Item.cs
Normal file
6496
Server/Item.cs
Normal file
File diff suppressed because it is too large
Load Diff
45
Server/ItemBounds.cs
Normal file
45
Server/ItemBounds.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.IO;
|
||||
#endregion
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public static class ItemBounds
|
||||
{
|
||||
private static readonly Rectangle2D[] m_Bounds;
|
||||
|
||||
public static Rectangle2D[] Table { get { return m_Bounds; } }
|
||||
|
||||
static ItemBounds()
|
||||
{
|
||||
m_Bounds = new Rectangle2D[TileData.ItemTable.Length];
|
||||
|
||||
if (File.Exists("Data/Binary/Bounds.bin"))
|
||||
{
|
||||
using (FileStream fs = new FileStream("Data/Binary/Bounds.bin", FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
BinaryReader bin = new BinaryReader(fs);
|
||||
|
||||
int count = Math.Min(m_Bounds.Length, (int)(fs.Length / 8));
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
int xMin = bin.ReadInt16();
|
||||
int yMin = bin.ReadInt16();
|
||||
int xMax = bin.ReadInt16();
|
||||
int yMax = bin.ReadInt16();
|
||||
|
||||
m_Bounds[i].Set(xMin, yMin, (xMax - xMin) + 1, (yMax - yMin) + 1);
|
||||
}
|
||||
|
||||
bin.Close();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Warning: Data/Binary/Bounds.bin does not exist");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
177
Server/Items/BaseMulti.cs
Normal file
177
Server/Items/BaseMulti.cs
Normal file
@@ -0,0 +1,177 @@
|
||||
#region References
|
||||
using Server.Network;
|
||||
using System;
|
||||
#endregion
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public class BaseMulti : Item
|
||||
{
|
||||
[Constructable]
|
||||
public BaseMulti(int itemID)
|
||||
: base(itemID)
|
||||
{
|
||||
Movable = false;
|
||||
}
|
||||
|
||||
public BaseMulti(Serial serial)
|
||||
: base(serial)
|
||||
{ }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public override int ItemID
|
||||
{
|
||||
get { return base.ItemID; }
|
||||
set
|
||||
{
|
||||
if (base.ItemID != value)
|
||||
{
|
||||
Map facet = (Parent == null ? Map : null);
|
||||
|
||||
if (facet != null)
|
||||
{
|
||||
facet.OnLeave(this);
|
||||
}
|
||||
|
||||
base.ItemID = value;
|
||||
|
||||
if (facet != null)
|
||||
{
|
||||
facet.OnEnter(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("Replace with calls to OnLeave and OnEnter surrounding component invalidation.", true)]
|
||||
public virtual void RefreshComponents()
|
||||
{
|
||||
if (Parent == null)
|
||||
{
|
||||
Map facet = Map;
|
||||
|
||||
if (facet != null)
|
||||
{
|
||||
facet.OnLeave(this);
|
||||
facet.OnEnter(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override int LabelNumber
|
||||
{
|
||||
get
|
||||
{
|
||||
MultiComponentList mcl = Components;
|
||||
|
||||
if (mcl.List.Length > 0)
|
||||
{
|
||||
int id = mcl.List[0].m_ItemID;
|
||||
|
||||
if (id < 0x4000)
|
||||
{
|
||||
return 1020000 + id;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1078872 + id;
|
||||
}
|
||||
}
|
||||
|
||||
return base.LabelNumber;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool AllowsRelativeDrop { get { return false; } }
|
||||
|
||||
public override int GetUpdateRange(Mobile m)
|
||||
{
|
||||
int min = m.NetState != null ? m.NetState.UpdateRange : Core.GlobalUpdateRange;
|
||||
int max = Core.GlobalRadarRange - 1;
|
||||
|
||||
int w = Components.Width;
|
||||
int h = Components.Height - 1;
|
||||
int v = min + ((w > h ? w : h) / 2);
|
||||
|
||||
if (v > max)
|
||||
v = max;
|
||||
else if (v < min)
|
||||
v = min;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public virtual MultiComponentList Components { get { return MultiData.GetComponents(ItemID); } }
|
||||
|
||||
public virtual bool Contains(Point2D p)
|
||||
{
|
||||
return Contains(p.m_X, p.m_Y);
|
||||
}
|
||||
|
||||
public virtual bool Contains(Point3D p)
|
||||
{
|
||||
return Contains(p.m_X, p.m_Y);
|
||||
}
|
||||
|
||||
public virtual bool Contains(IPoint3D p)
|
||||
{
|
||||
return Contains(p.X, p.Y);
|
||||
}
|
||||
|
||||
public virtual bool Contains(int x, int y)
|
||||
{
|
||||
MultiComponentList mcl = Components;
|
||||
|
||||
x -= X + mcl.Min.m_X;
|
||||
y -= Y + mcl.Min.m_Y;
|
||||
|
||||
return x >= 0 && x < mcl.Width && y >= 0 && y < mcl.Height && mcl.Tiles[x][y].Length > 0;
|
||||
}
|
||||
|
||||
public bool Contains(Mobile m)
|
||||
{
|
||||
if (m.Map == Map)
|
||||
{
|
||||
return Contains(m.X, m.Y);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Contains(Item item)
|
||||
{
|
||||
if (item.Map == Map)
|
||||
{
|
||||
return Contains(item.X, item.Y);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(1); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
|
||||
if (version == 0)
|
||||
{
|
||||
if (ItemID >= 0x4000)
|
||||
{
|
||||
ItemID -= 0x4000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2198
Server/Items/Container.cs
Normal file
2198
Server/Items/Container.cs
Normal file
File diff suppressed because it is too large
Load Diff
163
Server/Items/Containers.cs
Normal file
163
Server/Items/Containers.cs
Normal file
@@ -0,0 +1,163 @@
|
||||
#region References
|
||||
using System;
|
||||
|
||||
using Server.Accounting;
|
||||
using Server.Network;
|
||||
#endregion
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public class BankBox : Container
|
||||
{
|
||||
private static readonly Type _GoldType = ScriptCompiler.FindTypeByFullName("Server.Items.Gold");
|
||||
private static readonly Type _CheckType = ScriptCompiler.FindTypeByFullName("Server.Items.BankCheck");
|
||||
|
||||
public static bool SendDeleteOnClose { get; set; }
|
||||
|
||||
private Mobile m_Owner;
|
||||
private bool m_Open;
|
||||
|
||||
public override int DefaultMaxWeight { get { return 0; } }
|
||||
|
||||
public override bool IsVirtualItem { get { return true; } }
|
||||
|
||||
public Mobile Owner { get { return m_Owner; } }
|
||||
|
||||
public bool Opened { get { return m_Open; } }
|
||||
|
||||
public BankBox(Mobile owner)
|
||||
: base(0xE7C)
|
||||
{
|
||||
m_Owner = owner;
|
||||
|
||||
Movable = false;
|
||||
Layer = Layer.Bank;
|
||||
}
|
||||
|
||||
public BankBox(Serial serial)
|
||||
: base(serial)
|
||||
{ }
|
||||
|
||||
public void Open()
|
||||
{
|
||||
if (m_Owner != null && m_Owner.NetState != null)
|
||||
{
|
||||
m_Open = true;
|
||||
|
||||
m_Owner.PrivateOverheadMessage(
|
||||
MessageType.Regular,
|
||||
0x3B2,
|
||||
true,
|
||||
String.Format("Bank container has {0} items, {1} stones", TotalItems, TotalWeight),
|
||||
m_Owner.NetState);
|
||||
|
||||
m_Owner.Send(new EquipUpdate(this));
|
||||
|
||||
DisplayTo(m_Owner);
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
m_Open = false;
|
||||
|
||||
if (m_Owner != null && SendDeleteOnClose)
|
||||
{
|
||||
m_Owner.Send(RemovePacket);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSingleClick(Mobile from)
|
||||
{ }
|
||||
|
||||
public override void OnDoubleClick(Mobile from)
|
||||
{ }
|
||||
|
||||
public override DeathMoveResult OnParentDeath(Mobile parent)
|
||||
{
|
||||
return DeathMoveResult.RemainEquiped;
|
||||
}
|
||||
|
||||
public override bool IsAccessibleTo(Mobile check)
|
||||
{
|
||||
if ((check == m_Owner && m_Open) || check.AccessLevel >= AccessLevel.GameMaster)
|
||||
{
|
||||
return base.IsAccessibleTo(check);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool OnDragDrop(Mobile from, Item dropped)
|
||||
{
|
||||
if ((from == m_Owner && m_Open) || from.AccessLevel >= AccessLevel.GameMaster)
|
||||
{
|
||||
return base.OnDragDrop(from, dropped);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool OnDragDropInto(Mobile from, Item item, Point3D p)
|
||||
{
|
||||
if ((from == m_Owner && m_Open) || from.AccessLevel >= AccessLevel.GameMaster)
|
||||
{
|
||||
return base.OnDragDropInto(from, item, p);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetTotal(TotalType type)
|
||||
{
|
||||
if (AccountGold.Enabled && Owner != null && Owner.Account != null && type == TotalType.Gold)
|
||||
{
|
||||
return Owner.Account.TotalGold;
|
||||
}
|
||||
|
||||
return base.GetTotal(type);
|
||||
}
|
||||
|
||||
public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight)
|
||||
{
|
||||
Type type = item.GetType();
|
||||
|
||||
if (AccountGold.Enabled && Owner != null && Owner.Account != null && (type.IsAssignableFrom(_GoldType) || type.IsAssignableFrom(_CheckType)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.CheckHold(m, item, message, checkItems, plusItems, plusWeight);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
|
||||
writer.Write(m_Owner);
|
||||
writer.Write(m_Open);
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
reader.ReadInt();
|
||||
|
||||
m_Owner = reader.ReadMobile();
|
||||
m_Open = reader.ReadBool();
|
||||
|
||||
if (ItemID == 0xE41)
|
||||
{
|
||||
ItemID = 0xE7C;
|
||||
}
|
||||
|
||||
if (m_Owner == null)
|
||||
{
|
||||
Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
129
Server/Items/SecureTradeContainer.cs
Normal file
129
Server/Items/SecureTradeContainer.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
#region References
|
||||
using Server.Accounting;
|
||||
using Server.Network;
|
||||
#endregion
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public class SecureTradeContainer : Container
|
||||
{
|
||||
private readonly SecureTrade m_Trade;
|
||||
|
||||
public SecureTrade Trade { get { return m_Trade; } }
|
||||
|
||||
public SecureTradeContainer(SecureTrade trade)
|
||||
: base(0x1E5E)
|
||||
{
|
||||
m_Trade = trade;
|
||||
Movable = false;
|
||||
|
||||
Layer = Layer.SecureTrade;
|
||||
}
|
||||
|
||||
public SecureTradeContainer(Serial serial)
|
||||
: base(serial)
|
||||
{ }
|
||||
|
||||
public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight)
|
||||
{
|
||||
if (item == Trade.From.VirtualCheck || item == Trade.To.VirtualCheck)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var to = Trade.From.Container != this ? Trade.From.Mobile : Trade.To.Mobile;
|
||||
|
||||
return m.CheckTrade(to, item, this, message, checkItems, plusItems, plusWeight);
|
||||
}
|
||||
|
||||
public override bool CheckLift(Mobile from, Item item, ref LRReason reject)
|
||||
{
|
||||
reject = LRReason.CannotLift;
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool IsAccessibleTo(Mobile check)
|
||||
{
|
||||
if (!IsChildOf(check) || m_Trade == null || !m_Trade.Valid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.IsAccessibleTo(check);
|
||||
}
|
||||
|
||||
public override void OnItemAdded(Item item)
|
||||
{
|
||||
if (!(item is VirtualCheck))
|
||||
{
|
||||
ClearChecks();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnItemRemoved(Item item)
|
||||
{
|
||||
if (!(item is VirtualCheck))
|
||||
{
|
||||
ClearChecks();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSubItemAdded(Item item)
|
||||
{
|
||||
if (!(item is VirtualCheck))
|
||||
{
|
||||
ClearChecks();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSubItemRemoved(Item item)
|
||||
{
|
||||
if (!(item is VirtualCheck))
|
||||
{
|
||||
ClearChecks();
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearChecks()
|
||||
{
|
||||
if (m_Trade != null)
|
||||
{
|
||||
if (m_Trade.From != null && !m_Trade.From.IsDisposed)
|
||||
{
|
||||
m_Trade.From.Accepted = false;
|
||||
}
|
||||
|
||||
if (m_Trade.To != null && !m_Trade.To.IsDisposed)
|
||||
{
|
||||
m_Trade.To.Accepted = false;
|
||||
}
|
||||
|
||||
m_Trade.Update();
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsChildVisibleTo(Mobile m, Item child)
|
||||
{
|
||||
if (child is VirtualCheck)
|
||||
{
|
||||
return AccountGold.Enabled && (m.NetState == null || !m.NetState.NewSecureTrading);
|
||||
}
|
||||
|
||||
return base.IsChildVisibleTo(m, child);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0);
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
389
Server/Items/VirtualCheck.cs
Normal file
389
Server/Items/VirtualCheck.cs
Normal file
@@ -0,0 +1,389 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
using Server.Accounting;
|
||||
using Server.Gumps;
|
||||
using Server.Network;
|
||||
#endregion
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public sealed class VirtualCheck : Item
|
||||
{
|
||||
public static bool UseEditGump = false;
|
||||
|
||||
public override bool IsVirtualItem { get { return true; } }
|
||||
|
||||
public override bool DisplayWeight { get { return false; } }
|
||||
public override bool DisplayLootType { get { return false; } }
|
||||
|
||||
public override double DefaultWeight { get { return 0; } }
|
||||
|
||||
public override string DefaultName { get { return "Offer Of Currency"; } }
|
||||
|
||||
public EditGump Editor { get; private set; }
|
||||
|
||||
private int _Plat;
|
||||
|
||||
[CommandProperty(AccessLevel.Administrator)]
|
||||
public int Plat
|
||||
{
|
||||
get { return _Plat; }
|
||||
set
|
||||
{
|
||||
_Plat = value;
|
||||
InvalidateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
private int _Gold;
|
||||
|
||||
[CommandProperty(AccessLevel.Administrator)]
|
||||
public int Gold
|
||||
{
|
||||
get { return _Gold; }
|
||||
set
|
||||
{
|
||||
_Gold = value;
|
||||
InvalidateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
public VirtualCheck()
|
||||
: this(0, 0)
|
||||
{ }
|
||||
|
||||
public VirtualCheck(int plat, int gold)
|
||||
: base(0x14F0)
|
||||
{
|
||||
Plat = plat;
|
||||
Gold = gold;
|
||||
|
||||
Movable = false;
|
||||
}
|
||||
|
||||
public VirtualCheck(Serial serial)
|
||||
: base(serial)
|
||||
{ }
|
||||
|
||||
public override bool IsAccessibleTo(Mobile check)
|
||||
{
|
||||
var c = GetSecureTradeCont();
|
||||
|
||||
if (check == null || c == null)
|
||||
{
|
||||
return base.IsAccessibleTo(check);
|
||||
}
|
||||
|
||||
return c.RootParent == check && IsChildOf(c);
|
||||
}
|
||||
|
||||
public override void OnDoubleClickSecureTrade(Mobile from)
|
||||
{
|
||||
if (UseEditGump && IsAccessibleTo(from))
|
||||
{
|
||||
if (Editor == null || Editor.Check == null || Editor.Check.Deleted)
|
||||
{
|
||||
Editor = new EditGump(from, this);
|
||||
Editor.Send();
|
||||
}
|
||||
else
|
||||
{
|
||||
Editor.Refresh(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Editor != null)
|
||||
{
|
||||
Editor.Close();
|
||||
Editor = null;
|
||||
}
|
||||
|
||||
base.OnDoubleClickSecureTrade(from);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSingleClick(Mobile from)
|
||||
{
|
||||
LabelTo(from, "Offer: {0:#,0} platinum, {1:#,0} gold", Plat, Gold);
|
||||
}
|
||||
|
||||
public override void GetProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.GetProperties(list);
|
||||
|
||||
list.Add(1060738, String.Format("{0:#,0} platinum, {1:#,0} gold", Plat, Gold)); // value: ~1_val~
|
||||
}
|
||||
|
||||
public void UpdateTrade(Mobile user)
|
||||
{
|
||||
var c = GetSecureTradeCont();
|
||||
|
||||
if (c == null || c.Trade == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (user == c.Trade.From.Mobile)
|
||||
{
|
||||
c.Trade.UpdateFromCurrency();
|
||||
}
|
||||
else if (user == c.Trade.To.Mobile)
|
||||
{
|
||||
c.Trade.UpdateToCurrency();
|
||||
}
|
||||
|
||||
c.ClearChecks();
|
||||
}
|
||||
|
||||
public override void OnAfterDelete()
|
||||
{
|
||||
base.OnAfterDelete();
|
||||
|
||||
if (Editor != null)
|
||||
{
|
||||
Editor.Close();
|
||||
Editor = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{ }
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
Delete();
|
||||
}
|
||||
|
||||
public class EditGump : Gump
|
||||
{
|
||||
public enum Buttons
|
||||
{
|
||||
Close,
|
||||
Clear,
|
||||
Accept,
|
||||
AllPlat,
|
||||
AllGold
|
||||
}
|
||||
|
||||
private int _Plat, _Gold;
|
||||
|
||||
public Mobile User { get; private set; }
|
||||
public VirtualCheck Check { get; private set; }
|
||||
|
||||
public EditGump(Mobile user, VirtualCheck check)
|
||||
: base(50, 50)
|
||||
{
|
||||
User = user;
|
||||
Check = check;
|
||||
|
||||
_Plat = Check.Plat;
|
||||
_Gold = Check.Gold;
|
||||
|
||||
Closable = true;
|
||||
Disposable = true;
|
||||
Dragable = true;
|
||||
Resizable = false;
|
||||
|
||||
User.CloseGump(GetType());
|
||||
|
||||
CompileLayout();
|
||||
}
|
||||
|
||||
public override void OnServerClose(NetState owner)
|
||||
{
|
||||
base.OnServerClose(owner);
|
||||
|
||||
if (Check != null && !Check.Deleted)
|
||||
{
|
||||
Check.UpdateTrade(User);
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
User.CloseGump(GetType());
|
||||
|
||||
if (Check != null && !Check.Deleted)
|
||||
{
|
||||
Check.UpdateTrade(User);
|
||||
}
|
||||
else
|
||||
{
|
||||
Check = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Send()
|
||||
{
|
||||
if (Check != null && !Check.Deleted)
|
||||
{
|
||||
User.SendGump(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
public void Refresh(bool recompile)
|
||||
{
|
||||
if (Check == null || Check.Deleted)
|
||||
{
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (recompile)
|
||||
{
|
||||
CompileLayout();
|
||||
}
|
||||
|
||||
Close();
|
||||
Send();
|
||||
}
|
||||
|
||||
private void CompileLayout()
|
||||
{
|
||||
if (Check == null || Check.Deleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Entries.ForEach(e => e.Parent = null);
|
||||
Entries.Clear();
|
||||
|
||||
AddPage(0);
|
||||
|
||||
AddBackground(0, 0, 400, 160, 3500);
|
||||
|
||||
// Title
|
||||
AddImageTiled(25, 35, 350, 3, 96);
|
||||
AddImage(10, 8, 113);
|
||||
AddImage(360, 8, 113);
|
||||
|
||||
var title = String.Format(
|
||||
"<BASEFONT COLOR=#{0:X6}><CENTER>BANK OF {1}</CENTER>",
|
||||
Color.DarkSlateGray.ToArgb() & 0x00FFFFFF,
|
||||
User.RawName.ToUpper());
|
||||
|
||||
AddHtml(40, 15, 320, 20, title, false, false);
|
||||
|
||||
// Platinum Row
|
||||
AddBackground(15, 60, 175, 20, 9300);
|
||||
AddBackground(20, 45, 165, 30, 9350);
|
||||
AddItem(20, 45, 3826); // Plat
|
||||
AddLabel(60, 50, 0, User.Account.TotalPlat.ToString("#,0"));
|
||||
|
||||
AddButton(195, 50, 95, 95, (int)Buttons.AllPlat, GumpButtonType.Reply, 0); // ->
|
||||
|
||||
AddBackground(210, 60, 175, 20, 9300);
|
||||
AddBackground(215, 45, 165, 30, 9350);
|
||||
AddTextEntry(225, 50, 145, 20, 0, 0, _Plat.ToString(), User.Account.TotalPlat.ToString().Length);
|
||||
|
||||
// Gold Row
|
||||
AddBackground(15, 100, 175, 20, 9300);
|
||||
AddBackground(20, 85, 165, 30, 9350);
|
||||
AddItem(20, 85, 3823); // Gold
|
||||
AddLabel(60, 90, 0, User.Account.TotalGold.ToString("#,0"));
|
||||
|
||||
AddButton(195, 90, 95, 95, (int)Buttons.AllGold, GumpButtonType.Reply, 0); // ->
|
||||
|
||||
AddBackground(210, 100, 175, 20, 9300);
|
||||
AddBackground(215, 85, 165, 30, 9350);
|
||||
AddTextEntry(225, 90, 145, 20, 0, 1, _Gold.ToString(), User.Account.TotalGold.ToString().Length);
|
||||
|
||||
// Buttons
|
||||
AddButton(20, 128, 12006, 12007, (int)Buttons.Close, GumpButtonType.Reply, 0);
|
||||
AddButton(215, 128, 12003, 12004, (int)Buttons.Clear, GumpButtonType.Reply, 0);
|
||||
AddButton(305, 128, 12000, 12002, (int)Buttons.Accept, GumpButtonType.Reply, 0);
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo info)
|
||||
{
|
||||
if (Check == null || Check.Deleted || sender.Mobile != User)
|
||||
{
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
bool refresh = false, updated = false;
|
||||
|
||||
switch ((Buttons)info.ButtonID)
|
||||
{
|
||||
case Buttons.Close:
|
||||
break;
|
||||
case Buttons.Clear:
|
||||
{
|
||||
_Plat = _Gold = 0;
|
||||
refresh = true;
|
||||
}
|
||||
break;
|
||||
case Buttons.Accept:
|
||||
{
|
||||
var platText = info.GetTextEntry(0).Text;
|
||||
var goldText = info.GetTextEntry(1).Text;
|
||||
|
||||
if (!Int32.TryParse(platText, out _Plat))
|
||||
{
|
||||
User.SendMessage("That is not a valid amount of platinum.");
|
||||
refresh = true;
|
||||
}
|
||||
else if (!Int32.TryParse(goldText, out _Gold))
|
||||
{
|
||||
User.SendMessage("That is not a valid amount of gold.");
|
||||
refresh = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var cur = User.Account.TotalCurrency;
|
||||
var off = _Plat + (_Gold / Math.Max(1.0, AccountGold.CurrencyThreshold));
|
||||
|
||||
if (off > cur)
|
||||
{
|
||||
_Plat = User.Account.TotalPlat;
|
||||
_Gold = User.Account.TotalGold;
|
||||
User.SendMessage("You do not have that much currency.");
|
||||
refresh = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Check.Plat = _Plat;
|
||||
Check.Gold = _Gold;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Buttons.AllPlat:
|
||||
{
|
||||
_Plat = User.Account.TotalPlat;
|
||||
refresh = true;
|
||||
}
|
||||
break;
|
||||
case Buttons.AllGold:
|
||||
{
|
||||
_Gold = User.Account.TotalGold;
|
||||
refresh = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (updated)
|
||||
{
|
||||
User.SendMessage("Your offer has been updated.");
|
||||
}
|
||||
|
||||
if (refresh && Check != null && !Check.Deleted)
|
||||
{
|
||||
Refresh(true);
|
||||
return;
|
||||
}
|
||||
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
209
Server/Items/VirtualHair.cs
Normal file
209
Server/Items/VirtualHair.cs
Normal file
@@ -0,0 +1,209 @@
|
||||
#region References
|
||||
using Server.Network;
|
||||
#endregion
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public abstract class BaseHairInfo
|
||||
{
|
||||
private int m_ItemID;
|
||||
private int m_Hue;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int ItemID { get { return m_ItemID; } set { m_ItemID = value; } }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int Hue { get { return m_Hue; } set { m_Hue = value; } }
|
||||
|
||||
protected BaseHairInfo(int itemid)
|
||||
: this(itemid, 0)
|
||||
{ }
|
||||
|
||||
protected BaseHairInfo(int itemid, int hue)
|
||||
{
|
||||
m_ItemID = itemid;
|
||||
m_Hue = hue;
|
||||
}
|
||||
|
||||
protected BaseHairInfo(GenericReader reader)
|
||||
{
|
||||
int version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
m_ItemID = reader.ReadInt();
|
||||
m_Hue = reader.ReadInt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Serialize(GenericWriter writer)
|
||||
{
|
||||
writer.Write(0); //version
|
||||
writer.Write(m_ItemID);
|
||||
writer.Write(m_Hue);
|
||||
}
|
||||
}
|
||||
|
||||
public class HairInfo : BaseHairInfo
|
||||
{
|
||||
public HairInfo(int itemid)
|
||||
: base(itemid, 0)
|
||||
{ }
|
||||
|
||||
public HairInfo(int itemid, int hue)
|
||||
: base(itemid, hue)
|
||||
{ }
|
||||
|
||||
public HairInfo(GenericReader reader)
|
||||
: base(reader)
|
||||
{ }
|
||||
|
||||
public static int FakeSerial(Mobile parent)
|
||||
{
|
||||
return (0x7FFFFFFF - 0x400 - (parent.Serial * 4));
|
||||
}
|
||||
}
|
||||
|
||||
public class FacialHairInfo : BaseHairInfo
|
||||
{
|
||||
public FacialHairInfo(int itemid)
|
||||
: base(itemid, 0)
|
||||
{ }
|
||||
|
||||
public FacialHairInfo(int itemid, int hue)
|
||||
: base(itemid, hue)
|
||||
{ }
|
||||
|
||||
public FacialHairInfo(GenericReader reader)
|
||||
: base(reader)
|
||||
{ }
|
||||
|
||||
public static int FakeSerial(Mobile parent)
|
||||
{
|
||||
return (0x7FFFFFFF - 0x400 - 1 - (parent.Serial * 4));
|
||||
}
|
||||
}
|
||||
|
||||
public class FaceInfo : BaseHairInfo
|
||||
{
|
||||
public FaceInfo(int itemid)
|
||||
: base(itemid, 0)
|
||||
{
|
||||
}
|
||||
|
||||
public FaceInfo(int itemid, int hue)
|
||||
: base(itemid, hue)
|
||||
{
|
||||
}
|
||||
|
||||
public FaceInfo(GenericReader reader)
|
||||
: base(reader)
|
||||
{
|
||||
}
|
||||
|
||||
public static int FakeSerial(Mobile parent)
|
||||
{
|
||||
return (0x7FFFFFFF - 0x400 - 2 - (parent.Serial * 4));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class HairEquipUpdate : Packet
|
||||
{
|
||||
public HairEquipUpdate(Mobile parent)
|
||||
: base(0x2E, 15)
|
||||
{
|
||||
int hue = parent.HairHue;
|
||||
|
||||
if (parent.SolidHueOverride >= 0)
|
||||
{
|
||||
hue = parent.SolidHueOverride;
|
||||
}
|
||||
|
||||
int hairSerial = HairInfo.FakeSerial(parent);
|
||||
|
||||
m_Stream.Write(hairSerial);
|
||||
m_Stream.Write((short)parent.HairItemID);
|
||||
m_Stream.Write((byte)0);
|
||||
m_Stream.Write((byte)Layer.Hair);
|
||||
m_Stream.Write(parent.Serial);
|
||||
m_Stream.Write((short)hue);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class FacialHairEquipUpdate : Packet
|
||||
{
|
||||
public FacialHairEquipUpdate(Mobile parent)
|
||||
: base(0x2E, 15)
|
||||
{
|
||||
int hue = parent.FacialHairHue;
|
||||
|
||||
if (parent.SolidHueOverride >= 0)
|
||||
{
|
||||
hue = parent.SolidHueOverride;
|
||||
}
|
||||
|
||||
int hairSerial = FacialHairInfo.FakeSerial(parent);
|
||||
|
||||
m_Stream.Write(hairSerial);
|
||||
m_Stream.Write((short)parent.FacialHairItemID);
|
||||
m_Stream.Write((byte)0);
|
||||
m_Stream.Write((byte)Layer.FacialHair);
|
||||
m_Stream.Write(parent.Serial);
|
||||
m_Stream.Write((short)hue);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class FaceEquipUpdate : Packet
|
||||
{
|
||||
public FaceEquipUpdate(Mobile parent)
|
||||
: base(0x2E, 15)
|
||||
{
|
||||
int hue = parent.FaceHue;
|
||||
|
||||
if (parent.SolidHueOverride >= 0)
|
||||
{
|
||||
hue = parent.SolidHueOverride;
|
||||
}
|
||||
|
||||
int faceSerial = FaceInfo.FakeSerial(parent);
|
||||
|
||||
m_Stream.Write((int)faceSerial);
|
||||
m_Stream.Write((short)parent.FaceItemID);
|
||||
m_Stream.Write((byte)0);
|
||||
m_Stream.Write((byte)Layer.Face);
|
||||
m_Stream.Write((int)parent.Serial);
|
||||
m_Stream.Write((short)hue);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class RemoveHair : Packet
|
||||
{
|
||||
public RemoveHair(Mobile parent)
|
||||
: base(0x1D, 5)
|
||||
{
|
||||
m_Stream.Write(HairInfo.FakeSerial(parent));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class RemoveFacialHair : Packet
|
||||
{
|
||||
public RemoveFacialHair(Mobile parent)
|
||||
: base(0x1D, 5)
|
||||
{
|
||||
m_Stream.Write(FacialHairInfo.FakeSerial(parent));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class RemoveFace : Packet
|
||||
{
|
||||
public RemoveFace(Mobile parent)
|
||||
: base(0x1D, 5)
|
||||
{
|
||||
m_Stream.Write((int)FaceInfo.FakeSerial(parent));
|
||||
}
|
||||
}
|
||||
}
|
||||
65
Server/KeywordList.cs
Normal file
65
Server/KeywordList.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
namespace Server
|
||||
{
|
||||
public class KeywordList
|
||||
{
|
||||
private int[] m_Keywords;
|
||||
private int m_Count;
|
||||
|
||||
public KeywordList()
|
||||
{
|
||||
m_Keywords = new int[8];
|
||||
m_Count = 0;
|
||||
}
|
||||
|
||||
public int Count { get { return m_Count; } }
|
||||
|
||||
public bool Contains(int keyword)
|
||||
{
|
||||
bool contains = false;
|
||||
|
||||
for (int i = 0; !contains && i < m_Count; ++i)
|
||||
{
|
||||
contains = (keyword == m_Keywords[i]);
|
||||
}
|
||||
|
||||
return contains;
|
||||
}
|
||||
|
||||
public void Add(int keyword)
|
||||
{
|
||||
if ((m_Count + 1) > m_Keywords.Length)
|
||||
{
|
||||
var old = m_Keywords;
|
||||
m_Keywords = new int[old.Length * 2];
|
||||
|
||||
for (int i = 0; i < old.Length; ++i)
|
||||
{
|
||||
m_Keywords[i] = old[i];
|
||||
}
|
||||
}
|
||||
|
||||
m_Keywords[m_Count++] = keyword;
|
||||
}
|
||||
|
||||
private static readonly int[] m_EmptyInts = new int[0];
|
||||
|
||||
public int[] ToArray()
|
||||
{
|
||||
if (m_Count == 0)
|
||||
{
|
||||
return m_EmptyInts;
|
||||
}
|
||||
|
||||
var keywords = new int[m_Count];
|
||||
|
||||
for (int i = 0; i < m_Count; ++i)
|
||||
{
|
||||
keywords[i] = m_Keywords[i];
|
||||
}
|
||||
|
||||
m_Count = 0;
|
||||
|
||||
return keywords;
|
||||
}
|
||||
}
|
||||
}
|
||||
1029
Server/Main.cs
Normal file
1029
Server/Main.cs
Normal file
File diff suppressed because it is too large
Load Diff
3188
Server/Map.cs
Normal file
3188
Server/Map.cs
Normal file
File diff suppressed because it is too large
Load Diff
15
Server/Menus/IMenu.cs
Normal file
15
Server/Menus/IMenu.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
#region References
|
||||
using Server.Network;
|
||||
#endregion
|
||||
|
||||
namespace Server.Menus
|
||||
{
|
||||
public interface IMenu
|
||||
{
|
||||
int Serial { get; }
|
||||
int EntryLength { get; }
|
||||
void SendTo(NetState state);
|
||||
void OnCancel(NetState state);
|
||||
void OnResponse(NetState state, int index);
|
||||
}
|
||||
}
|
||||
74
Server/Menus/ItemListMenu.cs
Normal file
74
Server/Menus/ItemListMenu.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
#region References
|
||||
using Server.Network;
|
||||
#endregion
|
||||
|
||||
namespace Server.Menus.ItemLists
|
||||
{
|
||||
public class ItemListEntry
|
||||
{
|
||||
private readonly string m_Name;
|
||||
private readonly int m_ItemID;
|
||||
private readonly int m_Hue;
|
||||
|
||||
public string Name { get { return m_Name; } }
|
||||
|
||||
public int ItemID { get { return m_ItemID; } }
|
||||
|
||||
public int Hue { get { return m_Hue; } }
|
||||
|
||||
public ItemListEntry(string name, int itemID)
|
||||
: this(name, itemID, 0)
|
||||
{ }
|
||||
|
||||
public ItemListEntry(string name, int itemID, int hue)
|
||||
{
|
||||
m_Name = name;
|
||||
m_ItemID = itemID;
|
||||
m_Hue = hue;
|
||||
}
|
||||
}
|
||||
|
||||
public class ItemListMenu : IMenu
|
||||
{
|
||||
private readonly string m_Question;
|
||||
private ItemListEntry[] m_Entries;
|
||||
|
||||
private readonly int m_Serial;
|
||||
private static int m_NextSerial;
|
||||
|
||||
int IMenu.Serial { get { return m_Serial; } }
|
||||
|
||||
int IMenu.EntryLength { get { return m_Entries.Length; } }
|
||||
|
||||
public string Question { get { return m_Question; } }
|
||||
|
||||
public ItemListEntry[] Entries { get { return m_Entries; } set { m_Entries = value; } }
|
||||
|
||||
public ItemListMenu(string question, ItemListEntry[] entries)
|
||||
{
|
||||
m_Question = question;
|
||||
m_Entries = entries;
|
||||
|
||||
do
|
||||
{
|
||||
m_Serial = m_NextSerial++;
|
||||
m_Serial &= 0x7FFFFFFF;
|
||||
}
|
||||
while (m_Serial == 0);
|
||||
|
||||
m_Serial = (int)((uint)m_Serial | 0x80000000);
|
||||
}
|
||||
|
||||
public virtual void OnCancel(NetState state)
|
||||
{ }
|
||||
|
||||
public virtual void OnResponse(NetState state, int index)
|
||||
{ }
|
||||
|
||||
public void SendTo(NetState state)
|
||||
{
|
||||
state.AddMenu(this);
|
||||
state.Send(new DisplayItemListMenu(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
47
Server/Menus/QuestionMenu.cs
Normal file
47
Server/Menus/QuestionMenu.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
#region References
|
||||
using Server.Network;
|
||||
#endregion
|
||||
|
||||
namespace Server.Menus.Questions
|
||||
{
|
||||
public class QuestionMenu : IMenu
|
||||
{
|
||||
private readonly string[] m_Answers;
|
||||
|
||||
private readonly int m_Serial;
|
||||
private static int m_NextSerial;
|
||||
|
||||
int IMenu.Serial { get { return m_Serial; } }
|
||||
|
||||
int IMenu.EntryLength { get { return m_Answers.Length; } }
|
||||
|
||||
public string Question { get; set; }
|
||||
|
||||
public string[] Answers { get { return m_Answers; } }
|
||||
|
||||
public QuestionMenu(string question, string[] answers)
|
||||
{
|
||||
Question = question;
|
||||
m_Answers = answers;
|
||||
|
||||
do
|
||||
{
|
||||
m_Serial = ++m_NextSerial;
|
||||
m_Serial &= 0x7FFFFFFF;
|
||||
}
|
||||
while (m_Serial == 0);
|
||||
}
|
||||
|
||||
public virtual void OnCancel(NetState state)
|
||||
{ }
|
||||
|
||||
public virtual void OnResponse(NetState state, int index)
|
||||
{ }
|
||||
|
||||
public void SendTo(NetState state)
|
||||
{
|
||||
state.AddMenu(this);
|
||||
state.Send(new DisplayQuestionMenu(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
12837
Server/Mobile.cs
Normal file
12837
Server/Mobile.cs
Normal file
File diff suppressed because it is too large
Load Diff
72
Server/Movement.cs
Normal file
72
Server/Movement.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
namespace Server.Movement
|
||||
{
|
||||
public static class Movement
|
||||
{
|
||||
private static IMovementImpl m_Impl;
|
||||
|
||||
public static IMovementImpl Impl { get { return m_Impl; } set { m_Impl = value; } }
|
||||
|
||||
/*public static bool CheckMovement(IPoint3D p, Direction d, out int newZ)
|
||||
{
|
||||
if (m_Impl != null)
|
||||
{
|
||||
return m_Impl.CheckMovement(p, d, out newZ);
|
||||
}
|
||||
|
||||
newZ = p.Z;
|
||||
return false;
|
||||
}*/
|
||||
|
||||
public static bool CheckMovement(IPoint3D p, Map map, Point3D loc, Direction d, out int newZ)
|
||||
{
|
||||
if (m_Impl != null)
|
||||
{
|
||||
return m_Impl.CheckMovement(p, map, loc, d, out newZ);
|
||||
}
|
||||
|
||||
newZ = p.Z;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void Offset(Direction d, ref int x, ref int y)
|
||||
{
|
||||
switch (d & Direction.Mask)
|
||||
{
|
||||
case Direction.North:
|
||||
--y;
|
||||
break;
|
||||
case Direction.South:
|
||||
++y;
|
||||
break;
|
||||
case Direction.West:
|
||||
--x;
|
||||
break;
|
||||
case Direction.East:
|
||||
++x;
|
||||
break;
|
||||
case Direction.Right:
|
||||
++x;
|
||||
--y;
|
||||
break;
|
||||
case Direction.Left:
|
||||
--x;
|
||||
++y;
|
||||
break;
|
||||
case Direction.Down:
|
||||
++x;
|
||||
++y;
|
||||
break;
|
||||
case Direction.Up:
|
||||
--x;
|
||||
--y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface IMovementImpl
|
||||
{
|
||||
//bool CheckMovement(IPoint3D p, Direction d, out int newZ);
|
||||
bool CheckMovement(IPoint3D p, Map map, Point3D loc, Direction d, out int newZ);
|
||||
}
|
||||
}
|
||||
996
Server/MultiData.cs
Normal file
996
Server/MultiData.cs
Normal file
@@ -0,0 +1,996 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using Server;
|
||||
using Server.Network;
|
||||
#endregion
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public static class MultiData
|
||||
{
|
||||
public static Dictionary<int, MultiComponentList> Components { get { return m_Components; } }
|
||||
private static readonly Dictionary<int, MultiComponentList> m_Components;
|
||||
|
||||
private static readonly BinaryReader m_IndexReader;
|
||||
private static readonly BinaryReader m_StreamReader;
|
||||
|
||||
public static bool UsingUOPFormat { get; private set; }
|
||||
|
||||
public static MultiComponentList GetComponents(int multiID)
|
||||
{
|
||||
MultiComponentList mcl;
|
||||
|
||||
multiID &= 0x3FFF; // The value of the actual multi is shifted by 0x4000, so this is left alone.
|
||||
|
||||
if (m_Components.ContainsKey(multiID))
|
||||
{
|
||||
mcl = m_Components[multiID];
|
||||
}
|
||||
else if (!UsingUOPFormat)
|
||||
{
|
||||
m_Components[multiID] = mcl = Load(multiID);
|
||||
}
|
||||
else
|
||||
{
|
||||
mcl = MultiComponentList.Empty;
|
||||
}
|
||||
|
||||
return mcl;
|
||||
}
|
||||
|
||||
public static MultiComponentList Load(int multiID)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_IndexReader.BaseStream.Seek(multiID * 12, SeekOrigin.Begin);
|
||||
|
||||
int lookup = m_IndexReader.ReadInt32();
|
||||
int length = m_IndexReader.ReadInt32();
|
||||
|
||||
if (lookup < 0 || length <= 0)
|
||||
{
|
||||
return MultiComponentList.Empty;
|
||||
}
|
||||
|
||||
m_StreamReader.BaseStream.Seek(lookup, SeekOrigin.Begin);
|
||||
|
||||
return new MultiComponentList(m_StreamReader, length / (MultiComponentList.PostHSFormat ? 16 : 12));
|
||||
}
|
||||
catch
|
||||
{
|
||||
return MultiComponentList.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public static void UOPLoad(string path)
|
||||
{
|
||||
var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
BinaryReader streamReader = new BinaryReader(stream);
|
||||
|
||||
// Head Information Start
|
||||
if (streamReader.ReadInt32() != 0x0050594D) // Not a UOP Files
|
||||
return;
|
||||
|
||||
if (streamReader.ReadInt32() > 5) // Bad Version
|
||||
return;
|
||||
|
||||
// Multi ID List Array Start
|
||||
var chunkIds = new Dictionary<ulong, int>();
|
||||
var chunkIds2 = new Dictionary<ulong, int>();
|
||||
|
||||
UOPHash.BuildChunkIDs(ref chunkIds, ref chunkIds2);
|
||||
// Multi ID List Array End
|
||||
|
||||
streamReader.ReadUInt32(); // format timestamp? 0xFD23EC43
|
||||
long startAddress = streamReader.ReadInt64();
|
||||
|
||||
int blockSize = streamReader.ReadInt32(); // files in each block
|
||||
int totalSize = streamReader.ReadInt32(); // Total File Count
|
||||
|
||||
stream.Seek(startAddress, SeekOrigin.Begin); // Head Information End
|
||||
|
||||
long nextBlock;
|
||||
|
||||
do
|
||||
{
|
||||
int blockFileCount = streamReader.ReadInt32();
|
||||
nextBlock = streamReader.ReadInt64();
|
||||
|
||||
int index = 0;
|
||||
|
||||
do
|
||||
{
|
||||
long offset = streamReader.ReadInt64();
|
||||
|
||||
int headerSize = streamReader.ReadInt32(); // header length
|
||||
int compressedSize = streamReader.ReadInt32(); // compressed size
|
||||
int decompressedSize = streamReader.ReadInt32(); // decompressed size
|
||||
|
||||
ulong filehash = streamReader.ReadUInt64(); // filename hash (HashLittle2)
|
||||
uint datablockhash = streamReader.ReadUInt32(); // data hash (Adler32)
|
||||
short flag = streamReader.ReadInt16(); // compression method (0 = none, 1 = zlib)
|
||||
|
||||
index++;
|
||||
|
||||
if (offset == 0 || decompressedSize == 0 || filehash == 0x126D1E99DDEDEE0A) // Exclude housing.bin
|
||||
continue;
|
||||
|
||||
// Multi ID Search Start
|
||||
int chunkID = -1;
|
||||
|
||||
if (!chunkIds.TryGetValue(filehash, out chunkID))
|
||||
{
|
||||
int tmpChunkID = 0;
|
||||
|
||||
if (chunkIds2.TryGetValue(filehash, out tmpChunkID))
|
||||
{
|
||||
chunkID = tmpChunkID;
|
||||
}
|
||||
}
|
||||
// Multi ID Search End
|
||||
|
||||
long positionpoint = stream.Position; // save current position
|
||||
|
||||
// Decompress Data Start
|
||||
stream.Seek(offset + headerSize, SeekOrigin.Begin);
|
||||
|
||||
byte[] sourceData = new byte[compressedSize];
|
||||
|
||||
if (stream.Read(sourceData, 0, compressedSize) != compressedSize)
|
||||
continue;
|
||||
|
||||
byte[] data;
|
||||
|
||||
if (flag == 1)
|
||||
{
|
||||
byte[] destData = new byte[decompressedSize];
|
||||
/*ZLibError error = */Compression.Compressor.Decompress(destData, ref decompressedSize, sourceData, compressedSize);
|
||||
|
||||
data = destData;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = sourceData;
|
||||
}
|
||||
// End Decompress Data
|
||||
|
||||
var tileList = new List<MultiTileEntry>();
|
||||
|
||||
using (MemoryStream fs = new MemoryStream(data))
|
||||
{
|
||||
using (BinaryReader reader = new BinaryReader(fs))
|
||||
{
|
||||
uint a = reader.ReadUInt32();
|
||||
uint count = reader.ReadUInt32();
|
||||
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
ushort ItemId = reader.ReadUInt16();
|
||||
short x = reader.ReadInt16();
|
||||
short y = reader.ReadInt16();
|
||||
short z = reader.ReadInt16();
|
||||
|
||||
ushort flagint = reader.ReadUInt16();
|
||||
|
||||
TileFlag flagg;
|
||||
|
||||
switch (flagint)
|
||||
{
|
||||
default:
|
||||
case 0: { flagg = TileFlag.Background; break; }
|
||||
case 1: { flagg = TileFlag.None; break; }
|
||||
case 257: { flagg = TileFlag.Generic; break; }
|
||||
}
|
||||
|
||||
uint clilocsCount = reader.ReadUInt32();
|
||||
|
||||
if (clilocsCount != 0)
|
||||
{
|
||||
fs.Seek(fs.Position + (clilocsCount * 4), SeekOrigin.Begin); // binary block bypass
|
||||
}
|
||||
|
||||
tileList.Add(new MultiTileEntry(ItemId, x, y, z, flagg));
|
||||
}
|
||||
|
||||
reader.Close();
|
||||
}
|
||||
}
|
||||
|
||||
m_Components[chunkID] = new MultiComponentList(tileList);
|
||||
|
||||
stream.Seek(positionpoint, SeekOrigin.Begin); // back to position
|
||||
}
|
||||
while (index < blockFileCount);
|
||||
}
|
||||
while (stream.Seek(nextBlock, SeekOrigin.Begin) != 0);
|
||||
|
||||
chunkIds.Clear();
|
||||
chunkIds2.Clear();
|
||||
}
|
||||
|
||||
static MultiData()
|
||||
{
|
||||
m_Components = new Dictionary<int, MultiComponentList>();
|
||||
|
||||
string multicollectionPath = Core.FindDataFile("MultiCollection.uop");
|
||||
|
||||
if (File.Exists(multicollectionPath))
|
||||
{
|
||||
UOPLoad(multicollectionPath);
|
||||
UsingUOPFormat = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
string idxPath = Core.FindDataFile("multi.idx");
|
||||
string mulPath = Core.FindDataFile("multi.mul");
|
||||
|
||||
if (File.Exists(idxPath) && File.Exists(mulPath))
|
||||
{
|
||||
var idx = new FileStream(idxPath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
m_IndexReader = new BinaryReader(idx);
|
||||
|
||||
var stream = new FileStream(mulPath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
m_StreamReader = new BinaryReader(stream);
|
||||
|
||||
string vdPath = Core.FindDataFile("verdata.mul");
|
||||
|
||||
if (File.Exists(vdPath))
|
||||
{
|
||||
using (FileStream fs = new FileStream(vdPath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
BinaryReader bin = new BinaryReader(fs);
|
||||
|
||||
int count = bin.ReadInt32();
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
int file = bin.ReadInt32();
|
||||
int index = bin.ReadInt32();
|
||||
int lookup = bin.ReadInt32();
|
||||
int length = bin.ReadInt32();
|
||||
/*int extra = */
|
||||
bin.ReadInt32();
|
||||
|
||||
if (file == 14 && index >= 0 && lookup >= 0 && length > 0)
|
||||
{
|
||||
bin.BaseStream.Seek(lookup, SeekOrigin.Begin);
|
||||
|
||||
m_Components[index] = new MultiComponentList(bin, length / 12);
|
||||
|
||||
bin.BaseStream.Seek(24 + (i * 20), SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
|
||||
bin.Close();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Warning: Multi data files not found!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct MultiTileEntry
|
||||
{
|
||||
public ushort m_ItemID;
|
||||
public short m_OffsetX, m_OffsetY, m_OffsetZ;
|
||||
public TileFlag m_Flags;
|
||||
|
||||
public MultiTileEntry(ushort itemID, short xOffset, short yOffset, short zOffset, TileFlag flags)
|
||||
{
|
||||
m_ItemID = itemID;
|
||||
m_OffsetX = xOffset;
|
||||
m_OffsetY = yOffset;
|
||||
m_OffsetZ = zOffset;
|
||||
m_Flags = flags;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MultiComponentList
|
||||
{
|
||||
public static bool PostHSFormat { get; set; }
|
||||
|
||||
private Point2D m_Min, m_Max, m_Center;
|
||||
private int m_Width, m_Height;
|
||||
private StaticTile[][][] m_Tiles;
|
||||
private MultiTileEntry[] m_List;
|
||||
|
||||
public static readonly MultiComponentList Empty = new MultiComponentList();
|
||||
|
||||
public Point2D Min { get { return m_Min; } }
|
||||
public Point2D Max { get { return m_Max; } }
|
||||
|
||||
public Point2D Center { get { return m_Center; } }
|
||||
|
||||
public int Width { get { return m_Width; } }
|
||||
public int Height { get { return m_Height; } }
|
||||
|
||||
public StaticTile[][][] Tiles { get { return m_Tiles; } }
|
||||
public MultiTileEntry[] List { get { return m_List; } }
|
||||
|
||||
public void Add(int itemID, int x, int y, int z)
|
||||
{
|
||||
itemID &= TileData.MaxItemValue;
|
||||
itemID |= 0x10000;
|
||||
|
||||
int vx = x + m_Center.m_X;
|
||||
int vy = y + m_Center.m_Y;
|
||||
|
||||
if (vx >= 0 && vx < m_Width && vy >= 0 && vy < m_Height)
|
||||
{
|
||||
var oldTiles = m_Tiles[vx][vy];
|
||||
|
||||
for (int i = oldTiles.Length - 1; i >= 0; --i)
|
||||
{
|
||||
ItemData data = TileData.ItemTable[itemID & TileData.MaxItemValue];
|
||||
|
||||
if (oldTiles[i].Z == z && (oldTiles[i].Height > 0 == data.Height > 0))
|
||||
{
|
||||
bool newIsRoof = (data.Flags & TileFlag.Roof) != 0;
|
||||
bool oldIsRoof = (TileData.ItemTable[oldTiles[i].ID & TileData.MaxItemValue].Flags & TileFlag.Roof) != 0;
|
||||
|
||||
if (newIsRoof == oldIsRoof)
|
||||
{
|
||||
Remove(oldTiles[i].ID, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
oldTiles = m_Tiles[vx][vy];
|
||||
|
||||
var newTiles = new StaticTile[oldTiles.Length + 1];
|
||||
|
||||
for (int i = 0; i < oldTiles.Length; ++i)
|
||||
{
|
||||
newTiles[i] = oldTiles[i];
|
||||
}
|
||||
|
||||
newTiles[oldTiles.Length] = new StaticTile((ushort)itemID, (sbyte)z);
|
||||
|
||||
m_Tiles[vx][vy] = newTiles;
|
||||
|
||||
var oldList = m_List;
|
||||
var newList = new MultiTileEntry[oldList.Length + 1];
|
||||
|
||||
for (int i = 0; i < oldList.Length; ++i)
|
||||
{
|
||||
newList[i] = oldList[i];
|
||||
}
|
||||
|
||||
newList[oldList.Length] = new MultiTileEntry((ushort)itemID, (short)x, (short)y, (short)z, TileFlag.Background);
|
||||
|
||||
m_List = newList;
|
||||
|
||||
if (x < m_Min.m_X)
|
||||
{
|
||||
m_Min.m_X = x;
|
||||
}
|
||||
|
||||
if (y < m_Min.m_Y)
|
||||
{
|
||||
m_Min.m_Y = y;
|
||||
}
|
||||
|
||||
if (x > m_Max.m_X)
|
||||
{
|
||||
m_Max.m_X = x;
|
||||
}
|
||||
|
||||
if (y > m_Max.m_Y)
|
||||
{
|
||||
m_Max.m_Y = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveXYZH(int x, int y, int z, int minHeight)
|
||||
{
|
||||
int vx = x + m_Center.m_X;
|
||||
int vy = y + m_Center.m_Y;
|
||||
|
||||
if (vx >= 0 && vx < m_Width && vy >= 0 && vy < m_Height)
|
||||
{
|
||||
var oldTiles = m_Tiles[vx][vy];
|
||||
|
||||
for (int i = 0; i < oldTiles.Length; ++i)
|
||||
{
|
||||
StaticTile tile = oldTiles[i];
|
||||
|
||||
if (tile.Z == z && tile.Height >= minHeight)
|
||||
{
|
||||
var newTiles = new StaticTile[oldTiles.Length - 1];
|
||||
|
||||
for (int j = 0; j < i; ++j)
|
||||
{
|
||||
newTiles[j] = oldTiles[j];
|
||||
}
|
||||
|
||||
for (int j = i + 1; j < oldTiles.Length; ++j)
|
||||
{
|
||||
newTiles[j - 1] = oldTiles[j];
|
||||
}
|
||||
|
||||
m_Tiles[vx][vy] = newTiles;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var oldList = m_List;
|
||||
|
||||
for (int i = 0; i < oldList.Length; ++i)
|
||||
{
|
||||
MultiTileEntry tile = oldList[i];
|
||||
|
||||
if (tile.m_OffsetX == (short)x && tile.m_OffsetY == (short)y && tile.m_OffsetZ == (short)z &&
|
||||
TileData.ItemTable[tile.m_ItemID & TileData.MaxItemValue].Height >= minHeight)
|
||||
{
|
||||
var newList = new MultiTileEntry[oldList.Length - 1];
|
||||
|
||||
for (int j = 0; j < i; ++j)
|
||||
{
|
||||
newList[j] = oldList[j];
|
||||
}
|
||||
|
||||
for (int j = i + 1; j < oldList.Length; ++j)
|
||||
{
|
||||
newList[j - 1] = oldList[j];
|
||||
}
|
||||
|
||||
m_List = newList;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove(int itemID, int x, int y, int z)
|
||||
{
|
||||
int vx = x + m_Center.m_X;
|
||||
int vy = y + m_Center.m_Y;
|
||||
|
||||
if (vx >= 0 && vx < m_Width && vy >= 0 && vy < m_Height)
|
||||
{
|
||||
var oldTiles = m_Tiles[vx][vy];
|
||||
|
||||
for (int i = 0; i < oldTiles.Length; ++i)
|
||||
{
|
||||
StaticTile tile = oldTiles[i];
|
||||
|
||||
if (tile.ID == itemID && tile.Z == z)
|
||||
{
|
||||
var newTiles = new StaticTile[oldTiles.Length - 1];
|
||||
|
||||
for (int j = 0; j < i; ++j)
|
||||
{
|
||||
newTiles[j] = oldTiles[j];
|
||||
}
|
||||
|
||||
for (int j = i + 1; j < oldTiles.Length; ++j)
|
||||
{
|
||||
newTiles[j - 1] = oldTiles[j];
|
||||
}
|
||||
|
||||
m_Tiles[vx][vy] = newTiles;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var oldList = m_List;
|
||||
|
||||
for (int i = 0; i < oldList.Length; ++i)
|
||||
{
|
||||
MultiTileEntry tile = oldList[i];
|
||||
|
||||
if (tile.m_ItemID == itemID && tile.m_OffsetX == (short)x && tile.m_OffsetY == (short)y &&
|
||||
tile.m_OffsetZ == (short)z)
|
||||
{
|
||||
var newList = new MultiTileEntry[oldList.Length - 1];
|
||||
|
||||
for (int j = 0; j < i; ++j)
|
||||
{
|
||||
newList[j] = oldList[j];
|
||||
}
|
||||
|
||||
for (int j = i + 1; j < oldList.Length; ++j)
|
||||
{
|
||||
newList[j - 1] = oldList[j];
|
||||
}
|
||||
|
||||
m_List = newList;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Resize(int newWidth, int newHeight)
|
||||
{
|
||||
int oldWidth = m_Width, oldHeight = m_Height;
|
||||
var oldTiles = m_Tiles;
|
||||
|
||||
int totalLength = 0;
|
||||
|
||||
var newTiles = new StaticTile[newWidth][][];
|
||||
|
||||
for (int x = 0; x < newWidth; ++x)
|
||||
{
|
||||
newTiles[x] = new StaticTile[newHeight][];
|
||||
|
||||
for (int y = 0; y < newHeight; ++y)
|
||||
{
|
||||
if (x < oldWidth && y < oldHeight)
|
||||
{
|
||||
newTiles[x][y] = oldTiles[x][y];
|
||||
}
|
||||
else
|
||||
{
|
||||
newTiles[x][y] = new StaticTile[0];
|
||||
}
|
||||
|
||||
totalLength += newTiles[x][y].Length;
|
||||
}
|
||||
}
|
||||
|
||||
m_Tiles = newTiles;
|
||||
m_List = new MultiTileEntry[totalLength];
|
||||
m_Width = newWidth;
|
||||
m_Height = newHeight;
|
||||
|
||||
m_Min = Point2D.Zero;
|
||||
m_Max = Point2D.Zero;
|
||||
|
||||
int index = 0;
|
||||
|
||||
for (int x = 0; x < newWidth; ++x)
|
||||
{
|
||||
for (int y = 0; y < newHeight; ++y)
|
||||
{
|
||||
var tiles = newTiles[x][y];
|
||||
|
||||
foreach (StaticTile tile in tiles)
|
||||
{
|
||||
int vx = x - m_Center.X;
|
||||
int vy = y - m_Center.Y;
|
||||
|
||||
if (vx < m_Min.m_X)
|
||||
{
|
||||
m_Min.m_X = vx;
|
||||
}
|
||||
|
||||
if (vy < m_Min.m_Y)
|
||||
{
|
||||
m_Min.m_Y = vy;
|
||||
}
|
||||
|
||||
if (vx > m_Max.m_X)
|
||||
{
|
||||
m_Max.m_X = vx;
|
||||
}
|
||||
|
||||
if (vy > m_Max.m_Y)
|
||||
{
|
||||
m_Max.m_Y = vy;
|
||||
}
|
||||
|
||||
m_List[index++] = new MultiTileEntry((ushort)tile.ID, (short)vx, (short)vy, (short)tile.Z, TileFlag.Background);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MultiComponentList(MultiComponentList toCopy)
|
||||
{
|
||||
m_Min = toCopy.m_Min;
|
||||
m_Max = toCopy.m_Max;
|
||||
|
||||
m_Center = toCopy.m_Center;
|
||||
|
||||
m_Width = toCopy.m_Width;
|
||||
m_Height = toCopy.m_Height;
|
||||
|
||||
m_Tiles = new StaticTile[m_Width][][];
|
||||
|
||||
for (int x = 0; x < m_Width; ++x)
|
||||
{
|
||||
m_Tiles[x] = new StaticTile[m_Height][];
|
||||
|
||||
for (int y = 0; y < m_Height; ++y)
|
||||
{
|
||||
m_Tiles[x][y] = new StaticTile[toCopy.m_Tiles[x][y].Length];
|
||||
|
||||
for (int i = 0; i < m_Tiles[x][y].Length; ++i)
|
||||
{
|
||||
m_Tiles[x][y][i] = toCopy.m_Tiles[x][y][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_List = new MultiTileEntry[toCopy.m_List.Length];
|
||||
|
||||
for (int i = 0; i < m_List.Length; ++i)
|
||||
{
|
||||
m_List[i] = toCopy.m_List[i];
|
||||
}
|
||||
}
|
||||
|
||||
public void Serialize(GenericWriter writer)
|
||||
{
|
||||
writer.Write(2); // version;
|
||||
|
||||
writer.Write(m_Min);
|
||||
writer.Write(m_Max);
|
||||
writer.Write(m_Center);
|
||||
|
||||
writer.Write(m_Width);
|
||||
writer.Write(m_Height);
|
||||
|
||||
writer.Write(m_List.Length);
|
||||
|
||||
foreach (MultiTileEntry ent in m_List)
|
||||
{
|
||||
writer.Write(ent.m_ItemID);
|
||||
writer.Write(ent.m_OffsetX);
|
||||
writer.Write(ent.m_OffsetY);
|
||||
writer.Write(ent.m_OffsetZ);
|
||||
|
||||
writer.Write((ulong)ent.m_Flags);
|
||||
}
|
||||
}
|
||||
|
||||
public MultiComponentList(GenericReader reader)
|
||||
{
|
||||
int version = reader.ReadInt();
|
||||
|
||||
m_Min = reader.ReadPoint2D();
|
||||
m_Max = reader.ReadPoint2D();
|
||||
m_Center = reader.ReadPoint2D();
|
||||
m_Width = reader.ReadInt();
|
||||
m_Height = reader.ReadInt();
|
||||
|
||||
int length = reader.ReadInt();
|
||||
|
||||
var allTiles = m_List = new MultiTileEntry[length];
|
||||
|
||||
if (version == 0)
|
||||
{
|
||||
for (int i = 0; i < length; ++i)
|
||||
{
|
||||
int id = reader.ReadShort();
|
||||
|
||||
if (id >= 0x4000)
|
||||
{
|
||||
id -= 0x4000;
|
||||
}
|
||||
|
||||
allTiles[i].m_ItemID = (ushort)id;
|
||||
allTiles[i].m_OffsetX = reader.ReadShort();
|
||||
allTiles[i].m_OffsetY = reader.ReadShort();
|
||||
allTiles[i].m_OffsetZ = reader.ReadShort();
|
||||
|
||||
allTiles[i].m_Flags = (TileFlag)reader.ReadUInt();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < length; ++i)
|
||||
{
|
||||
allTiles[i].m_ItemID = reader.ReadUShort();
|
||||
allTiles[i].m_OffsetX = reader.ReadShort();
|
||||
allTiles[i].m_OffsetY = reader.ReadShort();
|
||||
allTiles[i].m_OffsetZ = reader.ReadShort();
|
||||
|
||||
if (version > 1)
|
||||
allTiles[i].m_Flags = (TileFlag)reader.ReadULong();
|
||||
else
|
||||
allTiles[i].m_Flags = (TileFlag)reader.ReadUInt();
|
||||
}
|
||||
}
|
||||
|
||||
var tiles = new TileList[m_Width][];
|
||||
m_Tiles = new StaticTile[m_Width][][];
|
||||
|
||||
for (int x = 0; x < m_Width; ++x)
|
||||
{
|
||||
tiles[x] = new TileList[m_Height];
|
||||
m_Tiles[x] = new StaticTile[m_Height][];
|
||||
|
||||
for (int y = 0; y < m_Height; ++y)
|
||||
{
|
||||
tiles[x][y] = new TileList();
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < allTiles.Length; ++i)
|
||||
{
|
||||
if (i == 0 || allTiles[i].m_Flags != 0)
|
||||
{
|
||||
int xOffset = allTiles[i].m_OffsetX + m_Center.m_X;
|
||||
int yOffset = allTiles[i].m_OffsetY + m_Center.m_Y;
|
||||
int itemID = ((allTiles[i].m_ItemID & TileData.MaxItemValue) | 0x10000);
|
||||
|
||||
tiles[xOffset][yOffset].Add((ushort)itemID, (sbyte)allTiles[i].m_OffsetZ);
|
||||
}
|
||||
}
|
||||
|
||||
for (int x = 0; x < m_Width; ++x)
|
||||
{
|
||||
for (int y = 0; y < m_Height; ++y)
|
||||
{
|
||||
m_Tiles[x][y] = tiles[x][y].ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MultiComponentList(BinaryReader reader, int count)
|
||||
{
|
||||
var allTiles = m_List = new MultiTileEntry[count];
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
allTiles[i].m_ItemID = reader.ReadUInt16();
|
||||
allTiles[i].m_OffsetX = reader.ReadInt16();
|
||||
allTiles[i].m_OffsetY = reader.ReadInt16();
|
||||
allTiles[i].m_OffsetZ = reader.ReadInt16();
|
||||
|
||||
if (PostHSFormat)
|
||||
allTiles[i].m_Flags = (TileFlag)reader.ReadUInt64();
|
||||
else
|
||||
allTiles[i].m_Flags = (TileFlag)reader.ReadUInt32();
|
||||
|
||||
MultiTileEntry e = allTiles[i];
|
||||
|
||||
if (i == 0 || e.m_Flags != 0)
|
||||
{
|
||||
if (e.m_OffsetX < m_Min.m_X)
|
||||
{
|
||||
m_Min.m_X = e.m_OffsetX;
|
||||
}
|
||||
|
||||
if (e.m_OffsetY < m_Min.m_Y)
|
||||
{
|
||||
m_Min.m_Y = e.m_OffsetY;
|
||||
}
|
||||
|
||||
if (e.m_OffsetX > m_Max.m_X)
|
||||
{
|
||||
m_Max.m_X = e.m_OffsetX;
|
||||
}
|
||||
|
||||
if (e.m_OffsetY > m_Max.m_Y)
|
||||
{
|
||||
m_Max.m_Y = e.m_OffsetY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_Center = new Point2D(-m_Min.m_X, -m_Min.m_Y);
|
||||
m_Width = (m_Max.m_X - m_Min.m_X) + 1;
|
||||
m_Height = (m_Max.m_Y - m_Min.m_Y) + 1;
|
||||
|
||||
var tiles = new TileList[m_Width][];
|
||||
m_Tiles = new StaticTile[m_Width][][];
|
||||
|
||||
for (int x = 0; x < m_Width; ++x)
|
||||
{
|
||||
tiles[x] = new TileList[m_Height];
|
||||
m_Tiles[x] = new StaticTile[m_Height][];
|
||||
|
||||
for (int y = 0; y < m_Height; ++y)
|
||||
{
|
||||
tiles[x][y] = new TileList();
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < allTiles.Length; ++i)
|
||||
{
|
||||
if (i == 0 || allTiles[i].m_Flags != 0)
|
||||
{
|
||||
int xOffset = allTiles[i].m_OffsetX + m_Center.m_X;
|
||||
int yOffset = allTiles[i].m_OffsetY + m_Center.m_Y;
|
||||
int itemID = ((allTiles[i].m_ItemID & TileData.MaxItemValue) | 0x10000);
|
||||
|
||||
tiles[xOffset][yOffset].Add((ushort)itemID, (sbyte)allTiles[i].m_OffsetZ);
|
||||
}
|
||||
}
|
||||
|
||||
for (int x = 0; x < m_Width; ++x)
|
||||
{
|
||||
for (int y = 0; y < m_Height; ++y)
|
||||
{
|
||||
m_Tiles[x][y] = tiles[x][y].ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MultiComponentList(List<MultiTileEntry> list)
|
||||
{
|
||||
var allTiles = m_List = new MultiTileEntry[list.Count];
|
||||
|
||||
for (int i = 0; i < list.Count; ++i)
|
||||
{
|
||||
allTiles[i].m_ItemID = list[i].m_ItemID;
|
||||
allTiles[i].m_OffsetX = list[i].m_OffsetX;
|
||||
allTiles[i].m_OffsetY = list[i].m_OffsetY;
|
||||
allTiles[i].m_OffsetZ = list[i].m_OffsetZ;
|
||||
|
||||
allTiles[i].m_Flags = list[i].m_Flags;
|
||||
|
||||
MultiTileEntry e = allTiles[i];
|
||||
|
||||
if (i == 0 || e.m_Flags != 0)
|
||||
{
|
||||
if (e.m_OffsetX < m_Min.m_X)
|
||||
{
|
||||
m_Min.m_X = e.m_OffsetX;
|
||||
}
|
||||
|
||||
if (e.m_OffsetY < m_Min.m_Y)
|
||||
{
|
||||
m_Min.m_Y = e.m_OffsetY;
|
||||
}
|
||||
|
||||
if (e.m_OffsetX > m_Max.m_X)
|
||||
{
|
||||
m_Max.m_X = e.m_OffsetX;
|
||||
}
|
||||
|
||||
if (e.m_OffsetY > m_Max.m_Y)
|
||||
{
|
||||
m_Max.m_Y = e.m_OffsetY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_Center = new Point2D(-m_Min.m_X, -m_Min.m_Y);
|
||||
m_Width = (m_Max.m_X - m_Min.m_X) + 1;
|
||||
m_Height = (m_Max.m_Y - m_Min.m_Y) + 1;
|
||||
|
||||
var tiles = new TileList[m_Width][];
|
||||
m_Tiles = new StaticTile[m_Width][][];
|
||||
|
||||
for (int x = 0; x < m_Width; ++x)
|
||||
{
|
||||
tiles[x] = new TileList[m_Height];
|
||||
m_Tiles[x] = new StaticTile[m_Height][];
|
||||
|
||||
for (int y = 0; y < m_Height; ++y)
|
||||
{
|
||||
tiles[x][y] = new TileList();
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < allTiles.Length; ++i)
|
||||
{
|
||||
if (i == 0 || allTiles[i].m_Flags != 0)
|
||||
{
|
||||
int xOffset = allTiles[i].m_OffsetX + m_Center.m_X;
|
||||
int yOffset = allTiles[i].m_OffsetY + m_Center.m_Y;
|
||||
int itemID = ((allTiles[i].m_ItemID & TileData.MaxItemValue) | 0x10000);
|
||||
|
||||
tiles[xOffset][yOffset].Add((ushort)itemID, (sbyte)allTiles[i].m_OffsetZ);
|
||||
}
|
||||
}
|
||||
|
||||
for (int x = 0; x < m_Width; ++x)
|
||||
{
|
||||
for (int y = 0; y < m_Height; ++y)
|
||||
{
|
||||
m_Tiles[x][y] = tiles[x][y].ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private MultiComponentList()
|
||||
{
|
||||
m_Tiles = new StaticTile[0][][];
|
||||
m_List = new MultiTileEntry[0];
|
||||
}
|
||||
}
|
||||
|
||||
public class UOPHash
|
||||
{
|
||||
public static void BuildChunkIDs(ref Dictionary<ulong, int> chunkIds, ref Dictionary<ulong, int> chunkIds2)
|
||||
{
|
||||
int maxId;
|
||||
|
||||
string[] formats = GetHashFormat(0, out maxId);
|
||||
|
||||
for (int i = 0; i < maxId; ++i)
|
||||
{
|
||||
chunkIds[HashLittle2(String.Format(formats[0], i))] = i;
|
||||
}
|
||||
if (formats[1] != "")
|
||||
{
|
||||
for (int i = 0; i < maxId; ++i)
|
||||
chunkIds2[HashLittle2(String.Format(formats[1], i))] = i;
|
||||
}
|
||||
}
|
||||
|
||||
private static string[] GetHashFormat(int typeIndex, out int maxId)
|
||||
{
|
||||
/*
|
||||
* MaxID is only used for constructing a lookup table.
|
||||
* Decrease to save some possibly unneeded computation.
|
||||
*/
|
||||
maxId = 0x10000;
|
||||
|
||||
return new string[] { "build/multicollection/{0:000000}.bin", "" };
|
||||
}
|
||||
|
||||
private static ulong HashLittle2(string s)
|
||||
{
|
||||
int length = s.Length;
|
||||
|
||||
uint a, b, c;
|
||||
a = b = c = 0xDEADBEEF + (uint)length;
|
||||
|
||||
int k = 0;
|
||||
|
||||
while (length > 12)
|
||||
{
|
||||
a += s[k];
|
||||
a += ((uint)s[k + 1]) << 8;
|
||||
a += ((uint)s[k + 2]) << 16;
|
||||
a += ((uint)s[k + 3]) << 24;
|
||||
b += s[k + 4];
|
||||
b += ((uint)s[k + 5]) << 8;
|
||||
b += ((uint)s[k + 6]) << 16;
|
||||
b += ((uint)s[k + 7]) << 24;
|
||||
c += s[k + 8];
|
||||
c += ((uint)s[k + 9]) << 8;
|
||||
c += ((uint)s[k + 10]) << 16;
|
||||
c += ((uint)s[k + 11]) << 24;
|
||||
|
||||
a -= c; a ^= ((c << 4) | (c >> 28)); c += b;
|
||||
b -= a; b ^= ((a << 6) | (a >> 26)); a += c;
|
||||
c -= b; c ^= ((b << 8) | (b >> 24)); b += a;
|
||||
a -= c; a ^= ((c << 16) | (c >> 16)); c += b;
|
||||
b -= a; b ^= ((a << 19) | (a >> 13)); a += c;
|
||||
c -= b; c ^= ((b << 4) | (b >> 28)); b += a;
|
||||
|
||||
length -= 12;
|
||||
k += 12;
|
||||
}
|
||||
|
||||
if (length != 0)
|
||||
{
|
||||
switch (length)
|
||||
{
|
||||
case 12: c += ((uint)s[k + 11]) << 24; goto case 11;
|
||||
case 11: c += ((uint)s[k + 10]) << 16; goto case 10;
|
||||
case 10: c += ((uint)s[k + 9]) << 8; goto case 9;
|
||||
case 9: c += s[k + 8]; goto case 8;
|
||||
case 8: b += ((uint)s[k + 7]) << 24; goto case 7;
|
||||
case 7: b += ((uint)s[k + 6]) << 16; goto case 6;
|
||||
case 6: b += ((uint)s[k + 5]) << 8; goto case 5;
|
||||
case 5: b += s[k + 4]; goto case 4;
|
||||
case 4: a += ((uint)s[k + 3]) << 24; goto case 3;
|
||||
case 3: a += ((uint)s[k + 2]) << 16; goto case 2;
|
||||
case 2: a += ((uint)s[k + 1]) << 8; goto case 1;
|
||||
case 1: a += s[k]; break;
|
||||
}
|
||||
|
||||
c ^= b; c -= ((b << 14) | (b >> 18));
|
||||
a ^= c; a -= ((c << 11) | (c >> 21));
|
||||
b ^= a; b -= ((a << 25) | (a >> 7));
|
||||
c ^= b; c -= ((b << 16) | (b >> 16));
|
||||
a ^= c; a -= ((c << 4) | (c >> 28));
|
||||
b ^= a; b -= ((a << 14) | (a >> 18));
|
||||
c ^= b; c -= ((b << 24) | (b >> 8));
|
||||
}
|
||||
|
||||
return ((ulong)b << 32) | c;
|
||||
}
|
||||
}
|
||||
}
|
||||
73
Server/NativeReader.cs
Normal file
73
Server/NativeReader.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
#endregion
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public static class NativeReader
|
||||
{
|
||||
private static readonly INativeReader m_NativeReader;
|
||||
|
||||
static NativeReader()
|
||||
{
|
||||
if (Core.Unix)
|
||||
{
|
||||
m_NativeReader = new NativeReaderUnix();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_NativeReader = new NativeReaderWin32();
|
||||
}
|
||||
}
|
||||
|
||||
public static unsafe void Read(IntPtr ptr, void* buffer, int length)
|
||||
{
|
||||
m_NativeReader.Read(ptr, buffer, length);
|
||||
}
|
||||
}
|
||||
|
||||
public interface INativeReader
|
||||
{
|
||||
unsafe void Read(IntPtr ptr, void* buffer, int length);
|
||||
}
|
||||
|
||||
public sealed class NativeReaderWin32 : INativeReader
|
||||
{
|
||||
internal class UnsafeNativeMethods
|
||||
{
|
||||
/*[DllImport("kernel32")]
|
||||
internal unsafe static extern int _lread(IntPtr hFile, void* lpBuffer, int wBytes);*/
|
||||
|
||||
[DllImport("kernel32")]
|
||||
internal static extern unsafe bool ReadFile(
|
||||
IntPtr hFile,
|
||||
void* lpBuffer,
|
||||
uint nNumberOfBytesToRead,
|
||||
ref uint lpNumberOfBytesRead,
|
||||
NativeOverlapped* lpOverlapped);
|
||||
}
|
||||
|
||||
public unsafe void Read(IntPtr ptr, void* buffer, int length)
|
||||
{
|
||||
//UnsafeNativeMethods._lread( ptr, buffer, length );
|
||||
uint lpNumberOfBytesRead = 0;
|
||||
UnsafeNativeMethods.ReadFile(ptr, buffer, (uint)length, ref lpNumberOfBytesRead, null);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class NativeReaderUnix : INativeReader
|
||||
{
|
||||
internal class UnsafeNativeMethods
|
||||
{
|
||||
[DllImport("libc")]
|
||||
internal static extern unsafe int read(IntPtr ptr, void* buffer, int length);
|
||||
}
|
||||
|
||||
public unsafe void Read(IntPtr ptr, void* buffer, int length)
|
||||
{
|
||||
UnsafeNativeMethods.read(ptr, buffer, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
108
Server/Network/BufferPool.cs
Normal file
108
Server/Network/BufferPool.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
#region References
|
||||
using System.Collections.Generic;
|
||||
#endregion
|
||||
|
||||
namespace Server.Network
|
||||
{
|
||||
public class BufferPool
|
||||
{
|
||||
public static List<BufferPool> Pools { get; private set; }
|
||||
|
||||
static BufferPool()
|
||||
{
|
||||
Pools = new List<BufferPool>();
|
||||
}
|
||||
|
||||
private readonly string m_Name;
|
||||
|
||||
private readonly int m_InitialCapacity;
|
||||
private readonly int m_BufferSize;
|
||||
|
||||
private int m_Misses;
|
||||
|
||||
private readonly Queue<byte[]> m_FreeBuffers;
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (this)
|
||||
return m_FreeBuffers.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public void GetInfo(
|
||||
out string name,
|
||||
out int freeCount,
|
||||
out int initialCapacity,
|
||||
out int currentCapacity,
|
||||
out int bufferSize,
|
||||
out int misses)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
name = m_Name;
|
||||
freeCount = m_FreeBuffers.Count;
|
||||
initialCapacity = m_InitialCapacity;
|
||||
currentCapacity = m_InitialCapacity * (1 + m_Misses);
|
||||
bufferSize = m_BufferSize;
|
||||
misses = m_Misses;
|
||||
}
|
||||
}
|
||||
|
||||
public BufferPool(string name, int initialCapacity, int bufferSize)
|
||||
{
|
||||
m_Name = name;
|
||||
|
||||
m_InitialCapacity = initialCapacity;
|
||||
m_BufferSize = bufferSize;
|
||||
|
||||
m_FreeBuffers = new Queue<byte[]>(initialCapacity);
|
||||
|
||||
for (int i = 0; i < initialCapacity; ++i)
|
||||
{
|
||||
m_FreeBuffers.Enqueue(new byte[bufferSize]);
|
||||
}
|
||||
|
||||
lock (Pools)
|
||||
Pools.Add(this);
|
||||
}
|
||||
|
||||
public byte[] AcquireBuffer()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (m_FreeBuffers.Count > 0)
|
||||
{
|
||||
return m_FreeBuffers.Dequeue();
|
||||
}
|
||||
|
||||
++m_Misses;
|
||||
|
||||
for (int i = 0; i < m_InitialCapacity; ++i)
|
||||
{
|
||||
m_FreeBuffers.Enqueue(new byte[m_BufferSize]);
|
||||
}
|
||||
|
||||
return m_FreeBuffers.Dequeue();
|
||||
}
|
||||
}
|
||||
|
||||
public void ReleaseBuffer(byte[] buffer)
|
||||
{
|
||||
if (buffer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (this)
|
||||
m_FreeBuffers.Enqueue(buffer);
|
||||
}
|
||||
|
||||
public void Free()
|
||||
{
|
||||
lock (Pools)
|
||||
Pools.Remove(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
147
Server/Network/ByteQueue.cs
Normal file
147
Server/Network/ByteQueue.cs
Normal file
@@ -0,0 +1,147 @@
|
||||
#region References
|
||||
using System;
|
||||
#endregion
|
||||
|
||||
namespace Server.Network
|
||||
{
|
||||
public class ByteQueue
|
||||
{
|
||||
private int m_Head;
|
||||
private int m_Tail;
|
||||
private int m_Size;
|
||||
|
||||
private byte[] m_Buffer;
|
||||
|
||||
public int Length { get { return m_Size; } }
|
||||
|
||||
public ByteQueue()
|
||||
{
|
||||
m_Buffer = new byte[2048];
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
m_Head = 0;
|
||||
m_Tail = 0;
|
||||
m_Size = 0;
|
||||
}
|
||||
|
||||
private void SetCapacity(int capacity)
|
||||
{
|
||||
var newBuffer = new byte[capacity];
|
||||
|
||||
if (m_Size > 0)
|
||||
{
|
||||
if (m_Head < m_Tail)
|
||||
{
|
||||
Buffer.BlockCopy(m_Buffer, m_Head, newBuffer, 0, m_Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
Buffer.BlockCopy(m_Buffer, m_Head, newBuffer, 0, m_Buffer.Length - m_Head);
|
||||
Buffer.BlockCopy(m_Buffer, 0, newBuffer, m_Buffer.Length - m_Head, m_Tail);
|
||||
}
|
||||
}
|
||||
|
||||
m_Head = 0;
|
||||
m_Tail = m_Size;
|
||||
m_Buffer = newBuffer;
|
||||
}
|
||||
|
||||
public byte GetPacketID()
|
||||
{
|
||||
if (m_Size >= 1)
|
||||
{
|
||||
return m_Buffer[m_Head];
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
public int GetPacketLength()
|
||||
{
|
||||
if (m_Size >= 3)
|
||||
{
|
||||
return (m_Buffer[(m_Head + 1) % m_Buffer.Length] << 8) | m_Buffer[(m_Head + 2) % m_Buffer.Length];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int Dequeue(byte[] buffer, int offset, int size)
|
||||
{
|
||||
if (size > m_Size)
|
||||
{
|
||||
size = m_Size;
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (buffer != null)
|
||||
{
|
||||
if (m_Head < m_Tail)
|
||||
{
|
||||
Buffer.BlockCopy(m_Buffer, m_Head, buffer, offset, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
int rightLength = (m_Buffer.Length - m_Head);
|
||||
|
||||
if (rightLength >= size)
|
||||
{
|
||||
Buffer.BlockCopy(m_Buffer, m_Head, buffer, offset, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
Buffer.BlockCopy(m_Buffer, m_Head, buffer, offset, rightLength);
|
||||
Buffer.BlockCopy(m_Buffer, 0, buffer, offset + rightLength, size - rightLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_Head = (m_Head + size) % m_Buffer.Length;
|
||||
m_Size -= size;
|
||||
|
||||
if (m_Size == 0)
|
||||
{
|
||||
m_Head = 0;
|
||||
m_Tail = 0;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
public void Enqueue(byte[] buffer, int offset, int size)
|
||||
{
|
||||
if ((m_Size + size) > m_Buffer.Length)
|
||||
{
|
||||
SetCapacity((m_Size + size + 2047) & ~2047);
|
||||
}
|
||||
|
||||
if (m_Head < m_Tail)
|
||||
{
|
||||
int rightLength = (m_Buffer.Length - m_Tail);
|
||||
|
||||
if (rightLength >= size)
|
||||
{
|
||||
Buffer.BlockCopy(buffer, offset, m_Buffer, m_Tail, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
Buffer.BlockCopy(buffer, offset, m_Buffer, m_Tail, rightLength);
|
||||
Buffer.BlockCopy(buffer, offset + rightLength, m_Buffer, 0, size - rightLength);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Buffer.BlockCopy(buffer, offset, m_Buffer, m_Tail, size);
|
||||
}
|
||||
|
||||
m_Tail = (m_Tail + size) % m_Buffer.Length;
|
||||
m_Size += size;
|
||||
}
|
||||
}
|
||||
}
|
||||
394
Server/Network/Compression.cs
Normal file
394
Server/Network/Compression.cs
Normal file
@@ -0,0 +1,394 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
#endregion
|
||||
|
||||
namespace Server.Network
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles outgoing packet compression for the network.
|
||||
/// </summary>
|
||||
public static class Compression
|
||||
{
|
||||
private static readonly int[] _huffmanTable = new int[514]
|
||||
{
|
||||
0x2, 0x000, 0x5, 0x01F, 0x6, 0x022, 0x7, 0x034, 0x7, 0x075, 0x6, 0x028, 0x6, 0x03B, 0x7, 0x032, 0x8, 0x0E0, 0x8,
|
||||
0x062, 0x7, 0x056, 0x8, 0x079, 0x9, 0x19D, 0x8, 0x097, 0x6, 0x02A, 0x7, 0x057, 0x8, 0x071, 0x8, 0x05B, 0x9, 0x1CC,
|
||||
0x8, 0x0A7, 0x7, 0x025, 0x7, 0x04F, 0x8, 0x066, 0x8, 0x07D, 0x9, 0x191, 0x9, 0x1CE, 0x7, 0x03F, 0x9, 0x090, 0x8,
|
||||
0x059, 0x8, 0x07B, 0x8, 0x091, 0x8, 0x0C6, 0x6, 0x02D, 0x9, 0x186, 0x8, 0x06F, 0x9, 0x093, 0xA, 0x1CC, 0x8, 0x05A,
|
||||
0xA, 0x1AE, 0xA, 0x1C0, 0x9, 0x148, 0x9, 0x14A, 0x9, 0x082, 0xA, 0x19F, 0x9, 0x171, 0x9, 0x120, 0x9, 0x0E7, 0xA,
|
||||
0x1F3, 0x9, 0x14B, 0x9, 0x100, 0x9, 0x190, 0x6, 0x013, 0x9, 0x161, 0x9, 0x125, 0x9, 0x133, 0x9, 0x195, 0x9, 0x173,
|
||||
0x9, 0x1CA, 0x9, 0x086, 0x9, 0x1E9, 0x9, 0x0DB, 0x9, 0x1EC, 0x9, 0x08B, 0x9, 0x085, 0x5, 0x00A, 0x8, 0x096, 0x8,
|
||||
0x09C, 0x9, 0x1C3, 0x9, 0x19C, 0x9, 0x08F, 0x9, 0x18F, 0x9, 0x091, 0x9, 0x087, 0x9, 0x0C6, 0x9, 0x177, 0x9, 0x089,
|
||||
0x9, 0x0D6, 0x9, 0x08C, 0x9, 0x1EE, 0x9, 0x1EB, 0x9, 0x084, 0x9, 0x164, 0x9, 0x175, 0x9, 0x1CD, 0x8, 0x05E, 0x9,
|
||||
0x088, 0x9, 0x12B, 0x9, 0x172, 0x9, 0x10A, 0x9, 0x08D, 0x9, 0x13A, 0x9, 0x11C, 0xA, 0x1E1, 0xA, 0x1E0, 0x9, 0x187,
|
||||
0xA, 0x1DC, 0xA, 0x1DF, 0x7, 0x074, 0x9, 0x19F, 0x8, 0x08D, 0x8, 0x0E4, 0x7, 0x079, 0x9, 0x0EA, 0x9, 0x0E1, 0x8,
|
||||
0x040, 0x7, 0x041, 0x9, 0x10B, 0x9, 0x0B0, 0x8, 0x06A, 0x8, 0x0C1, 0x7, 0x071, 0x7, 0x078, 0x8, 0x0B1, 0x9, 0x14C,
|
||||
0x7, 0x043, 0x8, 0x076, 0x7, 0x066, 0x7, 0x04D, 0x9, 0x08A, 0x6, 0x02F, 0x8, 0x0C9, 0x9, 0x0CE, 0x9, 0x149, 0x9,
|
||||
0x160, 0xA, 0x1BA, 0xA, 0x19E, 0xA, 0x39F, 0x9, 0x0E5, 0x9, 0x194, 0x9, 0x184, 0x9, 0x126, 0x7, 0x030, 0x8, 0x06C,
|
||||
0x9, 0x121, 0x9, 0x1E8, 0xA, 0x1C1, 0xA, 0x11D, 0xA, 0x163, 0xA, 0x385, 0xA, 0x3DB, 0xA, 0x17D, 0xA, 0x106, 0xA,
|
||||
0x397, 0xA, 0x24E, 0x7, 0x02E, 0x8, 0x098, 0xA, 0x33C, 0xA, 0x32E, 0xA, 0x1E9, 0x9, 0x0BF, 0xA, 0x3DF, 0xA, 0x1DD,
|
||||
0xA, 0x32D, 0xA, 0x2ED, 0xA, 0x30B, 0xA, 0x107, 0xA, 0x2E8, 0xA, 0x3DE, 0xA, 0x125, 0xA, 0x1E8, 0x9, 0x0E9, 0xA,
|
||||
0x1CD, 0xA, 0x1B5, 0x9, 0x165, 0xA, 0x232, 0xA, 0x2E1, 0xB, 0x3AE, 0xB, 0x3C6, 0xB, 0x3E2, 0xA, 0x205, 0xA, 0x29A,
|
||||
0xA, 0x248, 0xA, 0x2CD, 0xA, 0x23B, 0xB, 0x3C5, 0xA, 0x251, 0xA, 0x2E9, 0xA, 0x252, 0x9, 0x1EA, 0xB, 0x3A0, 0xB,
|
||||
0x391, 0xA, 0x23C, 0xB, 0x392, 0xB, 0x3D5, 0xA, 0x233, 0xA, 0x2CC, 0xB, 0x390, 0xA, 0x1BB, 0xB, 0x3A1, 0xB, 0x3C4,
|
||||
0xA, 0x211, 0xA, 0x203, 0x9, 0x12A, 0xA, 0x231, 0xB, 0x3E0, 0xA, 0x29B, 0xB, 0x3D7, 0xA, 0x202, 0xB, 0x3AD, 0xA,
|
||||
0x213, 0xA, 0x253, 0xA, 0x32C, 0xA, 0x23D, 0xA, 0x23F, 0xA, 0x32F, 0xA, 0x11C, 0xA, 0x384, 0xA, 0x31C, 0xA, 0x17C,
|
||||
0xA, 0x30A, 0xA, 0x2E0, 0xA, 0x276, 0xA, 0x250, 0xB, 0x3E3, 0xA, 0x396, 0xA, 0x18F, 0xA, 0x204, 0xA, 0x206, 0xA,
|
||||
0x230, 0xA, 0x265, 0xA, 0x212, 0xA, 0x23E, 0xB, 0x3AC, 0xB, 0x393, 0xB, 0x3E1, 0xA, 0x1DE, 0xB, 0x3D6, 0xA, 0x31D,
|
||||
0xB, 0x3E5, 0xB, 0x3E4, 0xA, 0x207, 0xB, 0x3C7, 0xA, 0x277, 0xB, 0x3D4, 0x8, 0x0C0, 0xA, 0x162, 0xA, 0x3DA, 0xA,
|
||||
0x124, 0xA, 0x1B4, 0xA, 0x264, 0xA, 0x33D, 0xA, 0x1D1, 0xA, 0x1AF, 0xA, 0x39E, 0xA, 0x24F, 0xB, 0x373, 0xA, 0x249,
|
||||
0xB, 0x372, 0x9, 0x167, 0xA, 0x210, 0xA, 0x23A, 0xA, 0x1B8, 0xB, 0x3AF, 0xA, 0x18E, 0xA, 0x2EC, 0x7, 0x062, 0x4,
|
||||
0x00D
|
||||
};
|
||||
|
||||
private const int CountIndex = 0;
|
||||
private const int ValueIndex = 1;
|
||||
|
||||
// UO packets may not exceed 64kb in length
|
||||
private const int BufferSize = 0x10000;
|
||||
|
||||
// Optimal compression ratio is 2 / 8; worst compression ratio is 11 / 8
|
||||
private const int MinimalCodeLength = 2;
|
||||
private const int MaximalCodeLength = 11;
|
||||
|
||||
// Fixed overhead, in bits, per compression call
|
||||
private const int TerminalCodeLength = 4;
|
||||
|
||||
// If our input exceeds this length, we cannot possibly compress it within the buffer
|
||||
private const int DefiniteOverflow = ((BufferSize * 8) - TerminalCodeLength) / MinimalCodeLength;
|
||||
|
||||
// If our input exceeds this length, we may potentially overflow the buffer
|
||||
private const int PossibleOverflow = ((BufferSize * 8) - TerminalCodeLength) / MaximalCodeLength;
|
||||
|
||||
public static unsafe void Compress(byte[] input, int offset, int count, byte[] output, ref int length)
|
||||
{
|
||||
if (input == null)
|
||||
{
|
||||
throw new ArgumentNullException("input");
|
||||
}
|
||||
else if (offset < 0 || offset >= input.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("offset");
|
||||
}
|
||||
else if (count < 0 || count > input.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("count");
|
||||
}
|
||||
else if ((input.Length - offset) < count)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
length = 0;
|
||||
|
||||
if (count > DefiniteOverflow)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int bitCount = 0;
|
||||
int bitValue = 0;
|
||||
|
||||
fixed (int* pTable = _huffmanTable)
|
||||
{
|
||||
int* pEntry;
|
||||
|
||||
fixed (byte* pInputBuffer = input)
|
||||
{
|
||||
byte* pInput = pInputBuffer + offset, pInputEnd = pInput + count;
|
||||
|
||||
fixed (byte* pOutputBuffer = output)
|
||||
{
|
||||
byte* pOutput = pOutputBuffer, pOutputEnd = pOutput + BufferSize;
|
||||
|
||||
while (pInput < pInputEnd)
|
||||
{
|
||||
pEntry = &pTable[*pInput++ << 1];
|
||||
|
||||
bitCount += pEntry[CountIndex];
|
||||
|
||||
bitValue <<= pEntry[CountIndex];
|
||||
bitValue |= pEntry[ValueIndex];
|
||||
|
||||
while (bitCount >= 8)
|
||||
{
|
||||
bitCount -= 8;
|
||||
|
||||
if (pOutput < pOutputEnd)
|
||||
{
|
||||
*pOutput++ = (byte)(bitValue >> bitCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
length = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// terminal code
|
||||
pEntry = &pTable[0x200];
|
||||
|
||||
bitCount += pEntry[CountIndex];
|
||||
|
||||
bitValue <<= pEntry[CountIndex];
|
||||
bitValue |= pEntry[ValueIndex];
|
||||
|
||||
// align on byte boundary
|
||||
if ((bitCount & 7) != 0)
|
||||
{
|
||||
bitValue <<= (8 - (bitCount & 7));
|
||||
bitCount += (8 - (bitCount & 7));
|
||||
}
|
||||
|
||||
while (bitCount >= 8)
|
||||
{
|
||||
bitCount -= 8;
|
||||
|
||||
if (pOutput < pOutputEnd)
|
||||
{
|
||||
*pOutput++ = (byte)(bitValue >> bitCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
length = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
length = (int)(pOutput - pOutputBuffer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly ICompressor Compressor;
|
||||
|
||||
static Compression()
|
||||
{
|
||||
if (Core.Unix)
|
||||
{
|
||||
if (Core.Is64Bit)
|
||||
{
|
||||
Compressor = new CompressorUnix64();
|
||||
}
|
||||
else
|
||||
{
|
||||
Compressor = new CompressorUnix32();
|
||||
}
|
||||
}
|
||||
else if (Core.Is64Bit)
|
||||
{
|
||||
Compressor = new Compressor64();
|
||||
}
|
||||
else
|
||||
{
|
||||
Compressor = new Compressor32();
|
||||
}
|
||||
}
|
||||
|
||||
public static ZLibError Pack(byte[] dest, ref int destLength, byte[] source, int sourceLength)
|
||||
{
|
||||
return Compressor.Compress(dest, ref destLength, source, sourceLength);
|
||||
}
|
||||
|
||||
public static ZLibError Pack(byte[] dest, ref int destLength, byte[] source, int sourceLength, ZLibQuality quality)
|
||||
{
|
||||
return Compressor.Compress(dest, ref destLength, source, sourceLength, quality);
|
||||
}
|
||||
|
||||
public static ZLibError Unpack(byte[] dest, ref int destLength, byte[] source, int sourceLength)
|
||||
{
|
||||
return Compressor.Decompress(dest, ref destLength, source, sourceLength);
|
||||
}
|
||||
}
|
||||
|
||||
public interface ICompressor
|
||||
{
|
||||
string Version { get; }
|
||||
|
||||
ZLibError Compress(byte[] dest, ref int destLength, byte[] source, int sourceLength);
|
||||
ZLibError Compress(byte[] dest, ref int destLength, byte[] source, int sourceLength, ZLibQuality quality);
|
||||
|
||||
ZLibError Decompress(byte[] dest, ref int destLength, byte[] source, int sourceLength);
|
||||
}
|
||||
|
||||
public sealed class Compressor32 : ICompressor
|
||||
{
|
||||
internal class SafeNativeMethods
|
||||
{
|
||||
[DllImport("zlibwapi32")]
|
||||
internal static extern string zlibVersion();
|
||||
|
||||
[DllImport("zlibwapi32")]
|
||||
internal static extern ZLibError compress(byte[] dest, ref int destLength, byte[] source, int sourceLength);
|
||||
|
||||
[DllImport("zlibwapi32")]
|
||||
internal static extern ZLibError compress2(
|
||||
byte[] dest, ref int destLength, byte[] source, int sourceLength, ZLibQuality quality);
|
||||
|
||||
[DllImport("zlibwapi32")]
|
||||
internal static extern ZLibError uncompress(byte[] dest, ref int destLen, byte[] source, int sourceLen);
|
||||
}
|
||||
|
||||
public string Version { get { return SafeNativeMethods.zlibVersion(); } }
|
||||
|
||||
public ZLibError Compress(byte[] dest, ref int destLength, byte[] source, int sourceLength)
|
||||
{
|
||||
return SafeNativeMethods.compress(dest, ref destLength, source, sourceLength);
|
||||
}
|
||||
|
||||
public ZLibError Compress(byte[] dest, ref int destLength, byte[] source, int sourceLength, ZLibQuality quality)
|
||||
{
|
||||
return SafeNativeMethods.compress2(dest, ref destLength, source, sourceLength, quality);
|
||||
}
|
||||
|
||||
public ZLibError Decompress(byte[] dest, ref int destLength, byte[] source, int sourceLength)
|
||||
{
|
||||
return SafeNativeMethods.uncompress(dest, ref destLength, source, sourceLength);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Compressor64 : ICompressor
|
||||
{
|
||||
internal class SafeNativeMethods
|
||||
{
|
||||
[DllImport("zlibwapi64")]
|
||||
internal static extern string zlibVersion();
|
||||
|
||||
[DllImport("zlibwapi64")]
|
||||
internal static extern ZLibError compress(byte[] dest, ref int destLength, byte[] source, int sourceLength);
|
||||
|
||||
[DllImport("zlibwapi64")]
|
||||
internal static extern ZLibError compress2(
|
||||
byte[] dest, ref int destLength, byte[] source, int sourceLength, ZLibQuality quality);
|
||||
|
||||
[DllImport("zlibwapi64")]
|
||||
internal static extern ZLibError uncompress(byte[] dest, ref int destLen, byte[] source, int sourceLen);
|
||||
}
|
||||
|
||||
public string Version { get { return SafeNativeMethods.zlibVersion(); } }
|
||||
|
||||
public ZLibError Compress(byte[] dest, ref int destLength, byte[] source, int sourceLength)
|
||||
{
|
||||
return SafeNativeMethods.compress(dest, ref destLength, source, sourceLength);
|
||||
}
|
||||
|
||||
public ZLibError Compress(byte[] dest, ref int destLength, byte[] source, int sourceLength, ZLibQuality quality)
|
||||
{
|
||||
return SafeNativeMethods.compress2(dest, ref destLength, source, sourceLength, quality);
|
||||
}
|
||||
|
||||
public ZLibError Decompress(byte[] dest, ref int destLength, byte[] source, int sourceLength)
|
||||
{
|
||||
return SafeNativeMethods.uncompress(dest, ref destLength, source, sourceLength);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class CompressorUnix32 : ICompressor
|
||||
{
|
||||
internal class SafeNativeMethods
|
||||
{
|
||||
[DllImport("libz")]
|
||||
internal static extern string zlibVersion();
|
||||
|
||||
[DllImport("libz")]
|
||||
internal static extern ZLibError compress(byte[] dest, ref int destLength, byte[] source, int sourceLength);
|
||||
|
||||
[DllImport("libz")]
|
||||
internal static extern ZLibError compress2(
|
||||
byte[] dest, ref int destLength, byte[] source, int sourceLength, ZLibQuality quality);
|
||||
|
||||
[DllImport("libz")]
|
||||
internal static extern ZLibError uncompress(byte[] dest, ref int destLen, byte[] source, int sourceLen);
|
||||
}
|
||||
|
||||
public string Version { get { return SafeNativeMethods.zlibVersion(); } }
|
||||
|
||||
public ZLibError Compress(byte[] dest, ref int destLength, byte[] source, int sourceLength)
|
||||
{
|
||||
return SafeNativeMethods.compress(dest, ref destLength, source, sourceLength);
|
||||
}
|
||||
|
||||
public ZLibError Compress(byte[] dest, ref int destLength, byte[] source, int sourceLength, ZLibQuality quality)
|
||||
{
|
||||
return SafeNativeMethods.compress2(dest, ref destLength, source, sourceLength, quality);
|
||||
}
|
||||
|
||||
public ZLibError Decompress(byte[] dest, ref int destLength, byte[] source, int sourceLength)
|
||||
{
|
||||
return SafeNativeMethods.uncompress(dest, ref destLength, source, sourceLength);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class CompressorUnix64 : ICompressor
|
||||
{
|
||||
internal class SafeNativeMethods
|
||||
{
|
||||
[DllImport("libz")]
|
||||
internal static extern string zlibVersion();
|
||||
|
||||
[DllImport("libz")]
|
||||
internal static extern ZLibError compress(byte[] dest, ref long destLength, byte[] source, long sourceLength);
|
||||
|
||||
[DllImport("libz")]
|
||||
internal static extern ZLibError compress2(byte[] dest, ref long destLength, byte[] source, long sourceLength, ZLibQuality quality);
|
||||
|
||||
[DllImport("libz")]
|
||||
internal static extern ZLibError uncompress(byte[] dest, ref long destLen, byte[] source, long sourceLen);
|
||||
}
|
||||
|
||||
public string Version { get { return SafeNativeMethods.zlibVersion(); } }
|
||||
|
||||
public ZLibError Compress(byte[] dest, ref int destLength, byte[] source, int sourceLength)
|
||||
{
|
||||
long destLengthLong = destLength;
|
||||
ZLibError z = SafeNativeMethods.compress(dest, ref destLengthLong, source, sourceLength);
|
||||
destLength = (int)destLengthLong;
|
||||
return z;
|
||||
}
|
||||
|
||||
public ZLibError Compress(byte[] dest, ref int destLength, byte[] source, int sourceLength, ZLibQuality quality)
|
||||
{
|
||||
long destLengthLong = destLength;
|
||||
ZLibError z = SafeNativeMethods.compress2(dest, ref destLengthLong, source, sourceLength, quality);
|
||||
destLength = (int)destLengthLong;
|
||||
return z;
|
||||
}
|
||||
|
||||
public ZLibError Decompress(byte[] dest, ref int destLength, byte[] source, int sourceLength)
|
||||
{
|
||||
long destLengthLong = destLength;
|
||||
ZLibError z = SafeNativeMethods.uncompress(dest, ref destLengthLong, source, sourceLength);
|
||||
destLength = (int)destLengthLong;
|
||||
return z;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ZLibError
|
||||
{
|
||||
VersionError = -6,
|
||||
BufferError = -5,
|
||||
MemoryError = -4,
|
||||
DataError = -3,
|
||||
StreamError = -2,
|
||||
FileError = -1,
|
||||
|
||||
Okay = 0,
|
||||
|
||||
StreamEnd = 1,
|
||||
NeedDictionary = 2
|
||||
}
|
||||
|
||||
public enum ZLibQuality
|
||||
{
|
||||
Default = -1,
|
||||
|
||||
None = 0,
|
||||
|
||||
Speed = 1,
|
||||
Size = 9
|
||||
}
|
||||
}
|
||||
24
Server/Network/EncodedPacketHandler.cs
Normal file
24
Server/Network/EncodedPacketHandler.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
namespace Server.Network
|
||||
{
|
||||
public delegate void OnEncodedPacketReceive(NetState state, IEntity ent, EncodedReader pvSrc);
|
||||
|
||||
public class EncodedPacketHandler
|
||||
{
|
||||
private readonly int m_PacketID;
|
||||
private readonly bool m_Ingame;
|
||||
private readonly OnEncodedPacketReceive m_OnReceive;
|
||||
|
||||
public EncodedPacketHandler(int packetID, bool ingame, OnEncodedPacketReceive onReceive)
|
||||
{
|
||||
m_PacketID = packetID;
|
||||
m_Ingame = ingame;
|
||||
m_OnReceive = onReceive;
|
||||
}
|
||||
|
||||
public int PacketID { get { return m_PacketID; } }
|
||||
|
||||
public OnEncodedPacketReceive OnReceive { get { return m_OnReceive; } }
|
||||
|
||||
public bool Ingame { get { return m_Ingame; } }
|
||||
}
|
||||
}
|
||||
63
Server/Network/EncodedReader.cs
Normal file
63
Server/Network/EncodedReader.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
namespace Server.Network
|
||||
{
|
||||
public class EncodedReader
|
||||
{
|
||||
private readonly PacketReader m_Reader;
|
||||
|
||||
public EncodedReader(PacketReader reader)
|
||||
{
|
||||
m_Reader = reader;
|
||||
}
|
||||
|
||||
public byte[] Buffer { get { return m_Reader.Buffer; } }
|
||||
|
||||
public void Trace(NetState state)
|
||||
{
|
||||
m_Reader.Trace(state);
|
||||
}
|
||||
|
||||
public int ReadInt32()
|
||||
{
|
||||
if (m_Reader.ReadByte() != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m_Reader.ReadInt32();
|
||||
}
|
||||
|
||||
public Point3D ReadPoint3D()
|
||||
{
|
||||
if (m_Reader.ReadByte() != 3)
|
||||
{
|
||||
return Point3D.Zero;
|
||||
}
|
||||
|
||||
return new Point3D(m_Reader.ReadInt16(), m_Reader.ReadInt16(), m_Reader.ReadByte());
|
||||
}
|
||||
|
||||
public string ReadUnicodeStringSafe()
|
||||
{
|
||||
if (m_Reader.ReadByte() != 2)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
int length = m_Reader.ReadUInt16();
|
||||
|
||||
return m_Reader.ReadUnicodeStringSafe(length);
|
||||
}
|
||||
|
||||
public string ReadUnicodeString()
|
||||
{
|
||||
if (m_Reader.ReadByte() != 2)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
int length = m_Reader.ReadUInt16();
|
||||
|
||||
return m_Reader.ReadUnicodeString(length);
|
||||
}
|
||||
}
|
||||
}
|
||||
280
Server/Network/Listener.cs
Normal file
280
Server/Network/Listener.cs
Normal file
@@ -0,0 +1,280 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
#endregion
|
||||
|
||||
namespace Server.Network
|
||||
{
|
||||
public class Listener : IDisposable
|
||||
{
|
||||
private Socket m_Listener;
|
||||
private PingListener _PingListener;
|
||||
|
||||
private readonly Queue<Socket> m_Accepted;
|
||||
private readonly object m_AcceptedSyncRoot;
|
||||
|
||||
private readonly AsyncCallback m_OnAccept;
|
||||
|
||||
private static readonly Socket[] m_EmptySockets = new Socket[0];
|
||||
|
||||
public static IPEndPoint[] EndPoints { get; set; }
|
||||
|
||||
public Listener(IPEndPoint ipep)
|
||||
{
|
||||
m_Accepted = new Queue<Socket>();
|
||||
m_AcceptedSyncRoot = ((ICollection)m_Accepted).SyncRoot;
|
||||
|
||||
m_Listener = Bind(ipep);
|
||||
|
||||
if (m_Listener == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DisplayListener();
|
||||
_PingListener = new PingListener(ipep);
|
||||
|
||||
m_OnAccept = OnAccept;
|
||||
try
|
||||
{
|
||||
IAsyncResult res = m_Listener.BeginAccept(m_OnAccept, m_Listener);
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
NetState.TraceException(ex);
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{ }
|
||||
}
|
||||
|
||||
private Socket Bind(IPEndPoint ipep)
|
||||
{
|
||||
Socket s = new Socket(ipep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
try
|
||||
{
|
||||
s.LingerState.Enabled = false;
|
||||
|
||||
// Default is 'false' starting Windows Vista and Server 2008. Source: https://msdn.microsoft.com/en-us/library/system.net.sockets.socket.exclusiveaddressuse(v=vs.110).aspx?f=255&MSPPError=-2147217396
|
||||
s.ExclusiveAddressUse = false;
|
||||
|
||||
s.Bind(ipep);
|
||||
s.Listen(8);
|
||||
|
||||
return s;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (e is SocketException)
|
||||
{
|
||||
SocketException se = (SocketException)e;
|
||||
|
||||
if (se.ErrorCode == 10048)
|
||||
{
|
||||
// WSAEADDRINUSE
|
||||
Utility.PushColor(ConsoleColor.Red);
|
||||
Console.WriteLine("Listener Failed: {0}:{1} (In Use)", ipep.Address, ipep.Port);
|
||||
Utility.PopColor();
|
||||
}
|
||||
else if (se.ErrorCode == 10049)
|
||||
{
|
||||
// WSAEADDRNOTAVAIL
|
||||
Utility.PushColor(ConsoleColor.Red);
|
||||
Console.WriteLine("Listener Failed: {0}:{1} (Unavailable)", ipep.Address, ipep.Port);
|
||||
Utility.PopColor();
|
||||
}
|
||||
else
|
||||
{
|
||||
Utility.PushColor(ConsoleColor.Red);
|
||||
Console.WriteLine("Listener Exception:");
|
||||
Console.WriteLine(e);
|
||||
Utility.PopColor();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void DisplayListener()
|
||||
{
|
||||
IPEndPoint ipep = m_Listener.LocalEndPoint as IPEndPoint;
|
||||
|
||||
if (ipep == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ipep.Address.Equals(IPAddress.Any) || ipep.Address.Equals(IPAddress.IPv6Any))
|
||||
{
|
||||
var adapters = NetworkInterface.GetAllNetworkInterfaces();
|
||||
foreach (NetworkInterface adapter in adapters)
|
||||
{
|
||||
IPInterfaceProperties properties = adapter.GetIPProperties();
|
||||
foreach (IPAddressInformation unicast in properties.UnicastAddresses)
|
||||
{
|
||||
if (ipep.AddressFamily == unicast.Address.AddressFamily)
|
||||
{
|
||||
Utility.PushColor(ConsoleColor.Green);
|
||||
Console.WriteLine("Listening: {0}:{1}", unicast.Address, ipep.Port);
|
||||
Utility.PopColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
try {
|
||||
Console.WriteLine( "Listening: {0}:{1}", IPAddress.Loopback, ipep.Port );
|
||||
IPHostEntry iphe = Dns.GetHostEntry( Dns.GetHostName() );
|
||||
IPAddress[] ip = iphe.AddressList;
|
||||
for ( int i = 0; i < ip.Length; ++i )
|
||||
Console.WriteLine( "Listening: {0}:{1}", ip[i], ipep.Port );
|
||||
}
|
||||
catch { }
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
Utility.PushColor(ConsoleColor.Green);
|
||||
Console.WriteLine("Listening: {0}:{1}", ipep.Address, ipep.Port);
|
||||
Utility.PopColor();
|
||||
}
|
||||
|
||||
Utility.PushColor(ConsoleColor.DarkGreen);
|
||||
Console.WriteLine(@"----------------------------------------------------------------------");
|
||||
Utility.PopColor();
|
||||
}
|
||||
|
||||
private void OnAccept(IAsyncResult asyncResult)
|
||||
{
|
||||
Socket listener = (Socket)asyncResult.AsyncState;
|
||||
|
||||
Socket accepted = null;
|
||||
|
||||
try
|
||||
{
|
||||
accepted = listener.EndAccept(asyncResult);
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
NetState.TraceException(ex);
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (accepted != null)
|
||||
{
|
||||
if (VerifySocket(accepted))
|
||||
{
|
||||
Enqueue(accepted);
|
||||
}
|
||||
else
|
||||
{
|
||||
Release(accepted);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
listener.BeginAccept(m_OnAccept, listener);
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
NetState.TraceException(ex);
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{ }
|
||||
}
|
||||
|
||||
private bool VerifySocket(Socket socket)
|
||||
{
|
||||
try
|
||||
{
|
||||
SocketConnectEventArgs args = new SocketConnectEventArgs(socket);
|
||||
|
||||
EventSink.InvokeSocketConnect(args);
|
||||
|
||||
return args.AllowConnection;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
NetState.TraceException(ex);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void Enqueue(Socket socket)
|
||||
{
|
||||
lock (m_AcceptedSyncRoot)
|
||||
{
|
||||
m_Accepted.Enqueue(socket);
|
||||
}
|
||||
|
||||
Core.Set();
|
||||
}
|
||||
|
||||
private void Release(Socket socket)
|
||||
{
|
||||
try
|
||||
{
|
||||
socket.Shutdown(SocketShutdown.Both);
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
NetState.TraceException(ex);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
socket.Close();
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
NetState.TraceException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Socket[] Slice()
|
||||
{
|
||||
Socket[] array;
|
||||
|
||||
lock (m_AcceptedSyncRoot)
|
||||
{
|
||||
if (m_Accepted.Count == 0)
|
||||
{
|
||||
return m_EmptySockets;
|
||||
}
|
||||
|
||||
array = m_Accepted.ToArray();
|
||||
m_Accepted.Clear();
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Socket socket = Interlocked.Exchange(ref m_Listener, null);
|
||||
|
||||
if (socket != null)
|
||||
{
|
||||
socket.Close();
|
||||
}
|
||||
|
||||
if (_PingListener == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_PingListener.Dispose();
|
||||
_PingListener = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
366
Server/Network/MessagePump.cs
Normal file
366
Server/Network/MessagePump.cs
Normal file
@@ -0,0 +1,366 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
|
||||
using Server.Diagnostics;
|
||||
#endregion
|
||||
|
||||
namespace Server.Network
|
||||
{
|
||||
public class MessagePump
|
||||
{
|
||||
private Queue<NetState> m_Queue;
|
||||
private Queue<NetState> m_WorkingQueue;
|
||||
private readonly Queue<NetState> m_Throttled;
|
||||
|
||||
public Listener[] Listeners { get; set; }
|
||||
|
||||
public MessagePump()
|
||||
{
|
||||
var ipep = Listener.EndPoints;
|
||||
|
||||
Listeners = new Listener[ipep.Length];
|
||||
|
||||
bool success = false;
|
||||
|
||||
do
|
||||
{
|
||||
for (int i = 0; i < ipep.Length; i++)
|
||||
{
|
||||
Listeners[i] = new Listener(ipep[i]);
|
||||
|
||||
success = true;
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
Utility.PushColor(ConsoleColor.Yellow);
|
||||
Console.WriteLine("Retrying...");
|
||||
Utility.PopColor();
|
||||
|
||||
Thread.Sleep(10000);
|
||||
}
|
||||
}
|
||||
while (!success);
|
||||
|
||||
m_Queue = new Queue<NetState>();
|
||||
m_WorkingQueue = new Queue<NetState>();
|
||||
m_Throttled = new Queue<NetState>();
|
||||
}
|
||||
|
||||
public void AddListener(Listener l)
|
||||
{
|
||||
var old = Listeners;
|
||||
|
||||
Listeners = new Listener[old.Length + 1];
|
||||
|
||||
for (int i = 0; i < old.Length; ++i)
|
||||
{
|
||||
Listeners[i] = old[i];
|
||||
}
|
||||
|
||||
Listeners[old.Length] = l;
|
||||
}
|
||||
|
||||
private void CheckListener()
|
||||
{
|
||||
foreach (Listener l in Listeners)
|
||||
{
|
||||
var accepted = l.Slice();
|
||||
|
||||
foreach (Socket s in accepted)
|
||||
{
|
||||
NetState ns = new NetState(s, this);
|
||||
|
||||
ns.Start();
|
||||
|
||||
if (ns.Running && Display(ns))
|
||||
{
|
||||
Utility.PushColor(ConsoleColor.Green);
|
||||
Console.WriteLine("Client: {0}: Connected. [{1} Online]", ns, NetState.Instances.Count);
|
||||
Utility.PopColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Display(NetState ns)
|
||||
{
|
||||
if (ns == null)
|
||||
return false;
|
||||
|
||||
string state = ns.ToString();
|
||||
|
||||
foreach (var str in _NoDisplay)
|
||||
{
|
||||
if (str == state)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static string[] _NoDisplay =
|
||||
{
|
||||
"192.99.10.155",
|
||||
"192.99.69.21",
|
||||
};
|
||||
|
||||
public void OnReceive(NetState ns)
|
||||
{
|
||||
lock (this)
|
||||
m_Queue.Enqueue(ns);
|
||||
|
||||
Core.Set();
|
||||
}
|
||||
|
||||
public void Slice()
|
||||
{
|
||||
CheckListener();
|
||||
|
||||
lock (this)
|
||||
{
|
||||
var temp = m_WorkingQueue;
|
||||
m_WorkingQueue = m_Queue;
|
||||
m_Queue = temp;
|
||||
}
|
||||
|
||||
while (m_WorkingQueue.Count > 0)
|
||||
{
|
||||
NetState ns = m_WorkingQueue.Dequeue();
|
||||
|
||||
if (ns.Running)
|
||||
{
|
||||
HandleReceive(ns);
|
||||
}
|
||||
}
|
||||
|
||||
lock (this)
|
||||
{
|
||||
while (m_Throttled.Count > 0)
|
||||
{
|
||||
m_Queue.Enqueue(m_Throttled.Dequeue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private const int BufferSize = 4096;
|
||||
private readonly BufferPool m_Buffers = new BufferPool("Processor", 4, BufferSize);
|
||||
|
||||
public static bool HandleSeed(NetState ns, ByteQueue buffer)
|
||||
{
|
||||
if (buffer.GetPacketID() == 0xEF)
|
||||
{
|
||||
// new packet in client 6.0.5.0 replaces the traditional seed method with a seed packet
|
||||
// 0xEF = 239 = multicast IP, so this should never appear in a normal seed. So this is backwards compatible with older clients.
|
||||
ns.Seeded = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (buffer.Length >= 4)
|
||||
{
|
||||
var m_Peek = new byte[4];
|
||||
|
||||
buffer.Dequeue(m_Peek, 0, 4);
|
||||
|
||||
uint seed = (uint)((m_Peek[0] << 24) | (m_Peek[1] << 16) | (m_Peek[2] << 8) | m_Peek[3]);
|
||||
|
||||
if (seed == 0)
|
||||
{
|
||||
Utility.PushColor(ConsoleColor.Red);
|
||||
Console.WriteLine("Login: {0}: Invalid Client", ns);
|
||||
Utility.PopColor();
|
||||
|
||||
ns.Dispose();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ns.Seed = seed;
|
||||
ns.Seeded = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool CheckEncrypted(NetState ns, int packetID)
|
||||
{
|
||||
if (!ns.SentFirstPacket && packetID != 0xF0 && packetID != 0xF1 && packetID != 0xCF && packetID != 0x80 &&
|
||||
packetID != 0x91 && packetID != 0xA4 && packetID != 0xEF && packetID != 0xE4 && packetID != 0xFF)
|
||||
{
|
||||
Utility.PushColor(ConsoleColor.Red);
|
||||
Console.WriteLine("Client: {0}: Encrypted Client Unsupported", ns);
|
||||
Utility.PopColor();
|
||||
|
||||
ns.Dispose();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void HandleReceive(NetState ns)
|
||||
{
|
||||
ByteQueue buffer = ns.Buffer;
|
||||
|
||||
if (buffer == null || buffer.Length <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (buffer)
|
||||
{
|
||||
if (!ns.Seeded && !HandleSeed(ns, buffer))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int length = buffer.Length;
|
||||
|
||||
while (length > 0 && ns.Running)
|
||||
{
|
||||
int packetID = buffer.GetPacketID();
|
||||
|
||||
if (CheckEncrypted(ns, packetID))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PacketHandler handler = ns.GetHandler(packetID);
|
||||
|
||||
if (handler == null)
|
||||
{
|
||||
#if DEBUG
|
||||
var data = new byte[length];
|
||||
length = buffer.Dequeue(data, 0, length);
|
||||
new PacketReader(data, length, false).Trace(ns);
|
||||
#else
|
||||
buffer.Dequeue(null, 0, length);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
int packetLength = handler.Length;
|
||||
|
||||
if (packetLength <= 0)
|
||||
{
|
||||
if (length >= 3)
|
||||
{
|
||||
packetLength = buffer.GetPacketLength();
|
||||
|
||||
if (packetLength < 3)
|
||||
{
|
||||
ns.Dispose();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (length < packetLength)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (handler.Ingame)
|
||||
{
|
||||
if (ns.Mobile == null)
|
||||
{
|
||||
Utility.PushColor(ConsoleColor.Red);
|
||||
Console.WriteLine("Client: {0}: Packet (0x{1:X2}) Requires State Mobile", ns, packetID);
|
||||
Utility.PopColor();
|
||||
|
||||
ns.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ns.Mobile.Deleted)
|
||||
{
|
||||
Utility.PushColor(ConsoleColor.Red);
|
||||
Console.WriteLine("Client: {0}: Packet (0x{1:X2}) Ivalid State Mobile", ns, packetID);
|
||||
Utility.PopColor();
|
||||
|
||||
ns.Dispose();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ThrottlePacketCallback throttler = handler.ThrottleCallback;
|
||||
|
||||
if (throttler != null)
|
||||
{
|
||||
bool drop;
|
||||
|
||||
if (!throttler((byte)packetID, ns, out drop))
|
||||
{
|
||||
if (!drop)
|
||||
{
|
||||
m_Throttled.Enqueue(ns);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.Dequeue(null, 0, packetLength);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
PacketReceiveProfile prof = null;
|
||||
|
||||
if (Core.Profiling)
|
||||
{
|
||||
prof = PacketReceiveProfile.Acquire(packetID);
|
||||
}
|
||||
|
||||
if (prof != null)
|
||||
{
|
||||
prof.Start();
|
||||
}
|
||||
|
||||
byte[] packetBuffer;
|
||||
|
||||
if (BufferSize >= packetLength)
|
||||
{
|
||||
packetBuffer = m_Buffers.AcquireBuffer();
|
||||
}
|
||||
else
|
||||
{
|
||||
packetBuffer = new byte[packetLength];
|
||||
}
|
||||
|
||||
packetLength = buffer.Dequeue(packetBuffer, 0, packetLength);
|
||||
|
||||
if (packetBuffer != null && packetBuffer.Length > 0 && packetLength > 0)
|
||||
{
|
||||
PacketReader r = new PacketReader(packetBuffer, packetLength, handler.Length != 0);
|
||||
|
||||
handler.OnReceive(ns, r);
|
||||
|
||||
ns.SetPacketTime((byte)packetID);
|
||||
|
||||
if (BufferSize >= packetLength)
|
||||
{
|
||||
m_Buffers.ReleaseBuffer(packetBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (prof != null)
|
||||
{
|
||||
prof.Finish(packetLength);
|
||||
}
|
||||
|
||||
length = buffer.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1335
Server/Network/NetState.cs
Normal file
1335
Server/Network/NetState.cs
Normal file
File diff suppressed because it is too large
Load Diff
32
Server/Network/PacketHandler.cs
Normal file
32
Server/Network/PacketHandler.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
namespace Server.Network
|
||||
{
|
||||
public delegate void OnPacketReceive(NetState state, PacketReader pvSrc);
|
||||
|
||||
public delegate bool ThrottlePacketCallback(byte packetID, NetState state, out bool drop);
|
||||
|
||||
public class PacketHandler
|
||||
{
|
||||
private readonly int m_PacketID;
|
||||
private readonly int m_Length;
|
||||
private readonly bool m_Ingame;
|
||||
private readonly OnPacketReceive m_OnReceive;
|
||||
|
||||
public PacketHandler(int packetID, int length, bool ingame, OnPacketReceive onReceive)
|
||||
{
|
||||
m_PacketID = packetID;
|
||||
m_Length = length;
|
||||
m_Ingame = ingame;
|
||||
m_OnReceive = onReceive;
|
||||
}
|
||||
|
||||
public int PacketID { get { return m_PacketID; } }
|
||||
|
||||
public int Length { get { return m_Length; } }
|
||||
|
||||
public OnPacketReceive OnReceive { get { return m_OnReceive; } }
|
||||
|
||||
public ThrottlePacketCallback ThrottleCallback { get; set; }
|
||||
|
||||
public bool Ingame { get { return m_Ingame; } }
|
||||
}
|
||||
}
|
||||
3367
Server/Network/PacketHandlers.cs
Normal file
3367
Server/Network/PacketHandlers.cs
Normal file
File diff suppressed because it is too large
Load Diff
511
Server/Network/PacketReader.cs
Normal file
511
Server/Network/PacketReader.cs
Normal file
@@ -0,0 +1,511 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
#endregion
|
||||
|
||||
namespace Server.Network
|
||||
{
|
||||
public class PacketReader
|
||||
{
|
||||
private readonly byte[] m_Data;
|
||||
private readonly int m_Size;
|
||||
private int m_Index;
|
||||
|
||||
public PacketReader(byte[] data, int size, bool fixedSize)
|
||||
{
|
||||
m_Data = data;
|
||||
m_Size = size;
|
||||
m_Index = fixedSize ? 1 : 3;
|
||||
}
|
||||
|
||||
public byte[] Buffer { get { return m_Data; } }
|
||||
|
||||
public int Size { get { return m_Size; } }
|
||||
|
||||
public void Trace(NetState state)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (StreamWriter sw = new StreamWriter("Packets.log", true))
|
||||
{
|
||||
var buffer = m_Data;
|
||||
|
||||
if (buffer.Length > 0)
|
||||
{
|
||||
sw.WriteLine("Client: {0}: Unhandled packet 0x{1:X2}", state, buffer[0]);
|
||||
}
|
||||
|
||||
using (MemoryStream ms = new MemoryStream(buffer))
|
||||
{
|
||||
Utility.FormatBuffer(sw, ms, buffer.Length);
|
||||
}
|
||||
|
||||
sw.WriteLine();
|
||||
sw.WriteLine();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
|
||||
public int Seek(int offset, SeekOrigin origin)
|
||||
{
|
||||
switch (origin)
|
||||
{
|
||||
case SeekOrigin.Begin:
|
||||
m_Index = offset;
|
||||
break;
|
||||
case SeekOrigin.Current:
|
||||
m_Index += offset;
|
||||
break;
|
||||
case SeekOrigin.End:
|
||||
m_Index = m_Size - offset;
|
||||
break;
|
||||
}
|
||||
|
||||
return m_Index;
|
||||
}
|
||||
|
||||
public int ReadInt32()
|
||||
{
|
||||
if ((m_Index + 4) > m_Size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (m_Data[m_Index++] << 24) | (m_Data[m_Index++] << 16) | (m_Data[m_Index++] << 8) | m_Data[m_Index++];
|
||||
}
|
||||
|
||||
public short ReadInt16()
|
||||
{
|
||||
if ((m_Index + 2) > m_Size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (short)((m_Data[m_Index++] << 8) | m_Data[m_Index++]);
|
||||
}
|
||||
|
||||
public byte ReadByte()
|
||||
{
|
||||
if ((m_Index + 1) > m_Size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m_Data[m_Index++];
|
||||
}
|
||||
|
||||
public uint ReadUInt32()
|
||||
{
|
||||
if ((m_Index + 4) > m_Size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (uint)((m_Data[m_Index++] << 24) | (m_Data[m_Index++] << 16) | (m_Data[m_Index++] << 8) | m_Data[m_Index++]);
|
||||
}
|
||||
|
||||
public ushort ReadUInt16()
|
||||
{
|
||||
if ((m_Index + 2) > m_Size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (ushort)((m_Data[m_Index++] << 8) | m_Data[m_Index++]);
|
||||
}
|
||||
|
||||
public sbyte ReadSByte()
|
||||
{
|
||||
if ((m_Index + 1) > m_Size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (sbyte)m_Data[m_Index++];
|
||||
}
|
||||
|
||||
public bool ReadBoolean()
|
||||
{
|
||||
if ((m_Index + 1) > m_Size)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (m_Data[m_Index++] != 0);
|
||||
}
|
||||
|
||||
public string ReadUnicodeStringLE()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int c;
|
||||
|
||||
while ((m_Index + 1) < m_Size && (c = (m_Data[m_Index++] | (m_Data[m_Index++] << 8))) != 0)
|
||||
{
|
||||
sb.Append((char)c);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public string ReadUnicodeStringLESafe(int fixedLength)
|
||||
{
|
||||
int bound = m_Index + (fixedLength << 1);
|
||||
int end = bound;
|
||||
|
||||
if (bound > m_Size)
|
||||
{
|
||||
bound = m_Size;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int c;
|
||||
|
||||
while ((m_Index + 1) < bound && (c = (m_Data[m_Index++] | (m_Data[m_Index++] << 8))) != 0)
|
||||
{
|
||||
if (IsSafeChar(c))
|
||||
{
|
||||
sb.Append((char)c);
|
||||
}
|
||||
}
|
||||
|
||||
m_Index = end;
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public string ReadUnicodeStringLESafe()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int c;
|
||||
|
||||
while ((m_Index + 1) < m_Size && (c = (m_Data[m_Index++] | (m_Data[m_Index++] << 8))) != 0)
|
||||
{
|
||||
if (IsSafeChar(c))
|
||||
{
|
||||
sb.Append((char)c);
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public string ReadUnicodeStringSafe()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int c;
|
||||
|
||||
while ((m_Index + 1) < m_Size && (c = ((m_Data[m_Index++] << 8) | m_Data[m_Index++])) != 0)
|
||||
{
|
||||
if (IsSafeChar(c))
|
||||
{
|
||||
sb.Append((char)c);
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public string ReadUnicodeString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int c;
|
||||
|
||||
while ((m_Index + 1) < m_Size && (c = ((m_Data[m_Index++] << 8) | m_Data[m_Index++])) != 0)
|
||||
{
|
||||
sb.Append((char)c);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public bool IsSafeChar(int c)
|
||||
{
|
||||
return (c >= 0x20 && c < 0xFFFE);
|
||||
}
|
||||
|
||||
public string ReadUTF8StringSafe(int fixedLength)
|
||||
{
|
||||
if (m_Index >= m_Size)
|
||||
{
|
||||
m_Index += fixedLength;
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
int bound = m_Index + fixedLength;
|
||||
//int end = bound;
|
||||
|
||||
if (bound > m_Size)
|
||||
{
|
||||
bound = m_Size;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
int index = m_Index;
|
||||
int start = m_Index;
|
||||
|
||||
while (index < bound && m_Data[index++] != 0)
|
||||
{
|
||||
++count;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
|
||||
var buffer = new byte[count];
|
||||
int value = 0;
|
||||
|
||||
while (m_Index < bound && (value = m_Data[m_Index++]) != 0)
|
||||
{
|
||||
buffer[index++] = (byte)value;
|
||||
}
|
||||
|
||||
string s = Utility.UTF8.GetString(buffer);
|
||||
|
||||
bool isSafe = true;
|
||||
|
||||
for (int i = 0; isSafe && i < s.Length; ++i)
|
||||
{
|
||||
isSafe = IsSafeChar(s[i]);
|
||||
}
|
||||
|
||||
m_Index = start + fixedLength;
|
||||
|
||||
if (isSafe)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder(s.Length);
|
||||
|
||||
for (int i = 0; i < s.Length; ++i)
|
||||
{
|
||||
if (IsSafeChar(s[i]))
|
||||
{
|
||||
sb.Append(s[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public string ReadUTF8StringSafe()
|
||||
{
|
||||
if (m_Index >= m_Size)
|
||||
{
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
int index = m_Index;
|
||||
|
||||
while (index < m_Size && m_Data[index++] != 0)
|
||||
{
|
||||
++count;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
|
||||
var buffer = new byte[count];
|
||||
int value = 0;
|
||||
|
||||
while (m_Index < m_Size && (value = m_Data[m_Index++]) != 0)
|
||||
{
|
||||
buffer[index++] = (byte)value;
|
||||
}
|
||||
|
||||
string s = Utility.UTF8.GetString(buffer);
|
||||
|
||||
bool isSafe = true;
|
||||
|
||||
for (int i = 0; isSafe && i < s.Length; ++i)
|
||||
{
|
||||
isSafe = IsSafeChar(s[i]);
|
||||
}
|
||||
|
||||
if (isSafe)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder(s.Length);
|
||||
|
||||
for (int i = 0; i < s.Length; ++i)
|
||||
{
|
||||
if (IsSafeChar(s[i]))
|
||||
{
|
||||
sb.Append(s[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public string ReadUTF8String()
|
||||
{
|
||||
if (m_Index >= m_Size)
|
||||
{
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
int index = m_Index;
|
||||
|
||||
while (index < m_Size && m_Data[index++] != 0)
|
||||
{
|
||||
++count;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
|
||||
var buffer = new byte[count];
|
||||
int value = 0;
|
||||
|
||||
while (m_Index < m_Size && (value = m_Data[m_Index++]) != 0)
|
||||
{
|
||||
buffer[index++] = (byte)value;
|
||||
}
|
||||
|
||||
return Utility.UTF8.GetString(buffer);
|
||||
}
|
||||
|
||||
public string ReadString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int c;
|
||||
|
||||
while (m_Index < m_Size && (c = m_Data[m_Index++]) != 0)
|
||||
{
|
||||
sb.Append((char)c);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public string ReadStringSafe()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int c;
|
||||
|
||||
while (m_Index < m_Size && (c = m_Data[m_Index++]) != 0)
|
||||
{
|
||||
if (IsSafeChar(c))
|
||||
{
|
||||
sb.Append((char)c);
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public string ReadUnicodeStringSafe(int fixedLength)
|
||||
{
|
||||
int bound = m_Index + (fixedLength << 1);
|
||||
int end = bound;
|
||||
|
||||
if (bound > m_Size)
|
||||
{
|
||||
bound = m_Size;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int c;
|
||||
|
||||
while ((m_Index + 1) < bound && (c = ((m_Data[m_Index++] << 8) | m_Data[m_Index++])) != 0)
|
||||
{
|
||||
if (IsSafeChar(c))
|
||||
{
|
||||
sb.Append((char)c);
|
||||
}
|
||||
}
|
||||
|
||||
m_Index = end;
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public string ReadUnicodeString(int fixedLength)
|
||||
{
|
||||
int bound = m_Index + (fixedLength << 1);
|
||||
int end = bound;
|
||||
|
||||
if (bound > m_Size)
|
||||
{
|
||||
bound = m_Size;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int c;
|
||||
|
||||
while ((m_Index + 1) < bound && (c = ((m_Data[m_Index++] << 8) | m_Data[m_Index++])) != 0)
|
||||
{
|
||||
sb.Append((char)c);
|
||||
}
|
||||
|
||||
m_Index = end;
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public string ReadStringSafe(int fixedLength)
|
||||
{
|
||||
int bound = m_Index + fixedLength;
|
||||
int end = bound;
|
||||
|
||||
if (bound > m_Size)
|
||||
{
|
||||
bound = m_Size;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int c;
|
||||
|
||||
while (m_Index < bound && (c = m_Data[m_Index++]) != 0)
|
||||
{
|
||||
if (IsSafeChar(c))
|
||||
{
|
||||
sb.Append((char)c);
|
||||
}
|
||||
}
|
||||
|
||||
m_Index = end;
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public string ReadString(int fixedLength)
|
||||
{
|
||||
int bound = m_Index + fixedLength;
|
||||
int end = bound;
|
||||
|
||||
if (bound > m_Size)
|
||||
{
|
||||
bound = m_Size;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int c;
|
||||
|
||||
while (m_Index < bound && (c = m_Data[m_Index++]) != 0)
|
||||
{
|
||||
sb.Append((char)c);
|
||||
}
|
||||
|
||||
m_Index = end;
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
202
Server/Network/PacketThrottles.cs
Normal file
202
Server/Network/PacketThrottles.cs
Normal file
@@ -0,0 +1,202 @@
|
||||
using System;
|
||||
|
||||
using Server.Commands;
|
||||
|
||||
namespace Server.Network
|
||||
{
|
||||
public static class PacketThrottles
|
||||
{
|
||||
private static readonly int[] _Delays = new int[Byte.MaxValue];
|
||||
|
||||
private static readonly bool[] _Reserved = new bool[Byte.MaxValue];
|
||||
|
||||
static PacketThrottles()
|
||||
{
|
||||
_Delays[0x03] = 5; // speech
|
||||
_Delays[0xAD] = 5; // speech
|
||||
|
||||
_Delays[0x32] = 5; // fly toggle
|
||||
_Delays[0x72] = 5; // war toggle
|
||||
|
||||
_Delays[0x3B] = 100; // vendor buy response
|
||||
_Delays[0x9F] = 100; // vendor sell response
|
||||
|
||||
_Delays[0xB8] = 100; // profile request
|
||||
_Delays[0x6F] = 100; // trade request
|
||||
_Delays[0x75] = 100; // rename request
|
||||
_Delays[0x9B] = 100; // help request
|
||||
|
||||
_Delays[0xEC] = 100; // equip macro
|
||||
_Delays[0xED] = 100; // unequip macro
|
||||
|
||||
#region Reserved
|
||||
|
||||
// Reserved packets cannot be overridden by this throttle system
|
||||
|
||||
_Reserved[0x02] = true; // movement request, see: PlayerMobile
|
||||
_Reserved[0x80] = true; // login request, see: AccountAttackLimiter
|
||||
_Reserved[0x91] = true; // login request, see: AccountAttackLimiter
|
||||
_Reserved[0xCF] = true; // login request, see: AccountAttackLimiter
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static void Configure()
|
||||
{
|
||||
EventSink.WorldLoad += () => Persistence.Deserialize("Saves/PacketThrottles.bin", Load);
|
||||
EventSink.WorldSave += e => Persistence.Serialize("Saves/PacketThrottles.bin", Save);
|
||||
|
||||
CommandSystem.Register("GetThrottle", AccessLevel.Administrator, new CommandEventHandler(GetThrottle));
|
||||
CommandSystem.Register("SetThrottle", AccessLevel.Administrator, new CommandEventHandler(SetThrottle));
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
for (byte i = 0; i < Byte.MaxValue; i++)
|
||||
{
|
||||
if (!_Reserved[i] && _Delays[i] > 0)
|
||||
{
|
||||
PacketHandlers.RegisterThrottler(i, HandleThrottle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void GetThrottle(CommandEventArgs e)
|
||||
{
|
||||
if (e.Length != 1)
|
||||
{
|
||||
e.Mobile.SendMessage("Usage: {0}GetThrottle <packetID>", CommandSystem.Prefix);
|
||||
return;
|
||||
}
|
||||
|
||||
var packetID = e.GetInt32(0);
|
||||
|
||||
if (packetID < Byte.MinValue || packetID > Byte.MaxValue)
|
||||
{
|
||||
e.Mobile.SendMessage("Usage: PacketID must be between {0} and {1} inclusive", Byte.MinValue, Byte.MaxValue);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_Reserved[packetID])
|
||||
{
|
||||
e.Mobile.SendMessage("Packet 0x{0:X2} throttle is protected.");
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Mobile.SendMessage("Packet 0x{0:X2} throttle is {1}ms", packetID, _Delays[packetID]);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetThrottle(CommandEventArgs e)
|
||||
{
|
||||
if (e.Length < 2)
|
||||
{
|
||||
e.Mobile.SendMessage("Usage: {0}SetThrottle <packetID> <delayMS>", CommandSystem.Prefix);
|
||||
return;
|
||||
}
|
||||
|
||||
var packetID = e.GetInt32(0);
|
||||
var delay = e.GetInt32(1);
|
||||
|
||||
if (packetID < Byte.MinValue || packetID > Byte.MaxValue)
|
||||
{
|
||||
e.Mobile.SendMessage("Usage: PacketID must be between {0} and {1} inclusive", Byte.MinValue, Byte.MaxValue);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_Reserved[packetID])
|
||||
{
|
||||
e.Mobile.SendMessage("Packet 0x{0:X2} throttle is protected and can not be set");
|
||||
return;
|
||||
}
|
||||
|
||||
if (delay < 0 || delay > 5000)
|
||||
{
|
||||
e.Mobile.SendMessage("Usage: Delay must be between 0 and 5000 inclusive");
|
||||
return;
|
||||
}
|
||||
|
||||
SetThrottle((byte)packetID, delay);
|
||||
|
||||
if (delay > 0)
|
||||
{
|
||||
e.Mobile.SendMessage("Packet 0x{0:X} throttle is {1}ms", packetID, _Delays[packetID]);
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Mobile.SendMessage("Packet 0x{0:X} throttle has been removed", packetID, _Delays[packetID]);
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetThrottle(byte packetID)
|
||||
{
|
||||
if (!_Reserved[packetID])
|
||||
{
|
||||
return _Delays[packetID];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void SetThrottle(byte packetID, int delay)
|
||||
{
|
||||
if (_Reserved[packetID])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
delay = Math.Max(0, Math.Min(5000, delay));
|
||||
|
||||
var oldDelay = _Delays[packetID];
|
||||
|
||||
if (oldDelay <= 0 && delay > 0)
|
||||
{
|
||||
PacketHandlers.RegisterThrottler(packetID, HandleThrottle);
|
||||
}
|
||||
else if (oldDelay > 0 && delay <= 0)
|
||||
{
|
||||
PacketHandlers.RegisterThrottler(packetID, null);
|
||||
}
|
||||
|
||||
_Delays[packetID] = delay;
|
||||
}
|
||||
|
||||
private static bool HandleThrottle(byte packetID, NetState ns, out bool drop)
|
||||
{
|
||||
drop = false;
|
||||
|
||||
if (ns.Mobile == null || ns.Mobile.AccessLevel >= AccessLevel.Counselor)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ns.IsThrottled(packetID, _Delays[packetID]))
|
||||
{
|
||||
drop = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void Save(GenericWriter writer)
|
||||
{
|
||||
writer.WriteEncodedInt(0);
|
||||
|
||||
for (var i = 0; i < _Delays.Length; i++)
|
||||
{
|
||||
writer.WriteEncodedInt(_Delays[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private static void Load(GenericReader reader)
|
||||
{
|
||||
reader.ReadEncodedInt();
|
||||
|
||||
for (var i = 0; i < _Delays.Length; i++)
|
||||
{
|
||||
_Delays[i] = reader.ReadEncodedInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
439
Server/Network/PacketWriter.cs
Normal file
439
Server/Network/PacketWriter.cs
Normal file
@@ -0,0 +1,439 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
#endregion
|
||||
|
||||
namespace Server.Network
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides functionality for writing primitive binary data.
|
||||
/// </summary>
|
||||
public class PacketWriter
|
||||
{
|
||||
private static readonly Stack<PacketWriter> m_Pool = new Stack<PacketWriter>();
|
||||
|
||||
public static PacketWriter CreateInstance()
|
||||
{
|
||||
return CreateInstance(32);
|
||||
}
|
||||
|
||||
public static PacketWriter CreateInstance(int capacity)
|
||||
{
|
||||
PacketWriter pw = null;
|
||||
|
||||
lock (m_Pool)
|
||||
{
|
||||
if (m_Pool.Count > 0)
|
||||
{
|
||||
pw = m_Pool.Pop();
|
||||
|
||||
if (pw != null)
|
||||
{
|
||||
pw.m_Capacity = capacity;
|
||||
pw.m_Stream.SetLength(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pw == null)
|
||||
{
|
||||
pw = new PacketWriter(capacity);
|
||||
}
|
||||
|
||||
return pw;
|
||||
}
|
||||
|
||||
public static void ReleaseInstance(PacketWriter pw)
|
||||
{
|
||||
lock (m_Pool)
|
||||
{
|
||||
if (!m_Pool.Contains(pw))
|
||||
{
|
||||
m_Pool.Push(pw);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
using (StreamWriter op = new StreamWriter("neterr.log"))
|
||||
{
|
||||
op.WriteLine("{0}\tInstance pool contains writer", DateTime.UtcNow);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine("net error");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal stream which holds the entire packet.
|
||||
/// </summary>
|
||||
private readonly MemoryStream m_Stream;
|
||||
|
||||
private int m_Capacity;
|
||||
|
||||
/// <summary>
|
||||
/// Internal format buffer.
|
||||
/// </summary>
|
||||
private readonly byte[] m_Buffer = new byte[4];
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new PacketWriter instance with the default capacity of 4 bytes.
|
||||
/// </summary>
|
||||
public PacketWriter()
|
||||
: this(32)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new PacketWriter instance with a given capacity.
|
||||
/// </summary>
|
||||
/// <param name="capacity">Initial capacity for the internal stream.</param>
|
||||
public PacketWriter(int capacity)
|
||||
{
|
||||
m_Stream = new MemoryStream(capacity);
|
||||
m_Capacity = capacity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a 1-byte boolean value to the underlying stream. False is represented by 0, true by 1.
|
||||
/// </summary>
|
||||
public void Write(bool value)
|
||||
{
|
||||
m_Stream.WriteByte((byte)(value ? 1 : 0));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a 1-byte unsigned integer value to the underlying stream.
|
||||
/// </summary>
|
||||
public void Write(byte value)
|
||||
{
|
||||
m_Stream.WriteByte(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a 1-byte signed integer value to the underlying stream.
|
||||
/// </summary>
|
||||
public void Write(sbyte value)
|
||||
{
|
||||
m_Stream.WriteByte((byte)value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a 2-byte signed integer value to the underlying stream.
|
||||
/// </summary>
|
||||
public void Write(short value)
|
||||
{
|
||||
m_Buffer[0] = (byte)(value >> 8);
|
||||
m_Buffer[1] = (byte)value;
|
||||
|
||||
m_Stream.Write(m_Buffer, 0, 2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a 2-byte unsigned integer value to the underlying stream.
|
||||
/// </summary>
|
||||
public void Write(ushort value)
|
||||
{
|
||||
m_Buffer[0] = (byte)(value >> 8);
|
||||
m_Buffer[1] = (byte)value;
|
||||
|
||||
m_Stream.Write(m_Buffer, 0, 2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a 4-byte signed integer value to the underlying stream.
|
||||
/// </summary>
|
||||
public void Write(int value)
|
||||
{
|
||||
m_Buffer[0] = (byte)(value >> 24);
|
||||
m_Buffer[1] = (byte)(value >> 16);
|
||||
m_Buffer[2] = (byte)(value >> 8);
|
||||
m_Buffer[3] = (byte)value;
|
||||
|
||||
m_Stream.Write(m_Buffer, 0, 4);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a 4-byte unsigned integer value to the underlying stream.
|
||||
/// </summary>
|
||||
public void Write(uint value)
|
||||
{
|
||||
m_Buffer[0] = (byte)(value >> 24);
|
||||
m_Buffer[1] = (byte)(value >> 16);
|
||||
m_Buffer[2] = (byte)(value >> 8);
|
||||
m_Buffer[3] = (byte)value;
|
||||
|
||||
m_Stream.Write(m_Buffer, 0, 4);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a sequence of bytes to the underlying stream
|
||||
/// </summary>
|
||||
public void Write(byte[] buffer, int offset, int size)
|
||||
{
|
||||
m_Stream.Write(buffer, offset, size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a fixed-length ASCII-encoded string value to the underlying stream. To fit (size), the string content is either truncated or padded with null characters.
|
||||
/// </summary>
|
||||
public void WriteAsciiFixed(string value, int size)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
Console.WriteLine("Network: Attempted to WriteAsciiFixed() with null value");
|
||||
value = String.Empty;
|
||||
}
|
||||
|
||||
int length = value.Length;
|
||||
|
||||
m_Stream.SetLength(m_Stream.Length + size);
|
||||
|
||||
if (length >= size)
|
||||
{
|
||||
m_Stream.Position += Encoding.ASCII.GetBytes(value, 0, size, m_Stream.GetBuffer(), (int)m_Stream.Position);
|
||||
}
|
||||
else
|
||||
{
|
||||
Encoding.ASCII.GetBytes(value, 0, length, m_Stream.GetBuffer(), (int)m_Stream.Position);
|
||||
m_Stream.Position += size;
|
||||
}
|
||||
|
||||
/*byte[] buffer = Encoding.ASCII.GetBytes( value );
|
||||
|
||||
if ( buffer.Length >= size )
|
||||
{
|
||||
m_Stream.Write( buffer, 0, size );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Stream.Write( buffer, 0, buffer.Length );
|
||||
Fill( size - buffer.Length );
|
||||
}*/
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a dynamic-length ASCII-encoded string value to the underlying stream, followed by a 1-byte null character.
|
||||
/// </summary>
|
||||
public void WriteAsciiNull(string value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
Console.WriteLine("Network: Attempted to WriteAsciiNull() with null value");
|
||||
value = String.Empty;
|
||||
}
|
||||
|
||||
int length = value.Length;
|
||||
|
||||
m_Stream.SetLength(m_Stream.Length + length + 1);
|
||||
|
||||
Encoding.ASCII.GetBytes(value, 0, length, m_Stream.GetBuffer(), (int)m_Stream.Position);
|
||||
m_Stream.Position += length + 1;
|
||||
|
||||
/*byte[] buffer = Encoding.ASCII.GetBytes( value );
|
||||
|
||||
m_Stream.Write( buffer, 0, buffer.Length );
|
||||
m_Stream.WriteByte( 0 );*/
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a dynamic-length little-endian unicode string value to the underlying stream, followed by a 2-byte null character.
|
||||
/// </summary>
|
||||
public void WriteLittleUniNull(string value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
Console.WriteLine("Network: Attempted to WriteLittleUniNull() with null value");
|
||||
value = String.Empty;
|
||||
}
|
||||
|
||||
int length = value.Length;
|
||||
|
||||
m_Stream.SetLength(m_Stream.Length + ((length + 1) * 2));
|
||||
|
||||
m_Stream.Position += Encoding.Unicode.GetBytes(value, 0, length, m_Stream.GetBuffer(), (int)m_Stream.Position);
|
||||
m_Stream.Position += 2;
|
||||
|
||||
/*byte[] buffer = Encoding.Unicode.GetBytes( value );
|
||||
|
||||
m_Stream.Write( buffer, 0, buffer.Length );
|
||||
|
||||
m_Buffer[0] = 0;
|
||||
m_Buffer[1] = 0;
|
||||
m_Stream.Write( m_Buffer, 0, 2 );*/
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a fixed-length little-endian unicode string value to the underlying stream. To fit (size), the string content is either truncated or padded with null characters.
|
||||
/// </summary>
|
||||
public void WriteLittleUniFixed(string value, int size)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
Console.WriteLine("Network: Attempted to WriteLittleUniFixed() with null value");
|
||||
value = String.Empty;
|
||||
}
|
||||
|
||||
size *= 2;
|
||||
|
||||
int length = value.Length;
|
||||
|
||||
m_Stream.SetLength(m_Stream.Length + size);
|
||||
|
||||
if ((length * 2) >= size)
|
||||
{
|
||||
m_Stream.Position += Encoding.Unicode.GetBytes(value, 0, length, m_Stream.GetBuffer(), (int)m_Stream.Position);
|
||||
}
|
||||
else
|
||||
{
|
||||
Encoding.Unicode.GetBytes(value, 0, length, m_Stream.GetBuffer(), (int)m_Stream.Position);
|
||||
m_Stream.Position += size;
|
||||
}
|
||||
|
||||
/*size *= 2;
|
||||
|
||||
byte[] buffer = Encoding.Unicode.GetBytes( value );
|
||||
|
||||
if ( buffer.Length >= size )
|
||||
{
|
||||
m_Stream.Write( buffer, 0, size );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Stream.Write( buffer, 0, buffer.Length );
|
||||
Fill( size - buffer.Length );
|
||||
}*/
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a dynamic-length big-endian unicode string value to the underlying stream, followed by a 2-byte null character.
|
||||
/// </summary>
|
||||
public void WriteBigUniNull(string value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
Console.WriteLine("Network: Attempted to WriteBigUniNull() with null value");
|
||||
value = String.Empty;
|
||||
}
|
||||
|
||||
int length = value.Length;
|
||||
|
||||
m_Stream.SetLength(m_Stream.Length + ((length + 1) * 2));
|
||||
|
||||
m_Stream.Position += Encoding.BigEndianUnicode.GetBytes(
|
||||
value, 0, length, m_Stream.GetBuffer(), (int)m_Stream.Position);
|
||||
m_Stream.Position += 2;
|
||||
|
||||
/*byte[] buffer = Encoding.BigEndianUnicode.GetBytes( value );
|
||||
|
||||
m_Stream.Write( buffer, 0, buffer.Length );
|
||||
|
||||
m_Buffer[0] = 0;
|
||||
m_Buffer[1] = 0;
|
||||
m_Stream.Write( m_Buffer, 0, 2 );*/
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a fixed-length big-endian unicode string value to the underlying stream. To fit (size), the string content is either truncated or padded with null characters.
|
||||
/// </summary>
|
||||
public void WriteBigUniFixed(string value, int size)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
Console.WriteLine("Network: Attempted to WriteBigUniFixed() with null value");
|
||||
value = String.Empty;
|
||||
}
|
||||
|
||||
size *= 2;
|
||||
|
||||
int length = value.Length;
|
||||
|
||||
m_Stream.SetLength(m_Stream.Length + size);
|
||||
|
||||
if ((length * 2) >= size)
|
||||
{
|
||||
m_Stream.Position += Encoding.BigEndianUnicode.GetBytes(
|
||||
value, 0, length, m_Stream.GetBuffer(), (int)m_Stream.Position);
|
||||
}
|
||||
else
|
||||
{
|
||||
Encoding.BigEndianUnicode.GetBytes(value, 0, length, m_Stream.GetBuffer(), (int)m_Stream.Position);
|
||||
m_Stream.Position += size;
|
||||
}
|
||||
|
||||
/*size *= 2;
|
||||
|
||||
byte[] buffer = Encoding.BigEndianUnicode.GetBytes( value );
|
||||
|
||||
if ( buffer.Length >= size )
|
||||
{
|
||||
m_Stream.Write( buffer, 0, size );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Stream.Write( buffer, 0, buffer.Length );
|
||||
Fill( size - buffer.Length );
|
||||
}*/
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fills the stream from the current position up to (capacity) with 0x00's
|
||||
/// </summary>
|
||||
public void Fill()
|
||||
{
|
||||
Fill((int)(m_Capacity - m_Stream.Length));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a number of 0x00 byte values to the underlying stream.
|
||||
/// </summary>
|
||||
public void Fill(int length)
|
||||
{
|
||||
if (m_Stream.Position == m_Stream.Length)
|
||||
{
|
||||
m_Stream.SetLength(m_Stream.Length + length);
|
||||
m_Stream.Seek(0, SeekOrigin.End);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Stream.Write(new byte[length], 0, length);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total stream length.
|
||||
/// </summary>
|
||||
public long Length { get { return m_Stream.Length; } }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current stream position.
|
||||
/// </summary>
|
||||
public long Position { get { return m_Stream.Position; } set { m_Stream.Position = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// The internal stream used by this PacketWriter instance.
|
||||
/// </summary>
|
||||
public MemoryStream UnderlyingStream { get { return m_Stream; } }
|
||||
|
||||
/// <summary>
|
||||
/// Offsets the current position from an origin.
|
||||
/// </summary>
|
||||
public long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
return m_Stream.Seek(offset, origin);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the entire stream content as a byte array.
|
||||
/// </summary>
|
||||
public byte[] ToArray()
|
||||
{
|
||||
return m_Stream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
5492
Server/Network/Packets.cs
Normal file
5492
Server/Network/Packets.cs
Normal file
File diff suppressed because it is too large
Load Diff
98
Server/Network/PingListener.cs
Normal file
98
Server/Network/PingListener.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
#endregion
|
||||
|
||||
namespace Server.Network
|
||||
{
|
||||
public class PingListener : IDisposable
|
||||
{
|
||||
private UdpClient _Listener;
|
||||
const int Port = 12000;
|
||||
|
||||
private static UdpClient Bind(IPEndPoint ipep)
|
||||
{
|
||||
ipep = new IPEndPoint(ipep.Address, Port);
|
||||
|
||||
var s = new UdpClient
|
||||
{
|
||||
Client = new Socket(ipep.AddressFamily, SocketType.Dgram, ProtocolType.Udp)
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
s.Client.ExclusiveAddressUse = false;
|
||||
s.Client.Bind(ipep);
|
||||
|
||||
return s;
|
||||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
switch (e.ErrorCode)
|
||||
{
|
||||
case 10048: // WSAEADDRINUSE
|
||||
Console.WriteLine("Ping Listener Failed: {0}:{1} (In Use)", ipep.Address, Port);
|
||||
break;
|
||||
case 10049: // WSAEADDRNOTAVAIL
|
||||
Console.WriteLine("Ping Listener Failed: {0}:{1} (Unavailable)", ipep.Address, Port);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
Console.WriteLine("Ping Listener Exception:");
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public PingListener(IPEndPoint ipep)
|
||||
{
|
||||
_Listener = Bind(ipep);
|
||||
|
||||
BeginReceive();
|
||||
}
|
||||
|
||||
private void BeginReceive()
|
||||
{
|
||||
if (_Listener != null)
|
||||
{
|
||||
_Listener.BeginReceive(EndReceive, _Listener);
|
||||
}
|
||||
}
|
||||
|
||||
private void EndReceive(IAsyncResult r)
|
||||
{
|
||||
var ripep = new IPEndPoint(IPAddress.Any, Port);
|
||||
var recvd = _Listener.EndReceive(r, ref ripep);
|
||||
|
||||
//Console.WriteLine("[PING]: \"{0}\" Received from {1}", Encoding.UTF8.GetString(recvd), ripep);
|
||||
|
||||
BeginSend(recvd, ripep);
|
||||
|
||||
BeginReceive();
|
||||
}
|
||||
|
||||
private void BeginSend(byte[] data, IPEndPoint ipep)
|
||||
{
|
||||
//Console.WriteLine("[PONG]: \"{0}\" Sent to {1}", Encoding.UTF8.GetString(data), ipep);
|
||||
|
||||
_Listener.BeginSend(data, data.Length, ipep, EndSend, _Listener);
|
||||
}
|
||||
|
||||
private void EndSend(IAsyncResult asyncResult)
|
||||
{
|
||||
_Listener.EndSend(asyncResult);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_Listener.Close();
|
||||
_Listener = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
239
Server/Network/SendQueue.cs
Normal file
239
Server/Network/SendQueue.cs
Normal file
@@ -0,0 +1,239 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#endregion
|
||||
|
||||
namespace Server.Network
|
||||
{
|
||||
public class SendQueue
|
||||
{
|
||||
public class Gram
|
||||
{
|
||||
private static readonly Stack<Gram> _pool = new Stack<Gram>();
|
||||
|
||||
public static Gram Acquire()
|
||||
{
|
||||
lock (_pool)
|
||||
{
|
||||
Gram gram;
|
||||
|
||||
if (_pool.Count > 0)
|
||||
{
|
||||
gram = _pool.Pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
gram = new Gram();
|
||||
}
|
||||
|
||||
gram._buffer = AcquireBuffer();
|
||||
gram._length = 0;
|
||||
|
||||
return gram;
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] _buffer;
|
||||
private int _length;
|
||||
|
||||
public byte[] Buffer { get { return _buffer; } }
|
||||
|
||||
public int Length { get { return _length; } }
|
||||
|
||||
public int Available { get { return (_buffer.Length - _length); } }
|
||||
|
||||
public bool IsFull { get { return (_length == _buffer.Length); } }
|
||||
|
||||
private Gram()
|
||||
{ }
|
||||
|
||||
public int Write(byte[] buffer, int offset, int length)
|
||||
{
|
||||
int write = Math.Min(length, Available);
|
||||
|
||||
System.Buffer.BlockCopy(buffer, offset, _buffer, _length, write);
|
||||
|
||||
_length += write;
|
||||
|
||||
return write;
|
||||
}
|
||||
|
||||
public void Release()
|
||||
{
|
||||
lock (_pool)
|
||||
{
|
||||
_pool.Push(this);
|
||||
ReleaseBuffer(_buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int m_CoalesceBufferSize = 512;
|
||||
private static BufferPool m_UnusedBuffers = new BufferPool("Coalesced", 2048, m_CoalesceBufferSize);
|
||||
|
||||
public static int CoalesceBufferSize
|
||||
{
|
||||
get { return m_CoalesceBufferSize; }
|
||||
set
|
||||
{
|
||||
if (m_CoalesceBufferSize == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BufferPool old = m_UnusedBuffers;
|
||||
|
||||
lock (old)
|
||||
{
|
||||
if (m_UnusedBuffers != null)
|
||||
{
|
||||
m_UnusedBuffers.Free();
|
||||
}
|
||||
|
||||
m_CoalesceBufferSize = value;
|
||||
m_UnusedBuffers = new BufferPool("Coalesced", 2048, m_CoalesceBufferSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] AcquireBuffer()
|
||||
{
|
||||
lock (m_UnusedBuffers)
|
||||
return m_UnusedBuffers.AcquireBuffer();
|
||||
}
|
||||
|
||||
public static void ReleaseBuffer(byte[] buffer)
|
||||
{
|
||||
lock (m_UnusedBuffers)
|
||||
if (buffer != null && buffer.Length == m_CoalesceBufferSize)
|
||||
{
|
||||
m_UnusedBuffers.ReleaseBuffer(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Queue<Gram> _pending;
|
||||
|
||||
private Gram _buffered;
|
||||
|
||||
public bool IsFlushReady { get { return (_pending.Count == 0 && _buffered != null); } }
|
||||
|
||||
public bool IsEmpty { get { return (_pending.Count == 0 && _buffered == null); } }
|
||||
|
||||
public SendQueue()
|
||||
{
|
||||
_pending = new Queue<Gram>();
|
||||
}
|
||||
|
||||
public Gram CheckFlushReady()
|
||||
{
|
||||
Gram gram = _buffered;
|
||||
_pending.Enqueue(_buffered);
|
||||
_buffered = null;
|
||||
return gram;
|
||||
}
|
||||
|
||||
public Gram Dequeue()
|
||||
{
|
||||
Gram gram = null;
|
||||
|
||||
if (_pending.Count > 0)
|
||||
{
|
||||
_pending.Dequeue().Release();
|
||||
|
||||
if (_pending.Count > 0)
|
||||
{
|
||||
gram = _pending.Peek();
|
||||
}
|
||||
}
|
||||
|
||||
return gram;
|
||||
}
|
||||
|
||||
private const int PendingCap = 0x200000;
|
||||
|
||||
public Gram Enqueue(byte[] buffer, int length)
|
||||
{
|
||||
return Enqueue(buffer, 0, length);
|
||||
}
|
||||
|
||||
public Gram Enqueue(byte[] buffer, int offset, int length)
|
||||
{
|
||||
if (buffer == null)
|
||||
{
|
||||
throw new ArgumentNullException("buffer");
|
||||
}
|
||||
else if (!(offset >= 0 && offset < buffer.Length))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(
|
||||
"offset", offset, "Offset must be greater than or equal to zero and less than the size of the buffer.");
|
||||
}
|
||||
else if (length < 0 || length > buffer.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(
|
||||
"length", length, "Length cannot be less than zero or greater than the size of the buffer.");
|
||||
}
|
||||
else if ((buffer.Length - offset) < length)
|
||||
{
|
||||
throw new ArgumentException("Offset and length do not point to a valid segment within the buffer.");
|
||||
}
|
||||
|
||||
int existingBytes = (_pending.Count * m_CoalesceBufferSize) + (_buffered == null ? 0 : _buffered.Length);
|
||||
|
||||
if ((existingBytes + length) > PendingCap)
|
||||
{
|
||||
throw new CapacityExceededException();
|
||||
}
|
||||
|
||||
Gram gram = null;
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
if (_buffered == null)
|
||||
{
|
||||
// nothing yet buffered
|
||||
_buffered = Gram.Acquire();
|
||||
}
|
||||
|
||||
int bytesWritten = _buffered.Write(buffer, offset, length);
|
||||
|
||||
offset += bytesWritten;
|
||||
length -= bytesWritten;
|
||||
|
||||
if (_buffered.IsFull)
|
||||
{
|
||||
if (_pending.Count == 0)
|
||||
{
|
||||
gram = _buffered;
|
||||
}
|
||||
|
||||
_pending.Enqueue(_buffered);
|
||||
_buffered = null;
|
||||
}
|
||||
}
|
||||
|
||||
return gram;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
if (_buffered != null)
|
||||
{
|
||||
_buffered.Release();
|
||||
_buffered = null;
|
||||
}
|
||||
|
||||
while (_pending.Count > 0)
|
||||
{
|
||||
_pending.Dequeue().Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public sealed class CapacityExceededException : Exception
|
||||
{
|
||||
public CapacityExceededException()
|
||||
: base("Too much data pending.")
|
||||
{ }
|
||||
}
|
||||
}
|
||||
36
Server/Notoriety.cs
Normal file
36
Server/Notoriety.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
namespace Server
|
||||
{
|
||||
public delegate int NotorietyHandler(Mobile source, IDamageable target);
|
||||
|
||||
public static class Notoriety
|
||||
{
|
||||
public const int Innocent = 1;
|
||||
public const int Ally = 2;
|
||||
public const int CanBeAttacked = 3;
|
||||
public const int Criminal = 4;
|
||||
public const int Enemy = 5;
|
||||
public const int Murderer = 6;
|
||||
public const int Invulnerable = 7;
|
||||
|
||||
public static NotorietyHandler Handler { get; set; }
|
||||
|
||||
private static int[] m_Hues = {0x000, 0x059, 0x03F, 0x3B2, 0x3B2, 0x090, 0x022, 0x035};
|
||||
|
||||
public static int[] Hues { get { return m_Hues; } set { m_Hues = value; } }
|
||||
|
||||
public static int GetHue(int noto)
|
||||
{
|
||||
if (noto < 0 || noto >= m_Hues.Length)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m_Hues[noto];
|
||||
}
|
||||
|
||||
public static int Compute(Mobile source, IDamageable target)
|
||||
{
|
||||
return Handler == null ? CanBeAttacked : Handler(source, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user