Files
crtr/Assets/Cryville/Crtr/Console.cs
2023-03-26 23:25:20 +08:00

175 lines
4.1 KiB
C#

using Cryville.Common.Network;
using System;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Logger = Cryville.Common.Logger;
namespace Cryville.Crtr {
public class Console : MonoBehaviour {
public Text Logs;
public InputField InputBox;
CommandWorker worker;
readonly Queue<string> _fallbackQueue = new Queue<string>();
~Console() {
worker.Deactivate();
}
void Start() {
Game.Init();
InputBox.Select();
worker = new CommandWorker(MainThreadFallback);
worker.Activate();
}
void OnApplicationQuit() {
Game.Shutdown();
}
public void Submit() {
worker.Issue(InputBox.text);
}
void Update() {
if (
Input.GetKeyDown(KeyCode.Return)
|| Input.GetKeyDown(KeyCode.KeypadEnter)
) {
Submit();
InputBox.text = "";
InputBox.Select();
InputBox.ActivateInputField();
}
if (_fallbackQueue.Count > 0) {
switch (_fallbackQueue.Dequeue()) {
case "play":
SceneManager.LoadScene("Play");
break;
case "quit":
Application.Quit();
break;
default:
Logger.Log("main", 4, "Console", "Unknown command. Type \"help\" for help");
break;
}
}
string _logs = Logs.text;
Game.MainLogger.Enumerate((level, module, msg) => {
string color;
switch (level) {
case 0: color = "#888888"; break;
case 1: color = "#bbbbbb"; break;
case 2: color = "#0088ff"; break;
case 3: color = "#ffff00"; break;
case 4: color = "#ff0000"; break;
case 5: color = "#bb0000"; break;
default: color = "#ff00ff"; break;
}
_logs += string.Format(
"\r\n\x02<color={1}ff>[{0}] <{2}> {3}</color>",
DateTime.UtcNow.ToString("s"), color, module, msg
);
});
Logs.text = _logs.Substring(Mathf.Max(0, _logs.IndexOf('\x02', Mathf.Max(0, _logs.Length - 8192))));
}
void MainThreadFallback(string cmd) {
_fallbackQueue.Enqueue(cmd);
}
class CommandWorker {
readonly Action<string> _fallback;
Thread _thread;
readonly Queue<string> _queue = new Queue<string>();
public CommandWorker(Action<string> fallback) {
_fallback = fallback;
}
public void Activate() {
_thread = new Thread(ThreadLoop);
_thread.Start();
}
public void Deactivate() {
_thread.Abort();
}
public void Issue(string cmd) {
lock (_queue) {
_queue.Enqueue(cmd);
}
}
void ThreadLoop() {
while (true) {
string cmd = null;
lock (_queue) {
if (_queue.Count > 0) cmd = _queue.Dequeue();
}
if (cmd != null) ProcessCommand(cmd);
else Thread.Sleep(20);
}
}
void ProcessCommand(string cmd) {
Logger.Log("main", 2, "Console", "Command processing: {0}", cmd);
var p = cmd.Split(' ');
try {
switch (p[0]) {
case "!http":
var httpcl = new HttpClient(new Uri(p[1]));
httpcl.Connect();
httpcl.Request("GET", new Uri(p[1])).MessageBody.ReadToEnd();
httpcl.Close();
break;
case "!https":
var httpscl = new HttpsClient(new Uri(p[1]));
httpscl.Connect();
httpscl.Request("GET", new Uri(p[1])).MessageBody.ReadToEnd();
httpscl.Close();
break;
/*case "!lua":
Logger.Log("main", 1, "Console", "{0}", Script.RunString(p[1]));
break;*/
/*case "!tls":
var tlscl = new TlsTcpClient(p[1]);
tlscl.Close();
break;*/
case "connect":
Game.ConnectDatabase(p[1]);
break;
case "help": case "?":
Logger.Log(
"main", 1, "Console",
"\n\tconnect <i>name</i>" +
"\n\thelp" +
"\n\tlist" +
"\n\tplay" +
"\n\tquit"
);
break;
case "list":
Logger.Log("main", 1, "Console", "Database list:");
foreach (var i in Game.GetDatabaseList()) {
Logger.Log("main", 1, "Console", "{0}", i.Name);
}
break;
default:
_fallback.Invoke(cmd);
break;
}
}
catch (Exception ex) {
Logger.Log("main", 4, "Console", "{0}", ex);
}
Logger.Log("main", 2, "Console", "Command done: {0}", cmd);
}
}
}
}