#W# Initial Commit: Avatars Conquest
This commit is contained in:
commit
8eae46895e
7512 changed files with 416187 additions and 0 deletions
205
Scripts/Commands/Generic/Commands/BaseCommand.cs
Normal file
205
Scripts/Commands/Generic/Commands/BaseCommand.cs
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using Server;
|
||||
using Server.Gumps;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public enum ObjectTypes
|
||||
{
|
||||
Both,
|
||||
Items,
|
||||
Mobiles,
|
||||
All
|
||||
}
|
||||
|
||||
public abstract class BaseCommand
|
||||
{
|
||||
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 bool ListOptimized
|
||||
{
|
||||
get{ return m_ListOptimized; }
|
||||
set{ m_ListOptimized = value; }
|
||||
}
|
||||
|
||||
public string[] Commands
|
||||
{
|
||||
get{ return m_Commands; }
|
||||
set{ m_Commands = value; }
|
||||
}
|
||||
|
||||
public string Usage
|
||||
{
|
||||
get{ return m_Usage; }
|
||||
set{ m_Usage = value; }
|
||||
}
|
||||
|
||||
public string Description
|
||||
{
|
||||
get{ return m_Description; }
|
||||
set{ m_Description = value; }
|
||||
}
|
||||
|
||||
public AccessLevel AccessLevel
|
||||
{
|
||||
get{ return m_AccessLevel; }
|
||||
set{ m_AccessLevel = value; }
|
||||
}
|
||||
|
||||
public ObjectTypes ObjectTypes
|
||||
{
|
||||
get{ return m_ObjectTypes; }
|
||||
set{ m_ObjectTypes = value; }
|
||||
}
|
||||
|
||||
public CommandSupport Supports
|
||||
{
|
||||
get{ return m_Implementors; }
|
||||
set{ m_Implementors = value; }
|
||||
}
|
||||
|
||||
public BaseCommand()
|
||||
{
|
||||
m_Responses = new ArrayList();
|
||||
m_Failures = new ArrayList();
|
||||
}
|
||||
|
||||
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 )
|
||||
Execute( e, list[i] );
|
||||
}
|
||||
|
||||
public virtual void Execute( CommandEventArgs e, object obj )
|
||||
{
|
||||
}
|
||||
|
||||
public virtual bool ValidateArgs( BaseCommandImplementor impl, CommandEventArgs e )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private ArrayList m_Responses, m_Failures;
|
||||
|
||||
private class MessageEntry
|
||||
{
|
||||
public string m_Message;
|
||||
public int m_Count;
|
||||
|
||||
public MessageEntry( string message )
|
||||
{
|
||||
m_Message = message;
|
||||
m_Count = 1;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if ( m_Count > 1 )
|
||||
return String.Format( "{0} ({1})", m_Message, m_Count );
|
||||
|
||||
return m_Message;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddResponse( string message )
|
||||
{
|
||||
for ( int i = 0; i < m_Responses.Count; ++i )
|
||||
{
|
||||
MessageEntry entry = (MessageEntry)m_Responses[i];
|
||||
|
||||
if ( entry.m_Message == message )
|
||||
{
|
||||
++entry.m_Count;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_Responses.Count == 10 )
|
||||
return;
|
||||
|
||||
m_Responses.Add( new MessageEntry( message ) );
|
||||
}
|
||||
|
||||
public void AddResponse( Gump gump )
|
||||
{
|
||||
m_Responses.Add( gump );
|
||||
}
|
||||
|
||||
public void LogFailure( string message )
|
||||
{
|
||||
for ( int i = 0; i < m_Failures.Count; ++i )
|
||||
{
|
||||
MessageEntry entry = (MessageEntry)m_Failures[i];
|
||||
|
||||
if ( entry.m_Message == message )
|
||||
{
|
||||
++entry.m_Count;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_Failures.Count == 10 )
|
||||
return;
|
||||
|
||||
m_Failures.Add( new MessageEntry( message ) );
|
||||
}
|
||||
|
||||
public void Flush( Mobile from, bool flushToLog )
|
||||
{
|
||||
if ( m_Responses.Count > 0 )
|
||||
{
|
||||
for ( int i = 0; i < m_Responses.Count; ++i )
|
||||
{
|
||||
object obj = 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 < m_Failures.Count; ++i )
|
||||
from.SendMessage( ((MessageEntry)m_Failures[i]).ToString() );
|
||||
}
|
||||
|
||||
m_Responses.Clear();
|
||||
m_Failures.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
1039
Scripts/Commands/Generic/Commands/Commands.cs
Normal file
1039
Scripts/Commands/Generic/Commands/Commands.cs
Normal file
File diff suppressed because it is too large
Load diff
570
Scripts/Commands/Generic/Commands/Interface.cs
Normal file
570
Scripts/Commands/Generic/Commands/Interface.cs
Normal file
|
|
@ -0,0 +1,570 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Server;
|
||||
using Server.Gumps;
|
||||
using Server.Network;
|
||||
using Server.Targeting;
|
||||
using Server.Targets;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class InterfaceCommand : BaseCommand
|
||||
{
|
||||
public InterfaceCommand()
|
||||
{
|
||||
AccessLevel = AccessLevel.GameMaster;
|
||||
Supports = CommandSupport.Complex | CommandSupport.Simple;
|
||||
Commands = new string[]{ "Interface" };
|
||||
ObjectTypes = ObjectTypes.Both;
|
||||
Usage = "Interface [view <properties ...>]";
|
||||
Description = "Opens an interface to interact with matched objects. Generally used with condition arguments.";
|
||||
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
|
||||
{
|
||||
AddResponse( "No matching objects found." );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class InterfaceGump : BaseGridGump
|
||||
{
|
||||
private Mobile m_From;
|
||||
|
||||
private string[] m_Columns;
|
||||
|
||||
private ArrayList m_List;
|
||||
private int m_Page;
|
||||
|
||||
private object m_Select;
|
||||
|
||||
private const int EntriesPerPage = 15;
|
||||
|
||||
public InterfaceGump( Mobile from, string[] columns, ArrayList list, int page, object select ) : base( 30, 30 )
|
||||
{
|
||||
m_From = from;
|
||||
|
||||
m_Columns = columns;
|
||||
|
||||
m_List = list;
|
||||
m_Page = page;
|
||||
|
||||
m_Select = select;
|
||||
|
||||
Render();
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
AddNewPage();
|
||||
|
||||
if ( m_Page > 0 )
|
||||
AddEntryButton( 20, ArrowLeftID1, ArrowLeftID2, 1, ArrowLeftWidth, ArrowLeftHeight );
|
||||
else
|
||||
AddEntryHeader( 20 );
|
||||
|
||||
AddEntryHtml( 40 + ( m_Columns.Length * 130 ) - 20 + ( ( m_Columns.Length - 2 ) * OffsetSize ), Center( String.Format( "Page {0} of {1}", m_Page+1, (m_List.Count + EntriesPerPage - 1) / EntriesPerPage ) ) );
|
||||
|
||||
if ( (m_Page + 1) * EntriesPerPage < m_List.Count )
|
||||
AddEntryButton( 20, ArrowRightID1, ArrowRightID2, 2, ArrowRightWidth, ArrowRightHeight );
|
||||
else
|
||||
AddEntryHeader( 20 );
|
||||
|
||||
if ( m_Columns.Length > 1 )
|
||||
{
|
||||
AddNewLine();
|
||||
|
||||
for ( int i = 0; i < m_Columns.Length; ++i )
|
||||
{
|
||||
if ( i > 0 && m_List.Count > 0 )
|
||||
{
|
||||
object obj = m_List[0];
|
||||
|
||||
if ( obj != null )
|
||||
{
|
||||
string failReason = null;
|
||||
PropertyInfo[] chain = Properties.GetPropertyInfoChain( m_From, obj.GetType(), m_Columns[i], PropertyAccess.Read, ref failReason );
|
||||
|
||||
if ( chain != null && chain.Length > 0 )
|
||||
{
|
||||
m_Columns[i] = "";
|
||||
|
||||
for ( int j = 0; j < chain.Length; ++j )
|
||||
{
|
||||
if ( j > 0 )
|
||||
m_Columns[i] += '.';
|
||||
|
||||
m_Columns[i] += chain[j].Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AddEntryHtml( 130 + ( i == 0 ? 40 : 0 ), m_Columns[i] );
|
||||
}
|
||||
|
||||
AddEntryHeader( 20 );
|
||||
}
|
||||
|
||||
for ( int i = m_Page * EntriesPerPage, line = 0; line < EntriesPerPage && i < m_List.Count; ++i, ++line )
|
||||
{
|
||||
AddNewLine();
|
||||
|
||||
object obj = m_List[i];
|
||||
bool isDeleted = false;
|
||||
|
||||
if ( obj is Item )
|
||||
{
|
||||
Item item = (Item)obj;
|
||||
|
||||
if ( !(isDeleted = item.Deleted) )
|
||||
AddEntryHtml( 40 + 130, item.GetType().Name );
|
||||
}
|
||||
else if ( obj is Mobile )
|
||||
{
|
||||
Mobile mob = (Mobile)obj;
|
||||
|
||||
if ( !(isDeleted = mob.Deleted) )
|
||||
AddEntryHtml( 40 + 130, mob.Name );
|
||||
}
|
||||
|
||||
if ( isDeleted )
|
||||
{
|
||||
AddEntryHtml( 40 + 130, "(deleted)" );
|
||||
|
||||
for ( int j = 1; j < m_Columns.Length; ++j )
|
||||
AddEntryHtml( 130, "---" );
|
||||
|
||||
AddEntryHeader( 20 );
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( int j = 1; j < m_Columns.Length; ++j )
|
||||
{
|
||||
object src = obj;
|
||||
|
||||
string value;
|
||||
string failReason = "";
|
||||
|
||||
PropertyInfo[] chain = Properties.GetPropertyInfoChain( m_From, src.GetType(), 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 );
|
||||
}
|
||||
|
||||
AddEntryHtml( 130, value );
|
||||
}
|
||||
|
||||
bool isSelected = ( m_Select != null && obj == m_Select );
|
||||
|
||||
AddEntryButton( 20, ( isSelected ? 9762 : ArrowRightID1 ), ( isSelected ? 9763 : ArrowRightID2 ), 3 + i, ArrowRightWidth, ArrowRightHeight );
|
||||
}
|
||||
}
|
||||
|
||||
FinishPage();
|
||||
}
|
||||
|
||||
public override void OnResponse( NetState sender, RelayInfo info )
|
||||
{
|
||||
switch ( info.ButtonID )
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
if ( m_Page > 0 )
|
||||
m_From.SendGump( new InterfaceGump( m_From, m_Columns, m_List, m_Page - 1, m_Select ) );
|
||||
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
if ( (m_Page + 1) * EntriesPerPage < m_List.Count )
|
||||
m_From.SendGump( new InterfaceGump( m_From, m_Columns, m_List, m_Page + 1, m_Select ) );
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
int v = info.ButtonID - 3;
|
||||
|
||||
if ( v >= 0 && v < m_List.Count )
|
||||
{
|
||||
object obj = m_List[v];
|
||||
|
||||
if ( !BaseCommand.IsAccessible( m_From, obj ) )
|
||||
{
|
||||
m_From.SendMessage( "That is not accessible." );
|
||||
m_From.SendGump( new InterfaceGump( m_From, m_Columns, m_List, m_Page, m_Select ) );
|
||||
break;
|
||||
}
|
||||
|
||||
if ( obj is Item && !((Item)obj).Deleted )
|
||||
m_From.SendGump( new InterfaceItemGump( m_From, m_Columns, m_List, m_Page, (Item) obj ) );
|
||||
else if ( obj is Mobile && !((Mobile)obj).Deleted )
|
||||
m_From.SendGump( new InterfaceMobileGump( m_From, m_Columns, m_List, m_Page, (Mobile) obj ) );
|
||||
else
|
||||
m_From.SendGump( new InterfaceGump( m_From, m_Columns, m_List, m_Page, m_Select ) );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class InterfaceItemGump : BaseGridGump
|
||||
{
|
||||
private Mobile m_From;
|
||||
|
||||
private string[] m_Columns;
|
||||
|
||||
private ArrayList m_List;
|
||||
private int m_Page;
|
||||
|
||||
private Item m_Item;
|
||||
|
||||
public InterfaceItemGump( Mobile from, string[] columns, ArrayList list, int page, Item item ) : base( 30, 30 )
|
||||
{
|
||||
m_From = from;
|
||||
|
||||
m_Columns = columns;
|
||||
|
||||
m_List = list;
|
||||
m_Page = page;
|
||||
|
||||
m_Item = item;
|
||||
|
||||
Render();
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
AddNewPage();
|
||||
|
||||
AddEntryButton( 20, ArrowLeftID1, ArrowLeftID2, 1, ArrowLeftWidth, ArrowLeftHeight );
|
||||
AddEntryHtml( 160, m_Item.GetType().Name );
|
||||
AddEntryHeader( 20 );
|
||||
|
||||
AddNewLine();
|
||||
AddEntryHtml( 20 + OffsetSize + 160, "Properties" );
|
||||
AddEntryButton( 20, ArrowRightID1, ArrowRightID2, 2, ArrowRightWidth, ArrowRightHeight );
|
||||
|
||||
AddNewLine();
|
||||
AddEntryHtml( 20 + OffsetSize + 160, "Delete" );
|
||||
AddEntryButton( 20, ArrowRightID1, ArrowRightID2, 3, ArrowRightWidth, ArrowRightHeight );
|
||||
|
||||
AddNewLine();
|
||||
AddEntryHtml( 20 + OffsetSize + 160, "Go there" );
|
||||
AddEntryButton( 20, ArrowRightID1, ArrowRightID2, 4, ArrowRightWidth, ArrowRightHeight );
|
||||
|
||||
AddNewLine();
|
||||
AddEntryHtml( 20 + OffsetSize + 160, "Move to target" );
|
||||
AddEntryButton( 20, ArrowRightID1, ArrowRightID2, 5, ArrowRightWidth, ArrowRightHeight );
|
||||
|
||||
AddNewLine();
|
||||
AddEntryHtml( 20 + OffsetSize + 160, "Bring to pack" );
|
||||
AddEntryButton( 20, ArrowRightID1, ArrowRightID2, 6, ArrowRightWidth, ArrowRightHeight );
|
||||
|
||||
FinishPage();
|
||||
}
|
||||
|
||||
private void InvokeCommand( string ip )
|
||||
{
|
||||
CommandSystem.Handle( m_From, String.Format( "{0}{1}", CommandSystem.Prefix, ip ) );
|
||||
}
|
||||
|
||||
public override void OnResponse( NetState sender, RelayInfo info )
|
||||
{
|
||||
if ( m_Item.Deleted )
|
||||
{
|
||||
m_From.SendGump( new InterfaceGump( m_From, m_Columns, m_List, m_Page, m_Item ) );
|
||||
return;
|
||||
}
|
||||
else if ( !BaseCommand.IsAccessible( m_From, m_Item ) )
|
||||
{
|
||||
m_From.SendMessage( "That is no longer accessible." );
|
||||
m_From.SendGump( new InterfaceGump( m_From, m_Columns, m_List, m_Page, m_Item ) );
|
||||
return;
|
||||
}
|
||||
|
||||
switch ( info.ButtonID )
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
{
|
||||
m_From.SendGump( new InterfaceGump( m_From, m_Columns, m_List, m_Page, m_Item ) );
|
||||
break;
|
||||
}
|
||||
case 2: // Properties
|
||||
{
|
||||
m_From.SendGump( new InterfaceItemGump( m_From, m_Columns, m_List, m_Page, m_Item ) );
|
||||
m_From.SendGump( new PropertiesGump( m_From, m_Item ) );
|
||||
break;
|
||||
}
|
||||
case 3: // Delete
|
||||
{
|
||||
CommandLogging.WriteLine( m_From, "{0} {1} deleting {2}", m_From.AccessLevel, CommandLogging.Format( m_From ), CommandLogging.Format( m_Item ) );
|
||||
m_Item.Delete();
|
||||
m_From.SendGump( new InterfaceGump( m_From, m_Columns, m_List, m_Page, m_Item ) );
|
||||
break;
|
||||
}
|
||||
case 4: // Go there
|
||||
{
|
||||
m_From.SendGump( new InterfaceItemGump( m_From, m_Columns, m_List, m_Page, m_Item ) );
|
||||
InvokeCommand( String.Format( "Go {0}", m_Item.Serial.Value ) );
|
||||
break;
|
||||
}
|
||||
case 5: // Move to target
|
||||
{
|
||||
m_From.SendGump( new InterfaceItemGump( m_From, m_Columns, m_List, m_Page, m_Item ) );
|
||||
m_From.Target = new MoveTarget( m_Item );
|
||||
break;
|
||||
}
|
||||
case 6: // Bring to pack
|
||||
{
|
||||
Mobile owner = m_Item.RootParent as Mobile;
|
||||
|
||||
if ( owner != null && (owner.Map != null && owner.Map != Map.Internal) && !BaseCommand.IsAccessible( m_From, owner ) /* !m_From.CanSee( owner )*/ )
|
||||
{
|
||||
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 >= m_From.AccessLevel )
|
||||
{
|
||||
m_From.SendMessage( "You can not get what you can not see." );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_From.SendGump( new InterfaceItemGump( m_From, m_Columns, m_List, m_Page, m_Item ) );
|
||||
m_From.AddToBackpack( m_Item );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class InterfaceMobileGump : BaseGridGump
|
||||
{
|
||||
private Mobile m_From;
|
||||
|
||||
private string[] m_Columns;
|
||||
|
||||
private ArrayList m_List;
|
||||
private int m_Page;
|
||||
|
||||
private Mobile m_Mobile;
|
||||
|
||||
public InterfaceMobileGump( Mobile from, string[] columns, ArrayList list, int page, Mobile mob )
|
||||
: base( 30, 30 )
|
||||
{
|
||||
m_From = from;
|
||||
|
||||
m_Columns = columns;
|
||||
|
||||
m_List = list;
|
||||
m_Page = page;
|
||||
|
||||
m_Mobile = mob;
|
||||
|
||||
Render();
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
AddNewPage();
|
||||
|
||||
AddEntryButton( 20, ArrowLeftID1, ArrowLeftID2, 1, ArrowLeftWidth, ArrowLeftHeight );
|
||||
AddEntryHtml( 160, m_Mobile.Name );
|
||||
AddEntryHeader( 20 );
|
||||
|
||||
AddNewLine();
|
||||
AddEntryHtml( 20 + OffsetSize + 160, "Properties" );
|
||||
AddEntryButton( 20, ArrowRightID1, ArrowRightID2, 2, ArrowRightWidth, ArrowRightHeight );
|
||||
|
||||
if ( !m_Mobile.Player )
|
||||
{
|
||||
AddNewLine();
|
||||
AddEntryHtml( 20 + OffsetSize + 160, "Delete" );
|
||||
AddEntryButton( 20, ArrowRightID1, ArrowRightID2, 3, ArrowRightWidth, ArrowRightHeight );
|
||||
}
|
||||
|
||||
if ( m_Mobile != m_From )
|
||||
{
|
||||
AddNewLine();
|
||||
AddEntryHtml( 20 + OffsetSize + 160, "Go to there" );
|
||||
AddEntryButton( 20, ArrowRightID1, ArrowRightID2, 4, ArrowRightWidth, ArrowRightHeight );
|
||||
|
||||
AddNewLine();
|
||||
AddEntryHtml( 20 + OffsetSize + 160, "Bring them here" );
|
||||
AddEntryButton( 20, ArrowRightID1, ArrowRightID2, 5, ArrowRightWidth, ArrowRightHeight );
|
||||
}
|
||||
|
||||
AddNewLine();
|
||||
AddEntryHtml( 20 + OffsetSize + 160, "Move to target" );
|
||||
AddEntryButton( 20, ArrowRightID1, ArrowRightID2, 6, ArrowRightWidth, ArrowRightHeight );
|
||||
|
||||
if ( m_From == m_Mobile || m_From.AccessLevel > m_Mobile.AccessLevel )
|
||||
{
|
||||
AddNewLine();
|
||||
if ( m_Mobile.Alive )
|
||||
{
|
||||
AddEntryHtml( 20 + OffsetSize + 160, "Kill" );
|
||||
AddEntryButton( 20, ArrowRightID1, ArrowRightID2, 7, ArrowRightWidth, ArrowRightHeight );
|
||||
}
|
||||
else
|
||||
{
|
||||
AddEntryHtml( 20 + OffsetSize + 160, "Resurrect" );
|
||||
AddEntryButton( 20, ArrowRightID1, ArrowRightID2, 8, ArrowRightWidth, ArrowRightHeight );
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_Mobile.NetState != null )
|
||||
{
|
||||
AddNewLine();
|
||||
AddEntryHtml( 20 + OffsetSize + 160, "Client" );
|
||||
AddEntryButton( 20, ArrowRightID1, ArrowRightID2, 9, ArrowRightWidth, ArrowRightHeight );
|
||||
}
|
||||
|
||||
FinishPage();
|
||||
}
|
||||
|
||||
private void InvokeCommand( string ip )
|
||||
{
|
||||
CommandSystem.Handle( m_From, String.Format( "{0}{1}", CommandSystem.Prefix, ip ) );
|
||||
}
|
||||
|
||||
public override void OnResponse( NetState sender, RelayInfo info )
|
||||
{
|
||||
if ( m_Mobile.Deleted )
|
||||
{
|
||||
m_From.SendGump( new InterfaceGump( m_From, m_Columns, m_List, m_Page, m_Mobile ) );
|
||||
return;
|
||||
}
|
||||
else if ( !BaseCommand.IsAccessible( m_From, m_Mobile ) )
|
||||
{
|
||||
m_From.SendMessage( "That is no longer accessible." );
|
||||
m_From.SendGump( new InterfaceGump( m_From, m_Columns, m_List, m_Page, m_Mobile ) );
|
||||
return;
|
||||
}
|
||||
|
||||
switch ( info.ButtonID )
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
{
|
||||
m_From.SendGump( new InterfaceGump( m_From, m_Columns, m_List, m_Page, m_Mobile ) );
|
||||
break;
|
||||
}
|
||||
case 2: // Properties
|
||||
{
|
||||
m_From.SendGump( new InterfaceMobileGump( m_From, m_Columns, m_List, m_Page, m_Mobile ) );
|
||||
m_From.SendGump( new PropertiesGump( m_From, m_Mobile ) );
|
||||
break;
|
||||
}
|
||||
case 3: // Delete
|
||||
{
|
||||
if ( !m_Mobile.Player )
|
||||
{
|
||||
CommandLogging.WriteLine( m_From, "{0} {1} deleting {2}", m_From.AccessLevel, CommandLogging.Format( m_From ), CommandLogging.Format( m_Mobile ) );
|
||||
m_Mobile.Delete();
|
||||
m_From.SendGump( new InterfaceGump( m_From, m_Columns, m_List, m_Page, m_Mobile ) );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 4: // Go there
|
||||
{
|
||||
m_From.SendGump( new InterfaceMobileGump( m_From, m_Columns, m_List, m_Page, m_Mobile ) );
|
||||
InvokeCommand( String.Format( "Go {0}", m_Mobile.Serial.Value ) );
|
||||
break;
|
||||
}
|
||||
case 5: // Bring them here
|
||||
{
|
||||
if ( m_From.Map == null || m_From.Map == Map.Internal )
|
||||
{
|
||||
m_From.SendMessage( "You cannot bring that person here." );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_From.SendGump( new InterfaceMobileGump( m_From, m_Columns, m_List, m_Page, m_Mobile ) );
|
||||
m_Mobile.MoveToWorld( m_From.Location, m_From.Map );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 6: // Move to target
|
||||
{
|
||||
m_From.SendGump( new InterfaceMobileGump( m_From, m_Columns, m_List, m_Page, m_Mobile ) );
|
||||
m_From.Target = new MoveTarget( m_Mobile );
|
||||
break;
|
||||
}
|
||||
case 7: // Kill
|
||||
{
|
||||
if ( m_From == m_Mobile || m_From.AccessLevel > m_Mobile.AccessLevel )
|
||||
m_Mobile.Kill();
|
||||
|
||||
m_From.SendGump( new InterfaceMobileGump( m_From, m_Columns, m_List, m_Page, m_Mobile ) );
|
||||
|
||||
break;
|
||||
}
|
||||
case 8: // Res
|
||||
{
|
||||
if ( m_From == m_Mobile || m_From.AccessLevel > m_Mobile.AccessLevel )
|
||||
{
|
||||
m_Mobile.PlaySound( 0x214 );
|
||||
m_Mobile.FixedEffect( 0x376A, 10, 16 );
|
||||
|
||||
m_Mobile.Resurrect();
|
||||
}
|
||||
|
||||
m_From.SendGump( new InterfaceMobileGump( m_From, m_Columns, m_List, m_Page, m_Mobile ) );
|
||||
|
||||
break;
|
||||
}
|
||||
case 9: // Client
|
||||
{
|
||||
m_From.SendGump( new InterfaceMobileGump( m_From, m_Columns, m_List, m_Page, m_Mobile ) );
|
||||
|
||||
if ( m_Mobile.NetState != null )
|
||||
m_From.SendGump( new ClientGump( m_From, m_Mobile.NetState ) );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
184
Scripts/Commands/Generic/Extensions/BaseExtension.cs
Normal file
184
Scripts/Commands/Generic/Extensions/BaseExtension.cs
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public delegate BaseExtension ExtensionConstructor();
|
||||
|
||||
public sealed class ExtensionInfo
|
||||
{
|
||||
private static Dictionary<string, ExtensionInfo> m_Table = new Dictionary<string, ExtensionInfo>( StringComparer.InvariantCultureIgnoreCase );
|
||||
|
||||
public static Dictionary<string, ExtensionInfo> Table
|
||||
{
|
||||
get { return m_Table; }
|
||||
}
|
||||
|
||||
public static void Register( ExtensionInfo ext )
|
||||
{
|
||||
m_Table[ext.m_Name] = ext;
|
||||
}
|
||||
|
||||
private int m_Order;
|
||||
|
||||
private string m_Name;
|
||||
private int m_Size;
|
||||
|
||||
private ExtensionConstructor m_Constructor;
|
||||
|
||||
public int Order
|
||||
{
|
||||
get { return m_Order; }
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return m_Name; }
|
||||
}
|
||||
|
||||
public int Size
|
||||
{
|
||||
get { return m_Size; }
|
||||
}
|
||||
|
||||
public bool IsFixedSize
|
||||
{
|
||||
get { return ( m_Size >= 0 ); }
|
||||
}
|
||||
|
||||
public ExtensionConstructor Constructor
|
||||
{
|
||||
get { return m_Constructor; }
|
||||
}
|
||||
|
||||
public ExtensionInfo( int order, string name, int size, ExtensionConstructor constructor )
|
||||
{
|
||||
m_Name = name;
|
||||
m_Size = size;
|
||||
|
||||
m_Order = order;
|
||||
|
||||
m_Constructor = constructor;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Extensions : List<BaseExtension>
|
||||
{
|
||||
public Extensions()
|
||||
{
|
||||
}
|
||||
|
||||
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 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 abstract class BaseExtension
|
||||
{
|
||||
public abstract ExtensionInfo Info { get; }
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return Info.Name; }
|
||||
}
|
||||
|
||||
public int Size
|
||||
{
|
||||
get { return Info.Size; }
|
||||
}
|
||||
|
||||
public bool IsFixedSize
|
||||
{
|
||||
get { return Info.IsFixedSize; }
|
||||
}
|
||||
|
||||
public int Order
|
||||
{
|
||||
get { return 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,569 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Text;
|
||||
using Server;
|
||||
|
||||
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 Type m_Type;
|
||||
private object m_Value;
|
||||
private FieldInfo m_Field;
|
||||
|
||||
public Type Type
|
||||
{
|
||||
get { return m_Type; }
|
||||
}
|
||||
|
||||
public object Value
|
||||
{
|
||||
get { return m_Value; }
|
||||
}
|
||||
|
||||
public FieldInfo Field
|
||||
{
|
||||
get { return m_Field; }
|
||||
}
|
||||
|
||||
public bool HasField
|
||||
{
|
||||
get { return ( m_Field != null ); }
|
||||
}
|
||||
|
||||
public PropertyValue( Type type, object value )
|
||||
{
|
||||
m_Type = type;
|
||||
m_Value = value;
|
||||
}
|
||||
|
||||
public void Load( MethodEmitter method )
|
||||
{
|
||||
if ( m_Field != null )
|
||||
{
|
||||
method.LoadArgument( 0 );
|
||||
method.LoadField( m_Field );
|
||||
}
|
||||
else if ( m_Value == null )
|
||||
{
|
||||
method.LoadNull( m_Type );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_Value is int )
|
||||
method.Load( (int) m_Value );
|
||||
else if ( m_Value is long )
|
||||
method.Load( (long) m_Value );
|
||||
else if ( m_Value is float )
|
||||
method.Load( (float) m_Value );
|
||||
else if ( m_Value is double )
|
||||
method.Load( (double) m_Value );
|
||||
else if ( m_Value is char )
|
||||
method.Load( (char) m_Value );
|
||||
else if ( m_Value is bool )
|
||||
method.Load( (bool) m_Value );
|
||||
else if ( m_Value is string )
|
||||
method.Load( (string) m_Value );
|
||||
else if ( m_Value is Enum )
|
||||
method.Load( (Enum) m_Value );
|
||||
else
|
||||
throw new InvalidOperationException( "Unrecognized comparison value." );
|
||||
}
|
||||
}
|
||||
|
||||
public void Acquire( TypeBuilder typeBuilder, ILGenerator il, string fieldName )
|
||||
{
|
||||
if ( m_Value is string )
|
||||
{
|
||||
string toParse = (string) m_Value;
|
||||
|
||||
if ( !m_Type.IsValueType && toParse == "null" )
|
||||
{
|
||||
m_Value = null;
|
||||
}
|
||||
else if ( m_Type == typeof( string ) )
|
||||
{
|
||||
if ( toParse == @"@""null""" )
|
||||
toParse = "null";
|
||||
|
||||
m_Value = toParse;
|
||||
}
|
||||
else if ( m_Type.IsEnum )
|
||||
{
|
||||
m_Value = Enum.Parse( m_Type, toParse, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
MethodInfo parseMethod = null;
|
||||
object[] parseArgs = null;
|
||||
|
||||
MethodInfo parseNumber = 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 = m_Type.GetMethod(
|
||||
"Parse",
|
||||
BindingFlags.Public | BindingFlags.Static,
|
||||
null,
|
||||
new Type[] { typeof( string ) },
|
||||
null
|
||||
);
|
||||
|
||||
parseMethod = parseGeneral;
|
||||
parseArgs = new object[] { toParse };
|
||||
}
|
||||
|
||||
if ( parseMethod != null )
|
||||
{
|
||||
m_Value = parseMethod.Invoke( null, parseArgs );
|
||||
|
||||
if ( !m_Type.IsPrimitive )
|
||||
{
|
||||
m_Field = typeBuilder.DefineField(
|
||||
fieldName,
|
||||
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, m_Field );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
String.Format(
|
||||
"Unable to convert string \"{0}\" into type '{1}'.",
|
||||
m_Value,
|
||||
m_Type
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class PropertyCondition : ICondition
|
||||
{
|
||||
protected Property m_Property;
|
||||
protected bool m_Not;
|
||||
|
||||
public PropertyCondition( Property property, bool not )
|
||||
{
|
||||
m_Property = property;
|
||||
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 StringOperator m_Operator;
|
||||
private PropertyValue m_Value;
|
||||
|
||||
private bool m_IgnoreCase;
|
||||
|
||||
public StringCondition( Property property, bool not, StringOperator op, object value, bool ignoreCase )
|
||||
: base( property, not )
|
||||
{
|
||||
m_Operator = op;
|
||||
m_Value = new PropertyValue( property.Type, value );
|
||||
|
||||
m_IgnoreCase = ignoreCase;
|
||||
}
|
||||
|
||||
public override void Construct( TypeBuilder typeBuilder, ILGenerator il, int index )
|
||||
{
|
||||
m_Value.Acquire( typeBuilder, il, "v" + index );
|
||||
}
|
||||
|
||||
public override void Compile( MethodEmitter emitter )
|
||||
{
|
||||
bool inverse = false;
|
||||
|
||||
string methodName;
|
||||
|
||||
switch ( 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 ( m_IgnoreCase || methodName == "Equals" )
|
||||
{
|
||||
Type type = ( 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( m_Property );
|
||||
m_Value.Load( emitter );
|
||||
|
||||
emitter.FinishCall();
|
||||
}
|
||||
else
|
||||
{
|
||||
Label notNull = emitter.CreateLabel();
|
||||
Label moveOn = emitter.CreateLabel();
|
||||
|
||||
LocalBuilder temp = emitter.AcquireTemp( m_Property.Type );
|
||||
|
||||
emitter.Chain( 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
|
||||
)
|
||||
);
|
||||
|
||||
m_Value.Load( emitter );
|
||||
|
||||
emitter.FinishCall();
|
||||
|
||||
emitter.MarkLabel( moveOn );
|
||||
}
|
||||
|
||||
if ( m_Not != inverse )
|
||||
emitter.LogicalNot();
|
||||
}
|
||||
}
|
||||
|
||||
public enum ComparisonOperator
|
||||
{
|
||||
Equal,
|
||||
NotEqual,
|
||||
Greater,
|
||||
GreaterEqual,
|
||||
Lesser,
|
||||
LesserEqual
|
||||
}
|
||||
|
||||
public sealed class ComparisonCondition : PropertyCondition
|
||||
{
|
||||
private ComparisonOperator m_Operator;
|
||||
private PropertyValue m_Value;
|
||||
|
||||
public ComparisonCondition( Property property, bool not, ComparisonOperator op, object value )
|
||||
: base( property, not )
|
||||
{
|
||||
m_Operator = op;
|
||||
m_Value = new PropertyValue( property.Type, value );
|
||||
}
|
||||
|
||||
public override void Construct( TypeBuilder typeBuilder, ILGenerator il, int index )
|
||||
{
|
||||
m_Value.Acquire( typeBuilder, il, "v" + index );
|
||||
}
|
||||
|
||||
public override void Compile( MethodEmitter emitter )
|
||||
{
|
||||
emitter.Chain( m_Property );
|
||||
|
||||
bool inverse = false;
|
||||
|
||||
bool couldCompare =
|
||||
emitter.CompareTo( 1, delegate()
|
||||
{
|
||||
m_Value.Load( emitter );
|
||||
} );
|
||||
|
||||
if ( couldCompare )
|
||||
{
|
||||
emitter.Load( 0 );
|
||||
|
||||
switch ( 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
|
||||
|
||||
m_Value.Load( emitter );
|
||||
|
||||
switch ( 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 ( 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,249 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Text;
|
||||
using Server;
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
172
Scripts/Commands/Generic/Extensions/Compilers/SortCompiler.cs
Normal file
172
Scripts/Commands/Generic/Extensions/Compilers/SortCompiler.cs
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Text;
|
||||
using Server;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public sealed class OrderInfo
|
||||
{
|
||||
private Property m_Property;
|
||||
private int m_Order;
|
||||
|
||||
public Property Property
|
||||
{
|
||||
get { return m_Property; }
|
||||
set { m_Property = value; }
|
||||
}
|
||||
|
||||
public bool IsAscending
|
||||
{
|
||||
get { return ( m_Order > 0 ); }
|
||||
set { m_Order = ( value ? +1 : -1 ); }
|
||||
}
|
||||
|
||||
public bool IsDescending
|
||||
{
|
||||
get { return ( m_Order < 0 ); }
|
||||
set { m_Order = ( value ? -1 : +1 ); }
|
||||
}
|
||||
|
||||
public int Sign
|
||||
{
|
||||
get { return Math.Sign( m_Order ); }
|
||||
set
|
||||
{
|
||||
m_Order = Math.Sign( value );
|
||||
|
||||
if ( m_Order == 0 )
|
||||
throw new InvalidOperationException( "Sign cannot be zero." );
|
||||
}
|
||||
}
|
||||
|
||||
public OrderInfo( Property property, bool isAscending )
|
||||
{
|
||||
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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
89
Scripts/Commands/Generic/Extensions/DistinctExtension.cs
Normal file
89
Scripts/Commands/Generic/Extensions/DistinctExtension.cs
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public sealed class DistinctExtension : BaseExtension
|
||||
{
|
||||
public static ExtensionInfo ExtInfo = new ExtensionInfo( 30, "Distinct", -1, delegate() { return new DistinctExtension(); } );
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
ExtensionInfo.Register( ExtInfo );
|
||||
}
|
||||
|
||||
public override ExtensionInfo Info
|
||||
{
|
||||
get { return ExtInfo; }
|
||||
}
|
||||
|
||||
private List<Property> m_Properties;
|
||||
|
||||
private IComparer m_Comparer;
|
||||
|
||||
public DistinctExtension()
|
||||
{
|
||||
m_Properties = new List<Property>();
|
||||
}
|
||||
|
||||
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 m_Properties )
|
||||
{
|
||||
prop.BindTo( baseType, PropertyAccess.Read );
|
||||
prop.CheckAccess( from );
|
||||
}
|
||||
|
||||
if ( assembly == null )
|
||||
assembly = new AssemblyEmitter( "__dynamic", false );
|
||||
|
||||
m_Comparer = DistinctCompiler.Compile( assembly, baseType, 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++];
|
||||
|
||||
m_Properties.Add( new Property( binding ) );
|
||||
}
|
||||
}
|
||||
|
||||
public override void Filter( ArrayList list )
|
||||
{
|
||||
if ( m_Comparer == null )
|
||||
throw new InvalidOperationException( "The extension must first be optimized." );
|
||||
|
||||
ArrayList copy = new ArrayList( list );
|
||||
|
||||
copy.Sort( m_Comparer );
|
||||
|
||||
list.Clear();
|
||||
|
||||
object last = null;
|
||||
|
||||
for ( int i = 0; i < copy.Count; ++i )
|
||||
{
|
||||
object obj = copy[i];
|
||||
|
||||
if ( last == null || m_Comparer.Compare( obj, last ) != 0 )
|
||||
{
|
||||
list.Add( obj );
|
||||
last = obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
46
Scripts/Commands/Generic/Extensions/LimitExtension.cs
Normal file
46
Scripts/Commands/Generic/Extensions/LimitExtension.cs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public sealed class LimitExtension : BaseExtension
|
||||
{
|
||||
public static ExtensionInfo ExtInfo = new ExtensionInfo( 80, "Limit", 1, delegate() { return new LimitExtension(); } );
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
ExtensionInfo.Register( ExtInfo );
|
||||
}
|
||||
|
||||
public override ExtensionInfo Info
|
||||
{
|
||||
get { return ExtInfo; }
|
||||
}
|
||||
|
||||
private int m_Limit;
|
||||
|
||||
public int Limit
|
||||
{
|
||||
get { return m_Limit; }
|
||||
}
|
||||
|
||||
public LimitExtension()
|
||||
{
|
||||
}
|
||||
|
||||
public override void Parse( Mobile from, string[] arguments, int offset, int size )
|
||||
{
|
||||
m_Limit = Utility.ToInt32( arguments[offset] );
|
||||
|
||||
if ( m_Limit < 0 )
|
||||
throw new Exception( "Limit cannot be less than zero." );
|
||||
}
|
||||
|
||||
public override void Filter( ArrayList list )
|
||||
{
|
||||
if ( list.Count > m_Limit )
|
||||
list.RemoveRange( m_Limit, list.Count - m_Limit );
|
||||
}
|
||||
}
|
||||
}
|
||||
109
Scripts/Commands/Generic/Extensions/SortExtension.cs
Normal file
109
Scripts/Commands/Generic/Extensions/SortExtension.cs
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public sealed class SortExtension : BaseExtension
|
||||
{
|
||||
public static ExtensionInfo ExtInfo = new ExtensionInfo( 40, "Order", -1, delegate() { return new SortExtension(); } );
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
ExtensionInfo.Register( ExtInfo );
|
||||
}
|
||||
|
||||
public override ExtensionInfo Info
|
||||
{
|
||||
get { return ExtInfo; }
|
||||
}
|
||||
|
||||
private List<OrderInfo> m_Orders;
|
||||
|
||||
private IComparer m_Comparer;
|
||||
|
||||
public SortExtension()
|
||||
{
|
||||
m_Orders = new List<OrderInfo>();
|
||||
}
|
||||
|
||||
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 m_Orders )
|
||||
{
|
||||
order.Property.BindTo( baseType, PropertyAccess.Read );
|
||||
order.Property.CheckAccess( from );
|
||||
}
|
||||
|
||||
if ( assembly == null )
|
||||
assembly = new AssemblyEmitter( "__dynamic", false );
|
||||
|
||||
m_Comparer = SortCompiler.Compile( assembly, baseType, 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 );
|
||||
|
||||
m_Orders.Add( new OrderInfo( property, isAscending ) );
|
||||
}
|
||||
}
|
||||
|
||||
public override void Filter( ArrayList list )
|
||||
{
|
||||
if ( m_Comparer == null )
|
||||
throw new InvalidOperationException( "The extension must first be optimized." );
|
||||
|
||||
list.Sort( m_Comparer );
|
||||
}
|
||||
}
|
||||
}
|
||||
55
Scripts/Commands/Generic/Extensions/WhereExtension.cs
Normal file
55
Scripts/Commands/Generic/Extensions/WhereExtension.cs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Server.Commands;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public sealed class WhereExtension : BaseExtension
|
||||
{
|
||||
public static ExtensionInfo ExtInfo = new ExtensionInfo( 20, "Where", -1, delegate() { return new WhereExtension(); } );
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
ExtensionInfo.Register( ExtInfo );
|
||||
}
|
||||
|
||||
public override ExtensionInfo Info
|
||||
{
|
||||
get { return ExtInfo; }
|
||||
}
|
||||
|
||||
private ObjectConditional m_Conditional;
|
||||
|
||||
public ObjectConditional Conditional
|
||||
{
|
||||
get { return m_Conditional; }
|
||||
}
|
||||
|
||||
public WhereExtension()
|
||||
{
|
||||
}
|
||||
|
||||
public override void Optimize( Mobile from, Type baseType, ref AssemblyEmitter assembly )
|
||||
{
|
||||
if ( baseType == null )
|
||||
throw new InvalidOperationException( "Insanity." );
|
||||
|
||||
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." );
|
||||
|
||||
m_Conditional = ObjectConditional.ParseDirect( from, arguments, offset, size );
|
||||
}
|
||||
|
||||
public override bool IsValid( object obj )
|
||||
{
|
||||
return m_Conditional.CheckCondition( obj );
|
||||
}
|
||||
}
|
||||
}
|
||||
128
Scripts/Commands/Generic/Implementors/AreaCommandImplementor.cs
Normal file
128
Scripts/Commands/Generic/Implementors/AreaCommandImplementor.cs
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using Server;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class AreaCommandImplementor : BaseCommandImplementor
|
||||
{
|
||||
public AreaCommandImplementor()
|
||||
{
|
||||
Accessors = new string[]{ "Area", "Group" };
|
||||
SupportRequirement = CommandSupport.Area;
|
||||
SupportsConditionals = true;
|
||||
AccessLevel = AccessLevel.GameMaster;
|
||||
Usage = "Area <command> [condition]";
|
||||
Description = "Invokes the command on all appropriate objects in a targeted area. Optional condition arguments can further restrict the set of objects.";
|
||||
}
|
||||
|
||||
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 ( !CheckObjectTypes( 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 );
|
||||
|
||||
RunCommand( from, objs, command, args );
|
||||
}
|
||||
catch ( Exception ex )
|
||||
{
|
||||
from.SendMessage( ex.Message );
|
||||
}
|
||||
}
|
||||
|
||||
public void OnTarget( Mobile from, object targeted, object state )
|
||||
{
|
||||
try
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
RunCommand( from, targeted, command, args );
|
||||
|
||||
from.BeginTarget( -1, command.ObjectTypes == ObjectTypes.All, TargetFlags.None, new TargetStateCallback( OnTarget ), new object[]{ command, args } );
|
||||
}
|
||||
catch ( Exception ex )
|
||||
{
|
||||
from.SendMessage( ex.Message );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
338
Scripts/Commands/Generic/Implementors/BaseCommandImplementor.cs
Normal file
338
Scripts/Commands/Generic/Implementors/BaseCommandImplementor.cs
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Server;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
[Flags]
|
||||
public enum CommandSupport
|
||||
{
|
||||
Single = 0x0001,
|
||||
Global = 0x0002,
|
||||
Online = 0x0004,
|
||||
Multi = 0x0008,
|
||||
Area = 0x0010,
|
||||
Self = 0x0020,
|
||||
Region = 0x0040,
|
||||
Contained = 0x0080,
|
||||
|
||||
All = Single | Global | Online | Multi | Area | Self | Region | Contained,
|
||||
AllMobiles = All & ~Contained,
|
||||
AllNPCs = All & ~(Online | Self | Contained),
|
||||
AllItems = All & ~(Online | Self | Region),
|
||||
|
||||
Simple = Single | Multi,
|
||||
Complex = Global | Online | Area | Region | Contained
|
||||
}
|
||||
|
||||
public abstract class BaseCommandImplementor
|
||||
{
|
||||
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() );
|
||||
}
|
||||
|
||||
private string[] m_Accessors;
|
||||
private AccessLevel m_AccessLevel;
|
||||
private CommandSupport m_SupportRequirement;
|
||||
private Dictionary<string, BaseCommand> m_Commands;
|
||||
private string m_Usage;
|
||||
private string m_Description;
|
||||
private bool m_SupportsConditionals;
|
||||
|
||||
public bool SupportsConditionals
|
||||
{
|
||||
get{ return m_SupportsConditionals; }
|
||||
set{ m_SupportsConditionals = value; }
|
||||
}
|
||||
|
||||
public string[] Accessors
|
||||
{
|
||||
get{ return m_Accessors; }
|
||||
set{ m_Accessors = value; }
|
||||
}
|
||||
|
||||
public string Usage
|
||||
{
|
||||
get{ return m_Usage; }
|
||||
set{ m_Usage = value; }
|
||||
}
|
||||
|
||||
public string Description
|
||||
{
|
||||
get{ return m_Description; }
|
||||
set{ m_Description = value; }
|
||||
}
|
||||
|
||||
public AccessLevel AccessLevel
|
||||
{
|
||||
get{ return m_AccessLevel; }
|
||||
set{ m_AccessLevel = value; }
|
||||
}
|
||||
|
||||
public CommandSupport SupportRequirement
|
||||
{
|
||||
get{ return m_SupportRequirement; }
|
||||
set{ m_SupportRequirement = value; }
|
||||
}
|
||||
|
||||
public Dictionary<string, BaseCommand> Commands
|
||||
{
|
||||
get{ return m_Commands; }
|
||||
}
|
||||
|
||||
public BaseCommandImplementor()
|
||||
{
|
||||
m_Commands = new Dictionary<string, BaseCommand>( StringComparer.OrdinalIgnoreCase );
|
||||
}
|
||||
|
||||
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 )
|
||||
m_Commands[command.Commands[i]] = command;
|
||||
}
|
||||
|
||||
public bool CheckObjectTypes( 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 )
|
||||
{
|
||||
command.LogFailure( "You may not use a mobile type condition for this command." );
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ObjectTypes.Mobiles:
|
||||
{
|
||||
if ( condIsMobile )
|
||||
{
|
||||
mobiles = true;
|
||||
}
|
||||
else if ( condIsItem )
|
||||
{
|
||||
command.LogFailure( "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;
|
||||
|
||||
Compile( from, command, ref args, ref obj );
|
||||
|
||||
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], 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 )
|
||||
{
|
||||
RunCommand( from, command, args );
|
||||
}
|
||||
|
||||
public virtual void Execute( CommandEventArgs e )
|
||||
{
|
||||
if ( e.Length >= 1 )
|
||||
{
|
||||
BaseCommand command = null;
|
||||
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];
|
||||
|
||||
Process( e.Mobile, command, args );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Mobile.SendMessage( "You must supply a command name." );
|
||||
}
|
||||
}
|
||||
|
||||
public void Register()
|
||||
{
|
||||
if ( m_Accessors == null )
|
||||
return;
|
||||
|
||||
for ( int i = 0; i < m_Accessors.Length; ++i )
|
||||
CommandSystem.Register( m_Accessors[i], m_AccessLevel, new CommandEventHandler( Execute ) );
|
||||
}
|
||||
|
||||
public static void Register( BaseCommandImplementor impl )
|
||||
{
|
||||
m_Implementors.Add( impl );
|
||||
impl.Register();
|
||||
}
|
||||
|
||||
private static List<BaseCommandImplementor> m_Implementors;
|
||||
|
||||
public static List<BaseCommandImplementor> Implementors
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( m_Implementors == null )
|
||||
{
|
||||
m_Implementors = new List<BaseCommandImplementor>();
|
||||
RegisterImplementors();
|
||||
}
|
||||
|
||||
return m_Implementors;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using Server;
|
||||
using Server.Items;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class ContainedCommandImplementor : BaseCommandImplementor
|
||||
{
|
||||
public ContainedCommandImplementor()
|
||||
{
|
||||
Accessors = new string[]{ "Contained" };
|
||||
SupportRequirement = CommandSupport.Contained;
|
||||
AccessLevel = AccessLevel.GameMaster;
|
||||
Usage = "Contained <command> [condition]";
|
||||
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], 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 ( !CheckObjectTypes( 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 );
|
||||
|
||||
RunCommand( from, list, command, args );
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
from.SendMessage( e.Message );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using Server;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class GlobalCommandImplementor : BaseCommandImplementor
|
||||
{
|
||||
public GlobalCommandImplementor()
|
||||
{
|
||||
Accessors = new string[]{ "Global" };
|
||||
SupportRequirement = CommandSupport.Global;
|
||||
SupportsConditionals = true;
|
||||
AccessLevel = AccessLevel.Administrator;
|
||||
Usage = "Global <command> [condition]";
|
||||
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 ( !CheckObjectTypes( 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,77 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using Server;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class MultiCommandImplementor : BaseCommandImplementor
|
||||
{
|
||||
public MultiCommandImplementor()
|
||||
{
|
||||
Accessors = new string[]{ "Multi", "m" };
|
||||
SupportRequirement = CommandSupport.Multi;
|
||||
AccessLevel = AccessLevel.Counselor;
|
||||
Usage = "Multi <command>";
|
||||
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], 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;
|
||||
}
|
||||
}
|
||||
|
||||
RunCommand( from, targeted, command, args );
|
||||
|
||||
from.BeginTarget( -1, command.ObjectTypes == ObjectTypes.All, TargetFlags.None, new TargetStateCallback( OnTarget ), new object[]{ command, args } );
|
||||
}
|
||||
}
|
||||
}
|
||||
266
Scripts/Commands/Generic/Implementors/ObjectConditional.cs
Normal file
266
Scripts/Commands/Generic/Implementors/ObjectConditional.cs
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Server;
|
||||
using Server.Targeting;
|
||||
using CPA = Server.CommandPropertyAttribute;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public sealed class ObjectConditional
|
||||
{
|
||||
private static readonly Type typeofItem = typeof( Item );
|
||||
private static readonly Type typeofMobile = typeof( Mobile );
|
||||
|
||||
private Type m_ObjectType;
|
||||
|
||||
private ICondition[][] m_Conditions;
|
||||
|
||||
private IConditional[] m_Conditionals;
|
||||
|
||||
public Type Type
|
||||
{
|
||||
get { return m_ObjectType; }
|
||||
}
|
||||
|
||||
public bool IsItem
|
||||
{
|
||||
get { return ( m_ObjectType == null || m_ObjectType == typeofItem || m_ObjectType.IsSubclassOf( typeofItem ) ); }
|
||||
}
|
||||
|
||||
public bool IsMobile
|
||||
{
|
||||
get { return ( m_ObjectType == null || m_ObjectType == typeofMobile || m_ObjectType.IsSubclassOf( typeofMobile ) ); }
|
||||
}
|
||||
|
||||
public static readonly ObjectConditional Empty = new ObjectConditional( null, null );
|
||||
|
||||
public bool HasCompiled
|
||||
{
|
||||
get { return ( m_Conditionals != null ); }
|
||||
}
|
||||
|
||||
public void Compile( ref AssemblyEmitter emitter )
|
||||
{
|
||||
if ( emitter == null )
|
||||
emitter = new AssemblyEmitter( "__dynamic", false );
|
||||
|
||||
m_Conditionals = new IConditional[m_Conditions.Length];
|
||||
|
||||
for ( int i = 0; i < m_Conditionals.Length; ++i )
|
||||
m_Conditionals[i] = ConditionalCompiler.Compile( emitter, m_ObjectType, m_Conditions[i], i );
|
||||
}
|
||||
|
||||
public bool CheckCondition( object obj )
|
||||
{
|
||||
if ( m_ObjectType == null )
|
||||
return true; // null type means no condition
|
||||
|
||||
if ( !HasCompiled )
|
||||
{
|
||||
AssemblyEmitter emitter = null;
|
||||
|
||||
Compile( ref emitter );
|
||||
}
|
||||
|
||||
for ( int i = 0; i < m_Conditionals.Length; ++i )
|
||||
{
|
||||
if ( 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 ( conditions.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 )
|
||||
{
|
||||
m_ObjectType = objectType;
|
||||
m_Conditions = conditions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Server;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class OnlineCommandImplementor : BaseCommandImplementor
|
||||
{
|
||||
public OnlineCommandImplementor()
|
||||
{
|
||||
Accessors = new string[]{ "Online" };
|
||||
SupportRequirement = CommandSupport.Online;
|
||||
SupportsConditionals = true;
|
||||
AccessLevel = AccessLevel.GameMaster;
|
||||
Usage = "Online <command> [condition]";
|
||||
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 ( !CheckObjectTypes( command, ext, out items, out mobiles ) )
|
||||
return;
|
||||
|
||||
if ( !mobiles ) // sanity check
|
||||
{
|
||||
command.LogFailure( "This command does not support mobiles." );
|
||||
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,61 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using Server;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class RegionCommandImplementor : BaseCommandImplementor
|
||||
{
|
||||
public RegionCommandImplementor()
|
||||
{
|
||||
Accessors = new string[]{ "Region" };
|
||||
SupportRequirement = CommandSupport.Region;
|
||||
SupportsConditionals = true;
|
||||
AccessLevel = AccessLevel.GameMaster;
|
||||
Usage = "Region <command> [condition]";
|
||||
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 ( !CheckObjectTypes( 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;
|
||||
using System.Collections;
|
||||
using Server;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class SelfCommandImplementor : BaseCommandImplementor
|
||||
{
|
||||
public SelfCommandImplementor()
|
||||
{
|
||||
Accessors = new string[]{ "Self" };
|
||||
SupportRequirement = CommandSupport.Self;
|
||||
AccessLevel = AccessLevel.Counselor;
|
||||
Usage = "Self <command>";
|
||||
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,67 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using Server;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Commands.Generic
|
||||
{
|
||||
public class SerialCommandImplementor : BaseCommandImplementor
|
||||
{
|
||||
public SerialCommandImplementor()
|
||||
{
|
||||
Accessors = new string[]{ "Serial" };
|
||||
SupportRequirement = CommandSupport.Single;
|
||||
AccessLevel = AccessLevel.Counselor;
|
||||
Usage = "Serial <serial> <command>";
|
||||
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;
|
||||
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];
|
||||
|
||||
RunCommand( e.Mobile, obj, command, args );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Mobile.SendMessage( "You must supply an object serial and a command name." );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using Server;
|
||||
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;
|
||||
|
||||
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 ) )
|
||||
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], 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];
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
RunCommand( from, targeted, command, args );
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue