private static void _RestartProcesses(OperationProgressClient progressSender)
        {
            progressSender.SendStatus(0x00, $"Restarting processes...");
            foreach (var s in Program.server_types)
            {
                s.Value.StartAll();
            }
            progressSender.SendStatus(0x00, $"Processes started. Waiting for validation...");

            //Wait to see if any end
            Thread.Sleep(5000);

            //Count up processess running
            int running = 0;
            int ended   = 0;

            foreach (var s in Program.server_types)
            {
                foreach (var p in s.Value.instances)
                {
                    if (p.IsProcessRunning())
                    {
                        running++;
                    }
                    else
                    {
                        ended++;
                    }
                }
            }

            //Finish
            progressSender.SendStatus((byte)(ended == 0 ? 0x01 : 0x02), $"Processes started. {running} running, {ended} died.");
        }
        private static void _CloseProcesses(OperationProgressClient progressSender)
        {
            progressSender.SendStatus(0x00, "Shutting down all processes...");
            int procs = 0;

            foreach (var s in Program.server_types)
            {
                procs += s.Value.EndAll();
            }
            progressSender.SendStatus(0x00, $"{procs} processes shut down.");
        }
        public static void BeginUpdate(OperationProgressClient progressSender)
        {
            //Close all services
            _CloseProcesses(progressSender);

            //Update all
            _UpdatePackages(progressSender);

            //Restart all
            _RestartProcesses(progressSender);
        }
        public byte[] OnUpdateAllCommand(CoreNetworkServer server, CoreNetworkOpcode opcode, byte[] payload)
        {
            //Read token
            uint token       = BinaryTool.ReadUInt32(payload, 0);
            var  eventSender = new OperationProgressClient(this, token);

            //Begin thread
            var t = new Thread(() =>
            {
                PackageUpdater.BeginUpdate(eventSender);
            });

            t.IsBackground = true;
            t.Start();
            return(new byte[0]);
        }
        private static void _UpdatePackages(OperationProgressClient progressSender)
        {
            progressSender.SendStatus(0x00, $"Updating {Program.config.packages.Count} packages...");
            bool applied = true;

            for (int step = 0; applied; step++)
            {
                applied = false;
                foreach (var p in Program.config.packages)
                {
                    //Only apply if within index
                    if (step < p.Value.update_commands.Length)
                    {
                        //Apply
                        applied = true;
                        progressSender.SendStatus(0x00, $"[{step}-{p.Key}] Updating package...");
                        int code = ManagerTools.ExecuteShellCommand(p.Value.update_commands[step], out string result);
                        progressSender.SendStatus(0x03, result + "\n" + result);
                        progressSender.SendStatus(0x00, $"[{step}-{p.Key}] Package update finished with exit code {code}.");
                    }
                }
            }
            progressSender.SendStatus(0x00, $"Finished updating {Program.config.packages.Count} packages.");
        }