public ServerPacket RenderToPacket(bool isClick = false) { var response = new ServerPacket(0x31); if (this is Mailbox) { response.WriteByte(0x04); // 0x02 - public, 0x04 - mail response.WriteByte(0x01); // ??? - needs to be odd number unless board in world has been clicked response.WriteUInt16(0); // board ID; response.WriteString8("Mail"); response.WriteByte(Math.Min((byte)this.Count(), (byte)Constants.MESSAGE_RETURN_SIZE)); foreach (var message in this) { response.WriteBoolean(!message.Read); response.WriteInt16((short)message.Id); response.WriteString8(message.Sender); response.WriteByte((byte)message.Created.Month); response.WriteByte((byte)message.Created.Day); response.WriteString8(message.Subject); } } else if (this is Board) { // boardId 0 - get mail messages response.WriteByte(0x02); // 0x02 - public, 0x04 - mail response.WriteByte((byte)(isClick == true ? 0x02 : 0x01)); // ??? - needs to be odd number unless board in world has been clicked response.WriteUInt16((ushort)Id); // board ID; response.WriteString8(DisplayName); response.WriteByte(Math.Min((byte)this.Count(), (byte)Constants.MESSAGE_RETURN_SIZE)); foreach (var message in this) { response.WriteBoolean(message.Highlighted); response.WriteInt16((short)message.Id); response.WriteString8(message.Sender); response.WriteByte((byte)message.Created.Month); response.WriteByte((byte)message.Created.Day); response.WriteString8(message.Subject); } } return(response); }
private void PacketHandler_0x57_ServerTable(Client client, ClientPacket packet) { var mismatch = packet.ReadByte(); if (mismatch == 1) { var x56 = new ServerPacket(0x56); x56.WriteUInt16((ushort)Game.ServerTable.Length); x56.Write(Game.ServerTable); Logger.InfoFormat("ServerTable: Sent: {0}", BitConverter.ToString(x56.ToArray())); client.Enqueue(x56); } else { var server = packet.ReadByte(); var redirect = new Redirect(client, this, Game.Login, "socket", client.EncryptionSeed, client.EncryptionKey); client.Redirect(redirect); } }
public virtual void AcceptConnection(IAsyncResult ar) { // TODO: @norrismiv async callbacks+inheritance? and/or can these callbacks suck less? AllDone.Set(); Socket clientSocket = (Socket)ar.AsyncState; Socket handler = clientSocket.EndAccept(ar); Client client = new Client(handler, this); Clients.TryAdd(handler.Handle, client); GlobalConnectionManifest.RegisterClient(client); if (this is Lobby) { var x7E = new ServerPacket(0x7E); x7E.WriteByte(0x1B); x7E.WriteString("CONNECTED SERVER\n"); client.Enqueue(x7E); Logger.DebugFormat("Lobby: AcceptConnection occuring"); Logger.DebugFormat("Lobby: cid is {0}", client.ConnectionId); } else if (this is Login) { Logger.DebugFormat("Login: AcceptConnection occuring"); Logger.DebugFormat("Login: cid is {0}", client.ConnectionId); } else if (this is World) { Logger.DebugFormat("World: AcceptConnection occuring"); Logger.DebugFormat("World: cid is {0}", client.ConnectionId); } try { handler.BeginReceive(client.ClientState.Buffer, 0, client.ClientState.Buffer.Length, 0, new AsyncCallback(ReadCallback), client.ClientState); Logger.DebugFormat("AcceptConnection returning"); clientSocket.BeginAccept(new AsyncCallback(AcceptConnection), clientSocket); } catch (SocketException) { handler.Close(); } }
/// <summary> /// Atomically update the byte-based heartbeat values for the 0x3B packet and then /// queue for transmission to the client. This transmission is aborted if the client hasn't /// been alive more than BYTE_HEARTBEAT_INTERVAL seconds. /// If we don't receive a response to the 0x3B heartbeat within REAP_HEARTBEAT_INTERVAL /// the client is automatically disconnected. /// </summary> public void SendByteHeartbeat() { var aliveSince = new TimeSpan(DateTime.Now.Ticks - ConnectedSince); if (aliveSince.TotalSeconds < Constants.BYTE_HEARTBEAT_INTERVAL) { return; } var rnd = new Random(); var byteHeartbeat = new ServerPacket(0x3b); var a = rnd.Next(254); var b = rnd.Next(254); Interlocked.Exchange(ref _heartbeatA, a); Interlocked.Exchange(ref _heartbeatB, b); byteHeartbeat.WriteByte((byte)a); byteHeartbeat.WriteByte((byte)b); Enqueue(byteHeartbeat); Interlocked.Exchange(ref _byteHeartbeatSent, DateTime.Now.Ticks); }
internal List <ServerPacket> Packets() { var ret = new List <ServerPacket>(); var tile = 0; for (var row = 0; row < Map.Y; row++) { ServerPacket packet = new ServerPacket(OpCode); packet.WriteUInt16((ushort)row); for (int column = 0; column < Map.X * 6; column += 2) { packet.WriteByte(Map.RawData[tile + 1]); packet.WriteByte(Map.RawData[tile]); tile += 2; } ret.Add(packet); } return(ret); }
public void Redirect(Redirect redirect, bool isLogoff = false, int transmitDelay = 0) { GameLog.InfoFormat("Processing redirect"); GlobalConnectionManifest.RegisterRedirect(this, redirect); GameLog.InfoFormat("Redirect: cid {0}", this.ConnectionId); GameLog.Info($"Redirect EncryptionKey is {Encoding.ASCII.GetString(redirect.EncryptionKey)}"); if (isLogoff) { GlobalConnectionManifest.DeregisterClient(this); } redirect.Destination.ExpectedConnections.TryAdd(redirect.Id, redirect); var endPoint = Socket.RemoteEndPoint as IPEndPoint; byte[] addressBytes; if (Game.RedirectTarget != null) { addressBytes = Game.RedirectTarget.GetAddressBytes(); } else { addressBytes = IPAddress.IsLoopback(endPoint.Address) ? IPAddress.Loopback.GetAddressBytes() : Game.IpAddress.GetAddressBytes(); } Array.Reverse(addressBytes); var x03 = new ServerPacket(0x03); x03.Write(addressBytes); x03.WriteUInt16((ushort)redirect.Destination.Port); x03.WriteByte((byte)(redirect.EncryptionKey.Length + Encoding.ASCII.GetBytes(redirect.Name).Length + 7)); x03.WriteByte(redirect.EncryptionSeed); x03.WriteByte((byte)redirect.EncryptionKey.Length); x03.Write(redirect.EncryptionKey); x03.WriteString8(redirect.Name); x03.WriteUInt32(redirect.Id); x03.TransmitDelay = transmitDelay == 0 ? 250 : transmitDelay; Enqueue(x03); }
internal ServerPacket Packet() { ServerPacket packet = new ServerPacket(OpCode); packet.WriteByte(0x00); if (Id != 0) { packet.WriteUInt32(Id); packet.WriteUInt32(SenderId == 0 ? Id : SenderId); packet.WriteUInt16(AnimationId); packet.WriteUInt16(SenderAnimationId == 0 ? ushort.MinValue : SenderAnimationId); packet.WriteUInt16(Speed); packet.WriteByte(0x00); } else { packet.WriteUInt32(uint.MinValue); packet.WriteUInt16(AnimationId); packet.WriteUInt16(Speed); packet.WriteUInt16(X); packet.WriteUInt16(Y); } return(packet); }
public void SendMessage(string message, byte type) { var x0A = new ServerPacket(0x0A); x0A.WriteByte(type); x0A.WriteString16(message); Enqueue(x0A); }
public void LoginMessage(string message, byte type) { var x02 = new ServerPacket(0x02); x02.WriteByte(type); x02.WriteString8(message); Enqueue(x02); }
public void Redirect(Redirect redirect) { Logger.DebugFormat("Processing redirect"); GlobalConnectionManifest.DeregisterClient(this); redirect.Destination.ExpectedConnections.TryAdd(redirect.Id, redirect); var endPoint = Socket.RemoteEndPoint as IPEndPoint; byte[] addressBytes = IPAddress.IsLoopback(endPoint.Address) ? IPAddress.Loopback.GetAddressBytes() : Game.IpAddress.GetAddressBytes(); Array.Reverse(addressBytes); var x03 = new ServerPacket(0x03); x03.Write(addressBytes); x03.WriteUInt16((ushort)redirect.Destination.Port); x03.WriteByte((byte)(redirect.EncryptionKey.Length + Encoding.GetEncoding(949).GetBytes(redirect.Name).Length + 7)); x03.WriteByte(redirect.EncryptionSeed); x03.WriteByte((byte)redirect.EncryptionKey.Length); x03.Write(redirect.EncryptionKey); x03.WriteString8(redirect.Name); x03.WriteUInt32(redirect.Id); Enqueue(x03); }
private void PacketHandler_0x7B_RequestMetafile(Object obj, ClientPacket packet) { var user = (User) obj; var all = packet.ReadBoolean(); if (all) { var x6F = new ServerPacket(0x6F); x6F.WriteBoolean(all); x6F.WriteUInt16((ushort) Metafiles.Count); foreach (var metafile in Metafiles.Values) { x6F.WriteString8(metafile.Name); x6F.WriteUInt32(metafile.Checksum); } user.Enqueue(x6F); } else { var name = packet.ReadString8(); if (Metafiles.ContainsKey(name)) { var file = Metafiles[name]; var x6F = new ServerPacket(0x6F); x6F.WriteBoolean(all); x6F.WriteString8(file.Name); x6F.WriteUInt32(file.Checksum); x6F.WriteUInt16((ushort) file.Data.Length); x6F.Write(file.Data); user.Enqueue(x6F); } } }
private void PacketHandler_0x4B_RequestNotification(Client client, ClientPacket packet) { var x60 = new ServerPacket(0x60); x60.WriteByte(0x01); x60.WriteUInt16((ushort)Game.Notification.Length); x60.Write(Game.Notification); client.Enqueue(x60); }
public bool SendBufferTake(out ServerPacket packet) { return(_sendBuffer.TryDequeue(out packet)); }
public void Enqueue(ServerPacket packet) { Logger.DebugFormat("Enqueueing {0}", packet.Opcode); ClientState.SendBufferAdd(packet); }
public bool SendBufferTake(out ServerPacket packet) => _sendBuffer.TryDequeue(out packet);
public bool SendBufferPeek(out ServerPacket packet) => _sendBuffer.TryPeek(out packet);
private void PacketHandler_0x3B_AccessMessages(Object obj, ClientPacket packet) { var user = (User) obj; var messagePacket = new ServerPacket(0x31); messagePacket.WriteByte(0x01); messagePacket.WriteUInt16(0x00); messagePacket.WriteByte(0x00); user.Enqueue(messagePacket); }
internal ServerPacket Packet() { var packet = new ServerPacket(OpCode); packet.WriteByte((byte)MerchantDialogType); packet.WriteByte((byte)MerchantDialogObjectType); packet.WriteUInt32(ObjectId); packet.WriteByte(0); packet.WriteInt16((short)Tile1); packet.WriteByte(0); packet.WriteByte(1); packet.WriteInt16((short)Tile1); packet.WriteByte(0); packet.WriteByte(0); packet.WriteString8(Name); packet.WriteString16(Text); if (MerchantDialogType == MerchantDialogType.Options) { packet.WriteByte(Options.OptionsCount); foreach (var opt in Options.Options) { packet.WriteString8(opt.Text); packet.WriteUInt16(opt.Id); } } if (MerchantDialogType == MerchantDialogType.OptionsWithArgument) { packet.WriteString8(OptionsWithArgument.Argument); packet.WriteByte(OptionsWithArgument.OptionsCount); foreach (var opt in OptionsWithArgument.Options) { packet.WriteString8(opt.Text); packet.WriteUInt16(opt.Id); } } if (MerchantDialogType == MerchantDialogType.Input) { packet.WriteUInt16(Input.Id); } if (MerchantDialogType == MerchantDialogType.InputWithArgument) { packet.WriteString8(InputWithArgument.Argument); packet.WriteUInt16(InputWithArgument.Id); } if (MerchantDialogType == MerchantDialogType.MerchantShopItems) { packet.WriteUInt16(ShopItems.Id); packet.WriteUInt16(ShopItems.ItemsCount); foreach (var item in ShopItems.Items) { packet.WriteUInt16(item.Tile); packet.WriteByte(item.Color); packet.WriteUInt32(item.Price); packet.WriteString8(item.Name); packet.WriteString8(item.Description); } } if (MerchantDialogType == MerchantDialogType.MerchantSkills) { packet.WriteUInt16(Skills.Id); packet.WriteUInt16(Skills.SkillsCount); foreach (var skill in Skills.Skills) { packet.WriteByte(skill.IconType); packet.WriteUInt16(skill.Icon); packet.WriteByte(skill.Color); packet.WriteString8(skill.Name); } } if (MerchantDialogType == MerchantDialogType.MerchantSpells) { packet.WriteUInt16(Spells.Id); packet.WriteUInt16(Spells.SpellsCount); foreach (var spell in Spells.Spells) { packet.WriteByte(spell.IconType); packet.WriteUInt16(spell.Icon); packet.WriteByte(spell.Color); packet.WriteString8(spell.Name); } } if (MerchantDialogType == MerchantDialogType.UserSkillBook) { packet.WriteUInt16(UserSkills.Id); } if (MerchantDialogType == MerchantDialogType.UserSpellBook) { packet.WriteUInt16(UserSpells.Id); } if (MerchantDialogType == MerchantDialogType.UserInventoryItems) { packet.WriteUInt16(UserInventoryItems.Id); packet.WriteByte(UserInventoryItems.InventorySlotsCount); foreach (var slot in UserInventoryItems.InventorySlots) { packet.WriteByte(slot); } } return(packet); }
private void PacketHandler_0x05_RequestMap(Object obj, ClientPacket packet) { var user = (User) obj; int index = 0; for (ushort row = 0; row < user.Map.Y; ++row) { var x3C = new ServerPacket(0x3C); x3C.WriteUInt16(row); for (int col = 0; col < user.Map.X*6; col += 2) { x3C.WriteByte(user.Map.RawData[index + 1]); x3C.WriteByte(user.Map.RawData[index]); index += 2; } user.Enqueue(x3C); } }
public void Enqueue(ServerPacket packet) { Logger.DebugFormat("Enqueueing {0}", packet.Opcode); SendQueue.Enqueue(packet); }
private void PacketHandler_0x18_ShowPlayerList(Object obj, ClientPacket packet) { var me = (User) obj; var list = from user in Users.Values orderby user.IsMaster descending, user.Level descending, user.BaseHp + user.BaseMp * 2 descending, user.Name ascending select user; var listPacket = new ServerPacket(0x36); listPacket.WriteUInt16((ushort)list.Count()); listPacket.WriteUInt16((ushort)list.Count()); foreach (var user in list) { int levelDifference = Math.Abs((int)user.Level - me.Level); listPacket.WriteByte((byte)user.Class); if (!string.IsNullOrEmpty(me.Guild) && user.Guild == me.Guild) listPacket.WriteByte(84); else if (levelDifference <= 5) listPacket.WriteByte(151); else listPacket.WriteByte(255); listPacket.WriteByte((byte)user.GroupStatus); listPacket.WriteString8(user.Title); listPacket.WriteBoolean(user.IsMaster); listPacket.WriteString8(user.Name); } me.Enqueue(listPacket); }
private void PacketHandler_0x0B_ClientExit(Object obj, ClientPacket packet) { var user = (User) obj; var endSignal = packet.ReadByte(); if (endSignal == 1) { var x4C = new ServerPacket(0x4C); x4C.WriteByte(0x01); x4C.WriteUInt16(0x00); user.Enqueue(x4C); } else { long connectionId; user.Save(); user.UpdateLogoffTime(); user.Map.Remove(user); Remove(user); DeleteUser(user.Name); user.SendRedirectAndLogoff(this, Game.Login, user.Name); if (ActiveUsersByName.TryRemove(user.Name, out connectionId)) { ((IDictionary) ActiveUsers).Remove(connectionId); } Logger.InfoFormat("cid {0}: {1} leaving world", connectionId, user.Name); } }
/// <summary> /// Atomically update the byte-based heartbeat values for the 0x3B packet and then /// queue for transmission to the client. This transmission is aborted if the client hasn't /// been alive more than BYTE_HEARTBEAT_INTERVAL seconds. /// If we don't receive a response to the 0x3B heartbeat within REAP_HEARTBEAT_INTERVAL /// the client is automatically disconnected. /// </summary> public void SendByteHeartbeat() { var aliveSince = new TimeSpan(DateTime.Now.Ticks - ConnectedSince); if (aliveSince.TotalSeconds < Constants.BYTE_HEARTBEAT_INTERVAL) return; var rnd = new Random(); var byteHeartbeat = new ServerPacket(0x3b); var a = rnd.Next(254); var b = rnd.Next(254); Interlocked.Exchange(ref _heartbeatA, a); Interlocked.Exchange(ref _heartbeatB, b); byteHeartbeat.WriteByte((byte)a); byteHeartbeat.WriteByte((byte)b); Enqueue(byteHeartbeat); Interlocked.Exchange(ref _byteHeartbeatSent, DateTime.Now.Ticks); }
public void SendBufferAdd(ServerPacket packet) { _sendBuffer.Enqueue(packet); }
/// <summary> /// Atomically update the tick-based (0x68) heartbeat values and transmit /// it to the client. /// </summary> public void SendTickHeartbeat() { var aliveSince = new TimeSpan(DateTime.Now.Ticks - ConnectedSince); if (aliveSince.TotalSeconds < Constants.BYTE_HEARTBEAT_INTERVAL) return; var tickHeartbeat = new ServerPacket(0x68); // We never really want to deal with negative values var tickCount = Environment.TickCount & Int32.MaxValue; Interlocked.Exchange(ref _localTickCount, tickCount); tickHeartbeat.WriteInt32(tickCount); Enqueue(tickHeartbeat); Interlocked.Exchange(ref _tickHeartbeatSent, DateTime.Now.Ticks); }
private void PacketHandler_0x10_ClientJoin(Client client, ClientPacket packet) { var seed = packet.ReadByte(); var keyLength = packet.ReadByte(); var key = packet.Read(keyLength); var name = packet.ReadString8(); var id = packet.ReadUInt32(); var redirect = ExpectedConnections[id]; if (redirect.Matches(name, key, seed)) { ((IDictionary)ExpectedConnections).Remove(id); client.EncryptionKey = key; client.EncryptionSeed = seed; if (redirect.Source is Lobby) { var x60 = new ServerPacket(0x60); x60.WriteByte(0x00); x60.WriteUInt32(Game.NotificationCrc); client.Enqueue(x60); } } }
private void PacketHandler_0x68_RequestHomepage(Client client, ClientPacket packet) { var x03 = new ServerPacket(0x66); x03.WriteByte(0x03); x03.WriteString8("http://www.hybrasyl.com"); client.Enqueue(x03); }
private void PacketHandler_0x3A_DialogUse(Object obj, ClientPacket packet) { var user = (User) obj; if (user.CheckSquelch(0x38, null)) { Logger.InfoFormat("{0}: squelched (dialog use)", user.Name); return; } var header = packet.ReadDialogHeader(); var objectType = packet.ReadByte(); var objectID = packet.ReadUInt32(); var pursuitID = packet.ReadUInt16(); var pursuitIndex = packet.ReadUInt16(); Logger.DebugFormat("objectType {0}, objectID {1}, pursuitID {2}, pursuitIndex {3}", objectType, objectID, pursuitID, pursuitIndex); Logger.DebugFormat("active dialog via state object: pursuitID {0}, pursuitIndex {1}", user.DialogState.CurrentPursuitId, user.DialogState.CurrentPursuitIndex); if (pursuitID == user.DialogState.CurrentPursuitId && pursuitIndex == user.DialogState.CurrentPursuitIndex) { // If we get a packet back with the same index and ID, the dialog has been closed. Logger.DebugFormat("Dialog closed, resetting dialog state"); user.DialogState.EndDialog(); return; } if ((pursuitIndex > user.DialogState.CurrentPursuitIndex + 1) || (pursuitIndex < user.DialogState.CurrentPursuitIndex - 1)) { Logger.ErrorFormat("Dialog index is outside of acceptable limits (next/prev)"); return; } WorldObject wobj; if (user.World.Objects.TryGetValue(objectID, out wobj)) { VisibleObject clickTarget = wobj as VisibleObject; // Was the previous button clicked? Handle that first if (pursuitIndex == user.DialogState.CurrentPursuitIndex - 1) { Logger.DebugFormat("Handling prev: client passed index {0}, current index is {1}", pursuitIndex, user.DialogState.CurrentPursuitIndex); if (user.DialogState.SetDialogIndex(clickTarget, pursuitID, pursuitIndex)) { user.DialogState.ActiveDialog.ShowTo(user, clickTarget); return; } } // Is the active dialog an input or options dialog? if (user.DialogState.ActiveDialog is OptionsDialog) { var paramsLength = packet.ReadByte(); var option = packet.ReadByte(); var dialog = user.DialogState.ActiveDialog as OptionsDialog; dialog.HandleResponse(user, option, clickTarget); } if (user.DialogState.ActiveDialog is TextDialog) { var paramsLength = packet.ReadByte(); var response = packet.ReadString8(); var dialog = user.DialogState.ActiveDialog as TextDialog; dialog.HandleResponse(user, response, clickTarget); } // Did the handling of a response result in our active dialog sequence changing? If so, exit. if (user.DialogState.CurrentPursuitId != pursuitID) { Logger.DebugFormat("Dialog has changed, exiting"); return; } if (user.DialogState.SetDialogIndex(clickTarget, pursuitID, pursuitIndex)) { Logger.DebugFormat("Pursuit index is now {0}", pursuitIndex); user.DialogState.ActiveDialog.ShowTo(user, clickTarget); return; } else { Logger.DebugFormat("Sending close packet"); var p = new ServerPacket(0x30); p.WriteByte(0x0A); p.WriteByte(0x00); user.Enqueue(p); user.DialogState.EndDialog(); } } }