예제 #1
0
        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);
                }
            }
        }
예제 #2
0
파일: Login.cs 프로젝트: moseleyc/server
        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);
                }
            }
        }
예제 #3
0
파일: Login.cs 프로젝트: DomGrieco/server
        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);
                }
            }

        }
예제 #4
0
파일: World.cs 프로젝트: saroque/server
        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;
            }   
        }
예제 #5
0
파일: World.cs 프로젝트: saroque/server
        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();

            }

        }
예제 #6
0
파일: World.cs 프로젝트: saroque/server
        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();
                }
            }
        }
예제 #7
0
파일: World.cs 프로젝트: saroque/server
        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;
            }

        }
예제 #8
0
파일: World.cs 프로젝트: saroque/server
        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...?");
                    }                    
                }
            }
        }
예제 #9
0
파일: World.cs 프로젝트: saroque/server
        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");
                }
            }

        }
예제 #10
0
파일: World.cs 프로젝트: saroque/server
        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);
        }
예제 #11
0
파일: World.cs 프로젝트: saroque/server
        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);
                }
            }
        }