예제 #1
0
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            JArray jArray = JArray.Load(reader);
            var    inv    = new Inventory(jArray.Count);

            for (byte i = 0; i < jArray.Count; i++)
            {
                dynamic item;
                if (TryGetValue(jArray[i], out item))
                {
                    //itmType = Game.World.WorldData.Values<Item>().Where(x => x.Name == (string)item.FirstOrDefault().Value).FirstOrDefault().Name;
                    if (Game.World.WorldData.TryGetValue <Xml.Item>(item.Id, out Xml.Item itemTemplate))
                    {
                        inv[i] = new ItemObject(itemTemplate.Id, Game.World)
                        {
                            Count      = item.Count ?? 1,
                            Durability = item.Durability ?? itemTemplate.Properties.Physical.Durability
                        };
                        //this will need to be expanded later based on ItemObject properties being saved back to the database.
                    }
                    else
                    {
                        GameLog.Error($"Inventory deserializer error: item {item.Id} not found in index, skipping");
                    }
                }
            }

            return(inv);
        }
예제 #2
0
        public static bool ValidateEncryptionKey(string endpoint, ServerToken token)
        {
            bool valid;

            try
            {
                var webReq = WebRequest.Create(new Uri(endpoint));
                webReq.ContentType = "application/json";
                webReq.Method      = "POST";

                var json = JsonSerializer.Serialize(token);

                using (var sw = new StreamWriter(webReq.GetRequestStream()))
                {
                    sw.Write(json);
                }

                var response = webReq.GetResponse();
                using (var sr = new StreamReader(response.GetResponseStream()))
                {
                    valid = (bool)JsonSerializer.Deserialize(sr.ReadToEnd(), typeof(bool));
                }
            }
            catch (Exception e)
            {
                Game.ReportException(e);
                GameLog.Error("ValidateEncryptionKey failure: {e}", e);
                return(false);
            }
            return(valid);
        }
예제 #3
0
 public static void DeregisterClient(Client client)
 {
     ConnectedClients.TryRemove(client.ConnectionId, out Client _);
     GameLog.InfoFormat("Deregistering {0}", client.ConnectionId);
     // Send a control message to clean up after World users; Lobby and Login handle themselves
     if (client.ServerType == ServerTypes.World)
     {
         if (!WorldClients.TryRemove(client.ConnectionId, out Client _))
         {
             GameLog.Error("Couldn't deregister cid {id}", client.ConnectionId);
         }
         try
         {
             if (!World.ControlMessageQueue.IsCompleted)
             {
                 World.ControlMessageQueue.Add(new HybrasylControlMessage(ControlOpcodes.CleanupUser,
                                                                          CleanupType.ByConnectionId, client.ConnectionId));
             }
         }
         catch (InvalidOperationException e)
         {
             Game.ReportException(e);
             if (!World.ControlMessageQueue.IsCompleted)
             {
                 GameLog.ErrorFormat("Connection {id}: DeregisterClient failed", client.ConnectionId);
             }
         }
     }
 }
예제 #4
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);
        }
예제 #5
0
        public static byte[] RequestEncryptionKey(string endpoint, IPAddress remoteAddress)
        {
            byte[] key;

            try
            {
                var seed = new Seed()
                {
                    Ip = remoteAddress.ToString()
                };

                var webReq = WebRequest.Create(new Uri(endpoint));
                webReq.ContentType = "application/json";
                webReq.Method      = "POST";

                var json = JsonSerializer.Serialize(seed);

                using (var sw = new StreamWriter(webReq.GetRequestStream()))
                {
                    sw.Write(json);
                }

                var response = webReq.GetResponse();
                using (var sr = new StreamReader(response.GetResponseStream()))
                {
                    key = (byte[])JsonSerializer.Deserialize(sr.ReadToEnd(), typeof(byte[]));
                }
            }
            catch (Exception e)
            {
                GameLog.Error("RequestEncryptionKey failure: {e}", e);
                key = Encoding.ASCII.GetBytes("NOTVALID!");
            }
            return(key);
        }
예제 #6
0
        public virtual void AcceptConnection(IAsyncResult ar)
        {
            // TODO: @norrismiv async callbacks+inheritance? and/or can these callbacks suck less?
            AllDone.Set();
            if (!Active)
            {
                return;
            }
            Socket handler;
            Socket clientSocket;

            try
            {
                clientSocket = (Socket)ar.AsyncState;
                handler      = clientSocket.EndAccept(ar);
            }
            catch (ObjectDisposedException e)
            {
                GameLog.Error($"Disposed socket {e.Message}");
                return;
            }
            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);
                GameLog.DebugFormat("Lobby: AcceptConnection occuring");
                GameLog.DebugFormat("Lobby: cid is {0}", client.ConnectionId);
            }
            else if (this is Login)
            {
                GameLog.DebugFormat("Login: AcceptConnection occuring");
                GameLog.DebugFormat("Login: cid is {0}", client.ConnectionId);
            }
            else if (this is World)
            {
                GameLog.DebugFormat("World: AcceptConnection occuring");
                GameLog.DebugFormat("World: cid is {0}", client.ConnectionId);
            }
            try
            {
                handler.BeginReceive(client.ClientState.Buffer, 0, client.ClientState.Buffer.Length, 0,
                                     new AsyncCallback(ReadCallback), client.ClientState);
                GameLog.DebugFormat("AcceptConnection returning");
                clientSocket.BeginAccept(new AsyncCallback(AcceptConnection), clientSocket);
            }
            catch (SocketException e)
            {
                Game.ReportException(e);
                handler.Close();
            }
        }
예제 #7
0
 private static double _evalFormula(string formula, Xml.Castable castable, Creature target, Creature source)
 {
     try
     {
         return(new FormulaParser(source, castable, target).Eval(formula));
     }
     catch (Exception e)
     {
         GameLog.Error($"NumberCruncher formula error: castable {castable.Name}, target {target.Name}, source {source?.Name ?? "no source"}: {formula}, error: {e}");
         return(0);
     }
 }
예제 #8
0
 public void InsertNpc(Merchant toInsert)
 {
     World.Insert(toInsert);
     Insert(toInsert, toInsert.X, toInsert.Y);
     try
     {
         toInsert.OnSpawn();
     }
     catch (Exception e)
     {
         GameLog.Error("NPC {name}: exception occurred, aborting: {e}", toInsert.Name, e);
     }
 }
예제 #9
0
파일: Client.cs 프로젝트: Jinori/server
        public void FlushSendBuffer()
        {
            //lock (ClientState.SendLock)
            //{
            try
            {
                while (ClientState.SendBufferTake(out ServerPacket packet))
                {
                    Task.Run(async() =>
                    {
                        if (packet == null)
                        {
                            return;
                        }

                        if (packet.ShouldEncrypt)
                        {
                            ++ServerOrdinal;
                            packet.Ordinal = ServerOrdinal;

                            packet.GenerateFooter();
                            packet.Encrypt(this);
                        }
                        if (packet.TransmitDelay != 0)
                        {
                            await Task.Delay(packet.TransmitDelay);
                        }

                        var buffer = packet.ToArray();
                        try
                        {
                            Socket.BeginSend(buffer, 0, buffer.Length, 0, SendCallback, ClientState);
                        }
                        catch (ObjectDisposedException e)
                        {
                            GameLog.Warning($"FlushSendBuffer: {e.Message}");
                        }
                    });
                }
            }
            catch (ObjectDisposedException)
            {
                // Socket is gone, peace out
                ClientState.Dispose();
            }
            catch (Exception e)
            {
                GameLog.Error($"HALP: {e}");
            }
            //}
        }
예제 #10
0
        private void ProcessHandler(Xml.Handler handler)
        {
            if ((handler?.Function ?? String.Empty) == String.Empty)
            {
                return;
            }

            // If a handler is specified, check the script for it first. Note that we don't run both;
            // if you override something like OnDeath, that's your problem.
            VisibleObject invoker;
            VisibleObject invokee;

            if (handler.ScriptSource == Xml.ScriptSource.Target)
            {
                invokee = Target;
                invoker = Source;
            }
            else // Caster
            {
                invokee = Source;
                invoker = Target;
            }

            if (invokee.Script != null)
            {
                invokee.Script.ExecuteFunction(handler.Function, invoker);
                return;
            }

            Type type = invokee.GetType();

            try
            {
                MethodInfo methodInfo = type.GetMethod(handler.Function);
                methodInfo.Invoke(invokee, null);
            }
            catch (Exception e)
            {
                Game.ReportException(e);
                GameLog.Error("Exception processing status handler: {exception}", e);
            }
        }
예제 #11
0
        public void SendCallback(IAsyncResult ar)
        {
            ClientState state = (ClientState)ar.AsyncState;
            Client      client;

            GameLog.DebugFormat($"EndSend: SocketConnected: {state.WorkSocket.Connected}, IAsyncResult: Completed: {ar.IsCompleted}, CompletedSynchronously: {ar.CompletedSynchronously}");

            try
            {
                SocketError errorCode;
                var         bytesSent = state.WorkSocket.EndSend(ar, out errorCode);
                if (!GlobalConnectionManifest.ConnectedClients.TryGetValue(state.Id, out client))
                {
                    GameLog.ErrorFormat("Send: socket should not exist: cid {0}", state.Id);
                    state.WorkSocket.Close();
                    state.WorkSocket.Dispose();
                    return;
                }

                if (bytesSent == 0 || errorCode != SocketError.Success)
                {
                    GameLog.ErrorFormat("cid {0}: disconnected");
                    client.Disconnect();
                    throw new SocketException((int)errorCode);
                }
            }
            catch (SocketException e)
            {
                Game.ReportException(e);
                GameLog.Error($"Error Code: {e.ErrorCode}, {e.Message}");
                state.WorkSocket.Close();
            }
            catch (ObjectDisposedException)
            {
                //client.Disconnect();
                GameLog.Error($"ObjectDisposedException");
                state.WorkSocket.Close();
            }
            state.SendComplete.Set();
        }
예제 #12
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();
        }
예제 #13
0
        public void FlushSendBuffer()
        {
            MemoryStream buffer        = new MemoryStream();
            int          transmitDelay = 0;

            try
            {
                while (!ClientState.SendBufferEmpty)
                {
                    if (ClientState.SendBufferPeek(out ServerPacket precheck))
                    {
                        if (buffer.Length > 0 && (precheck.TransmitDelay > 0 && transmitDelay == 0))
                        {
                            // If we're dealing with a bunch of packets with delays, batch them together.
                            // Otherwise, send them individually.
                            //GameLog.Warning("TransmitDelay occurring");
                            break;
                        }
                        // Limit outbound transmissions to 65k bytes at a time
                        if (buffer.Length >= 65535)
                        {
                            //GameLog.Warning("Breaking up into chunks");
                            break;
                        }
                    }

                    if (ClientState.SendBufferTake(out ServerPacket packet))
                    {
                        // If no packets, just call the whole thing off
                        if (packet == null)
                        {
                            return;
                        }

                        if (packet.ShouldEncrypt)
                        {
                            ++ServerOrdinal;
                            packet.Ordinal = ServerOrdinal;
                            packet.GenerateFooter();
                            packet.Encrypt(this);
                        }
                        if (packet.TransmitDelay > 0)
                        {
                            transmitDelay = packet.TransmitDelay;
                        }
                        // Write packet to our memory stream
                        buffer.Write(packet.ToArray());
                    }
                }

                if (buffer.Length == 0)
                {
                    return;
                }

                // Background enqueue a send with our memory stream
                Task.Run(async() =>
                {
                    var socketbuf = buffer.ToArray();
                    try
                    {
                        //GameLog.Info($"transmit: {socketbuf.Length} with delay {transmitDelay}");
                        if (transmitDelay > 0)
                        {
                            await Task.Delay(transmitDelay);
                        }
                        Socket.BeginSend(socketbuf, 0, socketbuf.Length, 0, SendCallback, ClientState);
                    }
                    catch (ObjectDisposedException)
                    {
                        ClientState.Dispose();
                    }
                });
            }
            catch (ObjectDisposedException e)
            {
                // Socket is gone, peace out
                ClientState.Dispose();
            }
            catch (Exception e)
            {
                Game.ReportException(e);
                GameLog.Error($"HALP: {e}");
            }
        }
예제 #14
0
파일: Throttle.cs 프로젝트: Jinori/server
        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);
        }