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_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 (Game.World.WorldData.TryGetAuthInfo(name, out AuthInfo login)) { login.CurrentState = UserState.Login; login.Save(); } if (redirect.Matches(name, key, seed)) { ((IDictionary)ExpectedConnections).Remove(id); client.EncryptionKey = key; client.EncryptionSeed = seed; if (redirect.Source is Lobby || redirect.Source is World) { var x60 = new ServerPacket(0x60); x60.WriteByte(0x00); x60.WriteUInt32(Game.NotificationCrc); client.Enqueue(x60); } } }
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_0x4A_Trade(object obj, ClientPacket packet) { var user = (User) obj; var tradeStage = packet.ReadByte(); if (tradeStage == 0 && user.ActiveExchange != null) return; if (tradeStage != 0 && user.ActiveExchange == null) return; if (user.ActiveExchange != null && !user.ActiveExchange.ConditionsValid) return; switch (tradeStage) { case 0x00: { // Starting trade var x0PlayerId = packet.ReadInt32(); WorldObject target; if (Objects.TryGetValue((uint)x0PlayerId, out target)) { if (target is User) { var playerTarget = (User)target; if (Exchange.StartConditionsValid(user, playerTarget)) { user.SendMessage("That can't be done right now.", MessageTypes.SYSTEM); return; } // Initiate exchange var exchange = new Exchange(user, playerTarget); exchange.StartExchange(); } } } break; case 0x01: // Add item to trade { // We ignore playerId because we only allow one exchange at a time and we // keep track of the participants on both sides var x1playerId = packet.ReadInt32(); var x1ItemSlot = packet.ReadByte(); if (user.Inventory[x1ItemSlot] != null && user.Inventory[x1ItemSlot].Count > 1) { // Send quantity request user.SendExchangeQuantityPrompt(x1ItemSlot); } else user.ActiveExchange.AddItem(user, x1ItemSlot); } break; case 0x02: // Add item with quantity var x2PlayerId = packet.ReadInt32(); var x2ItemSlot = packet.ReadByte(); var x2ItemQuantity = packet.ReadByte(); user.ActiveExchange.AddItem(user, x2ItemSlot, x2ItemQuantity); break; case 0x03: // Add gold to trade var x3PlayerId = packet.ReadInt32(); var x3GoldQuantity = packet.ReadUInt32(); user.ActiveExchange.AddGold(user, x3GoldQuantity); break; case 0x04: // Cancel trade Logger.Debug("Cancelling trade"); user.ActiveExchange.CancelExchange(user); break; case 0x05: // Confirm trade Logger.Debug("Confirming trade"); user.ActiveExchange.ConfirmExchange(user); break; default: return; } }
private void PacketHandler_0x43_PointClick(Object obj, ClientPacket packet) { var user = (User) obj; var clickType = packet.ReadByte(); Rectangle commonViewport = user.GetViewport(); // User has clicked an X,Y point if (clickType == 3) { var x = (byte) packet.ReadUInt16(); var y = (byte) packet.ReadUInt16(); var coords = new Tuple<byte, byte>(x, y); Logger.DebugFormat("coordinates were {0}, {1}", x, y); if (user.Map.Doors.ContainsKey(coords)) { if (user.Map.Doors[coords].Closed) user.SendMessage("It's open.", 0x1); else user.SendMessage("It's closed.", 0x1); user.Map.ToggleDoors(x, y); } else if (user.Map.Signposts.ContainsKey(coords)) { user.Map.Signposts[coords].OnClick(user); } else { Logger.DebugFormat("User clicked {0}@{1},{2} but no door/signpost is present", user.Map.Name, x, y); } } // User has clicked on another entity else if (clickType == 1) { var entityId = packet.ReadUInt32(); Logger.DebugFormat("User {0} clicked ID {1}: ", user.Name, entityId); WorldObject clickTarget = new WorldObject(); if (user.World.Objects.TryGetValue(entityId, out clickTarget)) { if (clickTarget is User || clickTarget is Merchant) { Type type = clickTarget.GetType(); MethodInfo methodInfo = type.GetMethod("OnClick"); methodInfo.Invoke(clickTarget, new[] {user}); } } } else { Logger.DebugFormat("Unsupported clickType {0}", clickType); Logger.DebugFormat("Packet follows:"); packet.DumpPacket(); } }
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(); } } }
private void PacketHandler_0x39_NPCMainMenu(Object obj, ClientPacket packet) { var user = (User) obj; if (user.CheckSquelch(0x38, null)) { Logger.InfoFormat("{0}: squelched (NPC main menu)", user.Name); return; } // We just ignore the header, because, really, what exactly is a 16-bit encryption // key plus CRC really doing for you var header = packet.ReadDialogHeader(); var objectType = packet.ReadByte(); var objectId = packet.ReadUInt32(); var pursuitId = packet.ReadUInt16(); Logger.DebugFormat("main menu packet: ObjectType {0}, ID {1}, pursuitID {2}", objectType, objectId, pursuitId); // Sanity checks WorldObject wobj; if (Game.World.Objects.TryGetValue(objectId, out wobj)) { // Are we handling a global sequence? DialogSequence pursuit; VisibleObject clickTarget = wobj as VisibleObject; if (pursuitId < Constants.DIALOG_SEQUENCE_SHARED) { // Does the sequence exist in the global catalog? try { pursuit = Game.World.GlobalSequences[pursuitId]; } catch { Logger.ErrorFormat("{0}: pursuit ID {1} doesn't exist in the global catalog?", wobj.Name, pursuitId); return; } } else if (pursuitId >= Constants.DIALOG_SEQUENCE_HARDCODED) { if (!(wobj is Merchant)) { Logger.ErrorFormat("{0}: attempt to use hardcoded merchant menu item on non-merchant", wobj.Name, pursuitId); return; } var menuItem = (MerchantMenuItem) pursuitId; var merchant = (Merchant) wobj; MerchantMenuHandler handler; if (!merchantMenuHandlers.TryGetValue(menuItem, out handler)) { Logger.ErrorFormat("{0}: merchant menu item {1} doesn't exist?", wobj.Name, menuItem); return; } if (!merchant.Jobs.HasFlag(handler.RequiredJob)) { Logger.ErrorFormat("{0}: merchant does not have required job {1}", wobj.Name, handler.RequiredJob); return; } handler.Callback(user, merchant, packet); return; } else { // This is a local pursuit try { pursuit = clickTarget.Pursuits[pursuitId - Constants.DIALOG_SEQUENCE_SHARED]; } catch { Logger.ErrorFormat("{0}: local pursuit {1} doesn't exist?", wobj.Name, pursuitId); return; } } Logger.DebugFormat("{0}: showing initial dialog for Pursuit {1} ({2})", clickTarget.Name, pursuit.Id, pursuit.Name); user.DialogState.StartDialog(clickTarget, pursuit); pursuit.ShowTo(user, clickTarget); } else { Logger.WarnFormat("specified object ID {0} doesn't exist?", objectId); return; } }
private void PacketHandler_0x29_DropItemOnCreature(Object obj, ClientPacket packet) { var itemSlot = packet.ReadByte(); var targetId = packet.ReadUInt32(); var quantity = packet.ReadByte(); var user = (User) obj; // If the object is a creature or an NPC, simply give them the item, otherwise, // initiate an exchange WorldObject target; if (!user.World.Objects.TryGetValue(targetId, out target)) return; if (user.Map.Objects.Contains((VisibleObject)target)) { if (target is User) { var playerTarget = (User) target; // Pre-flight checks if (!Exchange.StartConditionsValid(user, playerTarget)) { user.SendSystemMessage("You can't do that."); return; } if (!playerTarget.IsAvailableForExchange) { user.SendSystemMessage("They can't do that right now."); return; } if (!user.IsAvailableForExchange) { user.SendSystemMessage("You can't do that right now."); } // Initiate exchange and put item in it var exchange = new Exchange(user, playerTarget); exchange.StartExchange(); if (user.Inventory[itemSlot] != null && user.Inventory[itemSlot].Count > 1) user.SendExchangeQuantityPrompt(itemSlot); else exchange.AddItem(user, itemSlot, quantity); } else if (target is Creature && user.IsInViewport((VisibleObject)target)) { var creature = (Creature) target; var item = user.Inventory[itemSlot]; if (item != null) { if (user.RemoveItem(itemSlot)) { creature.Inventory.AddItem(item); } else Logger.WarnFormat("0x29: Couldn't remove item from inventory...?"); } } } }
private void PacketHandler_0x2A_DropGoldOnCreature(Object obj, ClientPacket packet) { var goldAmount = packet.ReadUInt32(); var targetId = packet.ReadUInt32(); var user = (User) obj; // If the object is a creature or an NPC, simply give them the item, otherwise, // initiate an exchange WorldObject target; if (!user.World.Objects.TryGetValue(targetId, out target)) return; if (user.Map.Objects.Contains((VisibleObject)target)) { if (target is User) { // Initiate exchange and put gold in it var playerTarget = (User) target; // Pre-flight checks if (!Exchange.StartConditionsValid(user, playerTarget)) { user.SendSystemMessage("You can't do that."); return; } if (!playerTarget.IsAvailableForExchange) { user.SendMessage("They can't do that right now.", MessageTypes.SYSTEM); return; } if (!user.IsAvailableForExchange) { user.SendMessage("You can't do that right now.", MessageTypes.SYSTEM); } // Start exchange var exchange = new Exchange(user, playerTarget); exchange.StartExchange(); exchange.AddGold(user, goldAmount); } else if (target is Creature && user.IsInViewport((VisibleObject)target)) { // Give gold to Creature and go about our lives var creature = (Creature) target; creature.Gold += goldAmount; user.Gold -= goldAmount; user.UpdateAttributes(StatUpdateFlags.Stats); } else { Logger.DebugFormat("user {0}: invalid drop target"); } } }
private void PacketHandler_0x24_DropGold(Object obj, ClientPacket packet) { var user = (User) obj; var amount = packet.ReadUInt32(); var x = packet.ReadInt16(); var y = packet.ReadInt16(); Logger.DebugFormat("{0} {1} {2}", amount, x, y); // Do a few sanity checks // Is the distance valid? (Can't drop things beyond // MAXIMUM_DROP_DISTANCE tiles away) if (Math.Abs(x - user.X) > Constants.PICKUP_DISTANCE || Math.Abs(y - user.Y) > Constants.PICKUP_DISTANCE) { Logger.ErrorFormat("Request to drop gold exceeds maximum distance {0}", Hybrasyl.Constants.MAXIMUM_DROP_DISTANCE); return; } // Does the amount in the packet exceed the // amount of gold the player has? Are they trying to drop the item on something that // is impassable (i.e. a wall)? if ((amount > user.Gold) || (x >= user.Map.X) || (y >= user.Map.Y) || (x < 0) || (y < 0) || (user.Map.IsWall[x, y])) { Logger.ErrorFormat("Amount {0} exceeds amount {1}, or {2},{3} is a wall, or {2},{3} is out of bounds", amount, user.Gold, x, y); return; } var toDrop = new Gold(amount); user.RemoveGold(amount); Insert(toDrop); // Are we dropping an item onto a reactor? Reactor reactor; var coordinates = new Tuple<byte, byte>((byte)x, (byte)y); if (user.Map.Reactors.TryGetValue(coordinates, out reactor)) { reactor.OnDrop(user, toDrop); } else user.Map.AddGold(x, y, toDrop); }
private void PacketHandler_0x10_ClientJoin(Object obj, ClientPacket packet) { var connectionId = (long) obj; 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); if (PlayerExists(name)) { var user = new User(this, connectionId, name); user.SetEncryptionParameters(key, seed, name); user.LoadDataFromEntityFramework(true); user.UpdateLoginTime(); user.UpdateAttributes(StatUpdateFlags.Full); Logger.DebugFormat("Elapsed time since login: {0}", user.SinceLastLogin); if (user.Citizenship.spawn_points.Count != 0 && user.SinceLastLogin > Hybrasyl.Constants.NATION_SPAWN_TIMEOUT) { Insert(user); var spawnpoint = user.Citizenship.spawn_points.First(); user.Teleport((ushort) spawnpoint.map_id, (byte) spawnpoint.map_x, (byte) spawnpoint.map_y); } else if (user.MapId != null && Maps.ContainsKey(user.MapId)) { Insert(user); user.Teleport(user.MapId, (byte) user.MapX, (byte) user.MapY); } else { // Handle any weird cases where a map someone exited on was deleted, etc // This "default" of Mileth should be set somewhere else Insert(user); user.Teleport((ushort) 500, (byte) 50, (byte) 50); } Logger.DebugFormat("Adding {0} to hash", user.Name); AddUser(user); ActiveUsers[connectionId] = user; ActiveUsersByName[user.Name] = connectionId; Logger.InfoFormat("cid {0}: {1} entering world", connectionId, user.Name); } } }