Overwrite
Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
237
Scripts/Commands/Generic/Commands/BaseCommand.cs
Normal file
237
Scripts/Commands/Generic/Commands/BaseCommand.cs
Normal file
@@ -0,0 +1,237 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Server.Gumps;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public enum ObjectTypes
|
||||
{
|
||||
Both,
|
||||
Items,
|
||||
Mobiles,
|
||||
All
|
||||
}
|
||||
|
||||
public abstract class BaseCommand
|
||||
{
|
||||
private readonly ArrayList m_Responses;
|
||||
private readonly ArrayList m_Failures;
|
||||
private string[] m_Commands;
|
||||
private AccessLevel m_AccessLevel;
|
||||
private CommandSupport m_Implementors;
|
||||
private ObjectTypes m_ObjectTypes;
|
||||
private bool m_ListOptimized;
|
||||
private string m_Usage;
|
||||
private string m_Description;
|
||||
public BaseCommand()
|
||||
{
|
||||
this.m_Responses = new ArrayList();
|
||||
this.m_Failures = new ArrayList();
|
||||
}
|
||||
|
||||
public bool ListOptimized
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_ListOptimized;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.m_ListOptimized = value;
|
||||
}
|
||||
}
|
||||
public string[] Commands
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_Commands;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.m_Commands = value;
|
||||
}
|
||||
}
|
||||
public string Usage
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_Usage;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.m_Usage = value;
|
||||
}
|
||||
}
|
||||
public string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_Description;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.m_Description = value;
|
||||
}
|
||||
}
|
||||
public AccessLevel AccessLevel
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_AccessLevel;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.m_AccessLevel = value;
|
||||
}
|
||||
}
|
||||
public ObjectTypes ObjectTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_ObjectTypes;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.m_ObjectTypes = value;
|
||||
}
|
||||
}
|
||||
public CommandSupport Supports
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_Implementors;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.m_Implementors = value;
|
||||
}
|
||||
}
|
||||
public static bool IsAccessible(Mobile from, object obj)
|
||||
{
|
||||
if (from.AccessLevel >= AccessLevel.Administrator || obj == null)
|
||||
return true;
|
||||
|
||||
Mobile mob;
|
||||
|
||||
if (obj is Mobile)
|
||||
mob = (Mobile)obj;
|
||||
else if (obj is Item)
|
||||
mob = ((Item)obj).RootParent as Mobile;
|
||||
else
|
||||
mob = null;
|
||||
|
||||
if (mob == null || mob == from || from.AccessLevel > mob.AccessLevel)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual void ExecuteList(CommandEventArgs e, ArrayList list)
|
||||
{
|
||||
for (int i = 0; i < list.Count; ++i)
|
||||
this.Execute(e, list[i]);
|
||||
}
|
||||
|
||||
public virtual void Execute(CommandEventArgs e, object obj)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual bool ValidateArgs(BaseCommandImplementor impl, CommandEventArgs e)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void AddResponse(string message)
|
||||
{
|
||||
for (int i = 0; i < this.m_Responses.Count; ++i)
|
||||
{
|
||||
MessageEntry entry = (MessageEntry)this.m_Responses[i];
|
||||
|
||||
if (entry.m_Message == message)
|
||||
{
|
||||
++entry.m_Count;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.m_Responses.Count == 10)
|
||||
return;
|
||||
|
||||
this.m_Responses.Add(new MessageEntry(message));
|
||||
}
|
||||
|
||||
public void AddResponse(Gump gump)
|
||||
{
|
||||
this.m_Responses.Add(gump);
|
||||
}
|
||||
|
||||
public void LogFailure(string message)
|
||||
{
|
||||
for (int i = 0; i < this.m_Failures.Count; ++i)
|
||||
{
|
||||
MessageEntry entry = (MessageEntry)this.m_Failures[i];
|
||||
|
||||
if (entry.m_Message == message)
|
||||
{
|
||||
++entry.m_Count;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.m_Failures.Count == 10)
|
||||
return;
|
||||
|
||||
this.m_Failures.Add(new MessageEntry(message));
|
||||
}
|
||||
|
||||
public void Flush(Mobile from, bool flushToLog)
|
||||
{
|
||||
if (this.m_Responses.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < this.m_Responses.Count; ++i)
|
||||
{
|
||||
object obj = this.m_Responses[i];
|
||||
|
||||
if (obj is MessageEntry)
|
||||
{
|
||||
from.SendMessage(((MessageEntry)obj).ToString());
|
||||
|
||||
if (flushToLog)
|
||||
CommandLogging.WriteLine(from, ((MessageEntry)obj).ToString());
|
||||
}
|
||||
else if (obj is Gump)
|
||||
{
|
||||
from.SendGump((Gump)obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < this.m_Failures.Count; ++i)
|
||||
from.SendMessage(((MessageEntry)this.m_Failures[i]).ToString());
|
||||
}
|
||||
|
||||
this.m_Responses.Clear();
|
||||
this.m_Failures.Clear();
|
||||
}
|
||||
|
||||
private class MessageEntry
|
||||
{
|
||||
public readonly string m_Message;
|
||||
public int m_Count;
|
||||
public MessageEntry(string message)
|
||||
{
|
||||
this.m_Message = message;
|
||||
this.m_Count = 1;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (this.m_Count > 1)
|
||||
return String.Format("{0} ({1})", this.m_Message, this.m_Count);
|
||||
|
||||
return this.m_Message;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1282
Scripts/Commands/Generic/Commands/Commands.cs
Normal file
1282
Scripts/Commands/Generic/Commands/Commands.cs
Normal file
File diff suppressed because it is too large
Load Diff
205
Scripts/Commands/Generic/Commands/DesignInsert.cs
Normal file
205
Scripts/Commands/Generic/Commands/DesignInsert.cs
Normal file
@@ -0,0 +1,205 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Server.Gumps;
|
||||
using Server.Items;
|
||||
using Server.Multis;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class DesignInsertCommand : BaseCommand
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
TargetCommands.Register(new DesignInsertCommand());
|
||||
}
|
||||
|
||||
public DesignInsertCommand()
|
||||
{
|
||||
this.AccessLevel = AccessLevel.GameMaster;
|
||||
this.Supports = CommandSupport.Single | CommandSupport.Area;
|
||||
this.Commands = new string[] { "DesignInsert" };
|
||||
this.ObjectTypes = ObjectTypes.Items;
|
||||
this.Usage = "DesignInsert [allItems=false]";
|
||||
this.Description = "Inserts multiple targeted items into a customizable house's design.";
|
||||
}
|
||||
|
||||
#region Single targeting mode
|
||||
public override void Execute(CommandEventArgs e, object obj)
|
||||
{
|
||||
Target t = new DesignInsertTarget(new List<HouseFoundation>(), (e.Length < 1 || !e.GetBoolean(0)));
|
||||
t.Invoke(e.Mobile, obj);
|
||||
}
|
||||
|
||||
private class DesignInsertTarget : Target
|
||||
{
|
||||
private readonly List<HouseFoundation> m_Foundations;
|
||||
private readonly bool m_StaticsOnly;
|
||||
|
||||
public DesignInsertTarget(List<HouseFoundation> foundations, bool staticsOnly)
|
||||
: base(-1, false, TargetFlags.None)
|
||||
{
|
||||
this.m_Foundations = foundations;
|
||||
this.m_StaticsOnly = staticsOnly;
|
||||
}
|
||||
|
||||
protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType)
|
||||
{
|
||||
if (this.m_Foundations.Count != 0)
|
||||
{
|
||||
from.SendMessage("Your changes have been committed. Updating...");
|
||||
|
||||
foreach (HouseFoundation house in this.m_Foundations)
|
||||
house.Delta(ItemDelta.Update);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnTarget(Mobile from, object obj)
|
||||
{
|
||||
HouseFoundation house;
|
||||
DesignInsertResult result = ProcessInsert(obj as Item, this.m_StaticsOnly, out house);
|
||||
|
||||
switch ( result )
|
||||
{
|
||||
case DesignInsertResult.Valid:
|
||||
{
|
||||
if (this.m_Foundations.Count == 0)
|
||||
from.SendMessage("The item has been inserted into the house design. Press ESC when you are finished.");
|
||||
else
|
||||
from.SendMessage("The item has been inserted into the house design.");
|
||||
|
||||
if (!this.m_Foundations.Contains(house))
|
||||
this.m_Foundations.Add(house);
|
||||
|
||||
break;
|
||||
}
|
||||
case DesignInsertResult.InvalidItem:
|
||||
{
|
||||
from.SendMessage("That cannot be inserted. Try again.");
|
||||
break;
|
||||
}
|
||||
case DesignInsertResult.NotInHouse:
|
||||
case DesignInsertResult.OutsideHouseBounds:
|
||||
{
|
||||
from.SendMessage("That item is not inside a customizable house. Try again.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
from.Target = new DesignInsertTarget(this.m_Foundations, this.m_StaticsOnly);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Area targeting mode
|
||||
public override void ExecuteList(CommandEventArgs e, ArrayList list)
|
||||
{
|
||||
e.Mobile.SendGump(new WarningGump(1060637, 30720, String.Format("You are about to insert {0} objects. This cannot be undone without a full server revert.<br><br>Continue?", list.Count), 0xFFC000, 420, 280, new WarningGumpCallback(OnConfirmCallback), new object[] { e, list, (e.Length < 1 || !e.GetBoolean(0)) }));
|
||||
this.AddResponse("Awaiting confirmation...");
|
||||
}
|
||||
|
||||
private void OnConfirmCallback(Mobile from, bool okay, object state)
|
||||
{
|
||||
object[] states = (object[])state;
|
||||
CommandEventArgs e = (CommandEventArgs)states[0];
|
||||
ArrayList list = (ArrayList)states[1];
|
||||
bool staticsOnly = (bool)states[2];
|
||||
|
||||
bool flushToLog = false;
|
||||
|
||||
if (okay)
|
||||
{
|
||||
List<HouseFoundation> foundations = new List<HouseFoundation>();
|
||||
flushToLog = (list.Count > 20);
|
||||
|
||||
for (int i = 0; i < list.Count; ++i)
|
||||
{
|
||||
HouseFoundation house;
|
||||
DesignInsertResult result = ProcessInsert(list[i] as Item, staticsOnly, out house);
|
||||
|
||||
switch ( result )
|
||||
{
|
||||
case DesignInsertResult.Valid:
|
||||
{
|
||||
this.AddResponse("The item has been inserted into the house design.");
|
||||
|
||||
if (!foundations.Contains(house))
|
||||
foundations.Add(house);
|
||||
|
||||
break;
|
||||
}
|
||||
case DesignInsertResult.InvalidItem:
|
||||
{
|
||||
this.LogFailure("That cannot be inserted.");
|
||||
break;
|
||||
}
|
||||
case DesignInsertResult.NotInHouse:
|
||||
case DesignInsertResult.OutsideHouseBounds:
|
||||
{
|
||||
this.LogFailure("That item is not inside a customizable house.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (HouseFoundation house in foundations)
|
||||
house.Delta(ItemDelta.Update);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.AddResponse("Command aborted.");
|
||||
}
|
||||
|
||||
this.Flush(from, flushToLog);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public enum DesignInsertResult
|
||||
{
|
||||
Valid,
|
||||
InvalidItem,
|
||||
NotInHouse,
|
||||
OutsideHouseBounds
|
||||
}
|
||||
|
||||
public static DesignInsertResult ProcessInsert(Item item, bool staticsOnly, out HouseFoundation house)
|
||||
{
|
||||
house = null;
|
||||
|
||||
if (item == null || item is BaseMulti || item is HouseSign || (staticsOnly && !(item is Static)))
|
||||
return DesignInsertResult.InvalidItem;
|
||||
|
||||
house = BaseHouse.FindHouseAt(item) as HouseFoundation;
|
||||
|
||||
if (house == null)
|
||||
return DesignInsertResult.NotInHouse;
|
||||
|
||||
int x = item.X - house.X;
|
||||
int y = item.Y - house.Y;
|
||||
int z = item.Z - house.Z;
|
||||
|
||||
if (!TryInsertIntoState(house.CurrentState, item.ItemID, x, y, z))
|
||||
return DesignInsertResult.OutsideHouseBounds;
|
||||
|
||||
TryInsertIntoState(house.DesignState, item.ItemID, x, y, z);
|
||||
item.Delete();
|
||||
|
||||
return DesignInsertResult.Valid;
|
||||
}
|
||||
|
||||
private static bool TryInsertIntoState(DesignState state, int itemID, int x, int y, int z)
|
||||
{
|
||||
MultiComponentList mcl = state.Components;
|
||||
|
||||
if (x < mcl.Min.X || y < mcl.Min.Y || x > mcl.Max.X || y > mcl.Max.Y)
|
||||
return false;
|
||||
|
||||
mcl.Add(itemID, x, y, z);
|
||||
state.OnRevised();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
557
Scripts/Commands/Generic/Commands/Interface.cs
Normal file
557
Scripts/Commands/Generic/Commands/Interface.cs
Normal file
@@ -0,0 +1,557 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Server.Gumps;
|
||||
using Server.Network;
|
||||
using Server.Targets;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class InterfaceCommand : BaseCommand
|
||||
{
|
||||
public InterfaceCommand()
|
||||
{
|
||||
this.AccessLevel = AccessLevel.GameMaster;
|
||||
this.Supports = CommandSupport.Complex | CommandSupport.Simple;
|
||||
this.Commands = new string[] { "Interface" };
|
||||
this.ObjectTypes = ObjectTypes.Both;
|
||||
this.Usage = "Interface [view <properties ...>]";
|
||||
this.Description = "Opens an interface to interact with matched objects. Generally used with condition arguments.";
|
||||
this.ListOptimized = true;
|
||||
}
|
||||
|
||||
public override void ExecuteList(CommandEventArgs e, ArrayList list)
|
||||
{
|
||||
if (list.Count > 0)
|
||||
{
|
||||
List<string> columns = new List<string>();
|
||||
|
||||
columns.Add("Object");
|
||||
|
||||
if (e.Length > 0)
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
if (Insensitive.Equals(e.GetString(0), "view"))
|
||||
++offset;
|
||||
|
||||
while (offset < e.Length)
|
||||
columns.Add(e.GetString(offset++));
|
||||
}
|
||||
|
||||
e.Mobile.SendGump(new InterfaceGump(e.Mobile, columns.ToArray(), list, 0, null));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.AddResponse("No matching objects found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class InterfaceGump : BaseGridGump
|
||||
{
|
||||
private const int EntriesPerPage = 15;
|
||||
private readonly Mobile m_From;
|
||||
private readonly string[] m_Columns;
|
||||
private readonly ArrayList m_List;
|
||||
private readonly int m_Page;
|
||||
private readonly object m_Select;
|
||||
public InterfaceGump(Mobile from, string[] columns, ArrayList list, int page, object select)
|
||||
: base(30, 30)
|
||||
{
|
||||
this.m_From = from;
|
||||
|
||||
this.m_Columns = columns;
|
||||
|
||||
this.m_List = list;
|
||||
this.m_Page = page;
|
||||
|
||||
this.m_Select = select;
|
||||
|
||||
this.Render();
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
this.AddNewPage();
|
||||
|
||||
if (this.m_Page > 0)
|
||||
this.AddEntryButton(20, ArrowLeftID1, ArrowLeftID2, 1, ArrowLeftWidth, ArrowLeftHeight);
|
||||
else
|
||||
this.AddEntryHeader(20);
|
||||
|
||||
this.AddEntryHtml(40 + (this.m_Columns.Length * 130) - 20 + ((this.m_Columns.Length - 2) * this.OffsetSize), this.Center(String.Format("Page {0} of {1}", this.m_Page + 1, (this.m_List.Count + EntriesPerPage - 1) / EntriesPerPage)));
|
||||
|
||||
if ((this.m_Page + 1) * EntriesPerPage < this.m_List.Count)
|
||||
this.AddEntryButton(20, ArrowRightID1, ArrowRightID2, 2, ArrowRightWidth, ArrowRightHeight);
|
||||
else
|
||||
this.AddEntryHeader(20);
|
||||
|
||||
if (this.m_Columns.Length > 1)
|
||||
{
|
||||
this.AddNewLine();
|
||||
|
||||
for (int i = 0; i < this.m_Columns.Length; ++i)
|
||||
{
|
||||
if (i > 0 && this.m_List.Count > 0)
|
||||
{
|
||||
object obj = this.m_List[0];
|
||||
|
||||
if (obj != null)
|
||||
{
|
||||
string failReason = null;
|
||||
PropertyInfo[] chain = Properties.GetPropertyInfoChain(this.m_From, obj.GetType(), this.m_Columns[i], PropertyAccess.Read, ref failReason);
|
||||
|
||||
if (chain != null && chain.Length > 0)
|
||||
{
|
||||
this.m_Columns[i] = "";
|
||||
|
||||
for (int j = 0; j < chain.Length; ++j)
|
||||
{
|
||||
if (j > 0)
|
||||
this.m_Columns[i] += '.';
|
||||
|
||||
this.m_Columns[i] += chain[j].Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.AddEntryHtml(130 + (i == 0 ? 40 : 0), this.m_Columns[i]);
|
||||
}
|
||||
|
||||
this.AddEntryHeader(20);
|
||||
}
|
||||
|
||||
for (int i = this.m_Page * EntriesPerPage, line = 0; line < EntriesPerPage && i < this.m_List.Count; ++i, ++line)
|
||||
{
|
||||
this.AddNewLine();
|
||||
|
||||
object obj = this.m_List[i];
|
||||
bool isDeleted = false;
|
||||
|
||||
if (obj is Item)
|
||||
{
|
||||
Item item = (Item)obj;
|
||||
|
||||
if (!(isDeleted = item.Deleted))
|
||||
this.AddEntryHtml(40 + 130, item.GetType().Name);
|
||||
}
|
||||
else if (obj is Mobile)
|
||||
{
|
||||
Mobile mob = (Mobile)obj;
|
||||
|
||||
if (!(isDeleted = mob.Deleted))
|
||||
this.AddEntryHtml(40 + 130, mob.Name);
|
||||
}
|
||||
|
||||
if (isDeleted)
|
||||
{
|
||||
this.AddEntryHtml(40 + 130, "(deleted)");
|
||||
|
||||
for (int j = 1; j < this.m_Columns.Length; ++j)
|
||||
this.AddEntryHtml(130, "---");
|
||||
|
||||
this.AddEntryHeader(20);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j = 1; j < this.m_Columns.Length; ++j)
|
||||
{
|
||||
object src = obj;
|
||||
|
||||
string value;
|
||||
string failReason = "";
|
||||
|
||||
PropertyInfo[] chain = Properties.GetPropertyInfoChain(this.m_From, src.GetType(), this.m_Columns[j], PropertyAccess.Read, ref failReason);
|
||||
|
||||
if (chain == null || chain.Length == 0)
|
||||
{
|
||||
value = "---";
|
||||
}
|
||||
else
|
||||
{
|
||||
PropertyInfo p = Properties.GetPropertyInfo(ref src, chain, ref failReason);
|
||||
|
||||
if (p == null)
|
||||
value = "---";
|
||||
else
|
||||
value = PropertiesGump.ValueToString(src, p);
|
||||
}
|
||||
|
||||
this.AddEntryHtml(130, value);
|
||||
}
|
||||
|
||||
bool isSelected = (this.m_Select != null && obj == this.m_Select);
|
||||
|
||||
this.AddEntryButton(20, (isSelected ? 9762 : ArrowRightID1), (isSelected ? 9763 : ArrowRightID2), 3 + i, ArrowRightWidth, ArrowRightHeight);
|
||||
}
|
||||
}
|
||||
|
||||
this.FinishPage();
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo info)
|
||||
{
|
||||
switch ( info.ButtonID )
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
if (this.m_Page > 0)
|
||||
this.m_From.SendGump(new InterfaceGump(this.m_From, this.m_Columns, this.m_List, this.m_Page - 1, this.m_Select));
|
||||
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
if ((this.m_Page + 1) * EntriesPerPage < this.m_List.Count)
|
||||
this.m_From.SendGump(new InterfaceGump(this.m_From, this.m_Columns, this.m_List, this.m_Page + 1, this.m_Select));
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
int v = info.ButtonID - 3;
|
||||
|
||||
if (v >= 0 && v < this.m_List.Count)
|
||||
{
|
||||
object obj = this.m_List[v];
|
||||
|
||||
if (!BaseCommand.IsAccessible(this.m_From, obj))
|
||||
{
|
||||
this.m_From.SendMessage("That is not accessible.");
|
||||
this.m_From.SendGump(new InterfaceGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, this.m_Select));
|
||||
break;
|
||||
}
|
||||
|
||||
if (obj is Item && !((Item)obj).Deleted)
|
||||
this.m_From.SendGump(new InterfaceItemGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, (Item)obj));
|
||||
else if (obj is Mobile && !((Mobile)obj).Deleted)
|
||||
this.m_From.SendGump(new InterfaceMobileGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, (Mobile)obj));
|
||||
else
|
||||
this.m_From.SendGump(new InterfaceGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, this.m_Select));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class InterfaceItemGump : BaseGridGump
|
||||
{
|
||||
private readonly Mobile m_From;
|
||||
private readonly string[] m_Columns;
|
||||
private readonly ArrayList m_List;
|
||||
private readonly int m_Page;
|
||||
private readonly Item m_Item;
|
||||
public InterfaceItemGump(Mobile from, string[] columns, ArrayList list, int page, Item item)
|
||||
: base(30, 30)
|
||||
{
|
||||
this.m_From = from;
|
||||
|
||||
this.m_Columns = columns;
|
||||
|
||||
this.m_List = list;
|
||||
this.m_Page = page;
|
||||
|
||||
this.m_Item = item;
|
||||
|
||||
this.Render();
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
this.AddNewPage();
|
||||
|
||||
this.AddEntryButton(20, ArrowLeftID1, ArrowLeftID2, 1, ArrowLeftWidth, ArrowLeftHeight);
|
||||
this.AddEntryHtml(160, this.m_Item.GetType().Name);
|
||||
this.AddEntryHeader(20);
|
||||
|
||||
this.AddNewLine();
|
||||
this.AddEntryHtml(20 + this.OffsetSize + 160, "Properties");
|
||||
this.AddEntryButton(20, ArrowRightID1, ArrowRightID2, 2, ArrowRightWidth, ArrowRightHeight);
|
||||
|
||||
this.AddNewLine();
|
||||
this.AddEntryHtml(20 + this.OffsetSize + 160, "Delete");
|
||||
this.AddEntryButton(20, ArrowRightID1, ArrowRightID2, 3, ArrowRightWidth, ArrowRightHeight);
|
||||
|
||||
this.AddNewLine();
|
||||
this.AddEntryHtml(20 + this.OffsetSize + 160, "Go there");
|
||||
this.AddEntryButton(20, ArrowRightID1, ArrowRightID2, 4, ArrowRightWidth, ArrowRightHeight);
|
||||
|
||||
this.AddNewLine();
|
||||
this.AddEntryHtml(20 + this.OffsetSize + 160, "Move to target");
|
||||
this.AddEntryButton(20, ArrowRightID1, ArrowRightID2, 5, ArrowRightWidth, ArrowRightHeight);
|
||||
|
||||
this.AddNewLine();
|
||||
this.AddEntryHtml(20 + this.OffsetSize + 160, "Bring to pack");
|
||||
this.AddEntryButton(20, ArrowRightID1, ArrowRightID2, 6, ArrowRightWidth, ArrowRightHeight);
|
||||
|
||||
this.FinishPage();
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo info)
|
||||
{
|
||||
if (this.m_Item.Deleted)
|
||||
{
|
||||
this.m_From.SendGump(new InterfaceGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, this.m_Item));
|
||||
return;
|
||||
}
|
||||
else if (!BaseCommand.IsAccessible(this.m_From, this.m_Item))
|
||||
{
|
||||
this.m_From.SendMessage("That is no longer accessible.");
|
||||
this.m_From.SendGump(new InterfaceGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, this.m_Item));
|
||||
return;
|
||||
}
|
||||
|
||||
switch ( info.ButtonID )
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
{
|
||||
this.m_From.SendGump(new InterfaceGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, this.m_Item));
|
||||
break;
|
||||
}
|
||||
case 2: // Properties
|
||||
{
|
||||
this.m_From.SendGump(new InterfaceItemGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, this.m_Item));
|
||||
this.m_From.SendGump(new PropertiesGump(this.m_From, this.m_Item));
|
||||
break;
|
||||
}
|
||||
case 3: // Delete
|
||||
{
|
||||
CommandLogging.WriteLine(this.m_From, "{0} {1} deleting {2}", this.m_From.AccessLevel, CommandLogging.Format(this.m_From), CommandLogging.Format(this.m_Item));
|
||||
this.m_Item.Delete();
|
||||
this.m_From.SendGump(new InterfaceGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, this.m_Item));
|
||||
break;
|
||||
}
|
||||
case 4: // Go there
|
||||
{
|
||||
this.m_From.SendGump(new InterfaceItemGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, this.m_Item));
|
||||
this.InvokeCommand(String.Format("Go {0}", this.m_Item.Serial.Value));
|
||||
break;
|
||||
}
|
||||
case 5: // Move to target
|
||||
{
|
||||
this.m_From.SendGump(new InterfaceItemGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, this.m_Item));
|
||||
this.m_From.Target = new MoveTarget(this.m_Item);
|
||||
break;
|
||||
}
|
||||
case 6: // Bring to pack
|
||||
{
|
||||
Mobile owner = this.m_Item.RootParent as Mobile;
|
||||
|
||||
if (owner != null && (owner.Map != null && owner.Map != Map.Internal) && !BaseCommand.IsAccessible(this.m_From, owner) /* !m_From.CanSee( owner )*/)
|
||||
{
|
||||
this.m_From.SendMessage("You can not get what you can not see.");
|
||||
}
|
||||
else if (owner != null && (owner.Map == null || owner.Map == Map.Internal) && owner.Hidden && owner.AccessLevel >= this.m_From.AccessLevel)
|
||||
{
|
||||
this.m_From.SendMessage("You can not get what you can not see.");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_From.SendGump(new InterfaceItemGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, this.m_Item));
|
||||
this.m_From.AddToBackpack(this.m_Item);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void InvokeCommand(string ip)
|
||||
{
|
||||
CommandSystem.Handle(this.m_From, String.Format("{0}{1}", CommandSystem.Prefix, ip));
|
||||
}
|
||||
}
|
||||
|
||||
public class InterfaceMobileGump : BaseGridGump
|
||||
{
|
||||
private readonly Mobile m_From;
|
||||
private readonly string[] m_Columns;
|
||||
private readonly ArrayList m_List;
|
||||
private readonly int m_Page;
|
||||
private readonly Mobile m_Mobile;
|
||||
public InterfaceMobileGump(Mobile from, string[] columns, ArrayList list, int page, Mobile mob)
|
||||
: base(30, 30)
|
||||
{
|
||||
this.m_From = from;
|
||||
|
||||
this.m_Columns = columns;
|
||||
|
||||
this.m_List = list;
|
||||
this.m_Page = page;
|
||||
|
||||
this.m_Mobile = mob;
|
||||
|
||||
this.Render();
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
this.AddNewPage();
|
||||
|
||||
this.AddEntryButton(20, ArrowLeftID1, ArrowLeftID2, 1, ArrowLeftWidth, ArrowLeftHeight);
|
||||
this.AddEntryHtml(160, this.m_Mobile.Name);
|
||||
this.AddEntryHeader(20);
|
||||
|
||||
this.AddNewLine();
|
||||
this.AddEntryHtml(20 + this.OffsetSize + 160, "Properties");
|
||||
this.AddEntryButton(20, ArrowRightID1, ArrowRightID2, 2, ArrowRightWidth, ArrowRightHeight);
|
||||
|
||||
if (!this.m_Mobile.Player)
|
||||
{
|
||||
this.AddNewLine();
|
||||
this.AddEntryHtml(20 + this.OffsetSize + 160, "Delete");
|
||||
this.AddEntryButton(20, ArrowRightID1, ArrowRightID2, 3, ArrowRightWidth, ArrowRightHeight);
|
||||
}
|
||||
|
||||
if (this.m_Mobile != this.m_From)
|
||||
{
|
||||
this.AddNewLine();
|
||||
this.AddEntryHtml(20 + this.OffsetSize + 160, "Go to there");
|
||||
this.AddEntryButton(20, ArrowRightID1, ArrowRightID2, 4, ArrowRightWidth, ArrowRightHeight);
|
||||
|
||||
this.AddNewLine();
|
||||
this.AddEntryHtml(20 + this.OffsetSize + 160, "Bring them here");
|
||||
this.AddEntryButton(20, ArrowRightID1, ArrowRightID2, 5, ArrowRightWidth, ArrowRightHeight);
|
||||
}
|
||||
|
||||
this.AddNewLine();
|
||||
this.AddEntryHtml(20 + this.OffsetSize + 160, "Move to target");
|
||||
this.AddEntryButton(20, ArrowRightID1, ArrowRightID2, 6, ArrowRightWidth, ArrowRightHeight);
|
||||
|
||||
if (this.m_From == this.m_Mobile || this.m_From.AccessLevel > this.m_Mobile.AccessLevel)
|
||||
{
|
||||
this.AddNewLine();
|
||||
if (this.m_Mobile.Alive)
|
||||
{
|
||||
this.AddEntryHtml(20 + this.OffsetSize + 160, "Kill");
|
||||
this.AddEntryButton(20, ArrowRightID1, ArrowRightID2, 7, ArrowRightWidth, ArrowRightHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.AddEntryHtml(20 + this.OffsetSize + 160, "Resurrect");
|
||||
this.AddEntryButton(20, ArrowRightID1, ArrowRightID2, 8, ArrowRightWidth, ArrowRightHeight);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.m_Mobile.NetState != null)
|
||||
{
|
||||
this.AddNewLine();
|
||||
this.AddEntryHtml(20 + this.OffsetSize + 160, "Client");
|
||||
this.AddEntryButton(20, ArrowRightID1, ArrowRightID2, 9, ArrowRightWidth, ArrowRightHeight);
|
||||
}
|
||||
|
||||
this.FinishPage();
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo info)
|
||||
{
|
||||
if (this.m_Mobile.Deleted)
|
||||
{
|
||||
this.m_From.SendGump(new InterfaceGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, this.m_Mobile));
|
||||
return;
|
||||
}
|
||||
else if (!BaseCommand.IsAccessible(this.m_From, this.m_Mobile))
|
||||
{
|
||||
this.m_From.SendMessage("That is no longer accessible.");
|
||||
this.m_From.SendGump(new InterfaceGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, this.m_Mobile));
|
||||
return;
|
||||
}
|
||||
|
||||
switch ( info.ButtonID )
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
{
|
||||
this.m_From.SendGump(new InterfaceGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, this.m_Mobile));
|
||||
break;
|
||||
}
|
||||
case 2: // Properties
|
||||
{
|
||||
this.m_From.SendGump(new InterfaceMobileGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, this.m_Mobile));
|
||||
this.m_From.SendGump(new PropertiesGump(this.m_From, this.m_Mobile));
|
||||
break;
|
||||
}
|
||||
case 3: // Delete
|
||||
{
|
||||
if (!this.m_Mobile.Player)
|
||||
{
|
||||
CommandLogging.WriteLine(this.m_From, "{0} {1} deleting {2}", this.m_From.AccessLevel, CommandLogging.Format(this.m_From), CommandLogging.Format(this.m_Mobile));
|
||||
this.m_Mobile.Delete();
|
||||
this.m_From.SendGump(new InterfaceGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, this.m_Mobile));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 4: // Go there
|
||||
{
|
||||
this.m_From.SendGump(new InterfaceMobileGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, this.m_Mobile));
|
||||
this.InvokeCommand(String.Format("Go {0}", this.m_Mobile.Serial.Value));
|
||||
break;
|
||||
}
|
||||
case 5: // Bring them here
|
||||
{
|
||||
if (this.m_From.Map == null || this.m_From.Map == Map.Internal)
|
||||
{
|
||||
this.m_From.SendMessage("You cannot bring that person here.");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_From.SendGump(new InterfaceMobileGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, this.m_Mobile));
|
||||
this.m_Mobile.MoveToWorld(this.m_From.Location, this.m_From.Map);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 6: // Move to target
|
||||
{
|
||||
this.m_From.SendGump(new InterfaceMobileGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, this.m_Mobile));
|
||||
this.m_From.Target = new MoveTarget(this.m_Mobile);
|
||||
break;
|
||||
}
|
||||
case 7: // Kill
|
||||
{
|
||||
if (this.m_From == this.m_Mobile || this.m_From.AccessLevel > this.m_Mobile.AccessLevel)
|
||||
this.m_Mobile.Kill();
|
||||
|
||||
this.m_From.SendGump(new InterfaceMobileGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, this.m_Mobile));
|
||||
|
||||
break;
|
||||
}
|
||||
case 8: // Res
|
||||
{
|
||||
if (this.m_From == this.m_Mobile || this.m_From.AccessLevel > this.m_Mobile.AccessLevel)
|
||||
{
|
||||
this.m_Mobile.PlaySound(0x214);
|
||||
this.m_Mobile.FixedEffect(0x376A, 10, 16);
|
||||
|
||||
this.m_Mobile.Resurrect();
|
||||
}
|
||||
|
||||
this.m_From.SendGump(new InterfaceMobileGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, this.m_Mobile));
|
||||
|
||||
break;
|
||||
}
|
||||
case 9: // Client
|
||||
{
|
||||
this.m_From.SendGump(new InterfaceMobileGump(this.m_From, this.m_Columns, this.m_List, this.m_Page, this.m_Mobile));
|
||||
|
||||
if (this.m_Mobile.NetState != null)
|
||||
this.m_From.SendGump(new ClientGump(this.m_From, this.m_Mobile.NetState));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void InvokeCommand(string ip)
|
||||
{
|
||||
CommandSystem.Handle(this.m_From, String.Format("{0}{1}", CommandSystem.Prefix, ip));
|
||||
}
|
||||
}
|
||||
}
|
||||
198
Scripts/Commands/Generic/Extensions/BaseExtension.cs
Normal file
198
Scripts/Commands/Generic/Extensions/BaseExtension.cs
Normal file
@@ -0,0 +1,198 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public delegate BaseExtension ExtensionConstructor();
|
||||
|
||||
public sealed class ExtensionInfo
|
||||
{
|
||||
private static readonly Dictionary<string, ExtensionInfo> m_Table = new Dictionary<string, ExtensionInfo>(StringComparer.InvariantCultureIgnoreCase);
|
||||
private readonly int m_Order;
|
||||
private readonly string m_Name;
|
||||
private readonly int m_Size;
|
||||
private readonly ExtensionConstructor m_Constructor;
|
||||
public ExtensionInfo(int order, string name, int size, ExtensionConstructor constructor)
|
||||
{
|
||||
this.m_Name = name;
|
||||
this.m_Size = size;
|
||||
|
||||
this.m_Order = order;
|
||||
|
||||
this.m_Constructor = constructor;
|
||||
}
|
||||
|
||||
public static Dictionary<string, ExtensionInfo> Table
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Table;
|
||||
}
|
||||
}
|
||||
public int Order
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_Order;
|
||||
}
|
||||
}
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_Name;
|
||||
}
|
||||
}
|
||||
public int Size
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_Size;
|
||||
}
|
||||
}
|
||||
public bool IsFixedSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return (this.m_Size >= 0);
|
||||
}
|
||||
}
|
||||
public ExtensionConstructor Constructor
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_Constructor;
|
||||
}
|
||||
}
|
||||
public static void Register(ExtensionInfo ext)
|
||||
{
|
||||
m_Table[ext.m_Name] = ext;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Extensions : List<BaseExtension>
|
||||
{
|
||||
public Extensions()
|
||||
{
|
||||
}
|
||||
|
||||
public static Extensions Parse(Mobile from, ref string[] args)
|
||||
{
|
||||
Extensions parsed = new Extensions();
|
||||
|
||||
int size = args.Length;
|
||||
|
||||
Type baseType = null;
|
||||
|
||||
for (int i = args.Length - 1; i >= 0; --i)
|
||||
{
|
||||
ExtensionInfo extInfo = null;
|
||||
|
||||
if (!ExtensionInfo.Table.TryGetValue(args[i], out extInfo))
|
||||
continue;
|
||||
|
||||
if (extInfo.IsFixedSize && i != (size - extInfo.Size - 1))
|
||||
throw new Exception("Invalid extended argument count.");
|
||||
|
||||
BaseExtension ext = extInfo.Constructor();
|
||||
|
||||
ext.Parse(from, args, i + 1, size - i - 1);
|
||||
|
||||
if (ext is WhereExtension)
|
||||
baseType = (ext as WhereExtension).Conditional.Type;
|
||||
|
||||
parsed.Add(ext);
|
||||
|
||||
size = i;
|
||||
}
|
||||
|
||||
parsed.Sort(delegate(BaseExtension a, BaseExtension b)
|
||||
{
|
||||
return (a.Order - b.Order);
|
||||
});
|
||||
|
||||
AssemblyEmitter emitter = null;
|
||||
|
||||
foreach (BaseExtension update in parsed)
|
||||
update.Optimize(from, baseType, ref emitter);
|
||||
|
||||
if (size != args.Length)
|
||||
{
|
||||
string[] old = args;
|
||||
args = new string[size];
|
||||
|
||||
for (int i = 0; i < args.Length; ++i)
|
||||
args[i] = old[i];
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
public bool IsValid(object obj)
|
||||
{
|
||||
for (int i = 0; i < this.Count; ++i)
|
||||
{
|
||||
if (!this[i].IsValid(obj))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Filter(ArrayList list)
|
||||
{
|
||||
for (int i = 0; i < this.Count; ++i)
|
||||
this[i].Filter(list);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class BaseExtension
|
||||
{
|
||||
public abstract ExtensionInfo Info { get; }
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Info.Name;
|
||||
}
|
||||
}
|
||||
public int Size
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Info.Size;
|
||||
}
|
||||
}
|
||||
public bool IsFixedSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Info.IsFixedSize;
|
||||
}
|
||||
}
|
||||
public int Order
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Info.Order;
|
||||
}
|
||||
}
|
||||
public virtual void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Parse(Mobile from, string[] arguments, int offset, int size)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual bool IsValid(object obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual void Filter(ArrayList list)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,549 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public interface IConditional
|
||||
{
|
||||
bool Verify(object obj);
|
||||
}
|
||||
|
||||
public interface ICondition
|
||||
{
|
||||
// Invoked during the constructor
|
||||
void Construct(TypeBuilder typeBuilder, ILGenerator il, int index);
|
||||
|
||||
// Target object will be loaded on the stack
|
||||
void Compile(MethodEmitter emitter);
|
||||
}
|
||||
|
||||
public sealed class TypeCondition : ICondition
|
||||
{
|
||||
public static TypeCondition Default = new TypeCondition();
|
||||
|
||||
void ICondition.Construct(TypeBuilder typeBuilder, ILGenerator il, int index)
|
||||
{
|
||||
}
|
||||
|
||||
void ICondition.Compile(MethodEmitter emitter)
|
||||
{
|
||||
// The object was safely cast to be the conditionals type
|
||||
// If it's null, then the type cast didn't work...
|
||||
emitter.LoadNull();
|
||||
emitter.Compare(OpCodes.Ceq);
|
||||
emitter.LogicalNot();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class PropertyValue
|
||||
{
|
||||
private readonly Type m_Type;
|
||||
private object m_Value;
|
||||
private FieldInfo m_Field;
|
||||
|
||||
public Type Type
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_Type;
|
||||
}
|
||||
}
|
||||
|
||||
public object Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_Value;
|
||||
}
|
||||
}
|
||||
|
||||
public FieldInfo Field
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_Field;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasField
|
||||
{
|
||||
get
|
||||
{
|
||||
return (this.m_Field != null);
|
||||
}
|
||||
}
|
||||
|
||||
public PropertyValue(Type type, object value)
|
||||
{
|
||||
this.m_Type = type;
|
||||
this.m_Value = value;
|
||||
}
|
||||
|
||||
public void Load(MethodEmitter method)
|
||||
{
|
||||
if (this.m_Field != null)
|
||||
{
|
||||
method.LoadArgument(0);
|
||||
method.LoadField(this.m_Field);
|
||||
}
|
||||
else if (this.m_Value == null)
|
||||
{
|
||||
method.LoadNull(this.m_Type);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.m_Value is int)
|
||||
method.Load((int)this.m_Value);
|
||||
else if (this.m_Value is long)
|
||||
method.Load((long)this.m_Value);
|
||||
else if (this.m_Value is float)
|
||||
method.Load((float)this.m_Value);
|
||||
else if (this.m_Value is double)
|
||||
method.Load((double)this.m_Value);
|
||||
else if (this.m_Value is char)
|
||||
method.Load((char)this.m_Value);
|
||||
else if (this.m_Value is bool)
|
||||
method.Load((bool)this.m_Value);
|
||||
else if (this.m_Value is string)
|
||||
method.Load((string)this.m_Value);
|
||||
else if (this.m_Value is Enum)
|
||||
method.Load((Enum)this.m_Value);
|
||||
else
|
||||
throw new InvalidOperationException("Unrecognized comparison value.");
|
||||
}
|
||||
}
|
||||
|
||||
public void Acquire(TypeBuilder typeBuilder, ILGenerator il, string fieldName)
|
||||
{
|
||||
if (this.m_Value is string)
|
||||
{
|
||||
string toParse = (string)this.m_Value;
|
||||
|
||||
if (!this.m_Type.IsValueType && toParse == "null")
|
||||
{
|
||||
this.m_Value = null;
|
||||
}
|
||||
else if (this.m_Type == typeof(string))
|
||||
{
|
||||
if (toParse == @"@""null""")
|
||||
toParse = "null";
|
||||
|
||||
this.m_Value = toParse;
|
||||
}
|
||||
else if (this.m_Type.IsEnum)
|
||||
{
|
||||
this.m_Value = Enum.Parse(this.m_Type, toParse, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
MethodInfo parseMethod = null;
|
||||
object[] parseArgs = null;
|
||||
|
||||
MethodInfo parseNumber = this.m_Type.GetMethod(
|
||||
"Parse",
|
||||
BindingFlags.Public | BindingFlags.Static,
|
||||
null,
|
||||
new Type[] { typeof(string), typeof(NumberStyles) },
|
||||
null);
|
||||
|
||||
if (parseNumber != null)
|
||||
{
|
||||
NumberStyles style = NumberStyles.Integer;
|
||||
|
||||
if (Insensitive.StartsWith(toParse, "0x"))
|
||||
{
|
||||
style = NumberStyles.HexNumber;
|
||||
toParse = toParse.Substring(2);
|
||||
}
|
||||
|
||||
parseMethod = parseNumber;
|
||||
parseArgs = new object[] { toParse, style };
|
||||
}
|
||||
else
|
||||
{
|
||||
MethodInfo parseGeneral = this.m_Type.GetMethod(
|
||||
"Parse",
|
||||
BindingFlags.Public | BindingFlags.Static,
|
||||
null,
|
||||
new Type[] { typeof(string) },
|
||||
null);
|
||||
|
||||
parseMethod = parseGeneral;
|
||||
parseArgs = new object[] { toParse };
|
||||
}
|
||||
|
||||
if (parseMethod != null)
|
||||
{
|
||||
this.m_Value = parseMethod.Invoke(null, parseArgs);
|
||||
|
||||
if (!this.m_Type.IsPrimitive)
|
||||
{
|
||||
this.m_Field = typeBuilder.DefineField(
|
||||
fieldName,
|
||||
this.m_Type,
|
||||
FieldAttributes.Private | FieldAttributes.InitOnly);
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
|
||||
il.Emit(OpCodes.Ldstr, toParse);
|
||||
|
||||
if (parseArgs.Length == 2) // dirty evil hack :-(
|
||||
il.Emit(OpCodes.Ldc_I4, (int)parseArgs[1]);
|
||||
|
||||
il.Emit(OpCodes.Call, parseMethod);
|
||||
il.Emit(OpCodes.Stfld, this.m_Field);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
String.Format(
|
||||
"Unable to convert string \"{0}\" into type '{1}'.",
|
||||
this.m_Value,
|
||||
this.m_Type));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class PropertyCondition : ICondition
|
||||
{
|
||||
protected Property m_Property;
|
||||
protected bool m_Not;
|
||||
|
||||
public PropertyCondition(Property property, bool not)
|
||||
{
|
||||
this.m_Property = property;
|
||||
this.m_Not = not;
|
||||
}
|
||||
|
||||
public abstract void Construct(TypeBuilder typeBuilder, ILGenerator il, int index);
|
||||
|
||||
public abstract void Compile(MethodEmitter emitter);
|
||||
}
|
||||
|
||||
public enum StringOperator
|
||||
{
|
||||
Equal,
|
||||
NotEqual,
|
||||
|
||||
Contains,
|
||||
|
||||
StartsWith,
|
||||
EndsWith
|
||||
}
|
||||
|
||||
public sealed class StringCondition : PropertyCondition
|
||||
{
|
||||
private readonly StringOperator m_Operator;
|
||||
private readonly PropertyValue m_Value;
|
||||
|
||||
private readonly bool m_IgnoreCase;
|
||||
|
||||
public StringCondition(Property property, bool not, StringOperator op, object value, bool ignoreCase)
|
||||
: base(property, not)
|
||||
{
|
||||
this.m_Operator = op;
|
||||
this.m_Value = new PropertyValue(property.Type, value);
|
||||
|
||||
this.m_IgnoreCase = ignoreCase;
|
||||
}
|
||||
|
||||
public override void Construct(TypeBuilder typeBuilder, ILGenerator il, int index)
|
||||
{
|
||||
this.m_Value.Acquire(typeBuilder, il, "v" + index);
|
||||
}
|
||||
|
||||
public override void Compile(MethodEmitter emitter)
|
||||
{
|
||||
bool inverse = false;
|
||||
|
||||
string methodName;
|
||||
|
||||
switch ( this.m_Operator )
|
||||
{
|
||||
case StringOperator.Equal:
|
||||
methodName = "Equals";
|
||||
break;
|
||||
case StringOperator.NotEqual:
|
||||
methodName = "Equals";
|
||||
inverse = true;
|
||||
break;
|
||||
case StringOperator.Contains:
|
||||
methodName = "Contains";
|
||||
break;
|
||||
case StringOperator.StartsWith:
|
||||
methodName = "StartsWith";
|
||||
break;
|
||||
case StringOperator.EndsWith:
|
||||
methodName = "EndsWith";
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException("Invalid string comparison operator.");
|
||||
}
|
||||
|
||||
if (this.m_IgnoreCase || methodName == "Equals")
|
||||
{
|
||||
Type type = (this.m_IgnoreCase ? typeof(Insensitive) : typeof(String));
|
||||
|
||||
emitter.BeginCall(
|
||||
type.GetMethod(
|
||||
methodName,
|
||||
BindingFlags.Public | BindingFlags.Static,
|
||||
null,
|
||||
new Type[]
|
||||
{
|
||||
typeof(string),
|
||||
typeof(string)
|
||||
},
|
||||
null));
|
||||
|
||||
emitter.Chain(this.m_Property);
|
||||
this.m_Value.Load(emitter);
|
||||
|
||||
emitter.FinishCall();
|
||||
}
|
||||
else
|
||||
{
|
||||
Label notNull = emitter.CreateLabel();
|
||||
Label moveOn = emitter.CreateLabel();
|
||||
|
||||
LocalBuilder temp = emitter.AcquireTemp(this.m_Property.Type);
|
||||
|
||||
emitter.Chain(this.m_Property);
|
||||
|
||||
emitter.StoreLocal(temp);
|
||||
emitter.LoadLocal(temp);
|
||||
|
||||
emitter.BranchIfTrue(notNull);
|
||||
|
||||
emitter.Load(false);
|
||||
emitter.Pop();
|
||||
emitter.Branch(moveOn);
|
||||
|
||||
emitter.MarkLabel(notNull);
|
||||
emitter.LoadLocal(temp);
|
||||
|
||||
emitter.BeginCall(
|
||||
typeof(string).GetMethod(
|
||||
methodName,
|
||||
BindingFlags.Public | BindingFlags.Instance,
|
||||
null,
|
||||
new Type[]
|
||||
{
|
||||
typeof(string)
|
||||
},
|
||||
null));
|
||||
|
||||
this.m_Value.Load(emitter);
|
||||
|
||||
emitter.FinishCall();
|
||||
|
||||
emitter.MarkLabel(moveOn);
|
||||
}
|
||||
|
||||
if (this.m_Not != inverse)
|
||||
emitter.LogicalNot();
|
||||
}
|
||||
}
|
||||
|
||||
public enum ComparisonOperator
|
||||
{
|
||||
Equal,
|
||||
NotEqual,
|
||||
Greater,
|
||||
GreaterEqual,
|
||||
Lesser,
|
||||
LesserEqual
|
||||
}
|
||||
|
||||
public sealed class ComparisonCondition : PropertyCondition
|
||||
{
|
||||
private readonly ComparisonOperator m_Operator;
|
||||
private readonly PropertyValue m_Value;
|
||||
|
||||
public ComparisonCondition(Property property, bool not, ComparisonOperator op, object value)
|
||||
: base(property, not)
|
||||
{
|
||||
this.m_Operator = op;
|
||||
this.m_Value = new PropertyValue(property.Type, value);
|
||||
}
|
||||
|
||||
public override void Construct(TypeBuilder typeBuilder, ILGenerator il, int index)
|
||||
{
|
||||
this.m_Value.Acquire(typeBuilder, il, "v" + index);
|
||||
}
|
||||
|
||||
public override void Compile(MethodEmitter emitter)
|
||||
{
|
||||
emitter.Chain(this.m_Property);
|
||||
|
||||
bool inverse = false;
|
||||
|
||||
bool couldCompare =
|
||||
emitter.CompareTo(1, delegate()
|
||||
{
|
||||
this.m_Value.Load(emitter);
|
||||
});
|
||||
|
||||
if (couldCompare)
|
||||
{
|
||||
emitter.Load(0);
|
||||
|
||||
switch ( this.m_Operator )
|
||||
{
|
||||
case ComparisonOperator.Equal:
|
||||
emitter.Compare(OpCodes.Ceq);
|
||||
break;
|
||||
case ComparisonOperator.NotEqual:
|
||||
emitter.Compare(OpCodes.Ceq);
|
||||
inverse = true;
|
||||
break;
|
||||
case ComparisonOperator.Greater:
|
||||
emitter.Compare(OpCodes.Cgt);
|
||||
break;
|
||||
case ComparisonOperator.GreaterEqual:
|
||||
emitter.Compare(OpCodes.Clt);
|
||||
inverse = true;
|
||||
break;
|
||||
case ComparisonOperator.Lesser:
|
||||
emitter.Compare(OpCodes.Clt);
|
||||
break;
|
||||
case ComparisonOperator.LesserEqual:
|
||||
emitter.Compare(OpCodes.Cgt);
|
||||
inverse = true;
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException("Invalid comparison operator.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This type is -not- comparable
|
||||
// We can only support == and != operations
|
||||
this.m_Value.Load(emitter);
|
||||
|
||||
switch ( this.m_Operator )
|
||||
{
|
||||
case ComparisonOperator.Equal:
|
||||
emitter.Compare(OpCodes.Ceq);
|
||||
break;
|
||||
case ComparisonOperator.NotEqual:
|
||||
emitter.Compare(OpCodes.Ceq);
|
||||
inverse = true;
|
||||
break;
|
||||
case ComparisonOperator.Greater:
|
||||
case ComparisonOperator.GreaterEqual:
|
||||
case ComparisonOperator.Lesser:
|
||||
case ComparisonOperator.LesserEqual:
|
||||
throw new InvalidOperationException("Property does not support relational comparisons.");
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException("Invalid operator.");
|
||||
}
|
||||
}
|
||||
|
||||
if (this.m_Not != inverse)
|
||||
emitter.LogicalNot();
|
||||
}
|
||||
}
|
||||
|
||||
public static class ConditionalCompiler
|
||||
{
|
||||
public static IConditional Compile(AssemblyEmitter assembly, Type objectType, ICondition[] conditions, int index)
|
||||
{
|
||||
TypeBuilder typeBuilder = assembly.DefineType(
|
||||
"__conditional" + index,
|
||||
TypeAttributes.Public,
|
||||
typeof(object));
|
||||
|
||||
#region Constructor
|
||||
{
|
||||
ConstructorBuilder ctor = typeBuilder.DefineConstructor(
|
||||
MethodAttributes.Public,
|
||||
CallingConventions.Standard,
|
||||
Type.EmptyTypes);
|
||||
|
||||
ILGenerator il = ctor.GetILGenerator();
|
||||
|
||||
// : base()
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
|
||||
|
||||
for (int i = 0; i < conditions.Length; ++i)
|
||||
conditions[i].Construct(typeBuilder, il, i);
|
||||
|
||||
// return;
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IComparer
|
||||
typeBuilder.AddInterfaceImplementation(typeof(IConditional));
|
||||
|
||||
MethodBuilder compareMethod;
|
||||
|
||||
#region Compare
|
||||
{
|
||||
MethodEmitter emitter = new MethodEmitter(typeBuilder);
|
||||
|
||||
emitter.Define(
|
||||
/* name */ "Verify",
|
||||
/* attr */ MethodAttributes.Public | MethodAttributes.Virtual,
|
||||
/* return */ typeof(bool),
|
||||
/* params */ new Type[] { typeof(object) });
|
||||
|
||||
LocalBuilder obj = emitter.CreateLocal(objectType);
|
||||
LocalBuilder eq = emitter.CreateLocal(typeof(bool));
|
||||
|
||||
emitter.LoadArgument(1);
|
||||
emitter.CastAs(objectType);
|
||||
emitter.StoreLocal(obj);
|
||||
|
||||
Label done = emitter.CreateLabel();
|
||||
|
||||
for (int i = 0; i < conditions.Length; ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
emitter.LoadLocal(eq);
|
||||
|
||||
emitter.BranchIfFalse(done);
|
||||
}
|
||||
|
||||
emitter.LoadLocal(obj);
|
||||
|
||||
conditions[i].Compile(emitter);
|
||||
|
||||
emitter.StoreLocal(eq);
|
||||
}
|
||||
|
||||
emitter.MarkLabel(done);
|
||||
|
||||
emitter.LoadLocal(eq);
|
||||
|
||||
emitter.Return();
|
||||
|
||||
typeBuilder.DefineMethodOverride(
|
||||
emitter.Method,
|
||||
typeof(IConditional).GetMethod(
|
||||
"Verify",
|
||||
new Type[]
|
||||
{
|
||||
typeof(object)
|
||||
}));
|
||||
|
||||
compareMethod = emitter.Method;
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
Type conditionalType = typeBuilder.CreateType();
|
||||
|
||||
return (IConditional)Activator.CreateInstance(conditionalType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public static class DistinctCompiler
|
||||
{
|
||||
public static IComparer Compile(AssemblyEmitter assembly, Type objectType, Property[] props)
|
||||
{
|
||||
TypeBuilder typeBuilder = assembly.DefineType(
|
||||
"__distinct",
|
||||
TypeAttributes.Public,
|
||||
typeof(object));
|
||||
|
||||
#region Constructor
|
||||
{
|
||||
ConstructorBuilder ctor = typeBuilder.DefineConstructor(
|
||||
MethodAttributes.Public,
|
||||
CallingConventions.Standard,
|
||||
Type.EmptyTypes);
|
||||
|
||||
ILGenerator il = ctor.GetILGenerator();
|
||||
|
||||
// : base()
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
|
||||
|
||||
// return;
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IComparer
|
||||
typeBuilder.AddInterfaceImplementation(typeof(IComparer));
|
||||
|
||||
MethodBuilder compareMethod;
|
||||
|
||||
#region Compare
|
||||
{
|
||||
MethodEmitter emitter = new MethodEmitter(typeBuilder);
|
||||
|
||||
emitter.Define(
|
||||
/* name */ "Compare",
|
||||
/* attr */ MethodAttributes.Public | MethodAttributes.Virtual,
|
||||
/* return */ typeof(int),
|
||||
/* params */ new Type[] { typeof(object), typeof(object) });
|
||||
|
||||
LocalBuilder a = emitter.CreateLocal(objectType);
|
||||
LocalBuilder b = emitter.CreateLocal(objectType);
|
||||
|
||||
LocalBuilder v = emitter.CreateLocal(typeof(int));
|
||||
|
||||
emitter.LoadArgument(1);
|
||||
emitter.CastAs(objectType);
|
||||
emitter.StoreLocal(a);
|
||||
|
||||
emitter.LoadArgument(2);
|
||||
emitter.CastAs(objectType);
|
||||
emitter.StoreLocal(b);
|
||||
|
||||
emitter.Load(0);
|
||||
emitter.StoreLocal(v);
|
||||
|
||||
Label end = emitter.CreateLabel();
|
||||
|
||||
for (int i = 0; i < props.Length; ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
emitter.LoadLocal(v);
|
||||
emitter.BranchIfTrue(end); // if ( v != 0 ) return v;
|
||||
}
|
||||
|
||||
Property prop = props[i];
|
||||
|
||||
emitter.LoadLocal(a);
|
||||
emitter.Chain(prop);
|
||||
|
||||
bool couldCompare =
|
||||
emitter.CompareTo(1, delegate()
|
||||
{
|
||||
emitter.LoadLocal(b);
|
||||
emitter.Chain(prop);
|
||||
});
|
||||
|
||||
if (!couldCompare)
|
||||
throw new InvalidOperationException("Property is not comparable.");
|
||||
|
||||
emitter.StoreLocal(v);
|
||||
}
|
||||
|
||||
emitter.MarkLabel(end);
|
||||
|
||||
emitter.LoadLocal(v);
|
||||
emitter.Return();
|
||||
|
||||
typeBuilder.DefineMethodOverride(
|
||||
emitter.Method,
|
||||
typeof(IComparer).GetMethod(
|
||||
"Compare",
|
||||
new Type[]
|
||||
{
|
||||
typeof(object),
|
||||
typeof(object)
|
||||
}));
|
||||
|
||||
compareMethod = emitter.Method;
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region IEqualityComparer
|
||||
typeBuilder.AddInterfaceImplementation(typeof(IEqualityComparer<object>));
|
||||
|
||||
#region Equals
|
||||
{
|
||||
MethodEmitter emitter = new MethodEmitter(typeBuilder);
|
||||
|
||||
emitter.Define(
|
||||
/* name */ "Equals",
|
||||
/* attr */ MethodAttributes.Public | MethodAttributes.Virtual,
|
||||
/* return */ typeof(bool),
|
||||
/* params */ new Type[] { typeof(object), typeof(object) });
|
||||
|
||||
emitter.Generator.Emit(OpCodes.Ldarg_0);
|
||||
emitter.Generator.Emit(OpCodes.Ldarg_1);
|
||||
emitter.Generator.Emit(OpCodes.Ldarg_2);
|
||||
|
||||
emitter.Generator.Emit(OpCodes.Call, compareMethod);
|
||||
|
||||
emitter.Generator.Emit(OpCodes.Ldc_I4_0);
|
||||
|
||||
emitter.Generator.Emit(OpCodes.Ceq);
|
||||
|
||||
emitter.Generator.Emit(OpCodes.Ret);
|
||||
|
||||
typeBuilder.DefineMethodOverride(
|
||||
emitter.Method,
|
||||
typeof(IEqualityComparer<object>).GetMethod(
|
||||
"Equals",
|
||||
new Type[]
|
||||
{
|
||||
typeof(object),
|
||||
typeof(object)
|
||||
}));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetHashCode
|
||||
{
|
||||
MethodEmitter emitter = new MethodEmitter(typeBuilder);
|
||||
|
||||
emitter.Define(
|
||||
/* name */ "GetHashCode",
|
||||
/* attr */ MethodAttributes.Public | MethodAttributes.Virtual,
|
||||
/* return */ typeof(int),
|
||||
/* params */ new Type[] { typeof(object) });
|
||||
|
||||
LocalBuilder obj = emitter.CreateLocal(objectType);
|
||||
|
||||
emitter.LoadArgument(1);
|
||||
emitter.CastAs(objectType);
|
||||
emitter.StoreLocal(obj);
|
||||
|
||||
for (int i = 0; i < props.Length; ++i)
|
||||
{
|
||||
Property prop = props[i];
|
||||
|
||||
emitter.LoadLocal(obj);
|
||||
emitter.Chain(prop);
|
||||
|
||||
Type active = emitter.Active;
|
||||
|
||||
MethodInfo getHashCode = active.GetMethod("GetHashCode", Type.EmptyTypes);
|
||||
|
||||
if (getHashCode == null)
|
||||
getHashCode = typeof(object).GetMethod("GetHashCode", Type.EmptyTypes);
|
||||
|
||||
if (active != typeof(int))
|
||||
{
|
||||
if (!active.IsValueType)
|
||||
{
|
||||
LocalBuilder value = emitter.AcquireTemp(active);
|
||||
|
||||
Label valueNotNull = emitter.CreateLabel();
|
||||
Label done = emitter.CreateLabel();
|
||||
|
||||
emitter.StoreLocal(value);
|
||||
emitter.LoadLocal(value);
|
||||
|
||||
emitter.BranchIfTrue(valueNotNull);
|
||||
|
||||
emitter.Load(0);
|
||||
emitter.Pop(typeof(int));
|
||||
|
||||
emitter.Branch(done);
|
||||
|
||||
emitter.MarkLabel(valueNotNull);
|
||||
|
||||
emitter.LoadLocal(value);
|
||||
emitter.Call(getHashCode);
|
||||
|
||||
emitter.ReleaseTemp(value);
|
||||
|
||||
emitter.MarkLabel(done);
|
||||
}
|
||||
else
|
||||
{
|
||||
emitter.Call(getHashCode);
|
||||
}
|
||||
}
|
||||
|
||||
if (i > 0)
|
||||
emitter.Xor();
|
||||
}
|
||||
|
||||
emitter.Return();
|
||||
|
||||
typeBuilder.DefineMethodOverride(
|
||||
emitter.Method,
|
||||
typeof(IEqualityComparer<object>).GetMethod(
|
||||
"GetHashCode",
|
||||
new Type[]
|
||||
{
|
||||
typeof(object)
|
||||
}));
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
Type comparerType = typeBuilder.CreateType();
|
||||
|
||||
return (IComparer)Activator.CreateInstance(comparerType);
|
||||
}
|
||||
}
|
||||
}
|
||||
186
Scripts/Commands/Generic/Extensions/Compilers/SortCompiler.cs
Normal file
186
Scripts/Commands/Generic/Extensions/Compilers/SortCompiler.cs
Normal file
@@ -0,0 +1,186 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public sealed class OrderInfo
|
||||
{
|
||||
private Property m_Property;
|
||||
private int m_Order;
|
||||
|
||||
public Property Property
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_Property;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.m_Property = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsAscending
|
||||
{
|
||||
get
|
||||
{
|
||||
return (this.m_Order > 0);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.m_Order = (value ? +1 : -1);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsDescending
|
||||
{
|
||||
get
|
||||
{
|
||||
return (this.m_Order < 0);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.m_Order = (value ? -1 : +1);
|
||||
}
|
||||
}
|
||||
|
||||
public int Sign
|
||||
{
|
||||
get
|
||||
{
|
||||
return Math.Sign(this.m_Order);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.m_Order = Math.Sign(value);
|
||||
|
||||
if (this.m_Order == 0)
|
||||
throw new InvalidOperationException("Sign cannot be zero.");
|
||||
}
|
||||
}
|
||||
|
||||
public OrderInfo(Property property, bool isAscending)
|
||||
{
|
||||
this.m_Property = property;
|
||||
|
||||
this.IsAscending = isAscending;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SortCompiler
|
||||
{
|
||||
public static IComparer Compile(AssemblyEmitter assembly, Type objectType, OrderInfo[] orders)
|
||||
{
|
||||
TypeBuilder typeBuilder = assembly.DefineType(
|
||||
"__sort",
|
||||
TypeAttributes.Public,
|
||||
typeof(object));
|
||||
|
||||
#region Constructor
|
||||
{
|
||||
ConstructorBuilder ctor = typeBuilder.DefineConstructor(
|
||||
MethodAttributes.Public,
|
||||
CallingConventions.Standard,
|
||||
Type.EmptyTypes);
|
||||
|
||||
ILGenerator il = ctor.GetILGenerator();
|
||||
|
||||
// : base()
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
|
||||
|
||||
// return;
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IComparer
|
||||
typeBuilder.AddInterfaceImplementation(typeof(IComparer));
|
||||
|
||||
MethodBuilder compareMethod;
|
||||
|
||||
#region Compare
|
||||
{
|
||||
MethodEmitter emitter = new MethodEmitter(typeBuilder);
|
||||
|
||||
emitter.Define(
|
||||
/* name */ "Compare",
|
||||
/* attr */ MethodAttributes.Public | MethodAttributes.Virtual,
|
||||
/* return */ typeof(int),
|
||||
/* params */ new Type[] { typeof(object), typeof(object) });
|
||||
|
||||
LocalBuilder a = emitter.CreateLocal(objectType);
|
||||
LocalBuilder b = emitter.CreateLocal(objectType);
|
||||
|
||||
LocalBuilder v = emitter.CreateLocal(typeof(int));
|
||||
|
||||
emitter.LoadArgument(1);
|
||||
emitter.CastAs(objectType);
|
||||
emitter.StoreLocal(a);
|
||||
|
||||
emitter.LoadArgument(2);
|
||||
emitter.CastAs(objectType);
|
||||
emitter.StoreLocal(b);
|
||||
|
||||
emitter.Load(0);
|
||||
emitter.StoreLocal(v);
|
||||
|
||||
Label end = emitter.CreateLabel();
|
||||
|
||||
for (int i = 0; i < orders.Length; ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
emitter.LoadLocal(v);
|
||||
emitter.BranchIfTrue(end); // if ( v != 0 ) return v;
|
||||
}
|
||||
|
||||
OrderInfo orderInfo = orders[i];
|
||||
|
||||
Property prop = orderInfo.Property;
|
||||
int sign = orderInfo.Sign;
|
||||
|
||||
emitter.LoadLocal(a);
|
||||
emitter.Chain(prop);
|
||||
|
||||
bool couldCompare =
|
||||
emitter.CompareTo(sign, delegate()
|
||||
{
|
||||
emitter.LoadLocal(b);
|
||||
emitter.Chain(prop);
|
||||
});
|
||||
|
||||
if (!couldCompare)
|
||||
throw new InvalidOperationException("Property is not comparable.");
|
||||
|
||||
emitter.StoreLocal(v);
|
||||
}
|
||||
|
||||
emitter.MarkLabel(end);
|
||||
|
||||
emitter.LoadLocal(v);
|
||||
emitter.Return();
|
||||
|
||||
typeBuilder.DefineMethodOverride(
|
||||
emitter.Method,
|
||||
typeof(IComparer).GetMethod(
|
||||
"Compare",
|
||||
new Type[]
|
||||
{
|
||||
typeof(object),
|
||||
typeof(object)
|
||||
}));
|
||||
|
||||
compareMethod = emitter.Method;
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
Type comparerType = typeBuilder.CreateType();
|
||||
|
||||
return (IComparer)Activator.CreateInstance(comparerType);
|
||||
}
|
||||
}
|
||||
}
|
||||
86
Scripts/Commands/Generic/Extensions/DistinctExtension.cs
Normal file
86
Scripts/Commands/Generic/Extensions/DistinctExtension.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public sealed class DistinctExtension : BaseExtension
|
||||
{
|
||||
public static ExtensionInfo ExtInfo = new ExtensionInfo(30, "Distinct", -1, delegate() { return new DistinctExtension(); });
|
||||
private readonly List<Property> m_Properties;
|
||||
private IComparer m_Comparer;
|
||||
public DistinctExtension()
|
||||
{
|
||||
this.m_Properties = new List<Property>();
|
||||
}
|
||||
|
||||
public override ExtensionInfo Info
|
||||
{
|
||||
get
|
||||
{
|
||||
return ExtInfo;
|
||||
}
|
||||
}
|
||||
public static void Initialize()
|
||||
{
|
||||
ExtensionInfo.Register(ExtInfo);
|
||||
}
|
||||
|
||||
public override void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly)
|
||||
{
|
||||
if (baseType == null)
|
||||
throw new Exception("Distinct extension may only be used in combination with an object conditional.");
|
||||
|
||||
foreach (Property prop in this.m_Properties)
|
||||
{
|
||||
prop.BindTo(baseType, PropertyAccess.Read);
|
||||
prop.CheckAccess(from);
|
||||
}
|
||||
|
||||
if (assembly == null)
|
||||
assembly = new AssemblyEmitter("__dynamic", false);
|
||||
|
||||
this.m_Comparer = DistinctCompiler.Compile(assembly, baseType, this.m_Properties.ToArray());
|
||||
}
|
||||
|
||||
public override void Parse(Mobile from, string[] arguments, int offset, int size)
|
||||
{
|
||||
if (size < 1)
|
||||
throw new Exception("Invalid distinction syntax.");
|
||||
|
||||
int end = offset + size;
|
||||
|
||||
while (offset < end)
|
||||
{
|
||||
string binding = arguments[offset++];
|
||||
|
||||
this.m_Properties.Add(new Property(binding));
|
||||
}
|
||||
}
|
||||
|
||||
public override void Filter(ArrayList list)
|
||||
{
|
||||
if (this.m_Comparer == null)
|
||||
throw new InvalidOperationException("The extension must first be optimized.");
|
||||
|
||||
ArrayList copy = new ArrayList(list);
|
||||
|
||||
copy.Sort(this.m_Comparer);
|
||||
|
||||
list.Clear();
|
||||
|
||||
object last = null;
|
||||
|
||||
for (int i = 0; i < copy.Count; ++i)
|
||||
{
|
||||
object obj = copy[i];
|
||||
|
||||
if (last == null || this.m_Comparer.Compare(obj, last) != 0)
|
||||
{
|
||||
list.Add(obj);
|
||||
last = obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
47
Scripts/Commands/Generic/Extensions/LimitExtension.cs
Normal file
47
Scripts/Commands/Generic/Extensions/LimitExtension.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public sealed class LimitExtension : BaseExtension
|
||||
{
|
||||
public static ExtensionInfo ExtInfo = new ExtensionInfo(80, "Limit", 1, delegate() { return new LimitExtension(); });
|
||||
private int m_Limit;
|
||||
public LimitExtension()
|
||||
{
|
||||
}
|
||||
|
||||
public override ExtensionInfo Info
|
||||
{
|
||||
get
|
||||
{
|
||||
return ExtInfo;
|
||||
}
|
||||
}
|
||||
public int Limit
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_Limit;
|
||||
}
|
||||
}
|
||||
public static void Initialize()
|
||||
{
|
||||
ExtensionInfo.Register(ExtInfo);
|
||||
}
|
||||
|
||||
public override void Parse(Mobile from, string[] arguments, int offset, int size)
|
||||
{
|
||||
this.m_Limit = Utility.ToInt32(arguments[offset]);
|
||||
|
||||
if (this.m_Limit < 0)
|
||||
throw new Exception("Limit cannot be less than zero.");
|
||||
}
|
||||
|
||||
public override void Filter(ArrayList list)
|
||||
{
|
||||
if (list.Count > this.m_Limit)
|
||||
list.RemoveRange(this.m_Limit, list.Count - this.m_Limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
105
Scripts/Commands/Generic/Extensions/SortExtension.cs
Normal file
105
Scripts/Commands/Generic/Extensions/SortExtension.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public sealed class SortExtension : BaseExtension
|
||||
{
|
||||
public static ExtensionInfo ExtInfo = new ExtensionInfo(40, "Order", -1, delegate() { return new SortExtension(); });
|
||||
private readonly List<OrderInfo> m_Orders;
|
||||
private IComparer m_Comparer;
|
||||
public SortExtension()
|
||||
{
|
||||
this.m_Orders = new List<OrderInfo>();
|
||||
}
|
||||
|
||||
public override ExtensionInfo Info
|
||||
{
|
||||
get
|
||||
{
|
||||
return ExtInfo;
|
||||
}
|
||||
}
|
||||
public static void Initialize()
|
||||
{
|
||||
ExtensionInfo.Register(ExtInfo);
|
||||
}
|
||||
|
||||
public override void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly)
|
||||
{
|
||||
if (baseType == null)
|
||||
throw new Exception("The ordering extension may only be used in combination with an object conditional.");
|
||||
|
||||
foreach (OrderInfo order in this.m_Orders)
|
||||
{
|
||||
order.Property.BindTo(baseType, PropertyAccess.Read);
|
||||
order.Property.CheckAccess(from);
|
||||
}
|
||||
|
||||
if (assembly == null)
|
||||
assembly = new AssemblyEmitter("__dynamic", false);
|
||||
|
||||
this.m_Comparer = SortCompiler.Compile(assembly, baseType, this.m_Orders.ToArray());
|
||||
}
|
||||
|
||||
public override void Parse(Mobile from, string[] arguments, int offset, int size)
|
||||
{
|
||||
if (size < 1)
|
||||
throw new Exception("Invalid ordering syntax.");
|
||||
|
||||
if (Insensitive.Equals(arguments[offset], "by"))
|
||||
{
|
||||
++offset;
|
||||
--size;
|
||||
|
||||
if (size < 1)
|
||||
throw new Exception("Invalid ordering syntax.");
|
||||
}
|
||||
|
||||
int end = offset + size;
|
||||
|
||||
while (offset < end)
|
||||
{
|
||||
string binding = arguments[offset++];
|
||||
|
||||
bool isAscending = true;
|
||||
|
||||
if (offset < end)
|
||||
{
|
||||
string next = arguments[offset];
|
||||
|
||||
switch ( next.ToLower() )
|
||||
{
|
||||
case "+":
|
||||
case "up":
|
||||
case "asc":
|
||||
case "ascending":
|
||||
isAscending = true;
|
||||
++offset;
|
||||
break;
|
||||
case "-":
|
||||
case "down":
|
||||
case "desc":
|
||||
case "descending":
|
||||
isAscending = false;
|
||||
++offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Property property = new Property(binding);
|
||||
|
||||
this.m_Orders.Add(new OrderInfo(property, isAscending));
|
||||
}
|
||||
}
|
||||
|
||||
public override void Filter(ArrayList list)
|
||||
{
|
||||
if (this.m_Comparer == null)
|
||||
throw new InvalidOperationException("The extension must first be optimized.");
|
||||
|
||||
list.Sort(this.m_Comparer);
|
||||
}
|
||||
}
|
||||
}
|
||||
53
Scripts/Commands/Generic/Extensions/WhereExtension.cs
Normal file
53
Scripts/Commands/Generic/Extensions/WhereExtension.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public sealed class WhereExtension : BaseExtension
|
||||
{
|
||||
public static ExtensionInfo ExtInfo = new ExtensionInfo(20, "Where", -1, delegate() { return new WhereExtension(); });
|
||||
private ObjectConditional m_Conditional;
|
||||
public WhereExtension()
|
||||
{
|
||||
}
|
||||
|
||||
public override ExtensionInfo Info
|
||||
{
|
||||
get
|
||||
{
|
||||
return ExtInfo;
|
||||
}
|
||||
}
|
||||
public ObjectConditional Conditional
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_Conditional;
|
||||
}
|
||||
}
|
||||
public static void Initialize()
|
||||
{
|
||||
ExtensionInfo.Register(ExtInfo);
|
||||
}
|
||||
|
||||
public override void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly)
|
||||
{
|
||||
if (baseType == null)
|
||||
throw new InvalidOperationException("Insanity.");
|
||||
|
||||
this.m_Conditional.Compile(ref assembly);
|
||||
}
|
||||
|
||||
public override void Parse(Mobile from, string[] arguments, int offset, int size)
|
||||
{
|
||||
if (size < 1)
|
||||
throw new Exception("Invalid condition syntax.");
|
||||
|
||||
this.m_Conditional = ObjectConditional.ParseDirect(from, arguments, offset, size);
|
||||
}
|
||||
|
||||
public override bool IsValid(object obj)
|
||||
{
|
||||
return this.m_Conditional.CheckCondition(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class AreaCommandImplementor : BaseCommandImplementor
|
||||
{
|
||||
private static AreaCommandImplementor m_Instance;
|
||||
public AreaCommandImplementor()
|
||||
{
|
||||
this.Accessors = new string[] { "Area", "Group" };
|
||||
this.SupportRequirement = CommandSupport.Area;
|
||||
this.SupportsConditionals = true;
|
||||
this.AccessLevel = AccessLevel.GameMaster;
|
||||
this.Usage = "Area <command> [condition]";
|
||||
this.Description = "Invokes the command on all appropriate objects in a targeted area. Optional condition arguments can further restrict the set of objects.";
|
||||
|
||||
m_Instance = this;
|
||||
}
|
||||
|
||||
public static AreaCommandImplementor Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Instance;
|
||||
}
|
||||
}
|
||||
public override void Process(Mobile from, BaseCommand command, string[] args)
|
||||
{
|
||||
BoundingBoxPicker.Begin(from, new BoundingBoxCallback(OnTarget), new object[] { command, args });
|
||||
}
|
||||
|
||||
public void OnTarget(Mobile from, Map map, Point3D start, Point3D end, object state)
|
||||
{
|
||||
try
|
||||
{
|
||||
object[] states = (object[])state;
|
||||
BaseCommand command = (BaseCommand)states[0];
|
||||
string[] args = (string[])states[1];
|
||||
|
||||
Rectangle2D rect = new Rectangle2D(start.X, start.Y, end.X - start.X + 1, end.Y - start.Y + 1);
|
||||
|
||||
Extensions ext = Extensions.Parse(from, ref args);
|
||||
|
||||
bool items, mobiles;
|
||||
|
||||
if (!this.CheckObjectTypes(from, command, ext, out items, out mobiles))
|
||||
return;
|
||||
|
||||
IPooledEnumerable eable;
|
||||
|
||||
if (items && mobiles)
|
||||
eable = map.GetObjectsInBounds(rect);
|
||||
else if (items)
|
||||
eable = map.GetItemsInBounds(rect);
|
||||
else if (mobiles)
|
||||
eable = map.GetMobilesInBounds(rect);
|
||||
else
|
||||
return;
|
||||
|
||||
ArrayList objs = new ArrayList();
|
||||
|
||||
foreach (object obj in eable)
|
||||
{
|
||||
if (mobiles && obj is Mobile && !BaseCommand.IsAccessible(from, obj))
|
||||
continue;
|
||||
|
||||
if (ext.IsValid(obj))
|
||||
objs.Add(obj);
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
|
||||
ext.Filter(objs);
|
||||
|
||||
this.RunCommand(from, objs, command, args);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
from.SendMessage(ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
372
Scripts/Commands/Generic/Implementors/BaseCommandImplementor.cs
Normal file
372
Scripts/Commands/Generic/Implementors/BaseCommandImplementor.cs
Normal file
@@ -0,0 +1,372 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
[Flags]
|
||||
public enum CommandSupport
|
||||
{
|
||||
Single = 0x0001,
|
||||
Global = 0x0002,
|
||||
Online = 0x0004,
|
||||
Multi = 0x0008,
|
||||
Area = 0x0010,
|
||||
Self = 0x0020,
|
||||
Region = 0x0040,
|
||||
Contained = 0x0080,
|
||||
IPAddress = 0x0100,
|
||||
|
||||
All = Single | Global | Online | Multi | Area | Self | Region | Contained | IPAddress,
|
||||
AllMobiles = All & ~Contained,
|
||||
AllNPCs = All & ~(IPAddress | Online | Self | Contained),
|
||||
AllItems = All & ~(IPAddress | Online | Self | Region),
|
||||
|
||||
Simple = Single | Multi,
|
||||
Complex = Global | Online | Area | Region | Contained | IPAddress
|
||||
}
|
||||
|
||||
public abstract class BaseCommandImplementor
|
||||
{
|
||||
private static List<BaseCommandImplementor> m_Implementors;
|
||||
private readonly Dictionary<string, BaseCommand> m_Commands;
|
||||
private string[] m_Accessors;
|
||||
private AccessLevel m_AccessLevel;
|
||||
private CommandSupport m_SupportRequirement;
|
||||
private string m_Usage;
|
||||
private string m_Description;
|
||||
private bool m_SupportsConditionals;
|
||||
public BaseCommandImplementor()
|
||||
{
|
||||
this.m_Commands = new Dictionary<string, BaseCommand>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public static List<BaseCommandImplementor> Implementors
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_Implementors == null)
|
||||
{
|
||||
m_Implementors = new List<BaseCommandImplementor>();
|
||||
RegisterImplementors();
|
||||
}
|
||||
|
||||
return m_Implementors;
|
||||
}
|
||||
}
|
||||
public bool SupportsConditionals
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_SupportsConditionals;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.m_SupportsConditionals = value;
|
||||
}
|
||||
}
|
||||
public string[] Accessors
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_Accessors;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.m_Accessors = value;
|
||||
}
|
||||
}
|
||||
public string Usage
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_Usage;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.m_Usage = value;
|
||||
}
|
||||
}
|
||||
public string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_Description;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.m_Description = value;
|
||||
}
|
||||
}
|
||||
public AccessLevel AccessLevel
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_AccessLevel;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.m_AccessLevel = value;
|
||||
}
|
||||
}
|
||||
public CommandSupport SupportRequirement
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_SupportRequirement;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.m_SupportRequirement = value;
|
||||
}
|
||||
}
|
||||
public Dictionary<string, BaseCommand> Commands
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_Commands;
|
||||
}
|
||||
}
|
||||
public static void RegisterImplementors()
|
||||
{
|
||||
Register(new RegionCommandImplementor());
|
||||
Register(new GlobalCommandImplementor());
|
||||
Register(new OnlineCommandImplementor());
|
||||
Register(new SingleCommandImplementor());
|
||||
Register(new SerialCommandImplementor());
|
||||
Register(new MultiCommandImplementor());
|
||||
Register(new AreaCommandImplementor());
|
||||
Register(new SelfCommandImplementor());
|
||||
Register(new ContainedCommandImplementor());
|
||||
Register(new IPAddressCommandImplementor());
|
||||
|
||||
Register(new RangeCommandImplementor());
|
||||
Register(new ScreenCommandImplementor());
|
||||
Register(new FacetCommandImplementor());
|
||||
}
|
||||
|
||||
public static void Register(BaseCommandImplementor impl)
|
||||
{
|
||||
m_Implementors.Add(impl);
|
||||
impl.Register();
|
||||
}
|
||||
|
||||
public virtual void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj)
|
||||
{
|
||||
obj = null;
|
||||
}
|
||||
|
||||
public virtual void Register(BaseCommand command)
|
||||
{
|
||||
for (int i = 0; i < command.Commands.Length; ++i)
|
||||
this.m_Commands[command.Commands[i]] = command;
|
||||
}
|
||||
|
||||
public bool CheckObjectTypes(Mobile from, BaseCommand command, Extensions ext, out bool items, out bool mobiles)
|
||||
{
|
||||
items = mobiles = false;
|
||||
|
||||
ObjectConditional cond = ObjectConditional.Empty;
|
||||
|
||||
foreach (BaseExtension check in ext)
|
||||
{
|
||||
if (check is WhereExtension)
|
||||
{
|
||||
cond = (check as WhereExtension).Conditional;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool condIsItem = cond.IsItem;
|
||||
bool condIsMobile = cond.IsMobile;
|
||||
|
||||
switch ( command.ObjectTypes )
|
||||
{
|
||||
case ObjectTypes.All:
|
||||
case ObjectTypes.Both:
|
||||
{
|
||||
if (condIsItem)
|
||||
items = true;
|
||||
|
||||
if (condIsMobile)
|
||||
mobiles = true;
|
||||
|
||||
break;
|
||||
}
|
||||
case ObjectTypes.Items:
|
||||
{
|
||||
if (condIsItem)
|
||||
{
|
||||
items = true;
|
||||
}
|
||||
else if (condIsMobile)
|
||||
{
|
||||
from.SendMessage("You may not use a mobile type condition for this command.");
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ObjectTypes.Mobiles:
|
||||
{
|
||||
if (condIsMobile)
|
||||
{
|
||||
mobiles = true;
|
||||
}
|
||||
else if (condIsItem)
|
||||
{
|
||||
from.SendMessage("You may not use an item type condition for this command.");
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void RunCommand(Mobile from, BaseCommand command, string[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
object obj = null;
|
||||
|
||||
this.Compile(from, command, ref args, ref obj);
|
||||
|
||||
this.RunCommand(from, obj, command, args);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
from.SendMessage(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public string GenerateArgString(string[] args)
|
||||
{
|
||||
if (args.Length == 0)
|
||||
return "";
|
||||
|
||||
// NOTE: this does not preserve the case where quotation marks are used on a single word
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < args.Length; ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
sb.Append(' ');
|
||||
|
||||
if (args[i].IndexOf(' ') >= 0)
|
||||
{
|
||||
sb.Append('"');
|
||||
sb.Append(args[i]);
|
||||
sb.Append('"');
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(args[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public void RunCommand(Mobile from, object obj, BaseCommand command, string[] args)
|
||||
{
|
||||
// try
|
||||
// {
|
||||
CommandEventArgs e = new CommandEventArgs(from, command.Commands[0], this.GenerateArgString(args), args);
|
||||
|
||||
if (!command.ValidateArgs(this, e))
|
||||
return;
|
||||
|
||||
bool flushToLog = false;
|
||||
|
||||
if (obj is ArrayList)
|
||||
{
|
||||
ArrayList list = (ArrayList)obj;
|
||||
|
||||
if (list.Count > 20)
|
||||
CommandLogging.Enabled = false;
|
||||
else if (list.Count == 0)
|
||||
command.LogFailure("Nothing was found to use this command on.");
|
||||
|
||||
command.ExecuteList(e, list);
|
||||
|
||||
if (list.Count > 20)
|
||||
{
|
||||
flushToLog = true;
|
||||
CommandLogging.Enabled = true;
|
||||
}
|
||||
}
|
||||
else if (obj != null)
|
||||
{
|
||||
if (command.ListOptimized)
|
||||
{
|
||||
ArrayList list = new ArrayList();
|
||||
list.Add(obj);
|
||||
command.ExecuteList(e, list);
|
||||
}
|
||||
else
|
||||
{
|
||||
command.Execute(e, obj);
|
||||
}
|
||||
}
|
||||
|
||||
command.Flush(from, flushToLog);
|
||||
// }
|
||||
// catch ( Exception ex )
|
||||
// {
|
||||
// from.SendMessage( ex.Message );
|
||||
// }
|
||||
}
|
||||
|
||||
public virtual void Process(Mobile from, BaseCommand command, string[] args)
|
||||
{
|
||||
this.RunCommand(from, command, args);
|
||||
}
|
||||
|
||||
public virtual void Execute(CommandEventArgs e)
|
||||
{
|
||||
if (e.Length >= 1)
|
||||
{
|
||||
BaseCommand command = null;
|
||||
this.m_Commands.TryGetValue(e.GetString(0), out command);
|
||||
|
||||
if (command == null)
|
||||
{
|
||||
e.Mobile.SendMessage("That is either an invalid command name or one that does not support this modifier.");
|
||||
}
|
||||
else if (e.Mobile.AccessLevel < command.AccessLevel)
|
||||
{
|
||||
e.Mobile.SendMessage("You do not have access to that command.");
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] oldArgs = e.Arguments;
|
||||
string[] args = new string[oldArgs.Length - 1];
|
||||
|
||||
for (int i = 0; i < args.Length; ++i)
|
||||
args[i] = oldArgs[i + 1];
|
||||
|
||||
this.Process(e.Mobile, command, args);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Mobile.SendMessage("You must supply a command name.");
|
||||
}
|
||||
}
|
||||
|
||||
public void Register()
|
||||
{
|
||||
if (this.m_Accessors == null)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < this.m_Accessors.Length; ++i)
|
||||
CommandSystem.Register(this.m_Accessors[i], this.m_AccessLevel, new CommandEventHandler(Execute));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Server.Items;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class ContainedCommandImplementor : BaseCommandImplementor
|
||||
{
|
||||
public ContainedCommandImplementor()
|
||||
{
|
||||
this.Accessors = new string[] { "Contained" };
|
||||
this.SupportRequirement = CommandSupport.Contained;
|
||||
this.AccessLevel = AccessLevel.GameMaster;
|
||||
this.Usage = "Contained <command> [condition]";
|
||||
this.Description = "Invokes the command on all child items in a targeted container. Optional condition arguments can further restrict the set of objects.";
|
||||
}
|
||||
|
||||
public override void Process(Mobile from, BaseCommand command, string[] args)
|
||||
{
|
||||
if (command.ValidateArgs(this, new CommandEventArgs(from, command.Commands[0], this.GenerateArgString(args), args)))
|
||||
from.BeginTarget(-1, command.ObjectTypes == ObjectTypes.All, TargetFlags.None, new TargetStateCallback(OnTarget), new object[] { command, args });
|
||||
}
|
||||
|
||||
public void OnTarget(Mobile from, object targeted, object state)
|
||||
{
|
||||
if (!BaseCommand.IsAccessible(from, targeted))
|
||||
{
|
||||
from.SendMessage("That is not accessible.");
|
||||
return;
|
||||
}
|
||||
|
||||
object[] states = (object[])state;
|
||||
BaseCommand command = (BaseCommand)states[0];
|
||||
string[] args = (string[])states[1];
|
||||
|
||||
if (command.ObjectTypes == ObjectTypes.Mobiles)
|
||||
return; // sanity check
|
||||
|
||||
if (!(targeted is Container))
|
||||
{
|
||||
from.SendMessage("That is not a container.");
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
Extensions ext = Extensions.Parse(from, ref args);
|
||||
|
||||
bool items, mobiles;
|
||||
|
||||
if (!this.CheckObjectTypes(from, command, ext, out items, out mobiles))
|
||||
return;
|
||||
|
||||
if (!items)
|
||||
{
|
||||
from.SendMessage("This command only works on items.");
|
||||
return;
|
||||
}
|
||||
|
||||
Container cont = (Container)targeted;
|
||||
|
||||
Item[] found = cont.FindItemsByType(typeof(Item), true);
|
||||
|
||||
ArrayList list = new ArrayList();
|
||||
|
||||
for (int i = 0; i < found.Length; ++i)
|
||||
{
|
||||
if (ext.IsValid(found[i]))
|
||||
list.Add(found[i]);
|
||||
}
|
||||
|
||||
ext.Filter(list);
|
||||
|
||||
this.RunCommand(from, list, command, args);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
from.SendMessage(e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class FacetCommandImplementor : BaseCommandImplementor
|
||||
{
|
||||
public FacetCommandImplementor()
|
||||
{
|
||||
this.Accessors = new string[] { "Facet" };
|
||||
this.SupportRequirement = CommandSupport.Area;
|
||||
this.SupportsConditionals = true;
|
||||
this.AccessLevel = AccessLevel.GameMaster;
|
||||
this.Usage = "Facet <command> [condition]";
|
||||
this.Description = "Invokes the command on all appropriate objects within your facet's map bounds. Optional condition arguments can further restrict the set of objects.";
|
||||
}
|
||||
|
||||
public override void Process(Mobile from, BaseCommand command, string[] args)
|
||||
{
|
||||
AreaCommandImplementor impl = AreaCommandImplementor.Instance;
|
||||
|
||||
if (impl == null)
|
||||
return;
|
||||
|
||||
Map map = from.Map;
|
||||
|
||||
if (map == null || map == Map.Internal)
|
||||
return;
|
||||
|
||||
impl.OnTarget(from, map, Point3D.Zero, new Point3D(map.Width - 1, map.Height - 1, 0), new object[] { command, args });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class GlobalCommandImplementor : BaseCommandImplementor
|
||||
{
|
||||
public GlobalCommandImplementor()
|
||||
{
|
||||
this.Accessors = new string[] { "Global" };
|
||||
this.SupportRequirement = CommandSupport.Global;
|
||||
this.SupportsConditionals = true;
|
||||
this.AccessLevel = AccessLevel.Administrator;
|
||||
this.Usage = "Global <command> [condition]";
|
||||
this.Description = "Invokes the command on all appropriate objects in the world. Optional condition arguments can further restrict the set of objects.";
|
||||
}
|
||||
|
||||
public override void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
Extensions ext = Extensions.Parse(from, ref args);
|
||||
|
||||
bool items, mobiles;
|
||||
|
||||
if (!this.CheckObjectTypes(from, command, ext, out items, out mobiles))
|
||||
return;
|
||||
|
||||
ArrayList list = new ArrayList();
|
||||
|
||||
if (items)
|
||||
{
|
||||
foreach (Item item in World.Items.Values)
|
||||
{
|
||||
if (ext.IsValid(item))
|
||||
list.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
if (mobiles)
|
||||
{
|
||||
foreach (Mobile mob in World.Mobiles.Values)
|
||||
{
|
||||
if (ext.IsValid(mob))
|
||||
list.Add(mob);
|
||||
}
|
||||
}
|
||||
|
||||
ext.Filter(list);
|
||||
|
||||
obj = list;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
from.SendMessage(ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class IPAddressCommandImplementor : BaseCommandImplementor
|
||||
{
|
||||
public IPAddressCommandImplementor()
|
||||
{
|
||||
this.Accessors = new string[] { "IPAddress" };
|
||||
this.SupportRequirement = CommandSupport.IPAddress;
|
||||
this.SupportsConditionals = true;
|
||||
this.AccessLevel = AccessLevel.Administrator;
|
||||
this.Usage = "IPAddress <command> [condition]";
|
||||
this.Description = "Invokes the command on one mobile from each IP address that is logged in. Optional condition arguments can further restrict the set of objects.";
|
||||
}
|
||||
|
||||
public override void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
Extensions ext = Extensions.Parse(from, ref args);
|
||||
|
||||
bool items, mobiles;
|
||||
|
||||
if (!this.CheckObjectTypes(from, command, ext, out items, out mobiles))
|
||||
return;
|
||||
|
||||
if (!mobiles) // sanity check
|
||||
{
|
||||
command.LogFailure("This command does not support items.");
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayList list = new ArrayList();
|
||||
ArrayList addresses = new ArrayList();
|
||||
|
||||
System.Collections.Generic.List<NetState> states = NetState.Instances;
|
||||
|
||||
for (int i = 0; i < states.Count; ++i)
|
||||
{
|
||||
NetState ns = (NetState)states[i];
|
||||
Mobile mob = ns.Mobile;
|
||||
|
||||
if (mob != null && !addresses.Contains(ns.Address) && ext.IsValid(mob))
|
||||
{
|
||||
list.Add(mob);
|
||||
addresses.Add(ns.Address);
|
||||
}
|
||||
}
|
||||
|
||||
ext.Filter(list);
|
||||
|
||||
obj = list;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
from.SendMessage(ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class MultiCommandImplementor : BaseCommandImplementor
|
||||
{
|
||||
public MultiCommandImplementor()
|
||||
{
|
||||
this.Accessors = new string[] { "Multi", "m" };
|
||||
this.SupportRequirement = CommandSupport.Multi;
|
||||
this.AccessLevel = AccessLevel.Counselor;
|
||||
this.Usage = "Multi <command>";
|
||||
this.Description = "Invokes the command on multiple targeted objects.";
|
||||
}
|
||||
|
||||
public override void Process(Mobile from, BaseCommand command, string[] args)
|
||||
{
|
||||
if (command.ValidateArgs(this, new CommandEventArgs(from, command.Commands[0], this.GenerateArgString(args), args)))
|
||||
from.BeginTarget(-1, command.ObjectTypes == ObjectTypes.All, TargetFlags.None, new TargetStateCallback(OnTarget), new object[] { command, args });
|
||||
}
|
||||
|
||||
public void OnTarget(Mobile from, object targeted, object state)
|
||||
{
|
||||
object[] states = (object[])state;
|
||||
BaseCommand command = (BaseCommand)states[0];
|
||||
string[] args = (string[])states[1];
|
||||
|
||||
if (!BaseCommand.IsAccessible(from, targeted))
|
||||
{
|
||||
from.SendMessage("That is not accessible.");
|
||||
from.BeginTarget(-1, command.ObjectTypes == ObjectTypes.All, TargetFlags.None, new TargetStateCallback(OnTarget), new object[] { command, args });
|
||||
return;
|
||||
}
|
||||
|
||||
switch ( command.ObjectTypes )
|
||||
{
|
||||
case ObjectTypes.Both:
|
||||
{
|
||||
if (!(targeted is Item) && !(targeted is Mobile))
|
||||
{
|
||||
from.SendMessage("This command does not work on that.");
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ObjectTypes.Items:
|
||||
{
|
||||
if (!(targeted is Item))
|
||||
{
|
||||
from.SendMessage("This command only works on items.");
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ObjectTypes.Mobiles:
|
||||
{
|
||||
if (!(targeted is Mobile))
|
||||
{
|
||||
from.SendMessage("This command only works on mobiles.");
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.RunCommand(from, targeted, command, args);
|
||||
|
||||
from.BeginTarget(-1, command.ObjectTypes == ObjectTypes.All, TargetFlags.None, new TargetStateCallback(OnTarget), new object[] { command, args });
|
||||
}
|
||||
}
|
||||
}
|
||||
262
Scripts/Commands/Generic/Implementors/ObjectConditional.cs
Normal file
262
Scripts/Commands/Generic/Implementors/ObjectConditional.cs
Normal file
@@ -0,0 +1,262 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public sealed class ObjectConditional
|
||||
{
|
||||
private static readonly Type typeofItem = typeof(Item);
|
||||
private static readonly Type typeofMobile = typeof(Mobile);
|
||||
|
||||
private readonly Type m_ObjectType;
|
||||
|
||||
private readonly ICondition[][] m_Conditions;
|
||||
|
||||
private IConditional[] m_Conditionals;
|
||||
|
||||
public Type Type
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_ObjectType;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsItem
|
||||
{
|
||||
get
|
||||
{
|
||||
return (this.m_ObjectType == null || this.m_ObjectType == typeofItem || this.m_ObjectType.IsSubclassOf(typeofItem));
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsMobile
|
||||
{
|
||||
get
|
||||
{
|
||||
return (this.m_ObjectType == null || this.m_ObjectType == typeofMobile || this.m_ObjectType.IsSubclassOf(typeofMobile));
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly ObjectConditional Empty = new ObjectConditional(null, null);
|
||||
|
||||
public bool HasCompiled
|
||||
{
|
||||
get
|
||||
{
|
||||
return (this.m_Conditionals != null);
|
||||
}
|
||||
}
|
||||
|
||||
public void Compile(ref AssemblyEmitter emitter)
|
||||
{
|
||||
if (emitter == null)
|
||||
emitter = new AssemblyEmitter("__dynamic", false);
|
||||
|
||||
this.m_Conditionals = new IConditional[this.m_Conditions.Length];
|
||||
|
||||
for (int i = 0; i < this.m_Conditionals.Length; ++i)
|
||||
this.m_Conditionals[i] = ConditionalCompiler.Compile(emitter, this.m_ObjectType, this.m_Conditions[i], i);
|
||||
}
|
||||
|
||||
public bool CheckCondition(object obj)
|
||||
{
|
||||
if (this.m_ObjectType == null)
|
||||
return true; // null type means no condition
|
||||
|
||||
if (!this.HasCompiled)
|
||||
{
|
||||
AssemblyEmitter emitter = null;
|
||||
|
||||
this.Compile(ref emitter);
|
||||
}
|
||||
|
||||
for (int i = 0; i < this.m_Conditionals.Length; ++i)
|
||||
{
|
||||
if (this.m_Conditionals[i].Verify(obj))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false; // all conditions false
|
||||
}
|
||||
|
||||
public static ObjectConditional Parse(Mobile from, ref string[] args)
|
||||
{
|
||||
string[] conditionArgs = null;
|
||||
|
||||
for (int i = 0; i < args.Length; ++i)
|
||||
{
|
||||
if (Insensitive.Equals(args[i], "where"))
|
||||
{
|
||||
string[] origArgs = args;
|
||||
|
||||
args = new string[i];
|
||||
|
||||
for (int j = 0; j < args.Length; ++j)
|
||||
args[j] = origArgs[j];
|
||||
|
||||
conditionArgs = new string[origArgs.Length - i - 1];
|
||||
|
||||
for (int j = 0; j < conditionArgs.Length; ++j)
|
||||
conditionArgs[j] = origArgs[i + j + 1];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ParseDirect(from, conditionArgs, 0, conditionArgs.Length);
|
||||
}
|
||||
|
||||
public static ObjectConditional ParseDirect(Mobile from, string[] args, int offset, int size)
|
||||
{
|
||||
if (args == null || size == 0)
|
||||
return ObjectConditional.Empty;
|
||||
|
||||
int index = 0;
|
||||
|
||||
Type objectType = ScriptCompiler.FindTypeByName(args[offset + index], true);
|
||||
|
||||
if (objectType == null)
|
||||
throw new Exception(String.Format("No type with that name ({0}) was found.", args[offset + index]));
|
||||
|
||||
++index;
|
||||
|
||||
List<ICondition[]> conditions = new List<ICondition[]>();
|
||||
List<ICondition> current = new List<ICondition>();
|
||||
|
||||
current.Add(TypeCondition.Default);
|
||||
|
||||
while (index < size)
|
||||
{
|
||||
string cur = args[offset + index];
|
||||
|
||||
bool inverse = false;
|
||||
|
||||
if (Insensitive.Equals(cur, "not") || cur == "!")
|
||||
{
|
||||
inverse = true;
|
||||
++index;
|
||||
|
||||
if (index >= size)
|
||||
throw new Exception("Improperly formatted object conditional.");
|
||||
}
|
||||
else if (Insensitive.Equals(cur, "or") || cur == "||")
|
||||
{
|
||||
if (current.Count > 1)
|
||||
{
|
||||
conditions.Add(current.ToArray());
|
||||
|
||||
current.Clear();
|
||||
current.Add(TypeCondition.Default);
|
||||
}
|
||||
|
||||
++index;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
string binding = args[offset + index];
|
||||
index++;
|
||||
|
||||
if (index >= size)
|
||||
throw new Exception("Improperly formatted object conditional.");
|
||||
|
||||
string oper = args[offset + index];
|
||||
index++;
|
||||
|
||||
if (index >= size)
|
||||
throw new Exception("Improperly formatted object conditional.");
|
||||
|
||||
string val = args[offset + index];
|
||||
index++;
|
||||
|
||||
Property prop = new Property(binding);
|
||||
|
||||
prop.BindTo(objectType, PropertyAccess.Read);
|
||||
prop.CheckAccess(from);
|
||||
|
||||
ICondition condition = null;
|
||||
|
||||
switch ( oper )
|
||||
{
|
||||
#region Equality
|
||||
case "=":
|
||||
case "==":
|
||||
case "is":
|
||||
condition = new ComparisonCondition(prop, inverse, ComparisonOperator.Equal, val);
|
||||
break;
|
||||
case "!=":
|
||||
condition = new ComparisonCondition(prop, inverse, ComparisonOperator.NotEqual, val);
|
||||
break;
|
||||
#endregion
|
||||
|
||||
#region Relational
|
||||
case ">":
|
||||
condition = new ComparisonCondition(prop, inverse, ComparisonOperator.Greater, val);
|
||||
break;
|
||||
case "<":
|
||||
condition = new ComparisonCondition(prop, inverse, ComparisonOperator.Lesser, val);
|
||||
break;
|
||||
case ">=":
|
||||
condition = new ComparisonCondition(prop, inverse, ComparisonOperator.GreaterEqual, val);
|
||||
break;
|
||||
case "<=":
|
||||
condition = new ComparisonCondition(prop, inverse, ComparisonOperator.LesserEqual, val);
|
||||
break;
|
||||
#endregion
|
||||
|
||||
#region Strings
|
||||
case "==~":
|
||||
case "~==":
|
||||
case "=~":
|
||||
case "~=":
|
||||
case "is~":
|
||||
case "~is":
|
||||
condition = new StringCondition(prop, inverse, StringOperator.Equal, val, true);
|
||||
break;
|
||||
case "!=~":
|
||||
case "~!=":
|
||||
condition = new StringCondition(prop, inverse, StringOperator.NotEqual, val, true);
|
||||
break;
|
||||
case "starts":
|
||||
condition = new StringCondition(prop, inverse, StringOperator.StartsWith, val, false);
|
||||
break;
|
||||
case "starts~":
|
||||
case "~starts":
|
||||
condition = new StringCondition(prop, inverse, StringOperator.StartsWith, val, true);
|
||||
break;
|
||||
case "ends":
|
||||
condition = new StringCondition(prop, inverse, StringOperator.EndsWith, val, false);
|
||||
break;
|
||||
case "ends~":
|
||||
case "~ends":
|
||||
condition = new StringCondition(prop, inverse, StringOperator.EndsWith, val, true);
|
||||
break;
|
||||
case "contains":
|
||||
condition = new StringCondition(prop, inverse, StringOperator.Contains, val, false);
|
||||
break;
|
||||
case "contains~":
|
||||
case "~contains":
|
||||
condition = new StringCondition(prop, inverse, StringOperator.Contains, val, true);
|
||||
break;
|
||||
#endregion
|
||||
}
|
||||
|
||||
if (condition == null)
|
||||
throw new InvalidOperationException(String.Format("Unrecognized operator (\"{0}\").", oper));
|
||||
|
||||
current.Add(condition);
|
||||
}
|
||||
|
||||
conditions.Add(current.ToArray());
|
||||
|
||||
return new ObjectConditional(objectType, conditions.ToArray());
|
||||
}
|
||||
|
||||
public ObjectConditional(Type objectType, ICondition[][] conditions)
|
||||
{
|
||||
this.m_ObjectType = objectType;
|
||||
this.m_Conditions = conditions;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class OnlineCommandImplementor : BaseCommandImplementor
|
||||
{
|
||||
public OnlineCommandImplementor()
|
||||
{
|
||||
this.Accessors = new string[] { "Online" };
|
||||
this.SupportRequirement = CommandSupport.Online;
|
||||
this.SupportsConditionals = true;
|
||||
this.AccessLevel = AccessLevel.GameMaster;
|
||||
this.Usage = "Online <command> [condition]";
|
||||
this.Description = "Invokes the command on all mobiles that are currently logged in. Optional condition arguments can further restrict the set of objects.";
|
||||
}
|
||||
|
||||
public override void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
Extensions ext = Extensions.Parse(from, ref args);
|
||||
|
||||
bool items, mobiles;
|
||||
|
||||
if (!this.CheckObjectTypes(from, command, ext, out items, out mobiles))
|
||||
return;
|
||||
|
||||
if (!mobiles) // sanity check
|
||||
{
|
||||
command.LogFailure("This command does not support items.");
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayList list = new ArrayList();
|
||||
|
||||
List<NetState> states = NetState.Instances;
|
||||
|
||||
for (int i = 0; i < states.Count; ++i)
|
||||
{
|
||||
NetState ns = states[i];
|
||||
Mobile mob = ns.Mobile;
|
||||
|
||||
if (mob == null)
|
||||
continue;
|
||||
|
||||
if (!BaseCommand.IsAccessible(from, mob))
|
||||
continue;
|
||||
|
||||
if (ext.IsValid(mob))
|
||||
list.Add(mob);
|
||||
}
|
||||
|
||||
ext.Filter(list);
|
||||
|
||||
obj = list;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
from.SendMessage(ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class RangeCommandImplementor : BaseCommandImplementor
|
||||
{
|
||||
private static RangeCommandImplementor m_Instance;
|
||||
public RangeCommandImplementor()
|
||||
{
|
||||
this.Accessors = new string[] { "Range" };
|
||||
this.SupportRequirement = CommandSupport.Area;
|
||||
this.SupportsConditionals = true;
|
||||
this.AccessLevel = AccessLevel.GameMaster;
|
||||
this.Usage = "Range <range> <command> [condition]";
|
||||
this.Description = "Invokes the command on all appropriate objects within a specified range of you. Optional condition arguments can further restrict the set of objects.";
|
||||
|
||||
m_Instance = this;
|
||||
}
|
||||
|
||||
public static RangeCommandImplementor Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Instance;
|
||||
}
|
||||
}
|
||||
public override void Execute(CommandEventArgs e)
|
||||
{
|
||||
if (e.Length >= 2)
|
||||
{
|
||||
int range = e.GetInt32(0);
|
||||
|
||||
if (range < 0)
|
||||
{
|
||||
e.Mobile.SendMessage("The range must not be negative.");
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseCommand command = null;
|
||||
this.Commands.TryGetValue(e.GetString(1), out command);
|
||||
|
||||
if (command == null)
|
||||
{
|
||||
e.Mobile.SendMessage("That is either an invalid command name or one that does not support this modifier.");
|
||||
}
|
||||
else if (e.Mobile.AccessLevel < command.AccessLevel)
|
||||
{
|
||||
e.Mobile.SendMessage("You do not have access to that command.");
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] oldArgs = e.Arguments;
|
||||
string[] args = new string[oldArgs.Length - 2];
|
||||
|
||||
for (int i = 0; i < args.Length; ++i)
|
||||
args[i] = oldArgs[i + 2];
|
||||
|
||||
this.Process(range, e.Mobile, command, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Mobile.SendMessage("You must supply a range and a command name.");
|
||||
}
|
||||
}
|
||||
|
||||
public void Process(int range, Mobile from, BaseCommand command, string[] args)
|
||||
{
|
||||
AreaCommandImplementor impl = AreaCommandImplementor.Instance;
|
||||
|
||||
if (impl == null)
|
||||
return;
|
||||
|
||||
Map map = from.Map;
|
||||
|
||||
if (map == null || map == Map.Internal)
|
||||
return;
|
||||
|
||||
Point3D start = new Point3D(from.X - range, from.Y - range, from.Z);
|
||||
Point3D end = new Point3D(from.X + range, from.Y + range, from.Z);
|
||||
|
||||
impl.OnTarget(from, map, start, end, new object[] { command, args });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class RegionCommandImplementor : BaseCommandImplementor
|
||||
{
|
||||
public RegionCommandImplementor()
|
||||
{
|
||||
this.Accessors = new string[] { "Region" };
|
||||
this.SupportRequirement = CommandSupport.Region;
|
||||
this.SupportsConditionals = true;
|
||||
this.AccessLevel = AccessLevel.GameMaster;
|
||||
this.Usage = "Region <command> [condition]";
|
||||
this.Description = "Invokes the command on all appropriate mobiles in your current region. Optional condition arguments can further restrict the set of objects.";
|
||||
}
|
||||
|
||||
public override void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
Extensions ext = Extensions.Parse(from, ref args);
|
||||
|
||||
bool items, mobiles;
|
||||
|
||||
if (!this.CheckObjectTypes(from, command, ext, out items, out mobiles))
|
||||
return;
|
||||
|
||||
Region reg = from.Region;
|
||||
|
||||
ArrayList list = new ArrayList();
|
||||
|
||||
if (mobiles)
|
||||
{
|
||||
foreach (Mobile mob in reg.GetMobiles())
|
||||
{
|
||||
if (!BaseCommand.IsAccessible(from, mob))
|
||||
continue;
|
||||
|
||||
if (ext.IsValid(mob))
|
||||
list.Add(mob);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
command.LogFailure("This command does not support items.");
|
||||
return;
|
||||
}
|
||||
|
||||
ext.Filter(list);
|
||||
|
||||
obj = list;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
from.SendMessage(ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class ScreenCommandImplementor : BaseCommandImplementor
|
||||
{
|
||||
public ScreenCommandImplementor()
|
||||
{
|
||||
this.Accessors = new string[] { "Screen" };
|
||||
this.SupportRequirement = CommandSupport.Area;
|
||||
this.SupportsConditionals = true;
|
||||
this.AccessLevel = AccessLevel.GameMaster;
|
||||
this.Usage = "Screen <command> [condition]";
|
||||
this.Description = "Invokes the command on all appropriate objects in your screen. Optional condition arguments can further restrict the set of objects.";
|
||||
}
|
||||
|
||||
public override void Process(Mobile from, BaseCommand command, string[] args)
|
||||
{
|
||||
RangeCommandImplementor impl = RangeCommandImplementor.Instance;
|
||||
|
||||
if (impl == null)
|
||||
return;
|
||||
|
||||
impl.Process(18, from, command, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class SelfCommandImplementor : BaseCommandImplementor
|
||||
{
|
||||
public SelfCommandImplementor()
|
||||
{
|
||||
this.Accessors = new string[] { "Self" };
|
||||
this.SupportRequirement = CommandSupport.Self;
|
||||
this.AccessLevel = AccessLevel.Counselor;
|
||||
this.Usage = "Self <command>";
|
||||
this.Description = "Invokes the command on the commanding player.";
|
||||
}
|
||||
|
||||
public override void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj)
|
||||
{
|
||||
if (command.ObjectTypes == ObjectTypes.Items)
|
||||
return; // sanity check
|
||||
|
||||
obj = from;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class SerialCommandImplementor : BaseCommandImplementor
|
||||
{
|
||||
public SerialCommandImplementor()
|
||||
{
|
||||
this.Accessors = new string[] { "Serial" };
|
||||
this.SupportRequirement = CommandSupport.Single;
|
||||
this.AccessLevel = AccessLevel.Counselor;
|
||||
this.Usage = "Serial <serial> <command>";
|
||||
this.Description = "Invokes the command on a single object by serial.";
|
||||
}
|
||||
|
||||
public override void Execute(CommandEventArgs e)
|
||||
{
|
||||
if (e.Length >= 2)
|
||||
{
|
||||
Serial serial = e.GetInt32(0);
|
||||
|
||||
object obj = null;
|
||||
|
||||
if (serial.IsItem)
|
||||
obj = World.FindItem(serial);
|
||||
else if (serial.IsMobile)
|
||||
obj = World.FindMobile(serial);
|
||||
|
||||
if (obj == null)
|
||||
{
|
||||
e.Mobile.SendMessage("That is not a valid serial.");
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseCommand command = null;
|
||||
this.Commands.TryGetValue(e.GetString(1), out command);
|
||||
|
||||
if (command == null)
|
||||
{
|
||||
e.Mobile.SendMessage("That is either an invalid command name or one that does not support this modifier.");
|
||||
}
|
||||
else if (e.Mobile.AccessLevel < command.AccessLevel)
|
||||
{
|
||||
e.Mobile.SendMessage("You do not have access to that command.");
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ( command.ObjectTypes )
|
||||
{
|
||||
case ObjectTypes.Both:
|
||||
{
|
||||
if (!(obj is Item) && !(obj is Mobile))
|
||||
{
|
||||
e.Mobile.SendMessage("This command does not work on that.");
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ObjectTypes.Items:
|
||||
{
|
||||
if (!(obj is Item))
|
||||
{
|
||||
e.Mobile.SendMessage("This command only works on items.");
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ObjectTypes.Mobiles:
|
||||
{
|
||||
if (!(obj is Mobile))
|
||||
{
|
||||
e.Mobile.SendMessage("This command only works on mobiles.");
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
string[] oldArgs = e.Arguments;
|
||||
string[] args = new string[oldArgs.Length - 2];
|
||||
|
||||
for (int i = 0; i < args.Length; ++i)
|
||||
args[i] = oldArgs[i + 2];
|
||||
|
||||
this.RunCommand(e.Mobile, obj, command, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Mobile.SendMessage("You must supply an object serial and a command name.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using System;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class SingleCommandImplementor : BaseCommandImplementor
|
||||
{
|
||||
public SingleCommandImplementor()
|
||||
{
|
||||
Accessors = new string[] { "Single" };
|
||||
SupportRequirement = CommandSupport.Single;
|
||||
AccessLevel = AccessLevel.Counselor;
|
||||
Usage = "Single <command>";
|
||||
Description = "Invokes the command on a single targeted object. This is the same as just invoking the command directly.";
|
||||
}
|
||||
|
||||
public override void Register(BaseCommand command)
|
||||
{
|
||||
base.Register(command);
|
||||
|
||||
for (int i = 0; i < command.Commands.Length; ++i)
|
||||
CommandSystem.Register(command.Commands[i], command.AccessLevel, new CommandEventHandler(Redirect));
|
||||
}
|
||||
|
||||
public void Redirect(CommandEventArgs e)
|
||||
{
|
||||
BaseCommand command = null;
|
||||
|
||||
this.Commands.TryGetValue(e.Command, out command);
|
||||
|
||||
if (command == null)
|
||||
e.Mobile.SendMessage("That is either an invalid command name or one that does not support this modifier.");
|
||||
else if (e.Mobile.AccessLevel < command.AccessLevel)
|
||||
e.Mobile.SendMessage("You do not have access to that command.");
|
||||
else if (command.ValidateArgs(this, e))
|
||||
this.Process(e.Mobile, command, e.Arguments);
|
||||
}
|
||||
|
||||
public override void Process(Mobile from, BaseCommand command, string[] args)
|
||||
{
|
||||
if (command.ValidateArgs(this, new CommandEventArgs(from, command.Commands[0], this.GenerateArgString(args), args)))
|
||||
from.BeginTarget(-1, command.ObjectTypes == ObjectTypes.All, TargetFlags.None, new TargetStateCallback(OnTarget), new object[] { command, args });
|
||||
}
|
||||
|
||||
public void OnTarget(Mobile from, object targeted, object state)
|
||||
{
|
||||
if (!BaseCommand.IsAccessible(from, targeted))
|
||||
{
|
||||
from.SendLocalizedMessage(500447); // That is not accessible.
|
||||
return;
|
||||
}
|
||||
|
||||
object[] states = (object[])state;
|
||||
BaseCommand command = (BaseCommand)states[0];
|
||||
string[] args = (string[])states[1];
|
||||
|
||||
switch ( command.ObjectTypes )
|
||||
{
|
||||
case ObjectTypes.Both:
|
||||
{
|
||||
if (!(targeted is Item) && !(targeted is Mobile))
|
||||
{
|
||||
from.SendMessage("This command does not work on that.");
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ObjectTypes.Items:
|
||||
{
|
||||
if (!(targeted is Item))
|
||||
{
|
||||
from.SendMessage("This command only works on items.");
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ObjectTypes.Mobiles:
|
||||
{
|
||||
if (!(targeted is Mobile))
|
||||
{
|
||||
from.SendMessage("This command only works on mobiles.");
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.RunCommand(from, targeted, command, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user