AvatarsConquest/Source/Network/PacketHandlers.cs

2464 lines
No EOL
66 KiB
C#

/***************************************************************************
* PacketHandlers.cs
* -------------------
* begin : May 1, 2002
* copyright : (C) The RunUO Software Team
* email : info@runuo.com
*
* $Id$
*
***************************************************************************/
/***************************************************************************
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
***************************************************************************/
using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using Server.Accounting;
using Server.Gumps;
using Server.Targeting;
using Server.Items;
using Server.Menus;
using Server.Mobiles;
using Server.Movement;
using Server.Prompts;
using Server.HuePickers;
using Server.ContextMenus;
using Server.Diagnostics;
using CV = Server.ClientVersion;
namespace Server.Network
{
public enum MessageType
{
Regular = 0x00,
System = 0x01,
Emote = 0x02,
Label = 0x06,
Focus = 0x07,
Whisper = 0x08,
Yell = 0x09,
Spell = 0x0A,
Guild = 0x0D,
Alliance = 0x0E,
Command = 0x0F,
Encoded = 0xC0
}
public static class PacketHandlers
{
private static PacketHandler[] m_Handlers;
private static PacketHandler[] m_6017Handlers;
private static PacketHandler[] m_ExtendedHandlersLow;
private static Dictionary<int, PacketHandler> m_ExtendedHandlersHigh;
private static EncodedPacketHandler[] m_EncodedHandlersLow;
private static Dictionary<int, EncodedPacketHandler> m_EncodedHandlersHigh;
public static PacketHandler[] Handlers
{
get{ return m_Handlers; }
}
static PacketHandlers()
{
m_Handlers = new PacketHandler[0x100];
m_6017Handlers = new PacketHandler[0x100];
m_ExtendedHandlersLow = new PacketHandler[0x100];
m_ExtendedHandlersHigh = new Dictionary<int, PacketHandler>();
m_EncodedHandlersLow = new EncodedPacketHandler[0x100];
m_EncodedHandlersHigh = new Dictionary<int, EncodedPacketHandler>();
Register( 0x00, 104, false, new OnPacketReceive( CreateCharacter ) );
Register( 0x01, 5, false, new OnPacketReceive( Disconnect ) );
Register( 0x02, 7, true, new OnPacketReceive( MovementReq ) );
Register( 0x03, 0, true, new OnPacketReceive( AsciiSpeech ) );
Register( 0x04, 2, true, new OnPacketReceive( GodModeRequest ) );
Register( 0x05, 5, true, new OnPacketReceive( AttackReq ) );
Register( 0x06, 5, true, new OnPacketReceive( UseReq ) );
Register( 0x07, 7, true, new OnPacketReceive( LiftReq ) );
Register( 0x08, 14, true, new OnPacketReceive( DropReq ) );
Register( 0x09, 5, true, new OnPacketReceive( LookReq ) );
Register( 0x0A, 11, true, new OnPacketReceive( Edit ) );
Register( 0x12, 0, true, new OnPacketReceive( TextCommand ) );
Register( 0x13, 10, true, new OnPacketReceive( EquipReq ) );
Register( 0x14, 6, true, new OnPacketReceive( ChangeZ ) );
Register( 0x22, 3, true, new OnPacketReceive( Resynchronize ) );
Register( 0x2C, 2, true, new OnPacketReceive( DeathStatusResponse ) );
Register( 0x34, 10, true, new OnPacketReceive( MobileQuery ) );
Register( 0x3A, 0, true, new OnPacketReceive( ChangeSkillLock ) );
Register( 0x3B, 0, true, new OnPacketReceive( VendorBuyReply ) );
Register( 0x47, 11, true, new OnPacketReceive( NewTerrain ) );
Register( 0x48, 73, true, new OnPacketReceive( NewAnimData ) );
Register( 0x58, 106, true, new OnPacketReceive( NewRegion ) );
Register( 0x5D, 73, false, new OnPacketReceive( PlayCharacter ) );
Register( 0x61, 9, true, new OnPacketReceive( DeleteStatic ) );
Register( 0x6C, 19, true, new OnPacketReceive( TargetResponse ) );
Register( 0x6F, 0, true, new OnPacketReceive( SecureTrade ) );
Register( 0x72, 5, true, new OnPacketReceive( SetWarMode ) );
Register( 0x73, 2, false, new OnPacketReceive( PingReq ) );
Register( 0x75, 35, true, new OnPacketReceive( RenameRequest ) );
Register( 0x79, 9, true, new OnPacketReceive( ResourceQuery ) );
Register( 0x7E, 2, true, new OnPacketReceive( GodviewQuery ) );
Register( 0x7D, 13, true, new OnPacketReceive( MenuResponse ) );
Register( 0x80, 62, false, new OnPacketReceive( AccountLogin ) );
Register( 0x83, 39, false, new OnPacketReceive( DeleteCharacter ) );
Register( 0x91, 65, false, new OnPacketReceive( GameLogin ) );
Register( 0x95, 9, true, new OnPacketReceive( HuePickerResponse ) );
Register( 0x96, 0, true, new OnPacketReceive( GameCentralMoniter ) );
Register( 0x98, 0, true, new OnPacketReceive( MobileNameRequest ) );
Register( 0x9A, 0, true, new OnPacketReceive( AsciiPromptResponse ) );
Register( 0x9B, 258, true, new OnPacketReceive( HelpRequest ) );
Register( 0x9D, 51, true, new OnPacketReceive( GMSingle ) );
Register( 0x9F, 0, true, new OnPacketReceive( VendorSellReply ) );
Register( 0xA0, 3, false, new OnPacketReceive( PlayServer ) );
Register( 0xA4, 149, false, new OnPacketReceive( SystemInfo ) );
Register( 0xA7, 4, true, new OnPacketReceive( RequestScrollWindow ) );
Register( 0xAD, 0, true, new OnPacketReceive( UnicodeSpeech ) );
Register( 0xB1, 0, true, new OnPacketReceive( DisplayGumpResponse ) );
Register( 0xB5, 64, true, new OnPacketReceive( ChatRequest ) );
Register( 0xB6, 9, true, new OnPacketReceive( ObjectHelpRequest ) );
Register( 0xB8, 0, true, new OnPacketReceive( ProfileReq ) );
Register( 0xBB, 9, false, new OnPacketReceive( AccountID ) );
Register( 0xBD, 0, false, new OnPacketReceive( ClientVersion ) );
Register( 0xBE, 0, true, new OnPacketReceive( AssistVersion ) );
Register( 0xBF, 0, true, new OnPacketReceive( ExtendedCommand ) );
Register( 0xC2, 0, true, new OnPacketReceive( UnicodePromptResponse ) );
Register( 0xC8, 2, true, new OnPacketReceive( SetUpdateRange ) );
Register( 0xC9, 6, true, new OnPacketReceive( TripTime ) );
Register( 0xCA, 6, true, new OnPacketReceive( UTripTime ) );
Register( 0xCF, 0, false, new OnPacketReceive( AccountLogin ) );
Register( 0xD0, 0, true, new OnPacketReceive( ConfigurationFile ) );
Register( 0xD1, 2, true, new OnPacketReceive( LogoutReq ) );
Register( 0xD6, 0, true, new OnPacketReceive( BatchQueryProperties ) );
Register( 0xD7, 0, true, new OnPacketReceive( EncodedCommand ) );
Register( 0xE1, 0, false, new OnPacketReceive( ClientType ) );
Register( 0xEF, 21, false, new OnPacketReceive( LoginServerSeed ) );
Register( 0xF8, 106, false, new OnPacketReceive( CreateCharacter70160 ) );
Register6017( 0x08, 15, true, new OnPacketReceive( DropReq6017 ) );
RegisterExtended( 0x05, false, new OnPacketReceive( ScreenSize ) );
RegisterExtended( 0x06, true, new OnPacketReceive( PartyMessage ) );
RegisterExtended( 0x07, true, new OnPacketReceive( QuestArrow ) );
RegisterExtended( 0x09, true, new OnPacketReceive( DisarmRequest ) );
RegisterExtended( 0x0A, true, new OnPacketReceive( StunRequest ) );
RegisterExtended( 0x0B, false, new OnPacketReceive( Language ) );
RegisterExtended( 0x0C, true, new OnPacketReceive( CloseStatus ) );
RegisterExtended( 0x0E, true, new OnPacketReceive( Animate ) );
RegisterExtended( 0x0F, false, new OnPacketReceive( Empty ) ); // What's this?
RegisterExtended( 0x10, true, new OnPacketReceive( QueryProperties ) );
RegisterExtended( 0x13, true, new OnPacketReceive( ContextMenuRequest ) );
RegisterExtended( 0x15, true, new OnPacketReceive( ContextMenuResponse ) );
RegisterExtended( 0x1A, true, new OnPacketReceive( StatLockChange ) );
RegisterExtended( 0x1C, true, new OnPacketReceive( CastSpell ) );
RegisterExtended( 0x24, false, new OnPacketReceive( UnhandledBF ) );
RegisterEncoded( 0x19, true, new OnEncodedPacketReceive( SetAbility ) );
RegisterEncoded( 0x28, true, new OnEncodedPacketReceive( GuildGumpRequest ) );
RegisterEncoded( 0x32, true, new OnEncodedPacketReceive( QuestGumpRequest ) );
}
public static void Register( int packetID, int length, bool ingame, OnPacketReceive onReceive )
{
m_Handlers[packetID] = new PacketHandler( packetID, length, ingame, onReceive );
if ( m_6017Handlers[packetID] == null )
m_6017Handlers[packetID] = new PacketHandler( packetID, length, ingame, onReceive );
}
public static PacketHandler GetHandler( int packetID )
{
return m_Handlers[packetID];
}
public static void Register6017( int packetID, int length, bool ingame, OnPacketReceive onReceive )
{
m_6017Handlers[packetID] = new PacketHandler( packetID, length, ingame, onReceive );
}
public static PacketHandler Get6017Handler( int packetID )
{
return m_6017Handlers[packetID];
}
public static void RegisterExtended( int packetID, bool ingame, OnPacketReceive onReceive )
{
if ( packetID >= 0 && packetID < 0x100 )
m_ExtendedHandlersLow[packetID] = new PacketHandler( packetID, 0, ingame, onReceive );
else
m_ExtendedHandlersHigh[packetID] = new PacketHandler( packetID, 0, ingame, onReceive );
}
public static PacketHandler GetExtendedHandler( int packetID )
{
if ( packetID >= 0 && packetID < 0x100 )
return m_ExtendedHandlersLow[packetID];
else
{
PacketHandler handler;
m_ExtendedHandlersHigh.TryGetValue( packetID, out handler );
return handler;
}
}
public static void RemoveExtendedHandler( int packetID )
{
if ( packetID >= 0 && packetID < 0x100 )
m_ExtendedHandlersLow[packetID] = null;
else
m_ExtendedHandlersHigh.Remove( packetID );
}
public static void RegisterEncoded( int packetID, bool ingame, OnEncodedPacketReceive onReceive )
{
if ( packetID >= 0 && packetID < 0x100 )
m_EncodedHandlersLow[packetID] = new EncodedPacketHandler( packetID, ingame, onReceive );
else
m_EncodedHandlersHigh[packetID] = new EncodedPacketHandler( packetID, ingame, onReceive );
}
public static EncodedPacketHandler GetEncodedHandler( int packetID )
{
if ( packetID >= 0 && packetID < 0x100 )
return m_EncodedHandlersLow[packetID];
else
{
EncodedPacketHandler handler;
m_EncodedHandlersHigh.TryGetValue( packetID, out handler );
return handler;
}
}
public static void RemoveEncodedHandler( int packetID )
{
if ( packetID >= 0 && packetID < 0x100 )
m_EncodedHandlersLow[packetID] = null;
else
m_EncodedHandlersHigh.Remove( packetID );
}
public static void RegisterThrottler( int packetID, ThrottlePacketCallback t )
{
PacketHandler ph = GetHandler( packetID );
if ( ph != null )
ph.ThrottleCallback = t;
ph = Get6017Handler( packetID );
if ( ph != null )
ph.ThrottleCallback = t;
}
private static void UnhandledBF( NetState state, PacketReader pvSrc )
{
}
public static void Empty( NetState state, PacketReader pvSrc )
{
}
public static void SetAbility( NetState state, IEntity e, EncodedReader reader )
{
EventSink.InvokeSetAbility( new SetAbilityEventArgs( state.Mobile, reader.ReadInt32() ) );
}
public static void GuildGumpRequest( NetState state, IEntity e, EncodedReader reader )
{
EventSink.InvokeGuildGumpRequest( new GuildGumpRequestArgs( state.Mobile ) );
}
public static void QuestGumpRequest( NetState state, IEntity e, EncodedReader reader )
{
EventSink.InvokeQuestGumpRequest( new QuestGumpRequestArgs( state.Mobile ) );
}
public static void EncodedCommand( NetState state, PacketReader pvSrc )
{
IEntity e = World.FindEntity( pvSrc.ReadInt32() );
int packetID = pvSrc.ReadUInt16();
EncodedPacketHandler ph = GetEncodedHandler( packetID );
if ( ph != null )
{
if ( ph.Ingame && state.Mobile == null )
{
Console.WriteLine( "Client: {0}: Sent ingame packet (0xD7x{1:X2}) before having been attached to a mobile", state, packetID );
state.Dispose();
}
else if ( ph.Ingame && state.Mobile.Deleted )
{
state.Dispose();
}
else
{
ph.OnReceive( state, e, new EncodedReader( pvSrc ) );
}
}
else
{
pvSrc.Trace( state );
}
}
public static void RenameRequest( NetState state, PacketReader pvSrc )
{
Mobile from = state.Mobile;
Mobile targ = World.FindMobile( pvSrc.ReadInt32() );
if ( targ != null )
EventSink.InvokeRenameRequest( new RenameRequestEventArgs( from, targ, pvSrc.ReadStringSafe() ) );
}
public static void ChatRequest( NetState state, PacketReader pvSrc )
{
EventSink.InvokeChatRequest( new ChatRequestEventArgs( state.Mobile ) );
}
public static void SecureTrade( NetState state, PacketReader pvSrc )
{
switch ( pvSrc.ReadByte() )
{
case 1: // Cancel
{
Serial serial = pvSrc.ReadInt32();
SecureTradeContainer cont = World.FindItem( serial ) as SecureTradeContainer;
if ( cont != null && cont.Trade != null && (cont.Trade.From.Mobile == state.Mobile || cont.Trade.To.Mobile == state.Mobile) )
cont.Trade.Cancel();
break;
}
case 2: // Check
{
Serial serial = pvSrc.ReadInt32();
SecureTradeContainer cont = World.FindItem( serial ) as SecureTradeContainer;
if ( cont != null )
{
SecureTrade trade = cont.Trade;
bool value = ( pvSrc.ReadInt32() != 0 );
if ( trade != null && trade.From.Mobile == state.Mobile )
{
trade.From.Accepted = value;
trade.Update();
}
else if ( trade != null && trade.To.Mobile == state.Mobile )
{
trade.To.Accepted = value;
trade.Update();
}
}
break;
}
}
}
public static void VendorBuyReply( NetState state, PacketReader pvSrc )
{
pvSrc.Seek( 1, SeekOrigin.Begin );
int msgSize = pvSrc.ReadUInt16();
Mobile vendor = World.FindMobile( pvSrc.ReadInt32() );
byte flag = pvSrc.ReadByte();
if ( vendor == null )
{
return;
}
else if ( vendor.Deleted || !Utility.RangeCheck( vendor.Location, state.Mobile.Location, 10 ) )
{
state.Send( new EndVendorBuy( vendor ) );
return;
}
if ( flag == 0x02 )
{
msgSize -= 1+2+4+1;
if ( (msgSize / 7) > 100 )
return;
List<BuyItemResponse> buyList = new List<BuyItemResponse>( msgSize / 7 );
for ( ;msgSize>0;msgSize-=7)
{
byte layer = pvSrc.ReadByte();
Serial serial = pvSrc.ReadInt32();
int amount = pvSrc.ReadInt16();
buyList.Add( new BuyItemResponse( serial, amount ) );
}
if ( buyList.Count > 0 )
{
IVendor v = vendor as IVendor;
if ( v != null && v.OnBuyItems( state.Mobile, buyList ) )
state.Send( new EndVendorBuy( vendor ) );
}
}
else
{
state.Send( new EndVendorBuy( vendor ) );
}
}
public static void VendorSellReply( NetState state, PacketReader pvSrc )
{
Serial serial = pvSrc.ReadInt32();
Mobile vendor = World.FindMobile( serial );
if ( vendor == null )
{
return;
}
else if ( vendor.Deleted || !Utility.RangeCheck( vendor.Location, state.Mobile.Location, 10 ) )
{
state.Send( new EndVendorSell( vendor ) );
return;
}
int count = pvSrc.ReadUInt16();
if ( count < 100 && pvSrc.Size == (1+2+4+2+(count*6)) )
{
List<SellItemResponse> sellList = new List<SellItemResponse>( count );
for (int i=0;i<count;i++)
{
Item item = World.FindItem( pvSrc.ReadInt32() );
int Amount = pvSrc.ReadInt16();
if ( item != null && Amount > 0 )
sellList.Add( new SellItemResponse( item, Amount ) );
}
if ( sellList.Count > 0 )
{
IVendor v = vendor as IVendor;
if ( v != null && v.OnSellItems( state.Mobile, sellList ) )
state.Send( new EndVendorSell( vendor ) );
}
}
}
public static void DeleteCharacter( NetState state, PacketReader pvSrc )
{
pvSrc.Seek( 30, SeekOrigin.Current );
int index = pvSrc.ReadInt32();
EventSink.InvokeDeleteRequest( new DeleteRequestEventArgs( state, index ) );
}
public static void ResourceQuery( NetState state, PacketReader pvSrc )
{
if ( VerifyGC( state ) )
{
}
}
public static void GameCentralMoniter( NetState state, PacketReader pvSrc )
{
if ( VerifyGC( state ) )
{
int type = pvSrc.ReadByte();
int num1 = pvSrc.ReadInt32();
Console.WriteLine( "God Client: {0}: Game central moniter", state );
Console.WriteLine( " - Type: {0}", type );
Console.WriteLine( " - Number: {0}", num1 );
pvSrc.Trace( state );
}
}
public static void GodviewQuery( NetState state, PacketReader pvSrc )
{
if ( VerifyGC( state ) )
{
Console.WriteLine( "God Client: {0}: Godview query 0x{1:X}", state, pvSrc.ReadByte() );
}
}
public static void GMSingle( NetState state, PacketReader pvSrc )
{
if ( VerifyGC( state ) )
pvSrc.Trace( state );
}
public static void DeathStatusResponse( NetState state, PacketReader pvSrc )
{
// Ignored
}
public static void ObjectHelpRequest( NetState state, PacketReader pvSrc )
{
Mobile from = state.Mobile;
Serial serial = pvSrc.ReadInt32();
int unk = pvSrc.ReadByte();
string lang = pvSrc.ReadString( 3 );
if ( serial.IsItem )
{
Item item = World.FindItem( serial );
if ( item != null && from.Map == item.Map && Utility.InUpdateRange( item.GetWorldLocation(), from.Location ) && from.CanSee( item ) )
item.OnHelpRequest( from );
}
else if ( serial.IsMobile )
{
Mobile m = World.FindMobile( serial );
if ( m != null && from.Map == m.Map && Utility.InUpdateRange( m.Location, from.Location ) && from.CanSee( m ) )
m.OnHelpRequest( m );
}
}
public static void MobileNameRequest( NetState state, PacketReader pvSrc )
{
Mobile m = World.FindMobile( pvSrc.ReadInt32() );
if ( m != null && Utility.InUpdateRange( state.Mobile, m ) && state.Mobile.CanSee( m ) )
state.Send( new MobileName( m ) );
}
public static void RequestScrollWindow( NetState state, PacketReader pvSrc )
{
int lastTip = pvSrc.ReadInt16();
int type = pvSrc.ReadByte();
}
public static void AttackReq( NetState state, PacketReader pvSrc )
{
Mobile from = state.Mobile;
Mobile m = World.FindMobile( pvSrc.ReadInt32() );
if ( m != null )
from.Attack( m );
}
public static void HuePickerResponse( NetState state, PacketReader pvSrc ) {
int serial = pvSrc.ReadInt32();
int value = pvSrc.ReadInt16();
int hue = pvSrc.ReadInt16() & 0x3FFF;
hue = Utility.ClipDyedHue( hue );
foreach ( HuePicker huePicker in state.HuePickers ) {
if ( huePicker.Serial == serial ) {
state.RemoveHuePicker( huePicker );
huePicker.OnResponse( hue );
break;
}
}
}
public static void TripTime( NetState state, PacketReader pvSrc )
{
int unk1 = pvSrc.ReadByte();
int unk2 = pvSrc.ReadInt32();
state.Send( new TripTimeResponse( unk1 ) );
}
public static void UTripTime( NetState state, PacketReader pvSrc )
{
int unk1 = pvSrc.ReadByte();
int unk2 = pvSrc.ReadInt32();
state.Send( new UTripTimeResponse( unk1 ) );
}
public static void ChangeZ( NetState state, PacketReader pvSrc )
{
if ( VerifyGC( state ) )
{
int x = pvSrc.ReadInt16();
int y = pvSrc.ReadInt16();
int z = pvSrc.ReadSByte();
Console.WriteLine( "God Client: {0}: Change Z ({1}, {2}, {3})", state, x, y, z );
}
}
public static void SystemInfo( NetState state, PacketReader pvSrc )
{
int v1 = pvSrc.ReadByte();
int v2 = pvSrc.ReadUInt16();
int v3 = pvSrc.ReadByte();
string s1 = pvSrc.ReadString( 32 );
string s2 = pvSrc.ReadString( 32 );
string s3 = pvSrc.ReadString( 32 );
string s4 = pvSrc.ReadString( 32 );
int v4 = pvSrc.ReadUInt16();
int v5 = pvSrc.ReadUInt16();
int v6 = pvSrc.ReadInt32();
int v7 = pvSrc.ReadInt32();
int v8 = pvSrc.ReadInt32();
}
public static void Edit( NetState state, PacketReader pvSrc )
{
if ( VerifyGC( state ) )
{
int type = pvSrc.ReadByte(); // 10 = static, 7 = npc, 4 = dynamic
int x = pvSrc.ReadInt16();
int y = pvSrc.ReadInt16();
int id = pvSrc.ReadInt16();
int z = pvSrc.ReadSByte();
int hue = pvSrc.ReadUInt16();
Console.WriteLine( "God Client: {0}: Edit {6} ({1}, {2}, {3}) 0x{4:X} (0x{5:X})", state, x, y, z, id, hue, type );
}
}
public static void DeleteStatic( NetState state, PacketReader pvSrc )
{
if ( VerifyGC( state ) )
{
int x = pvSrc.ReadInt16();
int y = pvSrc.ReadInt16();
int z = pvSrc.ReadInt16();
int id = pvSrc.ReadUInt16();
Console.WriteLine( "God Client: {0}: Delete Static ({1}, {2}, {3}) 0x{4:X}", state, x, y, z, id );
}
}
public static void NewAnimData( NetState state, PacketReader pvSrc )
{
if ( VerifyGC( state ) )
{
Console.WriteLine( "God Client: {0}: New tile animation", state );
pvSrc.Trace( state );
}
}
public static void NewTerrain( NetState state, PacketReader pvSrc )
{
if ( VerifyGC( state ) )
{
int x = pvSrc.ReadInt16();
int y = pvSrc.ReadInt16();
int id = pvSrc.ReadUInt16();
int width = pvSrc.ReadInt16();
int height = pvSrc.ReadInt16();
Console.WriteLine( "God Client: {0}: New Terrain ({1}, {2})+({3}, {4}) 0x{5:X4}", state, x, y, width, height, id );
}
}
public static void NewRegion( NetState state, PacketReader pvSrc )
{
if ( VerifyGC( state ) )
{
string name = pvSrc.ReadString( 40 );
int unk = pvSrc.ReadInt32();
int x = pvSrc.ReadInt16();
int y = pvSrc.ReadInt16();
int width = pvSrc.ReadInt16();
int height = pvSrc.ReadInt16();
int zStart = pvSrc.ReadInt16();
int zEnd = pvSrc.ReadInt16();
string desc = pvSrc.ReadString( 40 );
int soundFX = pvSrc.ReadInt16();
int music = pvSrc.ReadInt16();
int nightFX = pvSrc.ReadInt16();
int dungeon = pvSrc.ReadByte();
int light = pvSrc.ReadInt16();
Console.WriteLine( "God Client: {0}: New Region '{1}' ('{2}')", state, name, desc );
}
}
public static void AccountID( NetState state, PacketReader pvSrc )
{
}
public static bool VerifyGC( NetState state )
{
if ( state.Mobile == null || state.Mobile.AccessLevel <= AccessLevel.Counselor )
{
if ( state.Running )
Console.WriteLine( "Warning: {0}: Player using godclient, disconnecting", state );
state.Dispose();
return false;
}
else
{
return true;
}
}
public static void TextCommand( NetState state, PacketReader pvSrc )
{
int type = pvSrc.ReadByte();
string command = pvSrc.ReadString();
Mobile m = state.Mobile;
switch ( type )
{
case 0x00: // Go
{
if ( VerifyGC( state ) )
{
try
{
string[] split = command.Split( ' ' );
int x = Utility.ToInt32( split[0] );
int y = Utility.ToInt32( split[1] );
int z;
if ( split.Length >= 3 )
z = Utility.ToInt32( split[2] );
else if ( m.Map != null )
z = m.Map.GetAverageZ( x, y );
else
z = 0;
m.Location = new Point3D( x, y, z );
}
catch
{
}
}
break;
}
case 0xC7: // Animate
{
EventSink.InvokeAnimateRequest( new AnimateRequestEventArgs( m, command ) );
break;
}
case 0x24: // Use skill
{
int skillIndex;
if ( !int.TryParse( command.Split( ' ' )[0], out skillIndex ) )
break;
Skills.UseSkill( m, skillIndex );
break;
}
case 0x43: // Open spellbook
{
int booktype;
if ( !int.TryParse( command, out booktype ) )
booktype = 1;
EventSink.InvokeOpenSpellbookRequest( new OpenSpellbookRequestEventArgs( m, booktype ) );
break;
}
case 0x27: // Cast spell from book
{
string[] split = command.Split( ' ' );
if ( split.Length > 0 )
{
int spellID = Utility.ToInt32( split[0] ) - 1;
int serial = split.Length > 1 ? Utility.ToInt32( split[1] ) : -1;
EventSink.InvokeCastSpellRequest( new CastSpellRequestEventArgs( m, spellID, World.FindItem( serial ) ) );
}
break;
}
case 0x58: // Open door
{
EventSink.InvokeOpenDoorMacroUsed( new OpenDoorMacroEventArgs( m ) );
break;
}
case 0x56: // Cast spell from macro
{
int spellID = Utility.ToInt32( command ) - 1;
EventSink.InvokeCastSpellRequest( new CastSpellRequestEventArgs( m, spellID, null ) );
break;
}
default:
{
Console.WriteLine( "Client: {0}: Unknown text-command type 0x{1:X2}: {2}", state, type, command );
break;
}
}
}
public static void GodModeRequest( NetState state, PacketReader pvSrc )
{
if ( VerifyGC( state ) )
{
state.Send( new GodModeReply( pvSrc.ReadBoolean() ) );
}
}
public static void AsciiPromptResponse( NetState state, PacketReader pvSrc )
{
int serial = pvSrc.ReadInt32();
int prompt = pvSrc.ReadInt32();
int type = pvSrc.ReadInt32();
string text = pvSrc.ReadStringSafe();
if ( text.Length > 128 )
return;
Mobile from = state.Mobile;
Prompt p = from.Prompt;
if ( p != null && p.Serial == serial && p.Serial == prompt )
{
from.Prompt = null;
if ( type == 0 )
p.OnCancel( from );
else
p.OnResponse( from, text );
}
}
public static void UnicodePromptResponse( NetState state, PacketReader pvSrc )
{
int serial = pvSrc.ReadInt32();
int prompt = pvSrc.ReadInt32();
int type = pvSrc.ReadInt32();
string lang = pvSrc.ReadString( 4 );
string text = pvSrc.ReadUnicodeStringLESafe();
if ( text.Length > 128 )
return;
Mobile from = state.Mobile;
Prompt p = from.Prompt;
if ( p != null && p.Serial == serial && p.Serial == prompt )
{
from.Prompt = null;
if ( type == 0 )
p.OnCancel( from );
else
p.OnResponse( from, text );
}
}
public static void MenuResponse( NetState state, PacketReader pvSrc ) {
int serial = pvSrc.ReadInt32();
int menuID = pvSrc.ReadInt16(); // unused in our implementation
int index = pvSrc.ReadInt16();
int itemID = pvSrc.ReadInt16();
int hue = pvSrc.ReadInt16();
index -= 1; // convert from 1-based to 0-based
foreach ( IMenu menu in state.Menus ) {
if ( menu.Serial == serial ) {
state.RemoveMenu( menu );
if ( index >= 0 && index < menu.EntryLength ) {
menu.OnResponse( state, index );
} else {
menu.OnCancel( state );
}
break;
}
}
}
public static void ProfileReq( NetState state, PacketReader pvSrc )
{
int type = pvSrc.ReadByte();
Serial serial = pvSrc.ReadInt32();
Mobile beholder = state.Mobile;
Mobile beheld = World.FindMobile( serial );
if ( beheld == null )
return;
switch ( type )
{
case 0x00: // display request
{
EventSink.InvokeProfileRequest( new ProfileRequestEventArgs( beholder, beheld ) );
break;
}
case 0x01: // edit request
{
pvSrc.ReadInt16(); // Skip
int length = pvSrc.ReadUInt16();
if ( length > 511 )
return;
string text = pvSrc.ReadUnicodeString( length );
EventSink.InvokeChangeProfileRequest( new ChangeProfileRequestEventArgs( beholder, beheld, text ) );
break;
}
}
}
public static void Disconnect( NetState state, PacketReader pvSrc )
{
int minusOne = pvSrc.ReadInt32();
}
public static void LiftReq( NetState state, PacketReader pvSrc )
{
Serial serial = pvSrc.ReadInt32();
int amount = pvSrc.ReadUInt16();
Item item = World.FindItem( serial );
bool rejected;
LRReason reject;
state.Mobile.Lift( item, amount, out rejected, out reject );
}
public static void EquipReq( NetState state, PacketReader pvSrc )
{
Mobile from = state.Mobile;
Item item = from.Holding;
bool valid = ( item != null && item.HeldBy == from && item.Map == Map.Internal );
from.Holding = null;
if ( !valid ) {
return;
}
pvSrc.Seek( 5, SeekOrigin.Current );
Mobile to = World.FindMobile( pvSrc.ReadInt32() );
if ( to == null )
to = from;
if ( !to.AllowEquipFrom( from ) || !to.EquipItem( item ) )
item.Bounce( from );
item.ClearBounce();
}
public static void DropReq( NetState state, PacketReader pvSrc )
{
pvSrc.ReadInt32(); // serial, ignored
int x = pvSrc.ReadInt16();
int y = pvSrc.ReadInt16();
int z = pvSrc.ReadSByte();
Serial dest = pvSrc.ReadInt32();
Point3D loc = new Point3D( x, y, z );
Mobile from = state.Mobile;
if ( dest.IsMobile )
from.Drop( World.FindMobile( dest ), loc );
else if ( dest.IsItem )
from.Drop( World.FindItem( dest ), loc );
else
from.Drop( loc );
}
public static void DropReq6017( NetState state, PacketReader pvSrc )
{
pvSrc.ReadInt32(); // serial, ignored
int x = pvSrc.ReadInt16();
int y = pvSrc.ReadInt16();
int z = pvSrc.ReadSByte();
pvSrc.ReadByte(); // Grid Location?
Serial dest = pvSrc.ReadInt32();
Point3D loc = new Point3D( x, y, z );
Mobile from = state.Mobile;
if ( dest.IsMobile )
from.Drop( World.FindMobile( dest ), loc );
else if ( dest.IsItem )
from.Drop( World.FindItem( dest ), loc );
else
from.Drop( loc );
}
public static void ConfigurationFile( NetState state, PacketReader pvSrc )
{
}
public static void LogoutReq( NetState state, PacketReader pvSrc )
{
state.Send( new LogoutAck() );
}
public static void ChangeSkillLock( NetState state, PacketReader pvSrc )
{
Skill s = state.Mobile.Skills[pvSrc.ReadInt16()];
if ( s != null )
s.SetLockNoRelay( (SkillLock)pvSrc.ReadByte() );
}
public static void HelpRequest( NetState state, PacketReader pvSrc )
{
EventSink.InvokeHelpRequest( new HelpRequestEventArgs( state.Mobile ) );
}
public static void TargetResponse( NetState state, PacketReader pvSrc )
{
int type = pvSrc.ReadByte();
int targetID = pvSrc.ReadInt32();
int flags = pvSrc.ReadByte();
Serial serial = pvSrc.ReadInt32();
int x = pvSrc.ReadInt16(), y = pvSrc.ReadInt16(), z = pvSrc.ReadInt16();
int graphic = pvSrc.ReadUInt16();
if ( targetID == unchecked( (int) 0xDEADBEEF ) )
return;
Mobile from = state.Mobile;
Target t = from.Target;
if ( t != null )
{
TargetProfile prof = TargetProfile.Acquire( t.GetType() );
if ( prof != null ) {
prof.Start();
}
try {
if ( x == -1 && y == -1 && !serial.IsValid )
{
// User pressed escape
t.Cancel( from, TargetCancelType.Canceled );
}
else
{
object toTarget;
if ( type == 1 )
{
if ( graphic == 0 )
{
toTarget = new LandTarget( new Point3D( x, y, z ), from.Map );
}
else
{
Map map = from.Map;
if ( map == null || map == Map.Internal )
{
t.Cancel( from, TargetCancelType.Canceled );
return;
}
else
{
StaticTile[] tiles = map.Tiles.GetStaticTiles( x, y, !t.DisallowMultis );
bool valid = false;
if ( state.HighSeas ) {
ItemData id = TileData.ItemTable[graphic&TileData.MaxItemValue];
if ( id.Surface ) {
z -= id.Height;
}
}
for ( int i = 0; !valid && i < tiles.Length; ++i )
{
if ( tiles[i].Z == z && tiles[i].ID == graphic )
valid = true;
}
if ( !valid )
{
t.Cancel( from, TargetCancelType.Canceled );
return;
}
else
{
toTarget = new StaticTarget( new Point3D( x, y, z ), graphic );
}
}
}
}
else if ( serial.IsMobile )
{
toTarget = World.FindMobile( serial );
}
else if ( serial.IsItem )
{
toTarget = World.FindItem( serial );
}
else
{
t.Cancel( from, TargetCancelType.Canceled );
return;
}
t.Invoke( from, toTarget );
}
} finally {
if ( prof != null ) {
prof.Finish();
}
}
}
}
public static void DisplayGumpResponse( NetState state, PacketReader pvSrc ) {
int serial = pvSrc.ReadInt32();
int typeID = pvSrc.ReadInt32();
int buttonID = pvSrc.ReadInt32();
foreach ( Gump gump in state.Gumps ) {
if ( gump.Serial == serial && gump.TypeID == typeID ) {
int switchCount = pvSrc.ReadInt32();
if ( switchCount < 0 || switchCount > gump.m_Switches ) {
state.WriteConsole( "Invalid gump response, disconnecting..." );
state.Dispose();
return;
}
int[] switches = new int[switchCount];
for ( int j = 0; j < switches.Length; ++j )
switches[j] = pvSrc.ReadInt32();
int textCount = pvSrc.ReadInt32();
if ( textCount < 0 || textCount > gump.m_TextEntries ) {
state.WriteConsole( "Invalid gump response, disconnecting..." );
state.Dispose();
return;
}
TextRelay[] textEntries = new TextRelay[textCount];
for ( int j = 0; j < textEntries.Length; ++j ) {
int entryID = pvSrc.ReadUInt16();
int textLength = pvSrc.ReadUInt16();
if ( textLength > 239 ) {
state.WriteConsole( "Invalid gump response, disconnecting..." );
state.Dispose();
return;
}
string text = pvSrc.ReadUnicodeStringSafe( textLength );
textEntries[j] = new TextRelay( entryID, text );
}
state.RemoveGump( gump );
GumpProfile prof = GumpProfile.Acquire( gump.GetType() );
if ( prof != null ) {
prof.Start();
}
gump.OnResponse( state, new RelayInfo( buttonID, switches, textEntries ) );
if ( prof != null ) {
prof.Finish();
}
return;
}
}
}
public static void SetWarMode( NetState state, PacketReader pvSrc )
{
state.Mobile.DelayChangeWarmode( pvSrc.ReadBoolean() );
}
public static void Resynchronize( NetState state, PacketReader pvSrc )
{
Mobile m = state.Mobile;
if ( state.StygianAbyss ) {
state.Send( new MobileUpdate( m ) );
state.Send( new MobileIncoming( m, m ) );
} else {
state.Send( new MobileUpdateOld( m ) );
state.Send( new MobileIncomingOld( m, m ) );
}
m.SendEverything();
state.Sequence = 0;
m.ClearFastwalkStack();
}
private static int[] m_EmptyInts = new int[0];
public static void AsciiSpeech( NetState state, PacketReader pvSrc )
{
Mobile from = state.Mobile;
MessageType type = (MessageType)pvSrc.ReadByte();
int hue = pvSrc.ReadInt16();
pvSrc.ReadInt16(); // font
string text = pvSrc.ReadStringSafe().Trim();
if ( text.Length <= 0 || text.Length > 128 )
return;
if ( !Enum.IsDefined( typeof( MessageType ), type ) )
type = MessageType.Regular;
from.DoSpeech( text, m_EmptyInts, type, Utility.ClipDyedHue( hue ) );
}
private static KeywordList m_KeywordList = new KeywordList();
public static void UnicodeSpeech( NetState state, PacketReader pvSrc )
{
Mobile from = state.Mobile;
MessageType type = (MessageType)pvSrc.ReadByte();
int hue = pvSrc.ReadInt16();
pvSrc.ReadInt16(); // font
string lang = pvSrc.ReadString( 4 );
string text;
bool isEncoded = (type & MessageType.Encoded) != 0;
int[] keywords;
if ( isEncoded )
{
int value = pvSrc.ReadInt16();
int count = (value & 0xFFF0) >> 4;
int hold = value & 0xF;
if ( count < 0 || count > 50 )
return;
KeywordList keyList = m_KeywordList;
for ( int i = 0; i < count; ++i )
{
int speechID;
if ( (i & 1) == 0 )
{
hold <<= 8;
hold |= pvSrc.ReadByte();
speechID = hold;
hold = 0;
}
else
{
value = pvSrc.ReadInt16();
speechID = (value & 0xFFF0) >> 4;
hold = value & 0xF;
}
if ( !keyList.Contains( speechID ) )
keyList.Add( speechID );
}
text = pvSrc.ReadUTF8StringSafe();
keywords = keyList.ToArray();
}
else
{
text = pvSrc.ReadUnicodeStringSafe();
keywords = m_EmptyInts;
}
text = text.Trim();
if ( text.Length <= 0 || text.Length > 128 )
return;
type &= ~MessageType.Encoded;
if ( !Enum.IsDefined( typeof( MessageType ), type ) )
type = MessageType.Regular;
from.Language = lang;
from.DoSpeech( text, keywords, type, Utility.ClipDyedHue( hue ) );
}
public static void UseReq( NetState state, PacketReader pvSrc )
{
Mobile from = state.Mobile;
if ( from.AccessLevel >= AccessLevel.Counselor || DateTime.Now >= from.NextActionTime )
{
int value = pvSrc.ReadInt32();
if ( (value & ~0x7FFFFFFF) != 0 )
{
from.OnPaperdollRequest();
}
else
{
Serial s = value;
if ( s.IsMobile )
{
Mobile m = World.FindMobile( s );
if ( m != null && !m.Deleted )
from.Use( m );
}
else if ( s.IsItem )
{
Item item = World.FindItem( s );
if ( item != null && !item.Deleted )
from.Use( item );
}
}
from.NextActionTime = DateTime.Now + TimeSpan.FromSeconds( 0.5 );
}
else
{
from.SendActionMessage();
}
}
private static bool m_SingleClickProps;
public static bool SingleClickProps
{
get{ return m_SingleClickProps; }
set{ m_SingleClickProps = value; }
}
public static void LookReq( NetState state, PacketReader pvSrc )
{
Mobile from = state.Mobile;
Serial s = pvSrc.ReadInt32();
if ( s.IsMobile )
{
Mobile m = World.FindMobile( s );
if ( m != null && from.CanSee( m ) && Utility.InUpdateRange( from, m ) )
{
if ( m_SingleClickProps )
{
m.OnAosSingleClick( from );
}
else
{
if ( from.Region.OnSingleClick( from, m ) )
m.OnSingleClick( from );
}
}
}
else if ( s.IsItem )
{
Item item = World.FindItem( s );
if ( item != null && !item.Deleted && from.CanSee( item ) && Utility.InUpdateRange( from.Location, item.GetWorldLocation() ) )
{
if ( m_SingleClickProps )
{
item.OnAosSingleClick( from );
}
else if ( from.Region.OnSingleClick( from, item ) )
{
if ( item.Parent is Item )
((Item)item.Parent).OnSingleClickContained( from, item );
item.OnSingleClick( from );
}
}
}
}
public static void PingReq( NetState state, PacketReader pvSrc )
{
state.Send( PingAck.Instantiate( pvSrc.ReadByte() ) );
}
public static void SetUpdateRange( NetState state, PacketReader pvSrc )
{
state.Send( ChangeUpdateRange.Instantiate( 18 ) );
}
private const int BadFood = unchecked( (int)0xBAADF00D );
private const int BadUOTD = unchecked( (int)0xFFCEFFCE );
public static void MovementReq( NetState state, PacketReader pvSrc )
{
Direction dir = (Direction)pvSrc.ReadByte();
int seq = pvSrc.ReadByte();
int key = pvSrc.ReadInt32();
Mobile m = state.Mobile;
if ( (state.Sequence == 0 && seq != 0) || !m.Move( dir ) )
{
state.Send( new MovementRej( seq, m ) );
state.Sequence = 0;
m.ClearFastwalkStack();
}
else
{
++seq;
if ( seq == 256 )
seq = 1;
state.Sequence = seq;
}
}
public static int[] m_ValidAnimations = new int[]
{
6, 21, 32, 33,
100, 101, 102,
103, 104, 105,
106, 107, 108,
109, 110, 111,
112, 113, 114,
115, 116, 117,
118, 119, 120,
121, 123, 124,
125, 126, 127,
128
};
public static int[] ValidAnimations{ get{ return m_ValidAnimations; } set{ m_ValidAnimations = value; } }
public static void Animate( NetState state, PacketReader pvSrc )
{
Mobile from = state.Mobile;
int action = pvSrc.ReadInt32();
bool ok = false;
for ( int i = 0; !ok && i < m_ValidAnimations.Length; ++i )
ok = ( action == m_ValidAnimations[i] );
if ( from != null && ok && from.Alive && from.Body.IsHuman && !from.Mounted )
from.Animate( action, 7, 1, true, false, 0 );
}
public static void QuestArrow( NetState state, PacketReader pvSrc )
{
bool rightClick = pvSrc.ReadBoolean();
Mobile from = state.Mobile;
if ( from != null && from.QuestArrow != null )
from.QuestArrow.OnClick( rightClick );
}
public static void ExtendedCommand( NetState state, PacketReader pvSrc )
{
int packetID = pvSrc.ReadUInt16();
PacketHandler ph = GetExtendedHandler( packetID );
if ( ph != null )
{
if ( ph.Ingame && state.Mobile == null )
{
Console.WriteLine( "Client: {0}: Sent ingame packet (0xBFx{1:X2}) before having been attached to a mobile", state, packetID );
state.Dispose();
}
else if ( ph.Ingame && state.Mobile.Deleted )
{
state.Dispose();
}
else
{
ph.OnReceive( state, pvSrc );
}
}
else
{
pvSrc.Trace( state );
}
}
public static void CastSpell( NetState state, PacketReader pvSrc )
{
Mobile from = state.Mobile;
if ( from == null )
return;
Item spellbook = null;
if ( pvSrc.ReadInt16() == 1 )
spellbook = World.FindItem( pvSrc.ReadInt32() );
int spellID = pvSrc.ReadInt16() - 1;
EventSink.InvokeCastSpellRequest( new CastSpellRequestEventArgs( from, spellID, spellbook ) );
}
public static void BatchQueryProperties( NetState state, PacketReader pvSrc )
{
if ( !ObjectPropertyList.Enabled )
return;
Mobile from = state.Mobile;
int length = pvSrc.Size-3;
if ( length < 0 || (length%4) != 0 )
return;
int count = length/4;
for ( int i = 0; i < count; ++i )
{
Serial s = pvSrc.ReadInt32();
if ( s.IsMobile )
{
Mobile m = World.FindMobile( s );
if ( m != null && from.CanSee( m ) && Utility.InUpdateRange( from, m ) )
m.SendPropertiesTo( from );
}
else if ( s.IsItem )
{
Item item = World.FindItem( s );
if ( item != null && !item.Deleted && from.CanSee( item ) && Utility.InUpdateRange( from.Location, item.GetWorldLocation() ) )
item.SendPropertiesTo( from );
}
}
}
public static void QueryProperties( NetState state, PacketReader pvSrc )
{
if ( !ObjectPropertyList.Enabled )
return;
Mobile from = state.Mobile;
Serial s = pvSrc.ReadInt32();
if ( s.IsMobile )
{
Mobile m = World.FindMobile( s );
if ( m != null && from.CanSee( m ) && Utility.InUpdateRange( from, m ) )
m.SendPropertiesTo( from );
}
else if ( s.IsItem )
{
Item item = World.FindItem( s );
if ( item != null && !item.Deleted && from.CanSee( item ) && Utility.InUpdateRange( from.Location, item.GetWorldLocation() ) )
item.SendPropertiesTo( from );
}
}
public static void PartyMessage( NetState state, PacketReader pvSrc )
{
if ( state.Mobile == null )
return;
switch ( pvSrc.ReadByte() )
{
case 0x01: PartyMessage_AddMember( state, pvSrc ); break;
case 0x02: PartyMessage_RemoveMember( state, pvSrc ); break;
case 0x03: PartyMessage_PrivateMessage( state, pvSrc ); break;
case 0x04: PartyMessage_PublicMessage( state, pvSrc ); break;
case 0x06: PartyMessage_SetCanLoot( state, pvSrc ); break;
case 0x08: PartyMessage_Accept( state, pvSrc ); break;
case 0x09: PartyMessage_Decline( state, pvSrc ); break;
default: pvSrc.Trace( state ); break;
}
}
public static void PartyMessage_AddMember( NetState state, PacketReader pvSrc )
{
if ( PartyCommands.Handler != null )
PartyCommands.Handler.OnAdd( state.Mobile );
}
public static void PartyMessage_RemoveMember( NetState state, PacketReader pvSrc )
{
if ( PartyCommands.Handler != null )
PartyCommands.Handler.OnRemove( state.Mobile, World.FindMobile( pvSrc.ReadInt32() ) );
}
public static void PartyMessage_PrivateMessage( NetState state, PacketReader pvSrc )
{
if ( PartyCommands.Handler != null )
PartyCommands.Handler.OnPrivateMessage( state.Mobile, World.FindMobile( pvSrc.ReadInt32() ), pvSrc.ReadUnicodeStringSafe() );
}
public static void PartyMessage_PublicMessage( NetState state, PacketReader pvSrc )
{
if ( PartyCommands.Handler != null )
PartyCommands.Handler.OnPublicMessage( state.Mobile, pvSrc.ReadUnicodeStringSafe() );
}
public static void PartyMessage_SetCanLoot( NetState state, PacketReader pvSrc )
{
if ( PartyCommands.Handler != null )
PartyCommands.Handler.OnSetCanLoot( state.Mobile, pvSrc.ReadBoolean() );
}
public static void PartyMessage_Accept( NetState state, PacketReader pvSrc )
{
if ( PartyCommands.Handler != null )
PartyCommands.Handler.OnAccept( state.Mobile, World.FindMobile( pvSrc.ReadInt32() ) );
}
public static void PartyMessage_Decline( NetState state, PacketReader pvSrc )
{
if ( PartyCommands.Handler != null )
PartyCommands.Handler.OnDecline( state.Mobile, World.FindMobile( pvSrc.ReadInt32() ) );
}
public static void StunRequest( NetState state, PacketReader pvSrc )
{
EventSink.InvokeStunRequest( new StunRequestEventArgs( state.Mobile ) );
}
public static void DisarmRequest( NetState state, PacketReader pvSrc )
{
EventSink.InvokeDisarmRequest( new DisarmRequestEventArgs( state.Mobile ) );
}
public static void StatLockChange( NetState state, PacketReader pvSrc )
{
int stat = pvSrc.ReadByte();
int lockValue = pvSrc.ReadByte();
if ( lockValue > 2 ) lockValue = 0;
Mobile m = state.Mobile;
if ( m != null )
{
switch ( stat )
{
case 0: m.StrLock = (StatLockType)lockValue; break;
case 1: m.DexLock = (StatLockType)lockValue; break;
case 2: m.IntLock = (StatLockType)lockValue; break;
}
}
}
public static void ScreenSize( NetState state, PacketReader pvSrc )
{
int width = pvSrc.ReadInt32();
int unk = pvSrc.ReadInt32();
}
public static void ContextMenuResponse( NetState state, PacketReader pvSrc )
{
Mobile from = state.Mobile;
if ( from != null )
{
ContextMenu menu = from.ContextMenu;
from.ContextMenu = null;
if ( menu != null && from != null && from == menu.From )
{
IEntity entity = World.FindEntity( pvSrc.ReadInt32() );
if ( entity != null && entity == menu.Target && from.CanSee( entity ) )
{
Point3D p;
if ( entity is Mobile )
p = entity.Location;
else if ( entity is Item )
p = ((Item)entity).GetWorldLocation();
else
return;
int index = pvSrc.ReadUInt16();
if ( index >= 0 && index < menu.Entries.Length )
{
ContextMenuEntry e = menu.Entries[index];
int range = e.Range;
if ( range == -1 )
range = 18;
if ( e.Enabled && from.InRange( p, range ) )
e.OnClick();
}
}
}
}
}
public static void ContextMenuRequest( NetState state, PacketReader pvSrc )
{
Mobile from = state.Mobile;
IEntity target = World.FindEntity( pvSrc.ReadInt32() );
if ( from != null && target != null && from.Map == target.Map && from.CanSee( target ) )
{
if ( target is Mobile && !Utility.InUpdateRange( from.Location, target.Location ) )
return;
else if ( target is Item && !Utility.InUpdateRange( from.Location, ((Item)target).GetWorldLocation() ) )
return;
if ( !from.CheckContextMenuDisplay( target ) )
return;
ContextMenu c = new ContextMenu( from, target );
if ( c.Entries.Length > 0 )
{
if ( target is Item )
{
object root = ((Item)target).RootParent;
if ( root is Mobile && root != from && ((Mobile)root).AccessLevel >= from.AccessLevel )
{
for ( int i = 0; i < c.Entries.Length; ++i )
{
if ( !c.Entries[i].NonLocalUse )
c.Entries[i].Enabled = false;
}
}
}
from.ContextMenu = c;
}
}
}
public static void CloseStatus( NetState state, PacketReader pvSrc )
{
Serial serial = pvSrc.ReadInt32();
}
public static void Language( NetState state, PacketReader pvSrc )
{
string lang = pvSrc.ReadString( 4 );
if ( state.Mobile != null )
state.Mobile.Language = lang;
}
public static void AssistVersion( NetState state, PacketReader pvSrc )
{
int unk = pvSrc.ReadInt32();
string av = pvSrc.ReadString();
}
public static void ClientVersion( NetState state, PacketReader pvSrc )
{
CV version = state.Version = new CV( pvSrc.ReadString() );
EventSink.InvokeClientVersionReceived( new ClientVersionReceivedArgs( state, version ) );
}
public static void ClientType( NetState state, PacketReader pvSrc )
{
pvSrc.ReadUInt16();
int type = pvSrc.ReadUInt16();
CV version = state.Version = new CV( pvSrc.ReadString() );
//EventSink.InvokeClientVersionReceived( new ClientVersionReceivedArgs( state, version ) );//todo
}
public static void MobileQuery( NetState state, PacketReader pvSrc )
{
Mobile from = state.Mobile;
pvSrc.ReadInt32(); // 0xEDEDEDED
int type = pvSrc.ReadByte();
Mobile m = World.FindMobile( pvSrc.ReadInt32() );
if ( m != null )
{
switch ( type )
{
case 0x00: // Unknown, sent by godclient
{
if ( VerifyGC( state ) )
Console.WriteLine( "God Client: {0}: Query 0x{1:X2} on {2} '{3}'", state, type, m.Serial, m.Name );
break;
}
case 0x04: // Stats
{
m.OnStatsQuery( from );
break;
}
case 0x05:
{
m.OnSkillsQuery( from );
break;
}
default:
{
pvSrc.Trace( state );
break;
}
}
}
}
private class LoginTimer : Timer
{
private NetState m_State;
private Mobile m_Mobile;
public LoginTimer( NetState state, Mobile m ) : base( TimeSpan.FromSeconds( 1.0 ), TimeSpan.FromSeconds( 1.0 ) )
{
m_State = state;
m_Mobile = m;
}
protected override void OnTick()
{
if ( m_State == null )
Stop();
if ( m_State.Version != null )
{
m_State.BlockAllPackets = false;
DoLogin( m_State, m_Mobile );
Stop();
}
}
}
public static void PlayCharacter( NetState state, PacketReader pvSrc )
{
pvSrc.ReadInt32(); // 0xEDEDEDED
string name = pvSrc.ReadString( 30 );
pvSrc.Seek( 2, SeekOrigin.Current );
int flags = pvSrc.ReadInt32();
pvSrc.Seek( 24, SeekOrigin.Current );
int charSlot = pvSrc.ReadInt32();
int clientIP = pvSrc.ReadInt32();
IAccount a = state.Account;
if ( a == null || charSlot < 0 || charSlot >= a.Length )
{
state.Dispose();
}
else
{
Mobile m = a[charSlot];
// Check if anyone is using this account
for ( int i = 0; i < a.Length; ++i )
{
Mobile check = a[i];
if ( check != null && check.Map != Map.Internal && check != m )
{
Console.WriteLine( "Login: {0}: Account in use", state );
state.Send( new PopupMessage( PMMessage.CharInWorld ) );
return;
}
}
if ( m == null )
{
state.Dispose();
}
else
{
if ( m.NetState != null )
m.NetState.Dispose();
NetState.ProcessDisposedQueue();
state.Send( new ClientVersionReq() );
state.BlockAllPackets = true;
state.Flags = (ClientFlags)flags;
state.Mobile = m;
m.NetState = state;
new LoginTimer( state, m ).Start();
}
}
}
public static void DoLogin( NetState state, Mobile m )
{
state.Send( new LoginConfirm( m ) );
if ( m.Map != null )
state.Send( new MapChange( m ) );
state.Send( new MapPatches() );
state.Send( SeasonChange.Instantiate( m.GetSeason(), true ) );
state.Send( SupportedFeatures.Instantiate( state ) );
state.Sequence = 0;
if ( state.StygianAbyss ) {
state.Send( new MobileUpdate( m ) );
state.Send( new MobileUpdate( m ) );
m.CheckLightLevels( true );
state.Send( new MobileUpdate( m ) );
state.Send( new MobileIncoming( m, m ) );
//state.Send( new MobileAttributes( m ) );
state.Send( new MobileStatus( m, m ) );
state.Send( Server.Network.SetWarMode.Instantiate( m.Warmode ) );
m.SendEverything();
state.Send( SupportedFeatures.Instantiate( state ) );
state.Send( new MobileUpdate( m ) );
//state.Send( new MobileAttributes( m ) );
state.Send( new MobileStatus( m, m ) );
state.Send( Server.Network.SetWarMode.Instantiate( m.Warmode ) );
state.Send( new MobileIncoming( m, m ) );
} else {
state.Send( new MobileUpdateOld( m ) );
state.Send( new MobileUpdateOld( m ) );
m.CheckLightLevels( true );
state.Send( new MobileUpdateOld( m ) );
state.Send( new MobileIncomingOld( m, m ) );
//state.Send( new MobileAttributes( m ) );
state.Send( new MobileStatus( m, m ) );
state.Send( Server.Network.SetWarMode.Instantiate( m.Warmode ) );
m.SendEverything();
state.Send( SupportedFeatures.Instantiate( state ) );
state.Send( new MobileUpdateOld( m ) );
//state.Send( new MobileAttributes( m ) );
state.Send( new MobileStatus( m, m ) );
state.Send( Server.Network.SetWarMode.Instantiate( m.Warmode ) );
state.Send( new MobileIncomingOld( m, m ) );
}
state.Send( LoginComplete.Instance );
state.Send( new CurrentTime() );
state.Send( SeasonChange.Instantiate( m.GetSeason(), true ) );
state.Send( new MapChange( m ) );
EventSink.InvokeLogin( new LoginEventArgs( m ) );
m.ClearFastwalkStack();
}
public static void CreateCharacter( NetState state, PacketReader pvSrc )
{
int unk1 = pvSrc.ReadInt32();
int unk2 = pvSrc.ReadInt32();
int unk3 = pvSrc.ReadByte();
string name = pvSrc.ReadString( 30 );
pvSrc.Seek( 2, SeekOrigin.Current );
int flags = pvSrc.ReadInt32();
pvSrc.Seek( 8, SeekOrigin.Current );
int prof = pvSrc.ReadByte();
pvSrc.Seek( 15, SeekOrigin.Current );
//bool female = pvSrc.ReadBoolean();
int genderRace = pvSrc.ReadByte();
int str = pvSrc.ReadByte();
int dex = pvSrc.ReadByte();
int intl= pvSrc.ReadByte();
int is1 = pvSrc.ReadByte();
int vs1 = pvSrc.ReadByte();
int is2 = pvSrc.ReadByte();
int vs2 = pvSrc.ReadByte();
int is3 = pvSrc.ReadByte();
int vs3 = pvSrc.ReadByte();
int hue = pvSrc.ReadUInt16();
int hairVal = pvSrc.ReadInt16();
int hairHue = pvSrc.ReadInt16();
int hairValf= pvSrc.ReadInt16();
int hairHuef= pvSrc.ReadInt16();
pvSrc.ReadByte();
int cityIndex = pvSrc.ReadByte();
int charSlot = pvSrc.ReadInt32();
int clientIP = pvSrc.ReadInt32();
int shirtHue = pvSrc.ReadInt16();
int pantsHue = pvSrc.ReadInt16();
/*
Pre-7.0.0.0:
0x00, 0x01 -> Human Male, Human Female
0x02, 0x03 -> Orc Male, Orc Female
Post-7.0.0.0:
0x00, 0x01
0x02, 0x03 -> Human Male, Human Female
0x04, 0x05 -> Orc Male, Orc Female
*/
bool female = ((genderRace % 2) != 0);
Race race = null;
if ( state.StygianAbyss ) {
byte raceID = (byte)(genderRace < 4 ? 0 : ((genderRace / 2) - 1));
race = Race.Races[raceID];
} else {
race = Race.Races[(byte)(genderRace / 2)];
}
if( race == null )
race = Race.DefaultRace;
CityInfo[] info = state.CityInfo;
IAccount a = state.Account;
if ( info == null || a == null || cityIndex < 0 || cityIndex >= info.Length )
{
state.Dispose();
}
else
{
// Check if anyone is using this account
for ( int i = 0; i < a.Length; ++i )
{
Mobile check = a[i];
if ( check != null && check.Map != Map.Internal )
{
Console.WriteLine( "Login: {0}: Account in use", state );
state.Send( new PopupMessage( PMMessage.CharInWorld ) );
return;
}
}
state.Flags = (ClientFlags)flags;
CharacterCreatedEventArgs args = new CharacterCreatedEventArgs(
state, a,
name, female, hue,
str, dex, intl,
info[cityIndex],
new SkillNameValue[3]
{
new SkillNameValue( (SkillName)is1, vs1 ),
new SkillNameValue( (SkillName)is2, vs2 ),
new SkillNameValue( (SkillName)is3, vs3 ),
},
shirtHue, pantsHue,
hairVal, hairHue,
hairValf, hairHuef,
prof,
race
);
state.Send( new ClientVersionReq() );
state.BlockAllPackets = true;
EventSink.InvokeCharacterCreated( args );
Mobile m = args.Mobile;
if ( m != null )
{
state.Mobile = m;
m.NetState = state;
new LoginTimer( state, m ).Start();
}
else
{
state.BlockAllPackets = false;
state.Dispose();
}
}
}
public static void CreateCharacter70160( NetState state, PacketReader pvSrc )
{
int unk1 = pvSrc.ReadInt32();
int unk2 = pvSrc.ReadInt32();
int unk3 = pvSrc.ReadByte();
string name = pvSrc.ReadString( 30 );
pvSrc.Seek( 2, SeekOrigin.Current );
int flags = pvSrc.ReadInt32();
pvSrc.Seek( 8, SeekOrigin.Current );
int prof = pvSrc.ReadByte();
pvSrc.Seek( 15, SeekOrigin.Current );
int genderRace = pvSrc.ReadByte();
int str = pvSrc.ReadByte();
int dex = pvSrc.ReadByte();
int intl= pvSrc.ReadByte();
int is1 = pvSrc.ReadByte();
int vs1 = pvSrc.ReadByte();
int is2 = pvSrc.ReadByte();
int vs2 = pvSrc.ReadByte();
int is3 = pvSrc.ReadByte();
int vs3 = pvSrc.ReadByte();
int is4 = pvSrc.ReadByte();
int vs4 = pvSrc.ReadByte();
int hue = pvSrc.ReadUInt16();
int hairVal = pvSrc.ReadInt16();
int hairHue = pvSrc.ReadInt16();
int hairValf= pvSrc.ReadInt16();
int hairHuef= pvSrc.ReadInt16();
pvSrc.ReadByte();
int cityIndex = pvSrc.ReadByte();
int charSlot = pvSrc.ReadInt32();
int clientIP = pvSrc.ReadInt32();
int shirtHue = pvSrc.ReadInt16();
int pantsHue = pvSrc.ReadInt16();
/*
0x00, 0x01
0x02, 0x03 -> Human Male, Human Female
0x04, 0x05 -> Orc Male, Orc Female
*/
bool female = ((genderRace % 2) != 0);
Race race = null;
byte raceID = (byte)(genderRace < 4 ? 0 : ((genderRace / 2) - 1));
race = Race.Races[raceID];
if( race == null )
race = Race.DefaultRace;
CityInfo[] info = state.CityInfo;
IAccount a = state.Account;
if ( info == null || a == null || cityIndex < 0 || cityIndex >= info.Length )
{
state.Dispose();
}
else
{
// Check if anyone is using this account
for ( int i = 0; i < a.Length; ++i )
{
Mobile check = a[i];
if ( check != null && check.Map != Map.Internal )
{
Console.WriteLine( "Login: {0}: Account in use", state );
state.Send( new PopupMessage( PMMessage.CharInWorld ) );
return;
}
}
state.Flags = (ClientFlags)flags;
CharacterCreatedEventArgs args = new CharacterCreatedEventArgs(
state, a,
name, female, hue,
str, dex, intl,
info[cityIndex],
new SkillNameValue[4]
{
new SkillNameValue( (SkillName)is1, vs1 ),
new SkillNameValue( (SkillName)is2, vs2 ),
new SkillNameValue( (SkillName)is3, vs3 ),
new SkillNameValue( (SkillName)is4, vs4 ),
},
shirtHue, pantsHue,
hairVal, hairHue,
hairValf, hairHuef,
prof,
race
);
state.Send( new ClientVersionReq() );
state.BlockAllPackets = true;
EventSink.InvokeCharacterCreated( args );
Mobile m = args.Mobile;
if ( m != null )
{
state.Mobile = m;
m.NetState = state;
new LoginTimer( state, m ).Start();
}
else
{
state.BlockAllPackets = false;
state.Dispose();
}
}
}
private static bool m_ClientVerification = true;
public static bool ClientVerification
{
get{ return m_ClientVerification; }
set{ m_ClientVerification = value; }
}
internal struct AuthIDPersistence {
public DateTime Age;
public ClientVersion Version;
public AuthIDPersistence( ClientVersion v ) {
Age = DateTime.Now;
Version = v;
}
}
private const int m_AuthIDWindowSize = 128;
private static Dictionary<int, AuthIDPersistence> m_AuthIDWindow = new Dictionary<int, AuthIDPersistence>( m_AuthIDWindowSize );
private static int GenerateAuthID( NetState state )
{
if ( m_AuthIDWindow.Count == m_AuthIDWindowSize ) {
int oldestID = 0;
DateTime oldest = DateTime.MaxValue;
foreach ( KeyValuePair<int, AuthIDPersistence> kvp in m_AuthIDWindow ) {
if ( kvp.Value.Age < oldest ) {
oldestID = kvp.Key;
oldest = kvp.Value.Age;
}
}
m_AuthIDWindow.Remove( oldestID );
}
int authID;
do {
authID = Utility.Random( 1, int.MaxValue - 1 );
if ( Utility.RandomBool() )
authID |= 1<<31;
} while ( m_AuthIDWindow.ContainsKey( authID ) );
m_AuthIDWindow[authID] = new AuthIDPersistence( state.Version );
return authID;
}
public static void GameLogin( NetState state, PacketReader pvSrc )
{
if ( state.SentFirstPacket )
{
state.Dispose();
return;
}
state.SentFirstPacket = true;
int authID = pvSrc.ReadInt32();
if ( m_AuthIDWindow.ContainsKey( authID ) ) {
AuthIDPersistence ap = m_AuthIDWindow[authID];
m_AuthIDWindow.Remove( authID );
state.Version = ap.Version;
} else if ( m_ClientVerification ) {
Console.WriteLine( "Login: {0}: Invalid client detected, disconnecting", state );
state.Dispose();
return;
}
if ( state.m_AuthID != 0 && authID != state.m_AuthID )
{
Console.WriteLine( "Login: {0}: Invalid client detected, disconnecting", state );
state.Dispose();
return;
}
else if ( state.m_AuthID == 0 && authID != state.m_Seed )
{
Console.WriteLine( "Login: {0}: Invalid client detected, disconnecting", state );
state.Dispose();
return;
}
string username = pvSrc.ReadString( 30 );
string password = pvSrc.ReadString( 30 );
GameLoginEventArgs e = new GameLoginEventArgs( state, username, password );
EventSink.InvokeGameLogin( e );
if ( e.Accepted )
{
state.CityInfo = e.CityInfo;
state.CompressionEnabled = true;
state.Send( SupportedFeatures.Instantiate( state ) );
if ( state.NewCharacterList ) {
state.Send( new CharacterList( state.Account, state.CityInfo ) );
} else {
state.Send( new CharacterListOld( state.Account, state.CityInfo ) );
}
}
else
{
state.Dispose();
}
}
public static void PlayServer( NetState state, PacketReader pvSrc )
{
int index = pvSrc.ReadInt16();
ServerInfo[] info = state.ServerInfo;
IAccount a = state.Account;
if ( info == null || a == null || index < 0 || index >= info.Length )
{
state.Dispose();
}
else
{
ServerInfo si = info[index];
state.m_AuthID = PlayServerAck.m_AuthID = GenerateAuthID( state );
state.SentFirstPacket = false;
state.Send( new PlayServerAck( si ) );
}
}
public static void LoginServerSeed( NetState state, PacketReader pvSrc )
{
state.m_Seed = pvSrc.ReadInt32();
state.Seeded = true;
if ( state.m_Seed == 0 )
{
Console.WriteLine("Login: {0}: Invalid client detected, disconnecting", state);
state.Dispose();
return;
}
int clientMaj = pvSrc.ReadInt32();
int clientMin = pvSrc.ReadInt32();
int clientRev = pvSrc.ReadInt32();
int clientPat = pvSrc.ReadInt32();
state.Version = new ClientVersion( clientMaj, clientMin, clientRev, clientPat );
}
public static void AccountLogin( NetState state, PacketReader pvSrc )
{
if ( state.SentFirstPacket )
{
state.Dispose();
return;
}
state.SentFirstPacket = true;
string username = pvSrc.ReadString( 30 );
string password = pvSrc.ReadString( 30 );
AccountLoginEventArgs e = new AccountLoginEventArgs( state, username, password );
EventSink.InvokeAccountLogin( e );
if ( e.Accepted )
AccountLogin_ReplyAck( state );
else
AccountLogin_ReplyRej( state, e.RejectReason );
}
public static void AccountLogin_ReplyAck( NetState state )
{
ServerListEventArgs e = new ServerListEventArgs( state, state.Account );
EventSink.InvokeServerList( e );
if ( e.Rejected )
{
state.Account = null;
state.Send( new AccountLoginRej( ALRReason.BadComm ) );
state.Dispose();
}
else
{
ServerInfo[] info = e.Servers.ToArray();
state.ServerInfo = info;
state.Send( new AccountLoginAck( info ) );
}
}
public static void AccountLogin_ReplyRej( NetState state, ALRReason reason )
{
state.Send( new AccountLoginRej( reason ) );
state.Dispose();
}
}
}