Beispiel #1
0
        public void ReadCallback(IAsyncResult ar)
        {
            ClientState  state = (ClientState)ar.AsyncState;
            Client       client;
            SocketError  errorCode = SocketError.SocketError;
            int          bytesRead = 0;
            ClientPacket receivedPacket;

            GameLog.Debug($"SocketConnected: {state.WorkSocket.Connected}, IAsyncResult: Completed: {ar.IsCompleted}, CompletedSynchronously: {ar.CompletedSynchronously}, queue size: {state.Buffer.Length}");
            GameLog.Debug("Running read callback");

            if (!GlobalConnectionManifest.ConnectedClients.TryGetValue(state.Id, out client))
            {
                // Is this a redirect?
                Redirect redirect;
                if (!GlobalConnectionManifest.TryGetRedirect(state.Id, out redirect))
                {
                    GameLog.ErrorFormat("Receive: data from unknown client (id {0}, closing connection", state.Id);
                    state.WorkSocket.Close();
                    state.WorkSocket.Dispose();
                    return;
                }
                client             = redirect.Client;
                client.ClientState = state;
                if (client.EncryptionKey == null)
                {
                    client.EncryptionKey = redirect.EncryptionKey;
                }
                GlobalConnectionManifest.RegisterClient(client);
            }

            try
            {
                bytesRead = state.WorkSocket.EndReceive(ar, out errorCode);
                if (bytesRead == 0 || errorCode != SocketError.Success)
                {
                    GameLog.Error($"bytesRead: {bytesRead}, errorCode: {errorCode}");
                    client.Disconnect();
                }
            }
            catch (Exception e)
            {
                GameLog.Fatal($"EndReceive Error:  {e.Message}");
                client.Disconnect();
            }

            try
            {
                // TODO: improve / refactor
                while (client.ClientState.TryGetPacket(out receivedPacket))
                {
                    client.Enqueue(receivedPacket);
                }
            }
            catch (Exception e)
            {
                GameLog.Error($"ReadCallback error: {e.Message}");
            }
            ContinueReceiving(state, client);
        }
Beispiel #2
0
        //public Dictionary<string, Xml.Spawn> Spawns { get; set; }

        /// <summary>
        /// Create a new Hybrasyl map from an XMLMap object.
        /// </summary>
        /// <param name="newMap">An XSD.Map object representing the XML map file.</param>
        /// <param name="theWorld">A world object where the map will be placed</param>
        public Map(Xml.Map newMap, World theWorld)
        {
            Init();
            World      = theWorld;
            SpawnDebug = false;
            //  Spawns = new List<Xml.Spawn>();

            // TODO: refactor Map class to not do this, but be a partial which overlays
            // TODO: XSD.Map
            Id           = newMap.Id;
            X            = newMap.X;
            Y            = newMap.Y;
            Name         = newMap.Name;
            AllowCasting = newMap.AllowCasting;
            EntityTree   = new QuadTree <VisibleObject>(0, 0, X, Y);
            Music        = newMap.Music;

            foreach (var warpElement in newMap.Warps)
            {
                var warp = new Warp(this)
                {
                    X = warpElement.X,
                    Y = warpElement.Y
                };

                if (warpElement.MapTarget != null)
                {
                    // map warp
                    warp.DestinationMapName = warpElement.MapTarget.Value;
                    warp.WarpType           = WarpType.Map;
                    warp.DestinationX       = warpElement.MapTarget.X;
                    warp.DestinationY       = warpElement.MapTarget.Y;
                }
                else if (warpElement.WorldMapTarget != string.Empty)
                {
                    // worldmap warp
                    warp.DestinationMapName = warpElement.WorldMapTarget;
                    warp.WarpType           = WarpType.WorldMap;
                }
                if (warpElement.Restrictions?.Level != null)
                {
                    warp.MinimumLevel = warpElement.Restrictions.Level.Min;
                    warp.MaximumLevel = warpElement.Restrictions.Level.Max;
                }
                if (warpElement.Restrictions?.Ab != null)
                {
                    warp.MinimumAbility = warpElement.Restrictions.Ab.Min;
                    warp.MaximumAbility = warpElement.Restrictions.Ab.Max;
                }
                warp.MobUse = warpElement.Restrictions?.NoMobUse ?? true;
                Warps[new Tuple <byte, byte>(warp.X, warp.Y)] = warp;
            }

            foreach (var npcElement in newMap.Npcs)
            {
                var npcTemplate = World.WorldData.Get <Xml.Npc>(npcElement.Name);
                if (npcTemplate == null)
                {
                    GameLog.Error("map ${Name}: NPC ${npcElement.Name} is missing, will not be loaded");
                    continue;
                }
                var merchant = new Merchant
                {
                    X         = npcElement.X,
                    Y         = npcElement.Y,
                    Name      = npcElement.Name,
                    Sprite    = npcTemplate.Appearance.Sprite,
                    Direction = npcElement.Direction,
                    Portrait  = npcTemplate.Appearance.Portrait,
                    AllowDead = npcTemplate.AllowDead
                };
                if (npcTemplate.Roles != null)
                {
                    if (npcTemplate.Roles.Post != null)
                    {
                        merchant.Jobs ^= MerchantJob.Post;
                    }
                    if (npcTemplate.Roles.Bank != null)
                    {
                        merchant.Jobs ^= MerchantJob.Bank;
                    }
                    if (npcTemplate.Roles.Repair != null)
                    {
                        merchant.Jobs ^= MerchantJob.Repair;
                    }
                    if (npcTemplate.Roles.Train != null)
                    {
                        if (npcTemplate.Roles.Train.Any(x => x.Type == "Skill"))
                        {
                            merchant.Jobs ^= MerchantJob.Skills;
                        }
                        if (npcTemplate.Roles.Train.Any(x => x.Type == "Spell"))
                        {
                            merchant.Jobs ^= MerchantJob.Spells;
                        }
                    }
                    if (npcTemplate.Roles.Vend != null)
                    {
                        merchant.Jobs ^= MerchantJob.Vend;
                    }

                    merchant.Roles = npcTemplate.Roles;
                }
                InsertNpc(merchant);
                // Keep the actual spawned object around in the index for later use
                World.WorldData.Set(merchant.Name, merchant);
            }

            foreach (var reactorElement in newMap.Reactors)
            {
                var reactor = new Reactor(reactorElement.X, reactorElement.Y, this,
                                          reactorElement.Script, reactorElement.Description, reactorElement.Blocking);
                reactor.AllowDead = reactorElement.AllowDead;
                InsertReactor(reactor);
                GameLog.Debug($"{reactor.Id} placed in {reactor.Map.Name}, description was {reactor.Description}");
            }
            foreach (var sign in newMap.Signs)
            {
                Signpost post;
                if (sign.Type == Xml.BoardType.Sign)
                {
                    post = new Signpost(sign.X, sign.Y, sign.Message);
                }
                else
                {
                    post = new Signpost(sign.X, sign.Y, sign.Message, true, sign.BoardKey);
                }
                InsertSignpost(post);
            }
            Load();
        }
Beispiel #3
0
        public ThrottleResult ProcessThrottle(Client client, ClientPacket packet)
        {
            ThrottleInfo   info;
            ThrottleResult result = ThrottleResult.Error;

            if (!client.ThrottleState.TryGetValue(packet.Opcode, out info))
            {
                client.ThrottleState[packet.Opcode] = new ThrottleInfo();
                info = client.ThrottleState[packet.Opcode];
            }

            Monitor.Enter(info);

            try
            {
                DateTime rightnow = DateTime.Now;
                //GameLog.Warning($"Right now is {rightnow}");
                var transmitInterval = (rightnow - info.LastReceived);
                var acceptedInterval = (rightnow - info.LastAccepted);
                info.PreviousReceived = info.LastReceived;
                info.LastReceived     = rightnow;
                info.TotalReceived++;
                GameLog.Debug($"Begin: PA: {info.PreviousAccepted} LA: {info.LastAccepted} AInterval is {acceptedInterval.TotalMilliseconds} TInterval {transmitInterval.TotalMilliseconds}");

                if (info.Throttled)
                {
                    result = ThrottleResult.Throttled;
                    if (acceptedInterval.TotalMilliseconds >= ThrottleDuration && acceptedInterval.TotalMilliseconds >= Interval)
                    {
                        //GameLog.Error($"Unthrottled: {acceptedInterval.TotalMilliseconds} > {ThrottleDuration} and {Interval}");
                        info.Throttled      = false;
                        info.TotalThrottled = 0;
                        result = ThrottleResult.ThrottleEnd;
                        info.PreviousAccepted = info.LastAccepted;
                        info.LastAccepted     = rightnow;
                        OnThrottleStop(new ClientTrigger(client));
                    }
                    else
                    {
                        info.TotalThrottled++;
                        //GameLog.Error($"Throttled, count is {info.TotalThrottled}");

                        result = ThrottleResult.Throttled;
                        if (ThrottleDisconnectThreshold > 0 && info.TotalThrottled > ThrottleDisconnectThreshold)
                        {
                            result = ThrottleResult.Disconnect;
                            OnDisconnectThreshold(new ClientTrigger(client));
                        }
                    }
                }
                else
                {
                    if (acceptedInterval.TotalMilliseconds <= Interval && info.LastAccepted != DateTime.MinValue)
                    {
                        GameLog.Debug($"TInterval {transmitInterval}, AInterval {acceptedInterval} - maximum is {Interval}, throttled");
                        info.Throttled = true;
                        OnThrottleStart(new ClientTrigger(client));
                        result = ThrottleResult.Throttled;
                    }
                    else
                    {
                        info.PreviousAccepted = info.LastAccepted;
                        info.LastAccepted     = rightnow;
                        info.TotalAccepted++;
                        result = ThrottleResult.OK;
                        GameLog.Debug($"Packet accepted, PA: {info.PreviousAccepted} LA: {info.LastAccepted}");
                    }
                }
            }
            finally
            {
                Monitor.Exit(info);
            }
            return(result);
        }
Beispiel #4
0
 public void OnSquelchStop(IThrottleTrigger trigger)
 {
     GameLog.Debug($"Client {trigger.Id}: squelch expired");
 }
Beispiel #5
0
 public void OnThrottleStop(IThrottleTrigger trigger)
 {
     GameLog.Debug($"Client {trigger.Id}: throttle expired");
 }
Beispiel #6
0
        public void FlushReceiveBuffer()
        {
            lock (ClientState.ReceiveLock)
            {
                try
                {
                    ClientPacket packet;
                    while (ClientState.ReceiveBufferTake(out packet))
                    {
                        if (packet.ShouldEncrypt)
                        {
                            packet.Decrypt(this);
                        }

                        if (packet.Opcode == 0x39 || packet.Opcode == 0x3A)
                        {
                            packet.DecryptDialog();
                        }
                        try
                        {
                            if (Server is Lobby)
                            {
                                GameLog.DebugFormat("Lobby: 0x{0:X2}", packet.Opcode);
                                var handler = (Server as Lobby).PacketHandlers[packet.Opcode];
                                handler.Invoke(this, packet);
                                GameLog.DebugFormat("Lobby packet done");
                                UpdateLastReceived();
                            }
                            else if (Server is Login)
                            {
                                GameLog.Debug($"Login: 0x{packet.Opcode:X2}");
                                var handler = (Server as Login).PacketHandlers[packet.Opcode];
                                handler.Invoke(this, packet);
                                GameLog.DebugFormat("Login packet done");
                                UpdateLastReceived();
                            }
                            else
                            {
                                UpdateLastReceived(packet.Opcode != 0x45 &&
                                                   packet.Opcode != 0x75);
                                GameLog.Debug($"Queuing: 0x{packet.Opcode:X2}");
                                //packet.DumpPacket();
                                // Check for throttling
                                var throttleResult = Server.PacketThrottleCheck(this, packet);
                                if (throttleResult == ThrottleResult.OK || throttleResult == ThrottleResult.ThrottleEnd || throttleResult == ThrottleResult.SquelchEnd)
                                {
                                    World.MessageQueue.Add(new HybrasylClientMessage(packet, ConnectionId));
                                }
                                else
                                if (packet.Opcode == 0x06)
                                {
                                    World.ControlMessageQueue.Add(new HybrasylControlMessage(ControlOpcodes.TriggerRefresh, ConnectionId));
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            Game.ReportException(e);
                            GameLog.ErrorFormat("EXCEPTION IN HANDLING: 0x{0:X2}: {1}", packet.Opcode, e);
                        }
                    }
                }
                catch (Exception e)
                {
                    Game.ReportException(e);
                    Console.WriteLine(e);
                    throw;
                }
            }
        }
Beispiel #7
0
 public void DumpPacket()
 {
     // Dump the packet to the console.
     GameLog.Debug($"Dumping packet: {Opcode:X2}");
     GameLog.Debug(ToString());
 }