删除未使用的大型 QuMod 加载框架,改为直接注册客户端和服务端 System,并显式管理按键监听、输出包装与双端销毁。 IPC 网络线程仅负责收包,所有 ModAPI 回调由游戏线程 Update 派发,同时补充断线重连、分帧读取和幂等关闭。
99 lines
2.6 KiB
Python
99 lines
2.6 KiB
Python
# -*- coding: utf-8 -*-
|
|
import sys
|
|
import threading
|
|
|
|
|
|
_OUTPUT_PREFIX = "[Python] "
|
|
_ACTIVE_SYSTEMS = set()
|
|
_STATE_LOCK = threading.Lock()
|
|
_ORIGINAL_STDOUT = None
|
|
_ORIGINAL_STDERR = None
|
|
|
|
|
|
class OutputWrapper(object):
|
|
_emod_cli_debug_wrapper = True
|
|
|
|
def __init__(self, stream):
|
|
self.stream = stream
|
|
self.lock = threading.Lock()
|
|
self.buffer = []
|
|
|
|
def __getattr__(self, name):
|
|
return getattr(self.stream, name)
|
|
|
|
def write(self, data):
|
|
with self.lock:
|
|
parts = data.splitlines(True)
|
|
for part in parts:
|
|
if part.endswith("\n"):
|
|
if self.buffer:
|
|
line = "".join(self.buffer) + part
|
|
self.buffer = []
|
|
else:
|
|
line = part
|
|
self.stream.write(_OUTPUT_PREFIX + line)
|
|
else:
|
|
self.buffer.append(part)
|
|
|
|
def close(self):
|
|
self.flush()
|
|
return self.stream.close()
|
|
|
|
def flush(self):
|
|
with self.lock:
|
|
if self.buffer:
|
|
self.stream.write(_OUTPUT_PREFIX + "".join(self.buffer))
|
|
self.buffer = []
|
|
self.stream.flush()
|
|
|
|
def writelines(self, lines):
|
|
for line in lines:
|
|
self.write(line)
|
|
|
|
def fileno(self):
|
|
return self.stream.fileno()
|
|
|
|
|
|
def _install_output_wrapper_locked():
|
|
global _ORIGINAL_STDOUT, _ORIGINAL_STDERR
|
|
|
|
if not getattr(sys.stdout, "_emod_cli_debug_wrapper", False):
|
|
_ORIGINAL_STDOUT = sys.stdout
|
|
sys.stdout = OutputWrapper(sys.stdout)
|
|
elif _ORIGINAL_STDOUT is None:
|
|
_ORIGINAL_STDOUT = getattr(sys.stdout, "stream")
|
|
|
|
if not getattr(sys.stderr, "_emod_cli_debug_wrapper", False):
|
|
_ORIGINAL_STDERR = sys.stderr
|
|
sys.stderr = OutputWrapper(sys.stderr)
|
|
elif _ORIGINAL_STDERR is None:
|
|
_ORIGINAL_STDERR = getattr(sys.stderr, "stream")
|
|
|
|
|
|
def install_output_wrapper():
|
|
with _STATE_LOCK:
|
|
_install_output_wrapper_locked()
|
|
|
|
|
|
def activate(system):
|
|
with _STATE_LOCK:
|
|
_install_output_wrapper_locked()
|
|
_ACTIVE_SYSTEMS.add(system)
|
|
|
|
|
|
def deactivate(system):
|
|
global _ORIGINAL_STDOUT, _ORIGINAL_STDERR
|
|
|
|
with _STATE_LOCK:
|
|
_ACTIVE_SYSTEMS.discard(system)
|
|
if _ACTIVE_SYSTEMS:
|
|
return
|
|
if _ORIGINAL_STDOUT is None or _ORIGINAL_STDERR is None:
|
|
return
|
|
sys.stdout.flush()
|
|
sys.stderr.flush()
|
|
sys.stdout = _ORIGINAL_STDOUT
|
|
sys.stderr = _ORIGINAL_STDERR
|
|
_ORIGINAL_STDOUT = None
|
|
_ORIGINAL_STDERR = None
|