rendered paste bodyusing System;
using System.Collections.Generic;
using log4net;
using WCell.Cryptography;
using WCell.Network;
using WCell.Network.Handler;
using WCell.RealmServer.UpdateFields;
//using WCell.DAL.TypedQueries;
//using Sooda;
namespace WCell.RealmServer
{
///<summary>
/// The world class
///</summary>
public class World
{
#region Fields
protected static ILog m_log = LogManager.GetLogger(typeof(World));
private static ObjectManager m_objectMgr;
/// <summary>
/// The Object Manager
/// </summary>
public static ObjectManager ObjectManager
{
get { return m_objectMgr; }
}
#endregion
/// <summary>
/// The resolver of World Class
/// </summary>
/// <param name="session"></param>
/// <returns></returns>
[Resolver]
private static World Resolver(RealmClient session)
{
m_objectMgr = ObjectManager.Instance;
return new World();
}
#region Packet Handlers
/// <summary>
/// Handles an incomming ping request
/// </summary>
/// <param name="session">the Session the incoming packet belongs to</param>
/// <param name="packet">the full packet</param>
[PacketHandler(RealmServerOpCode.CMSG_PING)]
public void PingRequest(RealmClient session, RealmPacketIn packet)
{
SendPingReply(session, packet.ReadUInt32());
}
/// <summary>
/// Handles incomming Auth Session Request
/// </summary>
/// <param name="session">the Session the incoming packet belongs to</param>
/// <param name="packet">the full packet</param>
[PacketHandler(RealmServerOpCode.CMSG_AUTH_SESSION)]
public void AuthSessionRequest(RealmClient session, RealmPacketIn packet)
{
packet.SkipBytes(4); //GameBuild
packet.SkipBytes(4); //Unknow field
string accName = packet.ReadString();
uint clientSeed = packet.ReadUInt32();
BigInteger clientDigest = packet.ReadBigInteger(20);
byte[] zeros = new byte[4];
//SecureRemotePassword srp = session.Client.Server.SessionKeyService.RequestSRP(accName); Currently not working
if (session.Account == null)
{
//TODO: implement acct lookup when we get DB. maybe find a better place to put this. currently session.Account is never assigned to.
session.Account = new Account(session, accName);
//session.Account.Username = accName;
}
BigInteger salt = new BigInteger(session.Server.SessionKeyService.RequestSalt(accName), 32);
BigInteger verifier = new BigInteger(session.Server.SessionKeyService.RequestVerifier(accName));
SecureRemotePassword srp = new SecureRemotePassword(accName, verifier, salt);
session.Account.SessionKey =
new BigInteger(session.Server.SessionKeyService.RequestSessionKey(accName));
BigInteger clientVerifier =
srp.Hash(srp.Username, zeros, clientSeed, 0xDEADBABE, session.Account.SessionKey);
session.IsEncrypted = true; // all packets from here on are encrypted, including the AuthSessionReplys
if (clientVerifier == clientDigest)
{
SendAuthSessionSuccessReply(session);
}
else
{
SendAuthSessionErrorReply(session, RealmErrorCode.AuthFailed);
}
}
/// <summary>
/// Handles incomming Char Enum Request
/// </summary>
/// <param name="session">the Session the incoming packet belongs to</param>
/// <param name="packet">the full packet</param>
[PacketHandler(RealmServerOpCode.CMSG_CHAR_ENUM)]
public void CharEnumRequest(RealmClient session, RealmPacketIn packet)
{
SendCharEnum(session);
}
/// <summary>
/// Handles incomming Char creation Request
/// </summary>
/// <param name="session">the Session the incoming packet belongs to</param>
/// <param name="packet">the full packet</param>
[PacketHandler(RealmServerOpCode.CMSG_CHAR_CREATE)]
public void CharCreateRequest(RealmClient session, RealmPacketIn packet)
{
try
{
String characterName = packet.ReadString();
//using (SoodaTransaction tran = new SoodaTransaction())
//{
// if (WCell.DAL.Character.LoadSingleObject(CharacterField.Name == characterName) != null)
// {
// SendCharCreateReply(session, RealmErrorCode.CharacterCreateNameInUse);
// return;
// }
// Character ch = new Character(session.Account);
// //ch.Name = packet.ReadString();
// ch.Name = characterName;
// ch.Race = (RaceTypes)packet.ReadByte();
// ch.Class = (ClassTypes)packet.ReadByte();
// ch.Gender = (GenderTypes)packet.ReadByte();
// ch.Skin = packet.ReadByte();
// ch.Face = packet.ReadByte();
// ch.HairStyle = packet.ReadByte();
// ch.HairColour = packet.ReadByte();
// ch.FacialHair = packet.ReadByte();
// ch.OutFit = packet.ReadByte();
// TODO: This should be handled elsewhere
//ch.Level = (byte)(40);
//ch.PositionX = -8949.950195f;
//ch.PositionY = -132.492996f;
//ch.PositionZ = 83.531197f;
//ch.Orientation = 0.0f;
// ch.Save();
// session.Account.Characters.Add(ch.GUID, ch);
// SendCharCreateReply(session, RealmErrorCode.CharacterCreateOk);
//}
}
catch (Exception e)
{
m_log.Error(e);
SendCharCreateReply(session, RealmErrorCode.CharacterCreateNameInUse);
}
}
/// <summary>
/// Handles incomming Char delete Request
/// </summary>
/// <param name="session">the Session the incoming packet belongs to</param>
/// <param name="packet">the full packet</param>
[PacketHandler(RealmServerOpCode.CMSG_CHAR_DELETE)]
public void CharDeleteRequest(RealmClient session, RealmPacketIn packet)
{
ulong charGUID = packet.ReadUInt64();
try
{
session.Account.Characters.Remove(charGUID);
//session.Account.Characters[charGUID].Delete();
SendCharDeleteReply(session, RealmErrorCode.CharacterDeleteOk);
}
catch (Exception)
{
SendCharDeleteReply(session, RealmErrorCode.CharacterDeleteFailed);
}
}
/// <summary>
/// Handles incomming Player Login Request
/// </summary>
/// <param name="session">the Session the incoming packet belongs to</param>
/// <param name="packet">the full packet</param>
[PacketHandler(RealmServerOpCode.CMSG_PLAYER_LOGIN)]
public void CharPlayerLoginRequest(RealmClient session, RealmPacketIn packet)
{
try
{
ulong charGUID = packet.ReadUInt64();
if (charGUID != 0)
{
if (!m_objectMgr.CharacterListByGUID.ContainsKey(charGUID))
{
/*foreach (Character ch in session.Account.Characters.Values)
{
if (ch.GUID == charGUID)
{
session.ActiveCharacter = ch;
m_worldUnitList.Add(ch.GUID, ch);
break;
}
}*/
if (session.Account.Characters.ContainsKey(charGUID))
{
session.ActiveCharacter = session.Account.Characters[charGUID];
m_objectMgr.AddCharToLists(session.ActiveCharacter);
}
else
throw new InvalidOperationException(
string.Format("Character with guid {0} not found in this account!", charGUID));
session.Account.SendAccountDataMD5(session);
//session.ActiveCharacter.SendSetRestStart(session);
//session.ActiveCharacter.SendBindPointUpdate(session);
session.ActiveCharacter.SendTutorialFlags(session);
//session.ActiveCharacter.SendInitialSpells(session);
//session.ActiveCharacter.SendActionButtons(session);
SendUpdateObject(session, UpdateTypes.CreateSelf);
session.ActiveCharacter.SendMoveUnlockMovementReply(session);
}
else
{
session.ActiveCharacter.SendCharacterLoginFail(session,
AccountCharacterErrorCodes.
ACCNT_MANIP_ALREADY_LOGGED_IN);
session.Server.DisconnectClient(m_objectMgr.CharacterListByGUID[charGUID].Account.Client);
}
}
}
catch (Exception e)
{
m_log.Error(e);
session.ActiveCharacter.SendCharacterLoginFail(session,
AccountCharacterErrorCodes.ACCNT_MANIP_AUTH_FAILED);
}
}
/// <summary>
/// Handles incomming Query time Request
/// </summary>
/// <param name="session">the Session the incoming packet belongs to</param>
/// <param name="packet">the full packet</param>
[PacketHandler(RealmServerOpCode.CMSG_QUERY_TIME)]
public void QueryTimeRequest(RealmClient session, RealmPacketIn packet)
{
SendQueryTimeReply(session);
}
/// <summary>
/// Handles incomming Name Query request
/// </summary>
/// <param name="session">the Session the incoming packet belongs to</param>
/// <param name="packet">the full packet</param>
[PacketHandler(RealmServerOpCode.CMSG_NAME_QUERY)]
public void NameQueryRequest(RealmClient session, RealmPacketIn packet)
{
SendNameQueryReply(session, session.ActiveCharacter);
}
/// <summary>
/// Handles incomming Imediate Logout request
/// </summary>
/// <param name="session">the Session the incoming packet belongs to</param>
/// <param name="packet">the full packet</param>
[PacketHandler(RealmServerOpCode.CMSG_PLAYER_LOGOUT)]
public void PlayerImediateLogoutRequest(RealmClient session, RealmPacketIn packet)
{
SendPlayerImediateLogoutReply(session);
}
/// <summary>
/// Handles incomming Logout request
/// </summary>
/// <param name="session">the Session the incoming packet belongs to</param>
/// <param name="packet">the full packet</param>
[PacketHandler(RealmServerOpCode.CMSG_LOGOUT_REQUEST)]
public void PlayerLogoutRequest(RealmClient session, RealmPacketIn packet)
{
SendLogoutReply(session, LogoutResponseCodes.LOGOUT_RESPONSE_ACCEPTED);
}
/// <summary>
/// Handles incomming Logout Cancel Request
/// </summary>
/// <param name="session">the Session the incoming packet belongs to</param>
/// <param name="packet">the full packet</param>
[PacketHandler(RealmServerOpCode.CMSG_LOGOUT_CANCEL)]
public void PlayerLogoutCancel(RealmClient session, RealmPacketIn packet)
{
SendLogoutCancelReply(session);
}
#endregion
#region Send/Reply methods
/// <summary>
/// Send the Ping Reply
/// </summary>
/// <param name="session">the Session the outdoing packet belongs to</param>
/// <param name="sequencial">the sequencial number sent by client</param>
public void SendPingReply(RealmClient session, uint sequencial)
{
using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_PONG))
{
packet.Write(sequencial);
session.Send(packet);
}
}
/// <summary>
/// Send the Error of Auth Session to client
/// </summary>
/// <param name="session">the Session the outdoing packet belongs to</param>
/// <param name="error">error code</param>
public void SendAuthSessionErrorReply(RealmClient session, RealmErrorCode error)
{
using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_AUTH_RESPONSE))
{
packet.Write((byte)error);
session.Send(packet);
}
}
/// <summary>
/// Send a success auth session reply to the client
/// </summary>
/// <param name="session">the Session the outdoing packet belongs to</param>
public void SendAuthSessionSuccessReply(RealmClient session)
{
using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_AUTH_RESPONSE))
{
packet.WriteByte((byte)RealmErrorCode.AuthOk);
packet.WriteByte(0xB0);
packet.WriteByte(0x09);
packet.WriteByte(0x02);
packet.WriteByte(0x00);
packet.WriteByte(0x02);
packet.WriteInt(0);
if (session.Account.BurningCrusadeEnabled)
{
packet.WriteByte(1);
}
else
{
packet.WriteByte(0);
}
session.Send(packet);
}
}
/// <summary>
/// Sends the Char Enum to client
/// </summary>
/// <param name="session">the Session the outdoing packet belongs to</param>
public void SendCharEnum(RealmClient session)
{
using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_CHAR_ENUM))
{
Dictionary<ulong, Character> characters = session.Account.Characters;
packet.WriteByte((byte)characters.Count);
foreach (Character c in characters.Values) //change to foreach so we dont get KeyNotFoundExceptions
{
packet.Write(c.GUID.Full);
packet.WriteString(c.Name);
packet.WriteByte((byte) c.Race);
packet.WriteByte((byte) c.Class);
packet.WriteByte((byte) c.Gender);
packet.WriteByte(c.Skin);
packet.WriteByte(c.Face);
packet.WriteByte(c.HairStyle);
packet.WriteByte(c.HairColour);
packet.WriteByte(c.FacialHair);
packet.WriteByte((byte)c.Level);
packet.WriteByte(c.OutFit); // displayId?
packet.Write(c.ZoneId);
packet.Write(c.MapId);
packet.Write(c.PositionX);
packet.Write(c.PositionY);
packet.Write(c.PositionZ);
packet.WriteByte(0); //unk1
packet.WriteByte(0); //unk2
packet.WriteByte(0); //unk3
if (c.IsLocked)
{
packet.WriteByte(1);
}
else
{
packet.WriteByte(0);
}
packet.WriteInt(0); // rest
packet.Write(c.PetInfoId);
packet.Write(c.PetLevel);
packet.Write(c.PetFamilyId);
packet.WriteZeros(100);
}
session.Send(packet);
}
}
///<summary>
/// Send Query Time Reply
///</summary>
///<param name="session">the Session the outdoing packet belongs to</param>
public void SendQueryTimeReply(RealmClient session)
{
using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_QUERY_TIME_RESPONSE))
{
packet.WriteDateTime(DateTime.Now);
session.Send(packet);
}
}
/// <summary>
/// Send a Name Query Reply
/// </summary>
///<param name="session">the Session the outdoing packet belongs to</param>
/// <param name="character">the character that will be send</param>
public void SendNameQueryReply(RealmClient session, Character character)
{
using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_NAME_QUERY_RESPONSE))
{
packet.Write(character.GUID);
packet.Write(character.Name);
packet.WriteZeros(1);
packet.Write((byte)character.Race);
packet.Write((byte)character.Gender);
packet.Write((byte)character.Class);
session.Send(packet);
}
}
public void SendUpdateObject(RealmClient client, UpdateTypes updateType)
{
using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_UPDATE_OBJECT))
{
packet.Write(1); // block count.
packet.WriteByte(1); // unk constant
// start repeat
packet.WriteByte((byte)updateType); // update type
packet.Write(client.ActiveCharacter.GUID.Packed);
packet.WriteByte((byte)ObjectTypeIds.Player); // player object type
WriteMovementUpdate(packet, client.ActiveCharacter, updateType);
client.ActiveCharacter.Strength = 12;
client.ActiveCharacter.Stamina = 3;
client.ActiveCharacter.Health = 1000;
client.ActiveCharacter.MaxHealth = 1500;
client.ActiveCharacter.Power1 = 10;
client.ActiveCharacter.MaxPower1 = 20;
client.ActiveCharacter.NativeDisplayId = client.ActiveCharacter.DisplayId;
client.ActiveCharacter.MountDisplayId = 15677;
client.ActiveCharacter.Type = (uint)(ObjectTypes.Player | ObjectTypes.Unit | ObjectTypes.Object);
client.ActiveCharacter.ScaleX = 1.0f;
client.ActiveCharacter.WriteUpdateMask(packet);
/*UpdateMask mask = new UpdateMask(PlayerFields._Count);
mask.SetBit(ObjectFields.Guid, session.ActiveCharacter.GUID);
mask.SetBit(UnitFields.UnitBytes0, session.ActiveCharacter.UnitBytes0);
mask.SetBit(UnitFields.Health, 100);
mask.SetBit(UnitFields.MaxHealth, 150);
mask.SetBit(UnitFields.Level, (uint)session.ActiveCharacter.Level);
mask.SetBit(UnitFields.DisplayId, session.ActiveCharacter.DisplayId);
mask.SetBit(UnitFields.NativeDisplayId, session.ActiveCharacter.DisplayId);
mask.SetBit(UnitFields.Power1, 10);
mask.SetBit(UnitFields.MaxPower1, 20);
mask.SetBit(UnitFields.MountDisplayId, 15677);
mask.SetBit(ObjectFields.Type, (uint)(ObjectTypes.Player | ObjectTypes.Unit | ObjectTypes.Object));
mask.SetBit(ObjectFields.ScaleX, 1.0f);
//mask.SetBit(
mask.Write(packet);*/
client.Send(packet);
}
}
private void WriteMovementUpdate(RealmPacketOut packet, Character c, UpdateTypes updateType)
{
byte flag1 = 0;
uint flag2 = 0;
switch (updateType)
{
case UpdateTypes.Create:
{
flag1 = 0x60;
break;
}
case UpdateTypes.CreateSelf:
{
flag1 = 0x61;
break;
}
}
packet.WriteByte(flag1);
packet.Write(flag2);
packet.WriteDateTime(DateTime.Now);
packet.Write(c.PositionX);
packet.Write(c.PositionY);
packet.Write(c.PositionZ);
packet.Write(c.Orientation); // orientation
packet.Write(0.0f); //unk
packet.Write(20f); // Walk
packet.Write(20f); // Run
packet.Write(20f); // SwimBack
packet.Write(20f); // Swim
packet.Write(20f); // WalkBack
packet.Write(20f); //FlightBack
packet.Write(20f); // flight
packet.Write((float)Math.PI); // turn
}
/// <summary>
/// Send Char Create Reply
/// </summary>
///<param name="session">the Session the outdoing packet belongs to</param>
/// <param name="error">Error code</param>
public void SendCharCreateReply(RealmClient session, RealmErrorCode error)
{
using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_CHAR_CREATE))
{
packet.Write((byte)error);
session.Send(packet);
}
}
/// <summary>
/// Send Char Delete Reply
/// </summary>
///<param name="session">the Session the outdoing packet belongs to</param>
/// <param name="error">Error code</param>
public void SendCharDeleteReply(RealmClient session, RealmErrorCode error)
{
using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_CHAR_DELETE))
{
packet.Write((byte)error);
session.Send(packet);
}
}
/// <summary>
/// Sent by the server to notify the client about the environmental speed change. Usualy this speed equals to real life.
/// </summary>
///<param name="session">the Session the outdoing packet belongs to</param>
public void SendLoginSetTimeSpeed(RealmClient session)
{
using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_LOGIN_SETTIMESPEED))
{
packet.WriteDateTime(DateTime.Now);
session.Send(packet);
}
}
/// <summary>
/// Sent by the server to mark the end of logout sequence. In reply to CMSG_PLAYER_LOGOUT.
/// </summary>
///<param name="session">the Session the outdoing packet belongs to</param>
public void SendPlayerImediateLogoutReply(RealmClient session)
{
using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_LOGOUT_COMPLETE))
{
m_objectMgr.RemoveCharFromLists(session.ActiveCharacter);
session.Send(packet);
}
}
/// <summary>
/// Send Logout Response
/// </summary>
///<param name="session">the Session the outdoing packet belongs to</param>
/// <param name="error">error code</param>
public void SendLogoutReply(RealmClient session, LogoutResponseCodes error)
{
using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_LOGOUT_RESPONSE))
{
packet.Write((byte)error);
packet.WriteZeros(4);
session.Send(packet);
}
}
/// <summary>
/// Send Logout Cancel Reply
/// </summary>
///<param name="session">the Session the outdoing packet belongs to</param>
public void SendLogoutCancelReply(RealmClient session)
{
using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_LOGOUT_CANCEL_ACK))
{
session.Send(packet);
}
}
#endregion
}
}