public override void ExecuteCommand(ShardSession session, ShardRequest request, QueryName header) { Character character = session.Server.Shard.GetCharacter(header.CharacterID); if (character == null) { // not online character = new CharacterDao().GetCharacterByID(session.Server.ShardDB, header.CharacterID); } if (character == null) { log.WarnFormat("received {0} for non-existing object id {1}", ShardClientOpcode.QueryName, header.CharacterID); } else { using (ByteBuffer response = new ByteBuffer()) { response.Append(character.ID); response.Append(character.Name); response.Append((byte)0); // used to identify shard name in cross-shard bg response.Append((int)character.Race); response.Append((int)character.Sex); response.Append((int)character.Class); session.Send(ShardServerOpcode.QueryName, response); } } }
public override void ExecuteCommand(ShardSession session, ShardRequest request, SetControlledUnit header) { if (header.UnitID != session.Player.ID) { log.WarnFormat("received {0} with incorrect unit id {1}. it should be {2}", ShardClientOpcode.SetControlledUnit, header.UnitID, session.Player.ID); } }
public override void ExecuteCommand(ShardSession session, ShardRequest request, ClientPacketHeader header) { using (ByteBuffer response = new ByteBuffer()) { response.Append(0); response.Append((byte)6); // ? session.Send(ShardServerOpcode.MeetingStoneSetQueue, response); } }
public override void ExecuteCommand(ShardSession session, ShardRequest request, ClientPacketHeader header) { using (ByteBuffer response = new ByteBuffer()) { response.Append(NoUnreadMail); // mystery float response.Append(0); // count of mails (to show on map?) session.Send(ShardServerOpcode.QueryNextMailTime, response); } }
private void DoStart(string msg) { // find shard in directory ConnectActor connect = new ConnectActor(this, ActorServer.GetInstance().FullHost, "KnownShards"); var data = Receive(ans => { return(ans is IMessageParam <string, ActorTag, IActor>); }); var res = data.Result as IMessageParam <string, ActorTag, IActor>; var shardDir = res.Item3; Assert.IsNotNull(shardDir); ShardRequest req = ShardRequest.CastRequest(this, this); shardDir.SendMessage(req); Become(new Behavior <ShardRequest>(WaitAns)); }
public override void ExecuteCommand(ShardSession session, ShardRequest request, MovementHeader header) { ObjectID? transportId = null; OrientedVector3?transportPosition = null; float? pitch = null; uint fallTime = 0; float? jumpVelocity = null; float? jumpSinAngle = null; float? jumpCosAngle = null; float? jumpXySpeed = null; using (BinaryReader reader = new BinaryReader(new MemoryStream(request.Packet, false), Encoding.UTF8, false)) { reader.BaseStream.Seek(Marshal.SizeOf <MovementHeader>(), SeekOrigin.Begin); if ((header.Flags & MovementFlags.OnTransport) != 0) { transportId = new ObjectID(reader.ReadUInt64()); transportPosition = new OrientedVector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); } if ((header.Flags & MovementFlags.ModeSwimming) != 0) { pitch = reader.ReadSingle(); } fallTime = reader.ReadUInt32(); if ((header.Flags & MovementFlags.ModeFalling) != 0) { jumpVelocity = reader.ReadSingle(); jumpSinAngle = reader.ReadSingle(); jumpCosAngle = reader.ReadSingle(); jumpXySpeed = reader.ReadSingle(); } } // TODO: implement falling, swimming, transport // TODO: verify that client isn't sending bogus data session.Player.Control.MovementFlags = header.Flags & ~(MovementFlags.ModeFalling | MovementFlags.ModeSwimming | MovementFlags.OnTransport); session.Player.Control.Position = header.Position; session.Player.Control.MovementTime = header.Time; }
public override void ExecuteCommand(ShardSession session, ShardRequest request, ClientPacketHeader header) { // well, it's a no-op. what did you expect? }
public override void ExecuteCommand(ShardSession session, ShardRequest request, PlayerLogin header) { Character player = new CharacterDao().GetCharacterByID(session.Server.ShardDB, header.CharacterID); log.DebugFormat("character '{0}' loaded successfully", player.Name); // initialize the character if it has never logged in before now if (player.FirstLogin) { log.DebugFormat("character '{0}' first login, initializing", player.Name); player.Initialize(session.Server.World); } // set session status to ingame and add the player to the Shard session.Player = player; session.Status = SessionStatus.Ingame; session.Server.Shard.AddCharacter(player); // send logon player response packet using (ByteBuffer packet = new ByteBuffer()) { packet.Append(player.MapID); packet.Append(player.Position); session.Send(ShardServerOpcode.LoginVerifyWorld, packet); } // not sure what this does session.Send(ShardServerOpcode.AccountDataTimes, new byte[128]); // not sure what this does, either session.Send(ShardServerOpcode.LoginSetRestStart, BitConverter.GetBytes(0)); // update bind point using (ByteBuffer packet = new ByteBuffer()) { // TODO: implement bind point other than initial world position CharacterTemplate ct = session.Server.World.CharacterTemplates[player.Race][player.Class]; packet.Append(ct.PositionX); // x packet.Append(ct.PositionY); // y packet.Append(ct.PositionZ); // z packet.Append(ct.MapID); // map id packet.Append(ct.ZoneID); // zone id session.Send(ShardServerOpcode.BindPointUpdate, packet); } // set tutorial state using (ByteBuffer buffer = new ByteBuffer()) { for (int i = 0; i < 8; ++i) { buffer.Append(-1); } session.Send(ShardServerOpcode.LoginTutorialFlags, buffer); } // set initial spells using (ByteBuffer packet = new ByteBuffer()) { packet.Append((byte)0); packet.Append((ushort)player.Spells.Where(spell => spell.Enabled).Count()); foreach (Character.Spell spell in player.Spells.Where(spell => spell.Enabled)) { packet.Append((ushort)spell.SpellID); packet.Append((short)0); } packet.Append((ushort)0); // spell cooldown count session.Send(ShardServerOpcode.LoginInitializeSpells, packet); } // set initial action buttons using (ByteBuffer packet = new ByteBuffer()) { for (int i = 0; i < Character.MaxActionButtons; ++i) { if (i < player.ActionButtons.Count) { packet.Append(player.ActionButtons[i]); } else { packet.Append(0); } } session.Send(ShardServerOpcode.LoginInitializeActionButtons, packet); } // set initial faction standing /*using (ByteBuffer packet = new ByteBuffer()) * { * packet.Append(FactionCount); * * for(int i = 0; i < FactionCount; ++i) * { * packet.Append((byte)0); // faction flags * packet.Append(0); // faction standing * } * * session.Send(ShardServerOpcode.LoginInitializeFactions, packet); * }*/ // set initial time and speed using (ByteBuffer packet = new ByteBuffer()) { packet.Append(DateTimes.GetBitfield(DateTime.Now)); packet.Append(GameSpeed); session.Send(ShardServerOpcode.LoginSetTimeAndSpeed, packet); } // trigger cinematic if this is the character's first login if (player.FirstLogin) { RaceDefinition rd; if (session.Server.World.RaceDefinitions.TryGetValue(player.Race, out rd)) { session.Send(ShardServerOpcode.TriggerCinematic, BitConverter.GetBytes(rd.FirstLoginCinematicID)); } else { log.WarnFormat("cannot send first login cinematic for undefined race '{0}'", player.Race); } } // send friend list and ignore list (empty for now) session.Send(ShardServerOpcode.FriendList, (byte)0); session.Send(ShardServerOpcode.IgnoreList, (byte)0); // initialize world state using (ByteBuffer packet = new ByteBuffer()) { packet.Append(player.MapID); packet.Append(player.ZoneID); packet.Append((ushort)0); // special map int64s (for battleground, outdoor pvp areas) session.Send(ShardServerOpcode.InitializeWorldState, packet); } }
public override void ExecuteCommand(ShardSession session, ShardRequest request, ClientPacketHeader header) { int offset = Marshal.SizeOf <ClientPacketHeader>(); string name = Strings.FromNullTerminated(request.Packet, ref offset); byte race = request.Packet[offset++]; byte @class = request.Packet[offset++]; byte sex = request.Packet[offset++]; byte skin = request.Packet[offset++]; byte face = request.Packet[offset++]; byte hairStyle = request.Packet[offset++]; byte hairColor = request.Packet[offset++]; byte facialHair = request.Packet[offset++]; byte outfitId = request.Packet[offset++]; Race raceEnum; if (!Enum.TryParse(race.ToString(), out raceEnum)) { log.WarnFormat("client attempted to create character with invalid race [{0}]", race); session.Send(ShardServerOpcode.CharacterCreate, (byte)CharacterCreateResponse.Failed); return; } Class classEnum; if (!Enum.TryParse(@class.ToString(), out classEnum)) { log.WarnFormat("client attempted to create character with invalid class [{0}]", @class); session.Send(ShardServerOpcode.CharacterCreate, (byte)CharacterCreateResponse.Failed); return; } if (sex != (byte)Sex.Male && sex != (byte)Sex.Female) { log.WarnFormat("client attempted to create character with invalid sex [{0}]", sex); session.Send(ShardServerOpcode.CharacterCreate, (byte)CharacterCreateResponse.Failed); return; } CharacterTemplate template; try { template = session.Server.World.CharacterTemplates[raceEnum][classEnum]; } catch (KeyNotFoundException) { // no template for race/class combination log.WarnFormat("cannot create character with race {0} and class {1} because that combination is not valid", raceEnum, classEnum); session.Send(ShardServerOpcode.CharacterCreate, (byte)CharacterCreateResponse.Failed); return; } if (session.Server.ShardDB.ExecuteQuery("select id from `character` where name = ?", name, result => { return(result.Read()); })) { // character already exists log.DebugFormat("cannot create character [{0}] because that name already exists", name); session.Send(ShardServerOpcode.CharacterCreate, (byte)CharacterCreateResponse.NameTaken); return; } int updated = session.Server.ShardDB.ExecuteNonQuery("insert into `character` (account_id, name, race, class, sex, skin, face, hair_style, hair_color, facial_hair, position_x, position_y, position_z, orientation, map_id, zone_id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", session.AccountID, name, race, @class, sex, skin, face, hairStyle, hairColor, facialHair, template.PositionX, template.PositionY, template.PositionZ, template.Orientation, template.MapID, template.ZoneID); if (updated != 1) { log.ErrorFormat("expected 1 row updated when inserting new character but got {0}", updated); session.Send(ShardServerOpcode.CharacterCreate, (byte)CharacterCreateResponse.Failed); return; } int characterId = session.Server.ShardDB.ExecuteQuery("select id from `character` where account_id = ? and name = ?", new object[] { session.AccountID, name }, result => { if (result.Read()) { return(result.GetInt32(0)); } else { return(-1); } }); if (characterId < 0) { log.ErrorFormat("unable to locate recently inserted character with account id [{0}] and name '{1}'", session.AccountID, name); session.Send(ShardServerOpcode.CharacterCreate, (byte)CharacterCreateResponse.Failed); return; } foreach (var spellId in template.SpellIDs) { if (session.Server.ShardDB.ExecuteNonQuery("insert into character_spell (character_id, spell_id) values (?, ?)", characterId, spellId) != 1) { log.Error("insert into character_spell did not affect 1 row"); } } for (int i = 0; i < template.ActionButtons.Count; ++i) { if (session.Server.ShardDB.ExecuteNonQuery("insert into character_action_button (character_id, button, action, type) values (?, ?, ?, ?)", characterId, i, template.ActionButtons[i].Action, template.ActionButtons[i].ButtonType) != 1) { log.Error("insert into character_action_button did not affect 1 row"); } } // success case log.InfoFormat("account [{0}] successfully created new {1} {2} named '{3}'", session.AccountID, raceEnum, classEnum, name); session.Send(ShardServerOpcode.CharacterCreate, (byte)CharacterCreateResponse.Success); }
public override void ExecuteCommand(ShardSession session, ShardRequest request, ClientPacketHeader header) { // no battlefields yet, so nothing to report }
public override void ExecuteCommand(ShardSession session, ShardRequest request, ClientPacketHeader header) { session.Send(ShardServerOpcode.QueryRaidInfo, BitConverter.GetBytes(0)); // number of saved instance ids }
public override void ExecuteCommand(ShardSession session, ShardRequest request, Ping header) { log.DebugFormat("client sends ping with latency = {0}", header.Latency); session.Send(ShardServerOpcode.Pong, BitConverter.GetBytes(header.Cookie)); }
public override void ExecuteCommand(ShardSession session, ShardRequest request, ClientPacketHeader header) { }
public override void ExecuteCommand(ShardSession session, ShardRequest request, MoveTimeSkipped header) { log.DebugFormat("received {0} packet. unit id = {1}, time skipped = {2}", ShardClientOpcode.MoveTimeSkipped, header.UnitID, header.TimeSkipped); }
public override void ExecuteCommand(ShardSession session, ShardRequest request, ZoneUpdate header) { log.DebugFormat("received {0} command. new zone id = {1}", Name, header.ZoneID); }
public override void ExecuteCommand(ShardSession session, ShardRequest request, ClientPacketHeader header) { int count = session.Server.ShardDB.ExecuteQuery("select count(0) from `character` where account_id = ?", session.AccountID, result => { if (result.Read()) { return(result.GetInt32(0)); } else { log.Error("selecting count on character table returned no result row"); return(0); } }); if (count > byte.MaxValue) { log.WarnFormat("character count [{0}] for account id [{1}] is larger than maximum [{2}] and is being limited", count, session.AccountID, byte.MaxValue); count = byte.MaxValue; } using (ByteBuffer response = new ByteBuffer()) { response.Append((byte)count); // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 session.Server.ShardDB.ExecuteQuery("select id, name, race, class, sex, skin, face, hair_style, hair_color, facial_hair, level, map_id, position_x, position_y, position_z, player_flags, zone_id from `character` where account_id = ? limit ?", new object[] { session.AccountID, byte.MaxValue }, result => { while (result.Read()) { response.Append(new ObjectID(result.GetInt32(0), ObjectID.Type.Player)); // id response.Append(result.GetString(1)); // name response.Append(result.GetByte(2)); // race response.Append(result.GetByte(3)); // class response.Append(result.GetByte(4)); // sex response.Append(result.GetByte(5)); // skin response.Append(result.GetByte(6)); // face response.Append(result.GetByte(7)); // hair style response.Append(result.GetByte(8)); // hair color response.Append(result.GetByte(9)); // facial hair response.Append(result.GetByte(10)); // level response.Append(result.GetInt32(16)); // zone response.Append(result.GetInt32(11)); // map id response.Append(result.GetFloat(12)); // x response.Append(result.GetFloat(13)); // y response.Append(result.GetFloat(14)); // z response.Append(0); // guild id response.Append(result.GetInt32(15)); // player flags response.Append((byte)1); // first login response.Append(0); // pet display id response.Append(0); // pet level response.Append(0); // pet family for (int i = 0; i < Enum.GetValues(typeof(EquipmentSlot)).Length; ++i) { response.Append(0); // display info id response.Append((byte)0); // inventory type } response.Append(0); // first bag display info id response.Append((byte)0); // first bag inventory type } return(true); }); session.Send(ShardServerOpcode.CharacterList, response); } }
public override void ExecuteCommand(ShardSession session, ShardRequest request, ClientPacketHeader header) { session.SendQueryTimePacket(); }
public override void ExecuteCommand(ShardSession session, ShardRequest request, ClientPacketHeader header) { session.SendQueryTimePacket(); session.Send(ShardServerOpcode.SupportTicketQuery, BitConverter.GetBytes((int)SupportTicketStatus.NotExists)); }
private void WaitAns(ShardRequest msg) { // waiting shard answer Assert.IsTrue(msg.Data.Count() == 1); }
public override void ExecuteCommand(ShardSession session, ShardRequest request, ClientPacketHeader header) { int clientBuild = BitConverter.ToInt32(request.Packet, 6); int identityLength; string identity = Strings.FromNullTerminated(request.Packet, 14, Encoding.UTF8, out identityLength); int clientSeed = BitConverter.ToInt32(request.Packet, 14 + identityLength + 1); // + 1 for null terminator byte[] clientDigest = new byte[20]; Array.Copy(request.Packet, 14 + identityLength + 1 + 4, clientDigest, 0, 20); log.DebugFormat("read {0} packet. client build = {1}, identity = {2}, client seed = {3:X}, packet size = {4}", header.Opcode, clientBuild, identity, clientSeed, request.Size); int accountId = -1; string sessionKey = null; if (!session.Server.AuthDB.ExecuteQuery("select name, session_key, id from account where name = ? and enabled = true", identity, result => { if (result.Read()) { identity = result.GetString(0); sessionKey = result.GetString(1); accountId = result.GetInt32(2); return(true); } return(false); })) { // no identity match log.DebugFormat("account {0} not found. sending {1} response", identity, AuthResponse.UnknownAccount); session.Send(ShardServerOpcode.AuthResponse, (byte)AuthResponse.UnknownAccount); return; } BigInteger sessionKeyInt = BigInteger.Parse(sessionKey, NumberStyles.AllowHexSpecifier); // verify client/server identity and session key match using (Digester sha1 = new Digester(new SHA1CryptoServiceProvider())) { byte[] serverDigest = sha1.CalculateDigest(new byte[][] { Encoding.UTF8.GetBytes(identity), new byte[4], BitConverter.GetBytes(clientSeed), BitConverter.GetBytes(session.Seed), Arrays.Left(sessionKeyInt.ToByteArray(), 40) }); log.DebugFormat("client digest = {0}", Strings.HexOf(clientDigest)); log.DebugFormat("server digest = {0}", Strings.HexOf(serverDigest)); if (Arrays.AreEqual(clientDigest, serverDigest)) { log.InfoFormat("client {0} successfully authenticated from {1}", identity, session.RemoteEndPoint.Address.ToString()); session.AccountID = accountId; session.Status = SessionStatus.Authenticated; session.InitializeCipher(sessionKeyInt); using (ByteBuffer authPacket = new ByteBuffer()) { authPacket.Append((byte)AuthResponse.Success); authPacket.Append(0); authPacket.Append((byte)0); authPacket.Append(0); session.Send(ShardServerOpcode.AuthResponse, authPacket); } using (ByteBuffer addonPacket = BuildAddonPacket(new ArraySegment <byte>(request.Packet, 14 + identityLength + 1 + 4 + 20, request.Size - (14 + identityLength + 1 + 4 + 20)))) session.Send(ShardServerOpcode.AddonInfo, addonPacket); } else { // digest mismatch log.DebugFormat("client digest did not match server digest for account {0}. sending {1} response", identity, AuthResponse.Failed); session.Send(ShardServerOpcode.AuthResponse, (byte)AuthResponse.Failed); return; } } }