Пример #1
0
        public static void AcceptCallback(IAsyncResult ar)
        {
            m_AcceptEvent.Set ();

            Socket webSocket = m_ListeningSocket.EndAccept (ar);
            WebSocketClient client = new WebSocketClient (webSocket);

            UOJS.Log ("Client [{0}]: Connection Detected", client.WebSocket.RemoteEndPoint);
            webSocket.BeginReceive (client.WriteBuffer, 0, client.WriteBuffer.Length, SocketFlags.None, new AsyncCallback (ReadCallback), client);
        }
Пример #2
0
        public static void Send(WebSocketClient client, byte[] data, RequestType type, bool mask)
        {
            // masking isn't needed?
            int headerLength = 2;
            byte payload = 0;
            byte[] maskKeys = null;
            byte[] tmp = new byte[data.Length + 1];
            tmp [0] = (byte)type;
            Array.Copy (data, 0, tmp, 1, data.Length);
            data = tmp;

            //data = Encoding.UTF8.GetBytes(((char)type) + Convert.ToBase64String(data));

            //data = Encoding.UTF8.GetBytes(Encoding.ASCII.GetString(data));
            //Console.WriteLine("Raw length={0}", data.Length);
            if (data.Length > short.MaxValue)
                UOJS.Log ("Client [{0}]: Sending Really Large Packet (not implemented)", client.WebSocket.RemoteEndPoint);
            if (data.Length >= 126) {
                headerLength += 2;
                payload = 126;
            } else
                payload = (byte)data.Length;
            if (mask) {
                headerLength += 4;
                Random r = new Random ();
                maskKeys = new byte[] { 1, 2, 3, 4 };
                r.NextBytes (maskKeys);
            }

            byte[] allData = new byte[headerLength + data.Length];
            allData [0] = 0x80 | 0x02;
            allData [1] = (byte)((mask ? 0x80 : 0) | payload & 0x40 | payload & 0x20 | payload & 0x10 | payload & 0x8 | payload & 0x4 | payload & 0x2 | payload & 0x1);

            if (payload == 126) {
                byte[] lengthBytes = BitConverter.GetBytes ((ushort)data.Length);
                allData [2] = lengthBytes [1]; // (byte)((data.Length >> 8) & 0xFF);
                allData [3] = lengthBytes [0]; // (byte)(data.Length & 0xFF);
            }

            Array.Copy (data, 0, allData, headerLength, data.Length);
            if (mask) {
                Array.Copy (maskKeys, 0, allData, 2, 4);
                for (int i = 0; i < data.Length; i++)
                    allData [i + headerLength] ^= maskKeys [i % 4];
            }

            if (client.WebSocket != null && client.WebSocket.Connected) {
                client.WebSocket.BeginSend (allData, 0, allData.Length, SocketFlags.None, new AsyncCallback (SendCallback), client);
            }
        }
Пример #3
0
 public static void Send(WebSocketClient client, string format, params object[] o)
 {
     GameProxy.Send (client, m_Encoding.GetBytes (string.Format (format, o)), RequestType.WebRequest, false);
 }
Пример #4
0
        public static byte[] ParseWebRequest(WebSocketClient client, string shortUri, string fullUri)
        {
            try {
                switch (shortUri) {
                    case "/td":
                        {
                            Dictionary<string, string> query = ParseVars (fullUri);
                            int id = int.Parse (query ["id"]);
                            Dictionary<string, string> dict = new Dictionary<string, string> ();

                            PropertyInfo info = m_Ultima.GetType ("Ultima.TileData").GetProperty ("ItemTable", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
                            Type itemData = m_Ultima.GetType ("Ultima.ItemData");
                            object o = ((Array)info.GetValue (null, null)).GetValue (id);
                            PropertyInfo[] pubInfo = itemData.GetProperties ();
                            foreach (PropertyInfo p in pubInfo)
                                dict.Add (p.Name, p.GetValue (o, null).ToString ());

                            return m_Encoding.GetBytes (LitJson.JsonMapper.ToJson (dict));
                        }

                    case "/getmapinfo":
                        {
                            Dictionary<string, string> query = ParseVars (fullUri);
                            int x = int.Parse (query ["x"]), y = int.Parse (query ["y"]), range = int.Parse (query ["r"]);
                            char facet = query ["m"] [0];
                            string map;

                            switch (facet) {
                                default:
                                case 'f':
                                    map = "Felucca";
                                    break;
                                case 't':
                                    map = "Trammel";
                                    break;
                                case 'i':
                                    map = "Ilshenar";
                                    break;
                                case 'm':
                                    map = "Malas";
                                    break;
                                case 'o':
                                    map = "Tokuno";
                                    break; // whoops
                            }

                            Type Map = m_Ultima.GetType ("Ultima.Map");
                            Type Tile = m_Ultima.GetType ("Ultima.Tile");
                            Type HuedTile = m_Ultima.GetType ("Ultima.HuedTile");
                            Type TileMatrix = m_Ultima.GetType ("Ultima.TileMatrix");
                            Dictionary<string, Dictionary<string, Dictionary<string, object>>> data
                                = new Dictionary<string, Dictionary<string, Dictionary<string, object>>> ();
                            object currentMap = ((FieldInfo)Map.GetMember (map) [0]).GetValue (null);
                            object tiles = Map.GetProperty ("Tiles").GetValue (currentMap, null);

                            for (int i = 0; i < range; i++) {
                                Dictionary<string, Dictionary<string, object>> row;
                                data.Add ((i + x).ToString (), row = new Dictionary<string, Dictionary<string, object>> ());

                                for (int j = 0; j < range; j++) {
                                    Dictionary<string, object> cell = new Dictionary<string, object> ();
                                    object landTile = TileMatrix.GetMethod ("GetLandTile").Invoke (tiles, new object[]{x + i, y + j});
                                    Array staticTiles = (Array)TileMatrix.GetMethod ("GetStaticTiles").Invoke (tiles, new object[]{x + i, y + j});
                                    int id = (int)Tile.GetProperty ("ID").GetValue (landTile, null);
                                    int z = (int)Tile.GetProperty ("Z").GetValue (landTile, null);

                                    cell.Add ("id", id);
                                    cell.Add ("z", z);
                                    cell.Add ("length", staticTiles.Length);
                                    TileInfo[] stiles = new TileInfo[staticTiles.Length];
                                    for (int k = 0; k < stiles.Length; k++) {
                                        stiles [k].ID = (int)(HuedTile.GetProperty ("ID").GetValue (staticTiles.GetValue (k), null)) % 0x4000;

                                        stiles [k].Hue = (int)HuedTile.GetProperty ("Hue").GetValue (staticTiles.GetValue (k), null);
                                        stiles [k].Z = (int)HuedTile.GetProperty ("Z").GetValue (staticTiles.GetValue (k), null);
                                    }
                                    cell.Add ("o", stiles);
                                    row.Add ((j + y).ToString (), cell);
                                }
                            }

                            return m_Encoding.GetBytes (LitJson.JsonMapper.ToJson (data));
                        }

                    case "/getgump":
                        {
                            Dictionary<string, string> query = ParseVars (fullUri);
                            foreach (KeyValuePair<string, string> kvp in query)
                                Console.WriteLine (kvp);
                            int id = int.Parse (query ["id"]);
                            Type Gumps = m_Ultima.GetType ("Ultima.Gumps");

                            //int hueIdx = int.Parse (query ["h"]);

                            //Hue hue = hueIdx == 0 ? null : Hues.List [(hueIdx & 0x3FFF) - 1];

                            //Bitmap b = (Bitmap)(Gumps.GetGump (id).Clone ());

                            Bitmap b = (Bitmap)Gumps.GetMethod ("GetGump", new Type[]{typeof(Int32)}).Invoke (null, new object[]{id});
                            //if (hue != null)
                            //	hue.ApplyTo (b, true);

                            MemoryStream ms = new MemoryStream ();
                            b.Save (ms, System.Drawing.Imaging.ImageFormat.Png);

                            return ms.GetBuffer ();
                        }

                    case "/getobj":
                        {
                            Dictionary<string, string> query = ParseVars (fullUri);
                            char type = query ["t"] [0];
                            int id = int.Parse (query ["i"]);
                            int hueIdx = int.Parse (query ["h"]);

                            string crop = query.ContainsKey ("c") ? query ["c"] : "";
                            Type Art = m_Ultima.GetType ("Ultima.Art");
                            Bitmap b = (Bitmap)(Art.GetMethod (type == 'l' ? "GetLand" : "GetStatic", new Type[]{typeof(Int32)}).Invoke (null, new object[]{id}));
                            //Bitmap b = (Bitmap)(type == 'l' ? Art.GetLand (id) : Art.GetStatic (id)); //don't hue the cached, clone it
                            //if (b == null)
                            //	b = Art.GetLand (0);
                            b = (Bitmap)b.Clone ();

                            //TODO: clone before hue (prevent modifying cache object)
                            //Hue hue = hueIdx == 0 ? null : Hues.List [(hueIdx & 0x3FFF) - 1];
                            //if (hue != null)
                            //	hue.ApplyTo (b, type == 'l');

                            switch (crop) {
                            // why can't this be done on the client side by only drawing half after
                            // the transformation? set the sX to the half or set the sW to the half
                            // depending on the side??
                                case "right":
                                    {
                                        for (int x = 0; x < b.Width/2; x++) {
                                            for (int y = 0; y < b.Height; y++) {
                                                b.SetPixel (x, y, Color.Transparent);
                                            }
                                        }
                                        break;
                                    }
                                case "left":
                                    {
                                        for (int x = b.Width/2; x < b.Width; x++) {
                                            for (int y = 0; y < b.Height; y++) {
                                                b.SetPixel (x, y, Color.Transparent);
                                            }
                                        }
                                        break;
                                    }
                            }
                            MemoryStream ms = new MemoryStream ();
                            b.Save (ms, System.Drawing.Imaging.ImageFormat.Png);
                            return ms.GetBuffer ();
                        }

                    case "/getcliloc":
                        {
                            Dictionary<string, string> query = ParseVars (fullUri);
                            int message = int.Parse (query ["i"]), i = 0;
                            Type StringList = m_Ultima.GetType ("Ultima.StringList");
                            System.Collections.Hashtable table = (System.Collections.Hashtable)StringList.GetProperty ("Table").GetValue (StringList.GetProperty ("EnglishStringList", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy).GetValue (null, null), null);
                            if (!table.ContainsKey (message))
                                return m_Encoding.GetBytes ("{\"text\": null}");

                            string entry = (string)table [message];

                            return UTF8Encoding.UTF8.GetBytes (entry);
                            //string replace = Regex.Replace (entry, @"~[A-Za-z0-9_]+~", match => (query.ContainsKey ("" + (++i)) ? query ["" + (i)] : ""));

                            //return UTF8Encoding.UTF8.GetBytes ("{\"text\":\"" + replace.Replace ("\"", "\\\"") + "\"}");
                        }

                    case "/getaniminfo":
                        {
                            Dictionary<string, string> query = ParseVars (fullUri);
                            int bodyId = int.Parse (query ["i"]);
                            int action = int.Parse (query ["a"]);
                            int dir = int.Parse (query ["d"]);
                            int hash = (bodyId << 16) | (action << 8) | (dir);
                            byte[] widths = null;

                            if (m_Widths.ContainsKey (hash))
                                widths = m_Widths [hash];
                            else {
                                Type Animations = m_Ultima.GetType ("Ultima.Animations");
                                Type Frame = m_Ultima.GetType ("Ultima.Frame");
                                Array frames = (Array)Animations.GetMethod ("GetAnimation").Invoke (null, new object[] {
                                bodyId,
                                action,
                                dir,
                                0,
                                true
                            });
                                //Frame[] frames = Animations.GetAnimation (bodyId, action, dir, 0, true);

                                if (frames == null)
                                    widths = new byte[0];
                                else {
                                    widths = new byte[frames.Length];
                                    for (int i = 0; i < frames.Length; i++) {
                                        System.Drawing.Bitmap b = (System.Drawing.Bitmap)Frame.GetProperty ("Bitmap").GetValue (frames.GetValue (i), null);
                                        widths [i] = (byte)b.Width;
                                    }
                                }
                            }
                            List<string> tmp = new List<string> ();
                            foreach (byte b in widths)
                                tmp.Add (b.ToString ());

                            return ASCIIEncoding.ASCII.GetBytes ("{\"widths\": [" + string.Join (",", tmp.ToArray ()) + "]}");
                        }

                    case "/getanim":
                        {
                            //todo: check if wearable and adjust bitmap accordingly if human
                            Dictionary<string, string> query = ParseVars (fullUri);
                            int bodyId = int.Parse (query ["i"]);
                            int action = int.Parse (query ["a"]);
                            int dir = int.Parse (query ["d"]);
                            int hueIdx = int.Parse (query ["h"]);
                            Type Animations = m_Ultima.GetType ("Ultima.Animations");
                            Type Frame = m_Ultima.GetType ("Ultima.Frame");
                            Array frames = (Array)Animations.GetMethod ("GetAnimation").Invoke (null, new object[] {
                            bodyId,
                            action,
                            dir,
                            0,
                            true
                        });
                            //Frame[] frames = Animations.GetAnimation (bodyId, action, dir, 0, true);
                            //Hue hue = hueIdx == 0 ? null : Hues.List [(hueIdx & 0x3FFF) - 1];
                            int hash = (bodyId << 16) | (action << 8) | (dir);
                            if (frames == null)
                                return new byte[] { };

                            int maxWidth = 0, maxHeight = 0;
                            for (int i = 0; i < frames.Length; i++) {
                                System.Drawing.Bitmap b = (System.Drawing.Bitmap)Frame.GetProperty ("Bitmap").GetValue (frames.GetValue (i), null);
                                if (b.Width > maxWidth)
                                    maxWidth = b.Width; // +Math.Abs(frame.Center.X);
                                if (b.Height > maxHeight)
                                    maxHeight = b.Height; // +Math.Abs(frame.Center.Y);
                            }
                            // should we cache full animation bitmaps?
                            Bitmap bitmap = new Bitmap (maxWidth * frames.Length, maxHeight);
                            Graphics g = Graphics.FromImage (bitmap);

                            byte[] widths = new byte[frames.Length];
                            for (int i = 0; i < frames.Length; i++) {
                                object frame = frames.GetValue (i);
                                System.Drawing.Bitmap single = (System.Drawing.Bitmap)Frame.GetProperty ("Bitmap").GetValue (frames.GetValue (i), null);

                                widths [i] = (byte)single.Width;
                                g.DrawImageUnscaled (single, i * maxWidth, 0);
                            }
                            if (!m_Widths.ContainsKey (hash))
                                m_Widths.Add (hash, widths);
                            //if (hueIdx != 0)
                            //	hue.ApplyTo (bitmap, TileData.AnimationData.ContainsKey (bodyId) && (TileData.AnimationData [bodyId].Flags & TileFlag.PartialHue) != 0);
                            bitmap.SetPixel (0, 0, Color.FromArgb (0, 0, 0, frames.Length));
                            MemoryStream ms = new MemoryStream ();
                            bitmap.Save (ms, System.Drawing.Imaging.ImageFormat.Png);
                            return ms.GetBuffer ();
                        }
                }
            } catch (Exception e) {
                UOJS.Log ("Error {0}\r\n{1}", e.Message, e.StackTrace);
                return ASCIIEncoding.ASCII.GetBytes (string.Format ("An error has occurred: {0}\r\n{1}", e.Message, e.StackTrace));

            }
            return new byte[] { };
        }
Пример #5
0
        public static void OnReceiveFromWebSocket(WebSocketClient client, byte[] data, int length)
        {
            try {
                switch ((char)data [0]) {
                // Reconnect
                    case 'R':
                        {
                            if (client.UOSocket != null && client.UOSocket.Connected)
                                client.UOSocket.Close ();
                            goto case 'C';
                        }

                // Connect
                    case 'C':
                        {
                            string[] strData = Encoding.ASCII.GetString (data, 0, data.Length).Split (' ');
                            for (int i = 0; i < strData.Length; i++)
                                Console.Write (strData [i] + ",");
                            client.UOSocket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                            Console.WriteLine (string.Join (",", strData));
                            client.UOSocket.BeginConnect (strData [1], int.Parse (strData [2]), new AsyncCallback (UOConnectCallback), client);
                            break;
                        }

                // Version
                    case 'V':
                        {
                            GameProxy.Send (client, "Version {0}", UOJS.Version);
                            break;
                        }

                    default:
                        {
                            client.UOSocket.BeginSend (data, 0, data.Length, SocketFlags.None, new AsyncCallback (UOSendCallback), client);
                            break;
                        }
                }
            } catch (Exception e) {
                UOJS.Log ("Client [d/c]: Threw {0}... closing!", e.GetType ());
                UOJS.Log (e.StackTrace);
                client.Close ();
            }
        }