PageRenderTime 53ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/Scripts/Commands/Handlers.cs

https://bitbucket.org/Kel/crepuscule
C# | 1257 lines | 955 code | 235 blank | 67 comment | 206 complexity | f59e2e5b437676a95124126c5d747e92 MD5 | raw file
  1. using System;
  2. using System.IO;
  3. using Server;
  4. using System.Text;
  5. using System.Collections;
  6. using System.Net;
  7. using Server.Accounting;
  8. using Server.Mobiles;
  9. using Server.Items;
  10. using Server.Menus;
  11. using Server.Menus.Questions;
  12. using Server.Menus.ItemLists;
  13. using Server.Network;
  14. using Server.Spells;
  15. using Server.Targeting;
  16. using Server.Targets;
  17. using Server.Gumps;
  18. using System.Collections.Generic;
  19. using System.Linq;
  20. using Server.Engines;
  21. namespace Server.Scripts.Commands
  22. {
  23. public class CommandHandlers
  24. {
  25. public static void Configure()
  26. {
  27. Server.Commands.CommandPrefix = ".";
  28. Server.Commands.BadCommandIgnoreLevel = AccessLevel.Player;
  29. }
  30. public static void Initialize()
  31. {
  32. Properties.Register();
  33. Register( "Go", AccessLevel.Counselor, new CommandEventHandler( Go_OnCommand ) );
  34. Register( "DropHolding", AccessLevel.Counselor, new CommandEventHandler( DropHolding_OnCommand ) );
  35. Register( "GetFollowers", AccessLevel.GameMaster, new CommandEventHandler( GetFollowers_OnCommand ) );
  36. Register( "ShaveHair", AccessLevel.GameMaster, new CommandEventHandler( ShaveHair_OnCommand ) );
  37. Register( "ShaveBeard", AccessLevel.GameMaster, new CommandEventHandler( ShaveBeard_OnCommand ) );
  38. Register( "Where", AccessLevel.Counselor, new CommandEventHandler( Where_OnCommand ) );
  39. Register( "AutoPageNotify", AccessLevel.Counselor, new CommandEventHandler( APN_OnCommand ) );
  40. Register( "APN", AccessLevel.Counselor, new CommandEventHandler( APN_OnCommand ) );
  41. Register( "Animate", AccessLevel.GameMaster, new CommandEventHandler( Animate_OnCommand ) );
  42. Register( "Cast", AccessLevel.Counselor, new CommandEventHandler( Cast_OnCommand ) );
  43. Register( "Stuck", AccessLevel.Counselor, new CommandEventHandler( Stuck_OnCommand ) );
  44. Register( "Help", AccessLevel.Player, new CommandEventHandler( Help_OnCommand ) );
  45. Register( "Save", AccessLevel.Seer, new CommandEventHandler( Save_OnCommand ) );
  46. Register( "Move", AccessLevel.GameMaster, new CommandEventHandler( Move_OnCommand ) );
  47. Register( "Client", AccessLevel.Counselor, new CommandEventHandler( Client_OnCommand ) );
  48. Register( "SMsg", AccessLevel.Counselor, new CommandEventHandler( StaffMessage_OnCommand ) );
  49. Register( "SM", AccessLevel.Counselor, new CommandEventHandler( StaffMessage_OnCommand ) );
  50. Register( "S", AccessLevel.Counselor, new CommandEventHandler( StaffMessage_OnCommand ) );
  51. Register( "BCast", AccessLevel.GameMaster, new CommandEventHandler( BroadcastMessage_OnCommand ) );
  52. Register( "BC", AccessLevel.GameMaster, new CommandEventHandler( BroadcastMessage_OnCommand ) );
  53. Register( "B", AccessLevel.GameMaster, new CommandEventHandler( BroadcastMessage_OnCommand ) );
  54. Register( "Bank", AccessLevel.GameMaster, new CommandEventHandler( Bank_OnCommand ) );
  55. Register( "Echo", AccessLevel.GameMaster, new CommandEventHandler( Echo_OnCommand ) );
  56. Register( "Sound", AccessLevel.GameMaster, new CommandEventHandler( Sound_OnCommand ) );
  57. Register( "ViewEquip", AccessLevel.GameMaster, new CommandEventHandler( ViewEquip_OnCommand ) );
  58. Register( "DumpTimers", AccessLevel.Administrator, new CommandEventHandler( DumpTimers_OnCommand ) );
  59. Register( "CountObjects", AccessLevel.Administrator, new CommandEventHandler( CountObjects_OnCommand ) );
  60. Register( "ProfileWorld", AccessLevel.Administrator, new CommandEventHandler( ProfileWorld_OnCommand ) );
  61. Register( "TraceInternal", AccessLevel.Administrator, new CommandEventHandler( TraceInternal_OnCommand ) );
  62. Register( "SetProfiles", AccessLevel.Administrator, new CommandEventHandler( SetProfiles_OnCommand ) );
  63. Register( "Light", AccessLevel.Counselor, new CommandEventHandler( Light_OnCommand ) );
  64. Register( "Stats", AccessLevel.Counselor, new CommandEventHandler( Stats_OnCommand ) );
  65. Register( "ReplaceBankers", AccessLevel.Administrator, new CommandEventHandler( ReplaceBankers_OnCommand ) );
  66. }
  67. public static void Register( string command, AccessLevel access, CommandEventHandler handler )
  68. {
  69. Server.Commands.Register( command, access, handler );
  70. }
  71. [Usage( "Where" )]
  72. [Description( "Tells the commanding player his coordinates, region, and facet." )]
  73. public static void Where_OnCommand( CommandEventArgs e )
  74. {
  75. Mobile from = e.Mobile;
  76. Map map = from.Map;
  77. from.SendMessage( "Vous êtes à {0} {1} {2}, {3}.", from.X, from.Y, from.Z, map );
  78. if ( map != null )
  79. {
  80. Region reg = from.Region;
  81. if ( reg != map.DefaultRegion )
  82. from.SendMessage( "Votre région est {0}.", reg );
  83. }
  84. }
  85. [Usage( "DropHolding" )]
  86. [Description( "Drops the item, if any, that a targeted player is holding. The item is placed into their backpack, or if that's full, at their feet." )]
  87. public static void DropHolding_OnCommand( CommandEventArgs e )
  88. {
  89. e.Mobile.BeginTarget( -1, false, TargetFlags.None, new TargetCallback( DropHolding_OnTarget ) );
  90. e.Mobile.SendMessage( "Target the player to drop what they are holding." );
  91. }
  92. public static void DropHolding_OnTarget( Mobile from, object obj )
  93. {
  94. if ( obj is Mobile && ((Mobile)obj).Player )
  95. {
  96. Mobile targ = (Mobile)obj;
  97. Item held = targ.Holding;
  98. if ( held == null )
  99. {
  100. from.SendMessage( "They are not holding anything." );
  101. }
  102. else
  103. {
  104. if ( from.AccessLevel == AccessLevel.Counselor )
  105. {
  106. Engines.Help.PageEntry pe = Engines.Help.PageQueue.GetEntry( targ );
  107. if ( pe == null || pe.Handler != from )
  108. {
  109. if ( pe == null )
  110. from.SendMessage( "You may only use this command on someone who has paged you." );
  111. else
  112. from.SendMessage( "You may only use this command if you are handling their help page." );
  113. return;
  114. }
  115. }
  116. if ( targ.AddToBackpack( held ) )
  117. from.SendMessage( "The item they were holding has been placed into their backpack." );
  118. else
  119. from.SendMessage( "The item they were holding has been placed at their feet." );
  120. held.ClearBounce();
  121. targ.Holding = null;
  122. }
  123. }
  124. else
  125. {
  126. from.BeginTarget( -1, false, TargetFlags.None, new TargetCallback( DropHolding_OnTarget ) );
  127. from.SendMessage( "That is not a player. Try again." );
  128. }
  129. }
  130. public static void DeleteList_Callback( Mobile from, bool okay, object state )
  131. {
  132. if ( okay )
  133. {
  134. ArrayList list = (ArrayList)state;
  135. CommandLogging.WriteLine( from, "{0} {1} deleting {2} objects", from.AccessLevel, CommandLogging.Format( from ), list.Count );
  136. for ( int i = 0; i < list.Count; ++i )
  137. {
  138. object obj = list[i];
  139. if ( obj is Item )
  140. ((Item)obj).Delete();
  141. else if ( obj is Mobile )
  142. ((Mobile)obj).Delete();
  143. }
  144. from.SendMessage( "You have deleted {0} object{1}.", list.Count, list.Count == 1 ? "" : "s" );
  145. }
  146. else
  147. {
  148. from.SendMessage( "You have chosen not to delete those objects." );
  149. }
  150. }
  151. [Usage( "GetFollowers" )]
  152. [Description( "Teleports all pets of a targeted player to your location." )]
  153. public static void GetFollowers_OnCommand( CommandEventArgs e )
  154. {
  155. e.Mobile.BeginTarget( -1, false, TargetFlags.None, new TargetCallback( GetFollowers_OnTarget ) );
  156. e.Mobile.SendMessage( "Target a player to get their pets." );
  157. }
  158. public static void GetFollowers_OnTarget( Mobile from, object obj )
  159. {
  160. if ( obj is Mobile && ((Mobile)obj).Player )
  161. {
  162. Mobile master = (Mobile)obj;
  163. ArrayList pets = new ArrayList();
  164. foreach ( Mobile m in World.Mobiles.Values )
  165. {
  166. if ( m is BaseCreature )
  167. {
  168. BaseCreature bc = (BaseCreature)m;
  169. if ( (bc.Controled && bc.ControlMaster == master) || (bc.Summoned && bc.SummonMaster == master) )
  170. pets.Add( bc );
  171. }
  172. }
  173. if ( pets.Count > 0 )
  174. {
  175. CommandLogging.WriteLine( from, "{0} {1} getting all followers of {2}", from.AccessLevel, CommandLogging.Format( from ), CommandLogging.Format( master ) );
  176. from.SendMessage( "That player has {0} pet{1}.", pets.Count, pets.Count != 1 ? "s" : "" );
  177. for ( int i = 0; i < pets.Count; ++i )
  178. {
  179. Mobile pet = (Mobile)pets[i];
  180. if ( pet is IMount )
  181. ((IMount)pet).Rider = null; // make sure it's dismounted
  182. pet.MoveToWorld( from.Location, from.Map );
  183. }
  184. }
  185. else
  186. {
  187. from.SendMessage( "There were no pets found for that player." );
  188. }
  189. }
  190. else
  191. {
  192. from.BeginTarget( -1, false, TargetFlags.None, new TargetCallback( GetFollowers_OnTarget ) );
  193. from.SendMessage( "That is not a player. Try again." );
  194. }
  195. }
  196. public static void ReplaceBankers_OnCommand( CommandEventArgs e )
  197. {
  198. ArrayList list = new ArrayList();
  199. foreach ( Mobile m in World.Mobiles.Values )
  200. {
  201. if ( (m is Banker) && !(m is BaseCreature) )
  202. list.Add( m );
  203. }
  204. foreach ( Mobile m in list )
  205. {
  206. Map map = m.Map;
  207. if ( map != null )
  208. {
  209. bool hasBankerSpawner = false;
  210. foreach ( Item item in m.GetItemsInRange( 0 ) )
  211. {
  212. if ( item is Spawner )
  213. {
  214. Spawner spawner = (Spawner)item;
  215. for ( int i = 0; !hasBankerSpawner && i < spawner.CreaturesName.Count; ++i )
  216. hasBankerSpawner = Insensitive.Equals( (string)spawner.CreaturesName[i], "banker" );
  217. if ( hasBankerSpawner )
  218. break;
  219. }
  220. }
  221. if ( !hasBankerSpawner )
  222. {
  223. Spawner spawner = new Spawner( 1, 1, 5, 0, 4, "banker" );
  224. spawner.MoveToWorld( m.Location, map );
  225. }
  226. }
  227. }
  228. }
  229. private class ViewEqTarget : Target
  230. {
  231. public ViewEqTarget() : base( -1, false, TargetFlags.None )
  232. {
  233. }
  234. protected override void OnTarget( Mobile from, object targeted )
  235. {
  236. if ( !BaseCommand.IsAccessible( from, targeted ) )
  237. {
  238. from.SendMessage( "That is not accessible." );
  239. return;
  240. }
  241. if ( targeted is Mobile )
  242. from.SendMenu( new EquipMenu( from, (Mobile)targeted, GetEquip( (Mobile)targeted ) ) );
  243. }
  244. private static ItemListEntry[] GetEquip( Mobile m )
  245. {
  246. ItemListEntry[] entries = new ItemListEntry[m.Items.Count];
  247. for ( int i = 0; i < m.Items.Count; ++i )
  248. {
  249. Item item = (Item)m.Items[i];
  250. entries[i] = new ItemListEntry( String.Format( "{0}: {1}", item.Layer, item.GetType().Name ), item.ItemID, item.Hue );
  251. }
  252. return entries;
  253. }
  254. private class EquipMenu: ItemListMenu
  255. {
  256. private Mobile m_Mobile;
  257. public EquipMenu( Mobile from, Mobile m, ItemListEntry[] entries ) : base( "Equipment", entries )
  258. {
  259. m_Mobile = m;
  260. CommandLogging.WriteLine( from, "{0} {1} getting equip for {2}", from.AccessLevel, CommandLogging.Format( from ), CommandLogging.Format( m ) );
  261. }
  262. public override void OnResponse( NetState state, int index )
  263. {
  264. if ( index >= 0 && index < m_Mobile.Items.Count )
  265. {
  266. Item item = (Item)m_Mobile.Items[index];
  267. state.Mobile.SendMenu( new EquipDetailsMenu( m_Mobile, item ) );
  268. }
  269. }
  270. private class EquipDetailsMenu : QuestionMenu
  271. {
  272. private Mobile m_Mobile;
  273. private Item m_Item;
  274. public EquipDetailsMenu( Mobile m, Item item ) : base( String.Format( "{0}: {1}", item.Layer, item.GetType().Name ), new string[]{"Move","Delete","Props"})
  275. {
  276. m_Mobile = m;
  277. m_Item = item;
  278. }
  279. public override void OnCancel( NetState state )
  280. {
  281. state.Mobile.SendMenu( new EquipMenu( state.Mobile, m_Mobile, ViewEqTarget.GetEquip( m_Mobile ) ) );
  282. }
  283. public override void OnResponse( NetState state, int index )
  284. {
  285. if ( index == 0 )
  286. {
  287. CommandLogging.WriteLine( state.Mobile, "{0} {1} moving equip item {2} of {3}", state.Mobile.AccessLevel, CommandLogging.Format( state.Mobile ), CommandLogging.Format( m_Item ), CommandLogging.Format( m_Mobile ) );
  288. state.Mobile.Target = new MoveTarget( m_Item );
  289. }
  290. else if ( index == 1 )
  291. {
  292. CommandLogging.WriteLine( state.Mobile, "{0} {1} deleting equip item {2} of {3}", state.Mobile.AccessLevel, CommandLogging.Format( state.Mobile ), CommandLogging.Format( m_Item ), CommandLogging.Format( m_Mobile ) );
  293. m_Item.Delete();
  294. }
  295. else if ( index == 2 )
  296. {
  297. CommandLogging.WriteLine( state.Mobile, "{0} {1} opening props for equip item {2} of {3}", state.Mobile.AccessLevel, CommandLogging.Format( state.Mobile ), CommandLogging.Format( m_Item ), CommandLogging.Format( m_Mobile ) );
  298. state.Mobile.SendGump( new APropertiesGump( state.Mobile, m_Item ) );
  299. }
  300. }
  301. }
  302. }
  303. }
  304. [Usage( "SetProfiles [true | false]" )]
  305. [Description( "Enables, disables, or toggles the state of core packet and timer profiling." )]
  306. public static void SetProfiles_OnCommand( CommandEventArgs e )
  307. {
  308. if ( e.Length == 1 )
  309. Core.Profiling = e.GetBoolean( 0 );
  310. else
  311. Core.Profiling = !Core.Profiling;
  312. e.Mobile.SendMessage( "Profiling has been {0}.", Core.Profiling ? "enabled" : "disabled" );
  313. }
  314. [Usage( "DumpTimers" )]
  315. [Description( "Generates a log file of all currently executing timers. Used for tracing timer leaks." )]
  316. public static void DumpTimers_OnCommand( CommandEventArgs e )
  317. {
  318. try
  319. {
  320. using ( StreamWriter sw = new StreamWriter( "timerdump.log", true ) )
  321. Timer.DumpInfo( sw );
  322. }
  323. catch
  324. {
  325. }
  326. }
  327. private class CountSorter : IComparer
  328. {
  329. public int Compare( object x, object y )
  330. {
  331. DictionaryEntry a = (DictionaryEntry)x;
  332. DictionaryEntry b = (DictionaryEntry)y;
  333. int aCount = (int)a.Value;
  334. int bCount = (int)b.Value;
  335. int v = -aCount.CompareTo( bCount );
  336. if ( v == 0 )
  337. {
  338. Type aType = (Type)a.Key;
  339. Type bType = (Type)b.Key;
  340. v = aType.FullName.CompareTo( bType.FullName );
  341. }
  342. return v;
  343. }
  344. }
  345. [Usage( "CountObjects" )]
  346. [Description( "Generates a log file detailing all item and mobile types in the world." )]
  347. public static void CountObjects_OnCommand( CommandEventArgs e )
  348. {
  349. using ( StreamWriter op = new StreamWriter( "objects.log" ) )
  350. {
  351. Hashtable table = new Hashtable();
  352. foreach ( Item item in World.Items.Values )
  353. {
  354. Type type = item.GetType();
  355. object o = (object)table[type];
  356. if ( o == null )
  357. table[type] = 1;
  358. else
  359. table[type] = 1 + (int)o;
  360. }
  361. ArrayList items = new ArrayList( table );
  362. table.Clear();
  363. foreach ( Mobile m in World.Mobiles.Values )
  364. {
  365. Type type = m.GetType();
  366. object o = (object)table[type];
  367. if ( o == null )
  368. table[type] = 1;
  369. else
  370. table[type] = 1 + (int)o;
  371. }
  372. ArrayList mobiles = new ArrayList( table );
  373. items.Sort( new CountSorter() );
  374. mobiles.Sort( new CountSorter() );
  375. op.WriteLine( "# Object count table generated on {0}", DateTime.Now );
  376. op.WriteLine();
  377. op.WriteLine();
  378. op.WriteLine( "# Items:" );
  379. foreach ( DictionaryEntry de in items )
  380. op.WriteLine( "{0}\t{1:F2}%\t{2}", de.Value, (100 * (int)de.Value) / (double)World.Items.Count, de.Key );
  381. op.WriteLine();
  382. op.WriteLine();
  383. op.WriteLine( "#Mobiles:" );
  384. foreach ( DictionaryEntry de in mobiles )
  385. op.WriteLine( "{0}\t{1:F2}%\t{2}", de.Value, (100 * (int)de.Value) / (double)World.Mobiles.Count, de.Key );
  386. }
  387. e.Mobile.SendMessage( "Object table has been generated. See the file : <runuo root>/objects.log" );
  388. }
  389. [Usage( "TraceInternal" )]
  390. [Description( "Generates a log file describing all items in the 'internal' map." )]
  391. public static void TraceInternal_OnCommand( CommandEventArgs e )
  392. {
  393. int totalCount = 0;
  394. Hashtable table = new Hashtable();
  395. foreach ( Item item in World.Items.Values )
  396. {
  397. if ( item.Parent != null || item.Map != Map.Internal )
  398. continue;
  399. ++totalCount;
  400. Type type = item.GetType();
  401. int[] parms = (int[])table[type];
  402. if ( parms == null )
  403. table[type] = parms = new int[]{ 0, 0 };
  404. parms[0]++;
  405. parms[1] += item.Amount;
  406. }
  407. using ( StreamWriter op = new StreamWriter( "internal.log" ) )
  408. {
  409. op.WriteLine( "# {0} items found", totalCount );
  410. op.WriteLine( "# {0} different types", table.Count );
  411. op.WriteLine();
  412. op.WriteLine();
  413. op.WriteLine( "Type\t\tCount\t\tAmount\t\tAvg. Amount" );
  414. foreach ( DictionaryEntry de in table )
  415. {
  416. Type type = (Type)de.Key;
  417. int[] parms = (int[])de.Value;
  418. op.WriteLine( "{0}\t\t{1}\t\t{2}\t\t{3:F2}", type.Name, parms[0], parms[1], (double)parms[1] / parms[0] );
  419. }
  420. }
  421. }
  422. [Usage( "ProfileWorld" )]
  423. [Description( "Prints the amount of data serialized for every object type in your world file." )]
  424. public static void ProfileWorld_OnCommand( CommandEventArgs e )
  425. {
  426. ProfileWorld( "items", "worldprofile_items.log" );
  427. ProfileWorld( "mobiles", "worldprofile_mobiles.log" );
  428. }
  429. public static void ProfileWorld( string type, string opFile )
  430. {
  431. try
  432. {
  433. ArrayList types = new ArrayList();
  434. using ( BinaryReader bin = new BinaryReader( new FileStream( String.Format( "Saves/{0}/{0}.tdb", type ), FileMode.Open, FileAccess.Read, FileShare.Read ) ) )
  435. {
  436. int count = bin.ReadInt32();
  437. for ( int i = 0; i < count; ++i )
  438. types.Add( ScriptCompiler.FindTypeByFullName( bin.ReadString() ) );
  439. }
  440. long total = 0;
  441. Hashtable table = new Hashtable();
  442. using ( BinaryReader bin = new BinaryReader( new FileStream( String.Format( "Saves/{0}/{0}.idx", type ), FileMode.Open, FileAccess.Read, FileShare.Read ) ) )
  443. {
  444. int count = bin.ReadInt32();
  445. for ( int i = 0; i < count; ++i )
  446. {
  447. int typeID = bin.ReadInt32();
  448. int serial = bin.ReadInt32();
  449. long pos = bin.ReadInt64();
  450. int length = bin.ReadInt32();
  451. Type objType = (Type)types[typeID];
  452. while ( objType != null && objType != typeof( object ) )
  453. {
  454. object obj = table[objType];
  455. if ( obj == null )
  456. table[objType] = length;
  457. else
  458. table[objType] = length + (int)obj;
  459. objType = objType.BaseType;
  460. total += length;
  461. }
  462. }
  463. }
  464. ArrayList list = new ArrayList( table );
  465. list.Sort( new CountSorter() );
  466. using ( StreamWriter op = new StreamWriter( opFile ) )
  467. {
  468. op.WriteLine( "# Profile of world {0}", type );
  469. op.WriteLine( "# Generated on {0}", DateTime.Now );
  470. op.WriteLine();
  471. op.WriteLine();
  472. foreach ( DictionaryEntry de in list )
  473. op.WriteLine( "{0}\t{1:F2}%\t{2}", de.Value, (100 * (int)de.Value) / (double)total, de.Key );
  474. }
  475. }
  476. catch
  477. {
  478. }
  479. }
  480. [Usage( "ViewEquip" )]
  481. [Description( "Lists equipment of a targeted mobile. From the list you can move, delete, or open props." )]
  482. public static void ViewEquip_OnCommand( CommandEventArgs e )
  483. {
  484. e.Mobile.Target = new ViewEqTarget();
  485. }
  486. [Usage( "Sound <index> [toAll=true]" )]
  487. [Description( "Plays a sound to players within 12 tiles of you. The (toAll) argument specifies to everyone, or just those who can see you." )]
  488. public static void Sound_OnCommand( CommandEventArgs e )
  489. {
  490. if ( e.Length == 1 )
  491. PlaySound( e.Mobile, e.GetInt32( 0 ), true );
  492. else if ( e.Length == 2 )
  493. PlaySound( e.Mobile, e.GetInt32( 0 ), e.GetBoolean( 1 ) );
  494. else
  495. e.Mobile.SendMessage( "Format: Sound <index> [toAll]" );
  496. }
  497. private static void PlaySound( Mobile m, int index, bool toAll )
  498. {
  499. Map map = m.Map;
  500. if ( map == null )
  501. return;
  502. CommandLogging.WriteLine( m, "{0} {1} playing sound {2} (toAll={3})", m.AccessLevel, CommandLogging.Format( m ), index, toAll );
  503. Packet p = new PlaySound( index, m.Location );
  504. foreach ( NetState state in m.GetClientsInRange( 12 ) )
  505. {
  506. if ( toAll || state.Mobile.CanSee( m ) )
  507. state.Send( p );
  508. }
  509. }
  510. private class BankTarget : Target
  511. {
  512. public BankTarget() : base( -1, false, TargetFlags.None )
  513. {
  514. }
  515. protected override void OnTarget( Mobile from, object targeted )
  516. {
  517. if ( targeted is Mobile )
  518. {
  519. Mobile m = (Mobile)targeted;
  520. BankBox box = ( m.Player ? m.BankBox : m.FindBankNoCreate() );
  521. if ( box != null )
  522. {
  523. CommandLogging.WriteLine( from, "{0} {1} opening bank box of {2}", from.AccessLevel, CommandLogging.Format( from ), CommandLogging.Format( targeted ) );
  524. if ( from == targeted )
  525. box.Open();
  526. else
  527. box.DisplayTo( from );
  528. }
  529. else
  530. {
  531. from.SendMessage( "They have no bank box." );
  532. }
  533. }
  534. }
  535. }
  536. [Usage( "Echo <text>" )]
  537. [Description( "Relays (text) as a system message." )]
  538. public static void Echo_OnCommand( CommandEventArgs e )
  539. {
  540. string toEcho = e.ArgString.Trim();
  541. if ( toEcho.Length > 0 )
  542. e.Mobile.SendMessage( toEcho );
  543. else
  544. e.Mobile.SendMessage( "Format: Echo \"<text>\"" );
  545. }
  546. [Usage( "Bank" )]
  547. [Description( "Opens the bank box of a given target." )]
  548. public static void Bank_OnCommand( CommandEventArgs e )
  549. {
  550. e.Mobile.Target = new BankTarget();
  551. }
  552. private class DismountTarget : Target
  553. {
  554. public DismountTarget() : base( -1, false, TargetFlags.None )
  555. {
  556. }
  557. protected override void OnTarget( Mobile from, object targeted )
  558. {
  559. if ( targeted is Mobile )
  560. {
  561. CommandLogging.WriteLine( from, "{0} {1} dismounting {2}", from.AccessLevel, CommandLogging.Format( from ), CommandLogging.Format( targeted ) );
  562. Mobile targ = (Mobile)targeted;
  563. for ( int i = 0; i < targ.Items.Count; ++i )
  564. {
  565. Item item = (Item)targ.Items[i];
  566. if ( item is IMountItem )
  567. {
  568. IMount mount = ((IMountItem)item).Mount;
  569. if ( mount != null )
  570. mount.Rider = null;
  571. if ( targ.Items.IndexOf( item ) == -1 )
  572. --i;
  573. }
  574. }
  575. for ( int i = 0; i < targ.Items.Count; ++i )
  576. {
  577. Item item = (Item)targ.Items[i];
  578. if ( item.Layer == Layer.Mount )
  579. {
  580. item.Delete();
  581. --i;
  582. }
  583. }
  584. }
  585. }
  586. }
  587. private class ClientTarget : Target
  588. {
  589. public ClientTarget() : base( -1, false, TargetFlags.None )
  590. {
  591. }
  592. protected override void OnTarget( Mobile from, object targeted )
  593. {
  594. if ( targeted is Mobile )
  595. {
  596. Mobile targ = (Mobile)targeted;
  597. if ( targ.NetState != null )
  598. {
  599. CommandLogging.WriteLine( from, "{0} {1} opening client menu of {2}", from.AccessLevel, CommandLogging.Format( from ), CommandLogging.Format( targeted ) );
  600. from.SendGump( new ClientGump( from, targ.NetState ) );
  601. }
  602. }
  603. }
  604. }
  605. [Usage( "Client" )]
  606. [Description( "Opens the client gump menu for a given player." )]
  607. private static void Client_OnCommand( CommandEventArgs e )
  608. {
  609. e.Mobile.Target = new ClientTarget();
  610. }
  611. [Usage( "Move" )]
  612. [Description( "Repositions a targeted item or mobile." )]
  613. private static void Move_OnCommand( CommandEventArgs e )
  614. {
  615. e.Mobile.Target = new PickMoveTarget();
  616. }
  617. private class FirewallTarget : Target
  618. {
  619. public FirewallTarget() : base( -1, false, TargetFlags.None )
  620. {
  621. }
  622. protected override void OnTarget( Mobile from, object targeted )
  623. {
  624. if ( targeted is Mobile )
  625. {
  626. Mobile targ = (Mobile)targeted;
  627. NetState state = targ.NetState;
  628. if ( state != null )
  629. {
  630. CommandLogging.WriteLine( from, "{0} {1} firewalling {2}", from.AccessLevel, CommandLogging.Format( from ), CommandLogging.Format( targeted ) );
  631. try
  632. {
  633. Firewall.Add( ((IPEndPoint)state.Socket.RemoteEndPoint).Address );
  634. }
  635. catch
  636. {
  637. }
  638. }
  639. }
  640. }
  641. }
  642. [Usage( "Save" )]
  643. [Description( "Saves the world." )]
  644. private static void Save_OnCommand( CommandEventArgs e )
  645. {
  646. ItemsSerializer.SaveNeeded = true;
  647. CreaturesSerializer.SaveNeeded = true;
  648. Misc.AutoSave.Save();
  649. }
  650. private static bool FixMap( ref Map map, ref Point3D loc, Item item )
  651. {
  652. if ( map == null || map == Map.Internal )
  653. {
  654. Mobile m = item.RootParent as Mobile;
  655. return ( m != null && FixMap( ref map, ref loc, m ) );
  656. }
  657. return true;
  658. }
  659. private static bool FixMap( ref Map map, ref Point3D loc, Mobile m )
  660. {
  661. if ( map == null || map == Map.Internal )
  662. {
  663. map = m.LogoutMap;
  664. loc = m.LogoutLocation;
  665. }
  666. return ( map != null && map != Map.Internal );
  667. }
  668. [Usage( "Go [name | serial | (x y [z]) | (deg min (N | S) deg min (E | W))]" )]
  669. [Description( "With no arguments, this command brings up the go menu. With one argument, (name), you are moved to that regions \"go location.\" Or, if a numerical value is specified for one argument, (serial), you are moved to that object. Two or three arguments, (x y [z]), will move your character to that location. When six arguments are specified, (deg min (N | S) deg min (E | W)), your character will go to an approximate of those sextant coordinates." )]
  670. private static void Go_OnCommand( CommandEventArgs e )
  671. {
  672. Mobile from = e.Mobile;
  673. if ( e.Length == 0 )
  674. {
  675. GoGump.DisplayTo( from );
  676. }
  677. else if ( e.Length == 1 )
  678. {
  679. try
  680. {
  681. int ser = e.GetInt32( 0 );
  682. IEntity ent = World.FindEntity( ser );
  683. if ( ent is Item )
  684. {
  685. Item item = (Item)ent;
  686. Map map = item.Map;
  687. Point3D loc = item.GetWorldLocation();
  688. Mobile owner = item.RootParent as Mobile;
  689. if ( owner != null && (owner.Map != null && owner.Map != Map.Internal) && !from.CanSee( owner ) )
  690. {
  691. from.SendMessage( "You can not go to what you can not see." );
  692. return;
  693. }
  694. else if ( owner != null && (owner.Map == null || owner.Map == Map.Internal) && owner.Hidden && owner.AccessLevel >= from.AccessLevel )
  695. {
  696. from.SendMessage( "You can not go to what you can not see." );
  697. return;
  698. }
  699. else if ( !FixMap( ref map, ref loc, item ) )
  700. {
  701. from.SendMessage( "That is an internal item and you cannot go to it." );
  702. return;
  703. }
  704. from.MoveToWorld( loc, map );
  705. return;
  706. }
  707. else if ( ent is Mobile )
  708. {
  709. Mobile m = (Mobile)ent;
  710. Map map = m.Map;
  711. Point3D loc = m.Location;
  712. Mobile owner = m;
  713. if ( owner != null && (owner.Map != null && owner.Map != Map.Internal) && !from.CanSee( owner ) )
  714. {
  715. from.SendMessage( "You can not go to what you can not see." );
  716. return;
  717. }
  718. else if ( owner != null && (owner.Map == null || owner.Map == Map.Internal) && owner.Hidden && owner.AccessLevel >= from.AccessLevel )
  719. {
  720. from.SendMessage( "You can not go to what you can not see." );
  721. return;
  722. }
  723. else if ( !FixMap( ref map, ref loc, m ) )
  724. {
  725. from.SendMessage( "That is an internal mobile and you cannot go to it." );
  726. return;
  727. }
  728. from.MoveToWorld( loc, map );
  729. return;
  730. }
  731. else
  732. {
  733. string name = e.GetString( 0 );
  734. ArrayList list = from.Map.Regions;
  735. for ( int i = 0; i < list.Count; ++i )
  736. {
  737. Region r = (Region)list[i];
  738. if ( Insensitive.Equals( r.Name, name ) )
  739. {
  740. from.Location = new Point3D( r.GoLocation );
  741. return;
  742. }
  743. }
  744. if ( ser != 0 )
  745. from.SendMessage( "No object with that serial was found." );
  746. else
  747. from.SendMessage( "No region with that name was found." );
  748. return;
  749. }
  750. }
  751. catch
  752. {
  753. }
  754. from.SendMessage( "Region name not found" );
  755. }
  756. else if ( e.Length == 2 )
  757. {
  758. Map map = from.Map;
  759. if ( map != null )
  760. {
  761. int x = e.GetInt32( 0 ), y = e.GetInt32( 1 );
  762. int z = map.GetAverageZ( x, y );
  763. from.Location = new Point3D( x, y, z );
  764. }
  765. }
  766. else if ( e.Length == 3 )
  767. {
  768. from.Location = new Point3D( e.GetInt32( 0 ), e.GetInt32( 1 ), e.GetInt32( 2 ) );
  769. }
  770. else if ( e.Length == 6 )
  771. {
  772. Map map = from.Map;
  773. if ( map != null )
  774. {
  775. Point3D p = Sextant.ReverseLookup( map, e.GetInt32( 3 ), e.GetInt32( 0 ), e.GetInt32( 4 ), e.GetInt32( 1 ), Insensitive.Equals( e.GetString( 5 ), "E" ), Insensitive.Equals( e.GetString( 2 ), "S" ) );
  776. if ( p != Point3D.Zero )
  777. from.Location = p;
  778. else
  779. from.SendMessage( "Sextant reverse lookup failed." );
  780. }
  781. }
  782. else
  783. {
  784. from.SendMessage( "Format: Go [name | serial | (x y [z]) | (deg min (N | S) deg min (E | W)]" );
  785. }
  786. }
  787. [Usage( "Help" )]
  788. [Description( "Lists all available commands." )]
  789. public static void Help_OnCommand( CommandEventArgs e )
  790. {
  791. Mobile m = e.Mobile;
  792. ArrayList list = new ArrayList();
  793. foreach ( CommandEntry entry in Server.Commands.Entries.Values )
  794. {
  795. if ( m.AccessLevel >= entry.AccessLevel )
  796. list.Add( entry );
  797. }
  798. list.Sort();
  799. StringBuilder sb = new StringBuilder();
  800. if ( list.Count > 0 )
  801. sb.Append( ((CommandEntry)list[0]).Command );
  802. for ( int i = 1; i < list.Count; ++i )
  803. {
  804. string v = ((CommandEntry)list[i]).Command;
  805. if ( (sb.Length + 1 + v.Length) >= 256 )
  806. {
  807. m.SendAsciiMessage( 0x482, sb.ToString() );
  808. sb = new StringBuilder();
  809. sb.Append( v );
  810. }
  811. else
  812. {
  813. sb.Append( ' ' );
  814. sb.Append( v );
  815. }
  816. }
  817. if ( sb.Length > 0 )
  818. m.SendAsciiMessage( 0x482, sb.ToString() );
  819. }
  820. [Usage( "SMsg <text>" )]
  821. [Aliases( "S", "SM" )]
  822. [Description( "Broadcasts a message to all online staff." )]
  823. public static void StaffMessage_OnCommand( CommandEventArgs e )
  824. {
  825. BroadcastMessage( AccessLevel.Counselor, e.Mobile.SpeechHue, String.Format( "[{0}] {1}", e.Mobile.Name, e.ArgString ) );
  826. }
  827. [Usage( "BCast <text>" )]
  828. [Aliases( "B", "BC" )]
  829. [Description( "Broadcasts a message to everyone online." )]
  830. public static void BroadcastMessage_OnCommand( CommandEventArgs e )
  831. {
  832. BroadcastMessage( AccessLevel.Player, 0x482, String.Format( "Staff message from {0}:", e.Mobile.Name ) );
  833. BroadcastMessage( AccessLevel.Player, 0x482, e.ArgString );
  834. }
  835. public static void BroadcastMessage ( AccessLevel ac, int hue, string message )
  836. {
  837. foreach ( NetState state in NetState.Instances )
  838. {
  839. Mobile m = state.Mobile;
  840. if ( m != null && m.AccessLevel >= ac )
  841. m.SendMessage( hue, message );
  842. }
  843. }
  844. private class DeleteItemByLayerTarget : Target
  845. {
  846. private Layer m_Layer;
  847. public DeleteItemByLayerTarget( Layer layer ) : base( -1, false, TargetFlags.None )
  848. {
  849. m_Layer = layer;
  850. }
  851. protected override void OnTarget( Mobile from, object targeted )
  852. {
  853. if ( targeted is Mobile )
  854. {
  855. Item item = ((Mobile)targeted).FindItemOnLayer( m_Layer );
  856. if ( item != null )
  857. {
  858. CommandLogging.WriteLine( from, "{0} {1} deleting item on layer {2} of {3}", from.AccessLevel, CommandLogging.Format( from ), m_Layer, CommandLogging.Format( targeted ) );
  859. item.Delete();
  860. }
  861. }
  862. else
  863. {
  864. from.SendMessage( "Target a mobile." );
  865. }
  866. }
  867. }
  868. [Usage( "ShaveHair" )]
  869. [Description( "Removes the hair of a targeted mobile." )]
  870. public static void ShaveHair_OnCommand( CommandEventArgs e )
  871. {
  872. e.Mobile.Target = new DeleteItemByLayerTarget( Layer.Hair );
  873. }
  874. [Usage( "ShaveBeard" )]
  875. [Description( "Removes the beard of a targeted mobile." )]
  876. public static void ShaveBeard_OnCommand( CommandEventArgs e )
  877. {
  878. e.Mobile.Target = new DeleteItemByLayerTarget( Layer.FacialHair );
  879. }
  880. [Usage( "AutoPageNotify" )]
  881. [Aliases( "APN" )]
  882. [Description( "Toggles your auto-page-notify status." )]
  883. public static void APN_OnCommand( CommandEventArgs e )
  884. {
  885. Mobile m = e.Mobile;
  886. m.AutoPageNotify = !m.AutoPageNotify;
  887. m.SendMessage( "Your auto-page-notify has been turned {0}.", m.AutoPageNotify ? "on" : "off" );
  888. }
  889. [Usage( "Animate <action> <frameCount> <repeatCount> <forward> <repeat> <delay>" )]
  890. [Description( "Makes your character do a specified animation." )]
  891. public static void Animate_OnCommand( CommandEventArgs e )
  892. {
  893. if ( e.Length == 6 )
  894. {
  895. e.Mobile.Animate( e.GetInt32( 0 ), e.GetInt32( 1 ), e.GetInt32( 2 ), e.GetBoolean( 3 ), e.GetBoolean( 4 ), e.GetInt32( 5 ) );
  896. }
  897. else
  898. {
  899. e.Mobile.SendMessage( "Format: Animate <action> <frameCount> <repeatCount> <forward> <repeat> <delay>" );
  900. }
  901. }
  902. [Usage( "Cast <name>" )]
  903. [Description( "Casts a spell by name." )]
  904. public static void Cast_OnCommand( CommandEventArgs e )
  905. {
  906. if ( e.Length == 1 )
  907. {
  908. if ( !Multis.DesignContext.Check( e.Mobile ) )
  909. return; // They are customizing
  910. Spell spell = SpellRegistry.NewSpell( e.GetString( 0 ), e.Mobile, null );
  911. if ( spell != null )
  912. spell.Cast();
  913. else
  914. e.Mobile.SendMessage( "That spell was not found." );
  915. }
  916. else
  917. {
  918. e.Mobile.SendMessage( "Format: Cast <name>" );
  919. }
  920. }
  921. private class StuckMenuTarget : Target
  922. {
  923. public StuckMenuTarget() : base( -1, false, TargetFlags.None )
  924. {
  925. }
  926. protected override void OnTarget( Mobile from, object targeted )
  927. {
  928. if ( targeted is Mobile )
  929. {
  930. from.SendGump( new StuckMenu( from, (Mobile) targeted, false ) );
  931. }
  932. }
  933. }
  934. [Usage( "Stuck" )]
  935. [Description( "Opens a menu of towns, used for teleporting stuck mobiles." )]
  936. public static void Stuck_OnCommand( CommandEventArgs e )
  937. {
  938. e.Mobile.Target = new StuckMenuTarget();
  939. }
  940. [Usage( "Light <level>")]
  941. [Description( "Set your local lightlevel." )]
  942. public static void Light_OnCommand( CommandEventArgs e )
  943. {
  944. e.Mobile.LightLevel = e.GetInt32( 0 );
  945. }
  946. [Usage( "Stats")]
  947. [Description( "View some stats about the server." )]
  948. public static void Stats_OnCommand( CommandEventArgs e )
  949. {
  950. e.Mobile.SendMessage("Open Connections: {0}", Network.NetState.Instances.Count);
  951. e.Mobile.SendMessage("Mobiles: {0}", World.Mobiles.Count);
  952. e.Mobile.SendMessage("Items: {0}", World.Items.Count);
  953. //e.Mobile.SendMessage("-------------");
  954. //{
  955. // List<Mobile> Mobiles = new List<Mobile>();
  956. // Dictionary<Type, int> MobileTypes = new Dictionary<Type, int>();
  957. // foreach (Mobile m in World.Mobiles.Values)
  958. // {
  959. // if (!MobileTypes.ContainsKey(m.GetType()))
  960. // {
  961. // MobileTypes.Add(m.GetType(), 0);
  962. // }
  963. // else
  964. // {
  965. // MobileTypes[m.GetType()]++;
  966. // }
  967. // }
  968. // foreach (Type mt in MobileTypes.Keys)
  969. // {
  970. // if (MobileTypes[mt] > 100)
  971. // e.Mobile.SendMessage("{0}s: {1}", mt.Name, MobileTypes[mt]);
  972. // }
  973. //}
  974. //{
  975. // List<Mobile> Mobiles = new List<Mobile>();
  976. // Dictionary<Map, int> MobileTypes = new Dictionary<Map, int>();
  977. // foreach (Mobile m in World.Mobiles.Values)
  978. // {
  979. // if (m is RacePlayerMobile)
  980. // {
  981. // if (!MobileTypes.ContainsKey(m.Map))
  982. // {
  983. // MobileTypes.Add(m.Map, 0);
  984. // }
  985. // else
  986. // {
  987. // MobileTypes[m.Map]++;
  988. // }
  989. // }
  990. // }
  991. // foreach (Map mt in MobileTypes.Keys)
  992. // {
  993. // if (MobileTypes[mt] > 50)
  994. // e.Mobile.SendMessage("{0}: {1}", mt.Name, MobileTypes[mt]);
  995. // }
  996. //}
  997. //{
  998. // List<Mobile> Mobiles = new List<Mobile>();
  999. // Dictionary<Point3D, int> MobileTypes = new Dictionary<Point3D, int>();
  1000. // foreach (Mobile m in World.Mobiles.Values)
  1001. // {
  1002. // if (m is RacePlayerMobile)
  1003. // {
  1004. // if (!MobileTypes.ContainsKey(m.Location))
  1005. // {
  1006. // MobileTypes.Add(m.Location, 0);
  1007. // }
  1008. // else
  1009. // {
  1010. // MobileTypes[m.Location]++;
  1011. // }
  1012. // }
  1013. // }
  1014. // foreach (Point3D mt in MobileTypes.Keys)
  1015. // {
  1016. // if (MobileTypes[mt] > 50)
  1017. // e.Mobile.SendMessage("{0}/{1}: {2}", mt.X, mt.Y, MobileTypes[mt]);
  1018. // }
  1019. //}
  1020. }
  1021. }
  1022. }