public override WebSocketCommandInfo FindCommand(SocketContext context, byte[] readBuffer, int offset, int length, bool isReusableBuffer)
        {
            int total = BufferSegments.Count + length;

            var socketContext = context as WebSocketContext;

            if (total == 8)
            {
                List<byte> key = new List<byte>();
                key.AddRange(BufferSegments.ToArrayData());
                key.AddRange(readBuffer.Skip(offset).Take(length));
                socketContext.SecWebSocketKey3 = key.ToArray();
                BufferSegments.ClearSegements();
                NextCommandReader = new WebSocketDataReader(this);
                return CreateHeadCommandInfo();
            }
            else if (total > 8)
            {
                List<byte> key = new List<byte>();
                key.AddRange(BufferSegments.ToArrayData());
                key.AddRange(readBuffer.Skip(offset).Take(8 - BufferSegments.Count));
                socketContext.SecWebSocketKey3 = key.ToArray();
                BufferSegments.ClearSegements();
                AddArraySegment(readBuffer, offset + 8 - BufferSegments.Count, total - 8, isReusableBuffer);
                NextCommandReader = new WebSocketDataReader(this);
                return CreateHeadCommandInfo();
            }
            else
            {
                AddArraySegment(readBuffer, offset, length, isReusableBuffer);
                NextCommandReader = this;
                return null;
            }
        }
Example #2
0
        public Task TryConnect(int port)
        {
            socketContext = new SocketContext();
            clientConnectedTCS = new TaskCompletionSource<bool>();

            socketContext.Connected = (clientSocketContext) =>
            {
                // Create an effect compiler per connection
                var effectCompiler = new EffectCompiler();

                var tempFilename = Path.GetTempFileName();
                var fileStream = new FileStream(tempFilename, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);

                // TODO: Properly close the file, and choose where to copy/move it?
                var recordedEffectCompile = new EffectLogStore(fileStream);

                // TODO: This should come from an "init" packet
                effectCompiler.SourceDirectories.Add(EffectCompilerBase.DefaultSourceShaderFolder);

                // Make a VFS that will access remotely the DatabaseFileProvider
                // TODO: Is that how we really want to do that in the future?
                var networkVFS = new NetworkVirtualFileProvider(clientSocketContext, "/asset");
                VirtualFileSystem.RegisterProvider(networkVFS);
                effectCompiler.FileProvider = networkVFS;

                clientSocketContext.AddPacketHandler<ShaderCompilerRequest>((packet) => ShaderCompilerRequestHandler(clientSocketContext, recordedEffectCompile, effectCompiler, packet));

                clientConnectedTCS.TrySetResult(true);
            };

            // Wait for a connection to be possible on adb forwarded port
            var clientDone = socketContext.StartClient(IPAddress.Loopback, port);

            return clientDone;
        }
        private void BeginReceive(SocketContext ctx)
        {
            if (ctx.receiveBuffer == null)
            {
                Byte[] buffer = new Byte[SessionConfig.ReadBufferSize];
                ctx.receiveBuffer = new SocketAsyncEventArgs();
                ctx.receiveBuffer.SetBuffer(buffer, 0, buffer.Length);
                ctx.receiveBuffer.Completed += new EventHandler<SocketAsyncEventArgs>(OnCompleted);
                ctx.receiveBuffer.UserToken = ctx;
            }

            ctx.receiveBuffer.RemoteEndPoint = new IPEndPoint(ctx.Socket.AddressFamily == AddressFamily.InterNetwork ?
                IPAddress.Any : IPAddress.IPv6Any, 0);

            Boolean willRaiseEvent;
            try
            {
                willRaiseEvent = ctx.Socket.ReceiveFromAsync(ctx.receiveBuffer);
            }
            catch (ObjectDisposedException)
            {
                // do nothing
                return;
            }
            if (!willRaiseEvent)
            {
                ProcessReceive(ctx.receiveBuffer);
            }
        }
 public void Initialize(Socket socket, IAsyncSocketSession socketSession, SocketContext socketContext)
 {
     var token = SocketEventArgs.UserToken as AsyncUserToken;
     token.Socket = socket;
     token.SocketSession = socketSession;
     token.SocketContext = socketContext;
 }
        public static void RegisterServer(SocketContext socketContext)
        {
            socketContext.AddPacketHandler<DownloadFileQuery>(
                async (packet) =>
                {
                    var stream = await VirtualFileSystem.OpenStreamAsync(packet.Url, VirtualFileMode.Open, VirtualFileAccess.Read);
                    var data = new byte[stream.Length];
                    await stream.ReadAsync(data, 0, data.Length);
                    stream.Close();
                    socketContext.Send(new DownloadFileAnswer { StreamId = packet.StreamId, Data = data });
                });

            socketContext.AddPacketHandler<UploadFilePacket>(
                async (packet) =>
                {
                    var stream = await VirtualFileSystem.OpenStreamAsync(packet.Url, VirtualFileMode.Create, VirtualFileAccess.Write);
                    await stream.WriteAsync(packet.Data, 0, packet.Data.Length);
                    stream.Close();
                });

            socketContext.AddPacketHandler<FileExistsQuery>(
                async (packet) =>
                    {
                        var fileExists = await VirtualFileSystem.FileExistsAsync(packet.Url);
                        socketContext.Send(new FileExistsAnswer { StreamId = packet.StreamId, FileExists = fileExists });
                    });
        }
 public NetworkVirtualFileProvider(SocketContext socketContext, string remoteUrl) : base(null)
 {
     this.socketContext = socketContext;
     RemoteUrl = remoteUrl;
     if (!RemoteUrl.EndsWith(VirtualFileSystem.DirectorySeparatorChar.ToString()))
         RemoteUrl += VirtualFileSystem.DirectorySeparatorChar;
 }
        /// <inheritdoc/>
        protected override IEnumerable<EndPoint> BindInternal(IEnumerable<EndPoint> localEndPoints)
        {
            Dictionary<EndPoint, System.Net.Sockets.Socket> newListeners = new Dictionary<EndPoint, System.Net.Sockets.Socket>();
            try
            {
                // Process all the addresses
                foreach (EndPoint localEP in localEndPoints)
                {
                    EndPoint ep = localEP;
                    if (ep == null)
                        ep = new IPEndPoint(IPAddress.Any, 0);
                    System.Net.Sockets.Socket listenSocket = new System.Net.Sockets.Socket(ep.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
                    //listenSocket.Bind(ep);
                    if (ep is IPEndPoint)
                    {
                        IPEndPoint iep = ep as IPEndPoint;

                        listenSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(iep.Address));
                        IPEndPoint ipep = new IPEndPoint(IPAddress.Any, iep.Port);
                        listenSocket.Bind(ipep);
                        newListeners[listenSocket.LocalEndPoint] = listenSocket;
                    }
                }
            }
            catch (Exception ex)
            {
                // Roll back if failed to bind all addresses
                foreach (System.Net.Sockets.Socket listenSocket in newListeners.Values)
                {
                    try
                    {
                        listenSocket.Close();
                    }
                    catch (Exception)
                    {
                        ExceptionMonitor.Instance.ExceptionCaught(ex);
                    }
                }

                throw;
            }

            foreach (KeyValuePair<EndPoint, System.Net.Sockets.Socket> pair in newListeners)
            {
                SocketContext ctx = new SocketContext(pair.Value, SessionConfig);
                _listenSockets[pair.Key] = ctx;
                BeginReceive(ctx);
            }

            _idleStatusChecker.Start();

            return newListeners.Keys;
        }
 private void BeginReceive(SocketContext ctx)
 {
     EndPoint remoteEP = new IPEndPoint(ctx.Socket.AddressFamily == AddressFamily.InterNetwork ?
         IPAddress.Any : IPAddress.IPv6Any, 0);
     try
     {
         ctx.Socket.BeginReceiveFrom(ctx.receiveBuffer, 0, ctx.receiveBuffer.Length, SocketFlags.None, ref remoteEP, ReceiveCallback, ctx);
     }
     catch (ObjectDisposedException)
     {
         // do nothing
     }
 }
Example #9
0
        private async void ShaderCompilerRequestHandler(SocketContext clientSocketContext, EffectLogStore recordedEffectCompile, EffectCompiler effectCompiler, ShaderCompilerRequest shaderCompilerRequest)
        {
            // Wait for a client to be connected
            await clientConnectedTCS.Task;

            // Yield so that this socket can continue its message loop to answer to shader file request.
            await Task.Yield();

            Console.WriteLine("Compiling shader");

            // A shader has been requested, compile it (asynchronously)!
            var precompiledEffectShaderPass = await effectCompiler.Compile(shaderCompilerRequest.MixinTree, null).AwaitResult();

            // Record compilation to asset file (only if parent)
            recordedEffectCompile[new EffectCompileRequest(shaderCompilerRequest.MixinTree.Name, shaderCompilerRequest.MixinTree.UsedParameters)] = true;
            
            // Send compiled shader
            clientSocketContext.Send(new ShaderCompilerAnswer { StreamId = shaderCompilerRequest.StreamId, EffectBytecode = precompiledEffectShaderPass.Bytecode });
        }
        public override WebSocketCommandInfo FindCommand(SocketContext context, byte[] readBuffer, int offset, int length, bool isReusableBuffer)
        {
            AddArraySegment(readBuffer, offset, length, isReusableBuffer);

            if (m_StartPos < 0)
            {
                m_StartPos = BufferSegments.IndexOf(WebSocketConstant.StartByte);

                if (m_StartPos < 0)
                {
                    //Continue to read following bytes to seek start pos
                    NextCommandReader = this;
                    return null;
                }
            }

            int endPos = BufferSegments.IndexOf(WebSocketConstant.EndByte, m_StartPos, BufferSegments.Count - m_StartPos);

            if (endPos < 0)
            {
                //Continue to search end byte
                NextCommandReader = this;
                return null;
            }

            var commandInfo = new WebSocketCommandInfo(Encoding.UTF8.GetString(BufferSegments.ToArrayData(m_StartPos + 1, endPos - m_StartPos - 1)));

            BufferSegments.ClearSegements();

            int left = BufferSegments.Count - endPos - 1;

            if (left > 0)
                AddArraySegment(readBuffer, offset + length - left, left, isReusableBuffer);

            m_StartPos = -1;
            NextCommandReader = this;
            return commandInfo;
        }
        public override WebSocketCommandInfo FindCommand(SocketContext context, byte[] readBuffer, int offset, int length, bool isReusableBuffer)
        {
            AddArraySegment(readBuffer, offset, length, isReusableBuffer);

            int? result = BufferSegments.SearchMark(m_HeaderTerminator);

            if (!result.HasValue || result.Value <= 0)
            {
                NextCommandReader = this;
                return null;
            }

            string header = Encoding.UTF8.GetString(BufferSegments.ToArrayData(0, result.Value));

            var socketContext = context as WebSocketContext;

            WebSocketServer.ParseHandshake(socketContext, new StringReader(header));

            var secWebSocketKey1 = socketContext.SecWebSocketKey1;
            var secWebSocketKey2 = socketContext.SecWebSocketKey2;

            int left = BufferSegments.Count - result.Value - m_HeaderTerminator.Length;

            BufferSegments.ClearSegements();

            if (string.IsNullOrEmpty(secWebSocketKey1) && string.IsNullOrEmpty(secWebSocketKey2))
            {
                //v.75
                if (left > 0)
                    AddArraySegment(readBuffer, offset + length - left, left, isReusableBuffer);

                NextCommandReader = new WebSocketDataReader(this);
                return CreateHeadCommandInfo();
            }
            else
            {
                //v.76
                //Read SecWebSocketKey3(8 bytes)
                if (left == 8)
                {
                    socketContext.SecWebSocketKey3 = readBuffer.Skip(offset + length - left).Take(left).ToArray();
                    NextCommandReader = new WebSocketDataReader(this);
                    return CreateHeadCommandInfo();
                }
                else if (left > 8)
                {
                    socketContext.SecWebSocketKey3 = readBuffer.Skip(offset + length - left).Take(8).ToArray();
                    AddArraySegment(readBuffer, offset + length - left + 8, left - 8, isReusableBuffer);
                    NextCommandReader = new WebSocketDataReader(this);
                    return CreateHeadCommandInfo();
                }
                else
                {
                    //left < 8
                    if (left > 0)
                        AddArraySegment(readBuffer, offset + length - left, left, isReusableBuffer);

                    NextCommandReader = new WebSocketSecKey3Reader(this);
                    return null;
                }
            }
        }
Example #12
0
 public abstract ISocketManager Send(SocketContext context);
Example #13
0
 public abstract ISocketManager Receive(SocketContext context);
Example #14
0
 /// <summary>
 /// Sets the socket context.
 /// </summary>
 /// <param name="context">The socket context.</param>
 public void SetContext(SocketContext context)
 {
     m_SocketContext  = context;
     m_blDisconnected = false;
 }
Example #15
0
        static void Main(string[] args)
        {
            Injector.Instance
            .Register <ILogger>(new ConsoleLogger())
            .Register <IDumper>(new HexDumper())
            .Register <InputHelper>(new InputHelper())
            .Register <ISocketManager>(new TCPServerSocketManager()
                                       .Initialize(new IPEndPoint(IPAddress.Any, RDP_DEFAULT_PORT))
                                       .Start());

            bool isBlocked = true;

            byte[] buffer = new byte[] { };

            Injector.Instance
            .Get <ISocketManager>()
            .Subscribe(EventType.RECEIVE, (rec, ctx) =>
            {
                var dump = Injector.Instance
                           .Get <IDumper>()
                           .Dump(ctx.Buffer);

                isBlocked = !ctx.Buffer.SequenceEqual(buffer);
            });

            try
            {
                ReadSequencesXML(ChooseSequence(),
                                 (seq) =>
                {
                    isBlocked = true;

                    buffer = Injector.Instance
                             .Get <InputHelper>()
                             .TextToByteArray(
                        seq.InnerText,
                        new string[] { "\t", "\n", "\r" },
                        NumberStyles.HexNumber);

                    while (isBlocked)
                    {
                        ;
                    }
                },
                                 (seq) =>
                {
                    var server = Injector.Instance
                                 .Get <ISocketManager>();

                    var context = new SocketContext()
                    {
                        Socket   = server.Clients.FirstOrDefault().Socket,
                        EndPoint = server.Clients.FirstOrDefault().EndPoint,
                        Buffer   = Injector.Instance
                                   .Get <InputHelper>()
                                   .TextToByteArray(
                            seq.InnerText,
                            new string[] { "\t", "\n", "\r" },
                            NumberStyles.HexNumber)
                    };

                    server.Send(context);
                });
            }
            catch (Exception ex)
            {
                Injector.Instance.Get <ILogger>().Error(ex);
            }
        }
Example #16
0
        public static async Task RunDebug(EngineContext engineContext)
        {
            var config = AppConfig.GetConfiguration<Config>("ScriptDebug");
            var renderingSetup = RenderingSetup.Singleton;

            engineContext.RenderContext.PrepareEffectPlugins += (effectBuilder, plugins) =>
                {
                    if (effectBuilder.PickingPassMainPlugin != null)
                    {
                        RenderPassPlugin pickingPlugin;
                        if (engineContext.DataContext.RenderPassPlugins.TryGetValue(effectBuilder.Name == "Gizmo" ? "MouseOverPickingPlugin" : "PickingPlugin", out pickingPlugin))
                            plugins.Add(new PickingShaderPlugin { RenderPassPlugin = (PickingPlugin)pickingPlugin, MainPlugin = effectBuilder.PickingPassMainPlugin });
                    }
                    if (effectBuilder.SupportWireframe)
                    {
                        RenderPassPlugin wireframePlugin;
                        if (engineContext.DataContext.RenderPassPlugins.TryGetValue("WireframePlugin", out wireframePlugin))
                            plugins.Add(new WireframeShaderPlugin { RenderPassPlugin = wireframePlugin, MainTargetPlugin = renderingSetup.MainTargetPlugin });
                    }
                };

            pickingSystem = new PickingSystem();
            pickingSystem.PropertyChanged += pickingSystem_PropertyChanged;
            engineContext.Scheduler.Add(() => pickingSystem.ProcessGizmoAndPicking(engineContext));

            var socketContext = new SocketContext();
            var socketContextAsync = new SocketContext();

            var currentScheduler = Scheduler.Current;

            var pendingClient = new PendingClient();

            socketContext.Connected = (clientSocketContext) =>
                {
                    lock (pendingClient)
                    {
                        pendingClient.MainSocket = clientSocketContext;
                        if (pendingClient.AsyncSocket != null)
                            currentScheduler.Add(() => ProcessClient(engineContext, pendingClient.MainSocket, pendingClient.AsyncSocket));
                    }
                };
            socketContextAsync.Connected = (clientSocketContext) =>
                {
                    lock (pendingClient)
                    {
                        pendingClient.AsyncSocket = clientSocketContext;
                        if (pendingClient.MainSocket != null)
                            currentScheduler.Add(() => ProcessClient(engineContext, pendingClient.MainSocket, pendingClient.AsyncSocket));
                    }
                };

            socketContext.StartServer(config.Port);
            socketContextAsync.StartServer(config.Port + 1);
        }
Example #17
0
 public void RaiseIdleState(SocketContext <TMessage> context, IdleStateEvent eventState)
 {
     OnIdleState?.Invoke(this, new IdleStateEventArgs <TMessage>(context));
 }
 public NetworkWriteStream(SocketContext socketContext, string url)
     : base(new MemoryStream())
 {
     this.memoryStream = (MemoryStream)InternalStream;
     this.url = url;
     this.socketContext = socketContext;
 }
Example #19
0
        public async static Task ProcessClient(EngineContext engineContext, SocketContext socketContext, SocketContext socketContextAsync)
        {
            socketContext.AddPacketHandler<DownloadFileQuery>(
                async (packet) =>
                {
                    var stream = await VirtualFileSystem.OpenStreamAsync(packet.Url, VirtualFileMode.Open, VirtualFileAccess.Read);
                    var data = new byte[stream.Length];
                    await stream.ReadAsync(data, 0, data.Length);
                    stream.Close();
                    socketContext.Send(new DownloadFileAnswer { StreamId = packet.StreamId, Data = data });
                });

            socketContext.AddPacketHandler<UploadFilePacket>(
                async (packet) =>
                {
                    var stream = await VirtualFileSystem.OpenStreamAsync(packet.Url, VirtualFileMode.Create, VirtualFileAccess.Write);
                    await stream.WriteAsync(packet.Data, 0, packet.Data.Length);
                    stream.Close();
                });

            var viewModelGlobalContext = new ViewModelGlobalContext();

            selectedEntitiesContext = new ViewModelContext(viewModelGlobalContext);
            selectedEntitiesContext.ChildrenPropertyEnumerators.Add(new EntityComponentEnumerator(engineContext));
            selectedEntitiesContext.ChildrenPropertyEnumerators.Add(new RenderPassPluginEnumerator());
            selectedEntitiesContext.ChildrenPropertyEnumerators.Add(new ChildrenPropertyInfoEnumerator());
            //selectedEntitiesContext.ChildrenPropertyEnumerators.Add(new EffectPropertyEnumerator(engineContext));

            var renderPassHierarchyContext = new ViewModelContext(viewModelGlobalContext);
            renderPassHierarchyContext.ChildrenPropertyEnumerators.Add(new RenderPassHierarchyEnumerator());
            renderPassHierarchyContext.Root = new ViewModelNode("Root", engineContext.RenderContext.RootRenderPass).GenerateChildren(renderPassHierarchyContext);

            var renderPassPluginsContext = new ViewModelContext(viewModelGlobalContext);
            renderPassPluginsContext.ChildrenPropertyEnumerators.Add(new RenderPassPluginsEnumerator { SelectedRenderPassPluginContext = selectedEntitiesContext });
            renderPassPluginsContext.Root = new ViewModelNode("Root", new EnumerableViewModelContent<ViewModelReference>(
                () => engineContext.RenderContext.RenderPassPlugins.Select(x => new ViewModelReference(x, true))));


            var entityHierarchyEnumerator = new EntityHierarchyEnumerator(engineContext.EntityManager, selectedEntitiesContext);
            var entityHierarchyContext = new ViewModelContext(viewModelGlobalContext);
            entityHierarchyContext.ChildrenPropertyEnumerators.Add(entityHierarchyEnumerator);
            entityHierarchyContext.ChildrenPropertyEnumerators.Add(new ChildrenPropertyInfoEnumerator());
            entityHierarchyContext.Root = new ViewModelNode("EntityHierarchyRoot", new EnumerableViewModelContent<ViewModelReference>(
                        () => engineContext.EntityManager.Entities
                                           .Where(x =>
                                           {
                                               var transformationComponent = x.Transformation;
                                               return (transformationComponent == null || transformationComponent.Parent == null);
                                           })
                                           .Select(x => new ViewModelReference(x, true))));

            entityHierarchyEnumerator.SelectedEntities.CollectionChanged += (sender, args) =>
                {
                    SelectEntity(entityHierarchyEnumerator.SelectedEntities);
                };
            //entityHierarchyContext.Root.Children.Add(new ViewModelNode("SelectedItems", EnumerableViewModelContent.FromUnaryLambda<ViewModelReference, ViewModelReference>(new NullViewModelContent(),
            //    (x) => { return new[] { new ViewModelReference(pickingSystem.SelectedEntity) }; })));
                /*(value) =>
                    {
                        var entityModelView = value != null ? entityHierarchyContext.GetModelView(value.Guid) : null;
                        var entity = entityModelView != null ? (Entity)entityModelView.NodeValue : null;
                        SelectEntity(entity);
                    })));*/
            entityHierarchyContext.Root.Children.Add(new ViewModelNode("DropEntity", new RootViewModelContent((ExecuteCommand)((viewModel2, parameter) =>
                {
                    var dropParameters = (DropCommandParameters)parameter;

                    var movedItem = dropParameters.Data is Guid ? entityHierarchyContext.GetModelView((Guid)dropParameters.Data) : null;
                    var newParent = dropParameters.Parent is Guid ? entityHierarchyContext.GetModelView((Guid)dropParameters.Parent) : null;

                    if (newParent == null || movedItem == null)
                        return;

                    var parent = ((Entity)newParent.NodeValue).Transformation;
                    if (dropParameters.TargetIndex > parent.Children.Count)
                        return;

                    var transformationComponent = ((Entity)movedItem.NodeValue).Transformation;
                    transformationComponent.Parent = null;
                    parent.Children.Insert(dropParameters.TargetIndex, transformationComponent);
                }))));

            entityHierarchyContext.Root.Children.Add(new ViewModelNode("DropAsset", new RootViewModelContent((ExecuteCommand)(async (viewModel2, parameter) =>
                {
                    var dropParameters = (DropCommandParameters)parameter;

                    var assetUrl = (string)dropParameters.Data;
                    /*var newParent = entityHierarchyContext.GetModelView((Guid)dropParameters.Parent);

                    if (newParent == null || assetUrl == null)
                        return;

                    var parent = ((Entity)newParent.NodeValue).Transformation;
                    if (dropParameters.ItemIndex > parent.Children.Count)
                        return;*/

                    engineContext.Scheduler.Add(async () =>
                    {
                        // Load prefab entity
                        var loadedEntityPrefab = await engineContext.AssetManager.LoadAsync<Entity>(assetUrl + "#");

                        // Build another entity from prefab
                        var loadedEntity = Prefab.Inherit(loadedEntityPrefab);

                        // Add it to scene
                        engineContext.EntityManager.AddEntity(loadedEntity);

                        if (loadedEntity.ContainsKey(AnimationComponent.Key))
                        {
                            Scheduler.Current.Add(() => AnimScript.AnimateFBXModel(engineContext, loadedEntity));
                        }
                    });
                }))));

            var scriptEngineContext = new ViewModelContext(viewModelGlobalContext);
            scriptEngineContext.ChildrenPropertyEnumerators.Add(new ScriptAssemblyEnumerator(engineContext));
            scriptEngineContext.ChildrenPropertyEnumerators.Add(new ChildrenPropertyInfoEnumerator());
            scriptEngineContext.Root = new ViewModelNode(new EnumerableViewModelContent<ViewModelReference>(
                        () => engineContext.ScriptManager.ScriptAssemblies.Select(x => new ViewModelReference(x, true))));
            scriptEngineContext.Root.Children.Add(new ViewModelNode("RunScript", new RootViewModelContent((ExecuteCommand)(async (viewModel2, parameter) =>
                {
                    var scriptName = (string)parameter;
                    var matchingScript = engineContext.ScriptManager.Scripts.Where(x => x.TypeName + "." + x.MethodName == scriptName);
                    if (matchingScript.Any())
                    {
                        var scriptEntry = matchingScript.Single();
                        var microThread = engineContext.ScriptManager.RunScript(scriptEntry, null);
                    }
                }))));

            var runningScriptsContext = new ViewModelContext(viewModelGlobalContext);
            runningScriptsContext.ChildrenPropertyEnumerators.Add(new MicroThreadEnumerator(selectedEntitiesContext));
            runningScriptsContext.ChildrenPropertyEnumerators.Add(new ChildrenPropertyInfoEnumerator());
            runningScriptsContext.Root = new ViewModelNode("MicroThreads", new EnumerableViewModelContent<ViewModelReference>(
                    () => engineContext.Scheduler.MicroThreads.Select(x => new ViewModelReference(x, true))
                ));

            var effectsContext = new ViewModelContext(viewModelGlobalContext);
            effectsContext.ChildrenPropertyEnumerators.Add(new EffectEnumerator(selectedEntitiesContext));
            effectsContext.ChildrenPropertyEnumerators.Add(new ChildrenPropertyInfoEnumerator());
            effectsContext.Root = new ViewModelNode("Effects", new EnumerableViewModelContent<ViewModelReference>(
                    () => engineContext.RenderContext.Effects.Select(x => new ViewModelReference(x, true))
                ));
            //effectsContext.Root.Children.Add(new ViewModelNode("PluginDefinitions", new RootViewModelContent()));

            var assetBrowserContext = new ViewModelContext(viewModelGlobalContext);
            assetBrowserContext.ChildrenPropertyEnumerators.Add(new AssetBrowserEnumerator(engineContext));
            assetBrowserContext.ChildrenPropertyEnumerators.Add(new ChildrenPropertyInfoEnumerator());
            assetBrowserContext.Root = new ViewModelNode("Root", "Root").GenerateChildren(assetBrowserContext);

            var editorContext = new ViewModelContext(viewModelGlobalContext);
            editorContext.Root = new ViewModelNode("Root");
            editorContext.Root.Children.Add(new ViewModelNode("SwitchSelectionMode", new CommandViewModelContent((sender, parameters) => { pickingSystem.ActiveGizmoActionMode = PickingSystem.GizmoAction.None; })));
            editorContext.Root.Children.Add(new ViewModelNode("SwitchTranslationMode", new CommandViewModelContent((sender, parameters) => { pickingSystem.ActiveGizmoActionMode = PickingSystem.GizmoAction.Translation; })));
            editorContext.Root.Children.Add(new ViewModelNode("SwitchRotationMode", new CommandViewModelContent((sender, parameters) => { pickingSystem.ActiveGizmoActionMode = PickingSystem.GizmoAction.Rotation; })));

            var contexts = new Dictionary<string, Tuple<ViewModelContext, ViewModelState>>();
            contexts.Add("Editor", Tuple.Create(editorContext, new ViewModelState()));
            contexts.Add("RenderPassPlugins", Tuple.Create(renderPassPluginsContext, new ViewModelState()));
            contexts.Add("RenderPasses", Tuple.Create(renderPassHierarchyContext, new ViewModelState()));
            contexts.Add("SelectedEntities", Tuple.Create(selectedEntitiesContext, new ViewModelState()));
            contexts.Add("EntityHierarchy", Tuple.Create(entityHierarchyContext, new ViewModelState()));
            contexts.Add("ScriptEngine", Tuple.Create(scriptEngineContext, new ViewModelState()));
            contexts.Add("MicroThreads", Tuple.Create(runningScriptsContext, new ViewModelState()));
            contexts.Add("AssetBrowser", Tuple.Create(assetBrowserContext, new ViewModelState()));
            contexts.Add("Effects", Tuple.Create(effectsContext, new ViewModelState()));

            int lastAckPacket = 0;

            var entitiesChangePackets = new ConcurrentQueue<EntitiesChangePacket>();
            socketContext.AddPacketHandler<EntitiesChangePacket>(
                (packet) =>
                    {
                        entitiesChangePackets.Enqueue(packet);
                        entitiesChangePacketEvent.Set();
                    });

            Action asyncThreadStart = () =>
                {
                    while (true)
                    {
                        Thread.Sleep(100);
                        foreach (var context in contexts)
                        {
                            // Process async data
                            Guid[] path = null;
                            object value = null;
                            lock (context.Value.Item1)
                            {
                                var pendingNode = context.Value.Item1.GetNextPendingAsyncNode();
                                if (pendingNode != null)
                                {
                                    value = pendingNode.Value;
                                    path = ViewModelController.BuildPath(pendingNode);
                                }
                            }
                            if (path != null)
                            {
                                // Temporary encoding through our serializer (until our serializer are used for packets)
                                var memoryStream = new MemoryStream();
                                var writer = new BinarySerializationWriter(memoryStream);
                                writer.SerializeExtended(null, value, ArchiveMode.Serialize);

                                var change = new NetworkChange { Path = path.ToArray(), Type = NetworkChangeType.ValueUpdateAsync, Value = memoryStream.ToArray() };
                                var packet = new EntitiesChangePacket { GroupKey = context.Key, Changes = new NetworkChange[] { change } };
                                socketContextAsync.Send(packet);
                                break;
                            }
                        }
                    }
                };

            new Thread(new ThreadStart(asyncThreadStart)).Start();

            // TODO: Move some of this code directly inside ViewModelContext/Controller classes
            while (true)
            {
                await TaskEx.WhenAny(TaskEx.Delay(250), entitiesChangePacketEvent.WaitAsync());

                EntitiesChangePacket packet;
                while (entitiesChangePackets.TryDequeue(out packet))
                {
                    ViewModelController.NetworkApplyChanges(contexts[packet.GroupKey].Item1, packet.Changes);
                    lastAckPacket = packet.Index;
                }

                // Wait a single frame so that network updates get applied properly by all rendering systems for next update
                await Scheduler.Current.NextFrame();

                // If entity disappeared, try to replace it with new one (happen during file reload)
                // It's little bit cumbersome to test, need some simplification of this specific entity view model root.
                if (selectedEntitiesContext.Root != null
                    && selectedEntitiesContext.Root.Parent != null
                    && selectedEntitiesContext.Root.Parent.NodeValue is Entity)
                {
                    var entity = (Entity)selectedEntitiesContext.Root.Parent.NodeValue;
                    if (!engineContext.EntityManager.Entities.Contains(entity))
                    {
                        entity = engineContext.EntityManager.Entities.FirstOrDefault(x => x.Guid == entity.Guid);
                        if (entity != null)
                        {
                            selectedEntitiesContext.ViewModelByGuid.Clear();
                            selectedEntitiesContext.Root = selectedEntitiesContext.GetModelView(entity).Children.First(x => x.PropertyName == "Components");
                        }
                    }
                }

                var data = new Dictionary<string, byte[]>();
                foreach (var context in contexts)
                {
                    lock (context.Value.Item1)
                    {
                        if (context.Value.Item1.Root != null)
                            context.Value.Item1.AddModelView(context.Value.Item1.Root);
                        ViewModelController.UpdateReferences(context.Value.Item1, true);
                        data[context.Key] = ViewModelController.NetworkSerialize(context.Value.Item1, context.Value.Item2);
                    }
                }

                viewModelGlobalContext.UpdateObjects(contexts.Select(x => x.Value.Item1));

                //Console.WriteLine("DataSize: {0}", data.Sum(x => x.Value.Length));
                await Task.Factory.StartNew(() => socketContext.Send(new EntitiesUpdatePacket { AckIndex = lastAckPacket, Data = data }));
            }
        }