mirror of
https://github.com/kuitoi/kuitoi-Server.git
synced 2025-08-17 16:25:36 +00:00
Compare commits
4 Commits
2368fec501
...
a50decb470
Author | SHA1 | Date | |
---|---|---|---|
a50decb470 | |||
9079750576 | |||
e440cdf022 | |||
43fd56f327 |
@ -40,11 +40,6 @@ class Client:
|
|||||||
self._connect_time = 0
|
self._connect_time = 0
|
||||||
self._last_position = {}
|
self._last_position = {}
|
||||||
|
|
||||||
ev.register_event("onServerStopped", self.__gracefully_kick)
|
|
||||||
|
|
||||||
async def __gracefully_kick(self, _):
|
|
||||||
await self.kick("Server shutdown!")
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _writer(self):
|
def _writer(self):
|
||||||
return self.__writer
|
return self.__writer
|
||||||
@ -112,7 +107,7 @@ class Client:
|
|||||||
if not reason:
|
if not reason:
|
||||||
reason = "Kicked!"
|
reason = "Kicked!"
|
||||||
else:
|
else:
|
||||||
reason = f"{reason!r}"
|
reason = f"{reason}"
|
||||||
if not self.__alive:
|
if not self.__alive:
|
||||||
self.log.debug(f"{self.nick}.kick('{reason}') skipped: Not alive;")
|
self.log.debug(f"{self.nick}.kick('{reason}') skipped: Not alive;")
|
||||||
return
|
return
|
||||||
@ -689,8 +684,8 @@ class Client:
|
|||||||
# TODO: i18n
|
# TODO: i18n
|
||||||
self.log.info(f"Disconnected, online time: {round((time.monotonic() - self._connect_time) / 60, 2)}min.")
|
self.log.info(f"Disconnected, online time: {round((time.monotonic() - self._connect_time) / 60, 2)}min.")
|
||||||
self.__Core.clients[self.cid] = None
|
self.__Core.clients[self.cid] = None
|
||||||
self.__Core.clients_by_id.pop(self.cid)
|
del self.__Core.clients_by_id[self.cid]
|
||||||
self.__Core.clients_by_nick.pop(self.nick)
|
del self.__Core.clients_by_nick[self.nick]
|
||||||
else:
|
else:
|
||||||
self.log.debug(f"Removing client; Closing connection...")
|
self.log.debug(f"Removing client; Closing connection...")
|
||||||
try:
|
try:
|
||||||
|
@ -116,6 +116,12 @@ class Core:
|
|||||||
self.log.error("Error in check_alive.")
|
self.log.error("Error in check_alive.")
|
||||||
self.log.exception(e)
|
self.log.exception(e)
|
||||||
|
|
||||||
|
async def __gracefully_kick(self):
|
||||||
|
for client in self.clients:
|
||||||
|
if not client:
|
||||||
|
continue
|
||||||
|
await client.kick("Server shutdown!")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def start_web():
|
def start_web():
|
||||||
uvconfig = uvicorn.Config("modules.WebAPISystem.app:web_app",
|
uvconfig = uvicorn.Config("modules.WebAPISystem.app:web_app",
|
||||||
@ -157,7 +163,6 @@ class Core:
|
|||||||
"version": self.BeamMP_version, "clientversion": self.client_major_version,
|
"version": self.BeamMP_version, "clientversion": self.client_major_version,
|
||||||
"name": config.Server["name"], "modlist": modlist, "modstotalsize": modstotalsize,
|
"name": config.Server["name"], "modlist": modlist, "modstotalsize": modstotalsize,
|
||||||
"modstotal": modstotal, "playerslist": "", "desc": config.Server['description'], "pass": False}
|
"modstotal": modstotal, "playerslist": "", "desc": config.Server['description'], "pass": False}
|
||||||
self.log.debug(f"Auth: data {data}")
|
|
||||||
|
|
||||||
# Sentry?
|
# Sentry?
|
||||||
ok = False
|
ok = False
|
||||||
@ -169,7 +174,6 @@ class Core:
|
|||||||
async with session.post(url, data=data, headers={"api-v": "2"}) as response:
|
async with session.post(url, data=data, headers={"api-v": "2"}) as response:
|
||||||
code = response.status
|
code = response.status
|
||||||
body = await response.json()
|
body = await response.json()
|
||||||
self.log.debug(f"Auth: code {code}, body {body}")
|
|
||||||
ok = True
|
ok = True
|
||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -183,15 +187,18 @@ class Core:
|
|||||||
self.log.error("Missing/invalid json members in backend response")
|
self.log.error("Missing/invalid json members in backend response")
|
||||||
raise KeyboardInterrupt
|
raise KeyboardInterrupt
|
||||||
|
|
||||||
if test:
|
|
||||||
status = body.get("status")
|
status = body.get("status")
|
||||||
msg = body.get("msg")
|
msg = body.get("msg")
|
||||||
if status == "2000":
|
if status == "2000":
|
||||||
|
if test:
|
||||||
# TODO: i18n
|
# TODO: i18n
|
||||||
self.log.info(f"Authenticated! {msg}")
|
self.log.info(f"Authenticated! {msg}")
|
||||||
elif status == "200":
|
elif status == "200":
|
||||||
|
if test:
|
||||||
self.log.info(f"Resumed authenticated session. {msg}")
|
self.log.info(f"Resumed authenticated session. {msg}")
|
||||||
else:
|
else:
|
||||||
|
self.log.debug(f"Auth: data {data}")
|
||||||
|
self.log.debug(f"Auth: code {code}, body {body}")
|
||||||
self.log.error(f"Backend REFUSED the auth key. Reason: "
|
self.log.error(f"Backend REFUSED the auth key. Reason: "
|
||||||
f"{msg or 'Backend did not provide a reason'}")
|
f"{msg or 'Backend did not provide a reason'}")
|
||||||
self.log.info(f"Server still runnig, but only in Direct connect mode.")
|
self.log.info(f"Server still runnig, but only in Direct connect mode.")
|
||||||
@ -296,6 +303,7 @@ class Core:
|
|||||||
ev.call_lua_event("onShutdown")
|
ev.call_lua_event("onShutdown")
|
||||||
ev.call_event("onServerStopped")
|
ev.call_event("onServerStopped")
|
||||||
await ev.call_async_event("onServerStopped")
|
await ev.call_async_event("onServerStopped")
|
||||||
|
await self.__gracefully_kick()
|
||||||
await ev.call_async_event("_plugins_unload")
|
await ev.call_async_event("_plugins_unload")
|
||||||
ev.call_event("_lua_plugins_unload")
|
ev.call_event("_lua_plugins_unload")
|
||||||
self.run = False
|
self.run = False
|
||||||
|
@ -40,6 +40,7 @@ class Core:
|
|||||||
def create_client(self, *args, **kwargs) -> Client: ...
|
def create_client(self, *args, **kwargs) -> Client: ...
|
||||||
def get_clients_list(self, need_cid=False) -> str: ...
|
def get_clients_list(self, need_cid=False) -> str: ...
|
||||||
async def check_alive(self) -> None: ...
|
async def check_alive(self) -> None: ...
|
||||||
|
async def __gracefully_kick(self): ...
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def start_web() -> None: ...
|
def start_web() -> None: ...
|
||||||
def stop_me(self) -> None: ...
|
def stop_me(self) -> None: ...
|
||||||
|
@ -23,8 +23,9 @@ class UDPServer(asyncio.DatagramTransport):
|
|||||||
self.port = port
|
self.port = port
|
||||||
self.run = False
|
self.run = False
|
||||||
|
|
||||||
def connection_made(self, transport):
|
def connection_made(self, *args, **kwargs): ...
|
||||||
...
|
def pause_writing(self, *args, **kwargs): ...
|
||||||
|
def resume_writing(self, *args, **kwargs): ...
|
||||||
|
|
||||||
async def handle_datagram(self, data, addr):
|
async def handle_datagram(self, data, addr):
|
||||||
try:
|
try:
|
||||||
@ -58,9 +59,10 @@ class UDPServer(asyncio.DatagramTransport):
|
|||||||
case _:
|
case _:
|
||||||
self.log.debug(f"[{cid}] Unknown code: {code}")
|
self.log.debug(f"[{cid}] Unknown code: {code}")
|
||||||
else:
|
else:
|
||||||
self.log.debug(f"Client not found.")
|
self.log.debug(f"[{cid}] Client not found.")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
||||||
self.log.error(f"Error handle_datagram: {e}")
|
self.log.error(f"Error handle_datagram: {e}")
|
||||||
|
|
||||||
def datagram_received(self, *args, **kwargs):
|
def datagram_received(self, *args, **kwargs):
|
||||||
@ -79,8 +81,9 @@ class UDPServer(asyncio.DatagramTransport):
|
|||||||
|
|
||||||
async def _start(self):
|
async def _start(self):
|
||||||
self.log.debug("Starting UDP server.")
|
self.log.debug("Starting UDP server.")
|
||||||
try:
|
|
||||||
while self.Core.run:
|
while self.Core.run:
|
||||||
|
try:
|
||||||
|
|
||||||
await asyncio.sleep(0.2)
|
await asyncio.sleep(0.2)
|
||||||
|
|
||||||
d = UDPServer
|
d = UDPServer
|
||||||
@ -90,21 +93,19 @@ class UDPServer(asyncio.DatagramTransport):
|
|||||||
)
|
)
|
||||||
d.transport = self.transport
|
d.transport = self.transport
|
||||||
|
|
||||||
if not self.run:
|
|
||||||
self.log.debug(f"UDP server started on {self.transport.get_extra_info('sockname')}")
|
self.log.debug(f"UDP server started on {self.transport.get_extra_info('sockname')}")
|
||||||
|
|
||||||
self.run = True
|
self.run = True
|
||||||
while not self.transport.is_closing():
|
while not self.transport.is_closing():
|
||||||
await asyncio.sleep(0.2)
|
await asyncio.sleep(0.2)
|
||||||
|
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
self.log.error("Cannot bind port or other error")
|
self.run = False
|
||||||
self.log.exception(e)
|
self.Core.run = False
|
||||||
|
self.log.error(f"Cannot bind port or other error: {e}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.log.error(f"Error: {e}")
|
self.log.error(f"Error: {e}")
|
||||||
self.log.exception(e)
|
self.log.exception(e)
|
||||||
finally:
|
|
||||||
self.run = False
|
|
||||||
self.Core.run = False
|
|
||||||
|
|
||||||
def _stop(self):
|
def _stop(self):
|
||||||
self.log.debug("Stopping UDP server")
|
self.log.debug("Stopping UDP server")
|
||||||
|
@ -73,9 +73,9 @@ class EventsSystem:
|
|||||||
f"async_event={async_event}, lua_event={lua}):")
|
f"async_event={async_event}, lua_event={lua}):")
|
||||||
if lua:
|
if lua:
|
||||||
if event_name not in self.__lua_events:
|
if event_name not in self.__lua_events:
|
||||||
self.__lua_events.update({str(event_name): [{"func": event_func, "name": lua}]})
|
self.__lua_events.update({str(event_name): [{"func_name": event_func, "lua": lua}]})
|
||||||
else:
|
else:
|
||||||
self.__lua_events[event_name].append({"func": event_func, "name": lua})
|
self.__lua_events[event_name].append({"func_name": event_func, "lua": lua})
|
||||||
self.log.debug("Register ok")
|
self.log.debug("Register ok")
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -141,13 +141,18 @@ class EventsSystem:
|
|||||||
funcs_data = []
|
funcs_data = []
|
||||||
if event_name in self.__lua_events.keys():
|
if event_name in self.__lua_events.keys():
|
||||||
for data in self.__lua_events[event_name]:
|
for data in self.__lua_events[event_name]:
|
||||||
func = data['func']
|
lua = data['lua']
|
||||||
|
func_name = data["func_name"]
|
||||||
try:
|
try:
|
||||||
|
func = lua.globals()[func_name]
|
||||||
|
if not func:
|
||||||
|
self.log.warning(f"Cannot trigger local event: '{func_name}' not found!")
|
||||||
|
continue
|
||||||
fd = func(*args)
|
fd = func(*args)
|
||||||
funcs_data.append(fd)
|
funcs_data.append(fd)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# TODO: i18n
|
# TODO: i18n
|
||||||
self.log.error(f'Error while calling lua event "{event_name}"; In function: "{data["name"]}"')
|
self.log.error(f'Error while calling lua event "{event_name}"; In function: "{func_name}"')
|
||||||
self.log.exception(e)
|
self.log.exception(e)
|
||||||
else:
|
else:
|
||||||
# TODO: i18n
|
# TODO: i18n
|
||||||
|
@ -45,8 +45,6 @@ class EventTimer:
|
|||||||
# noinspection PyPep8Naming
|
# noinspection PyPep8Naming
|
||||||
class MP:
|
class MP:
|
||||||
|
|
||||||
# In ./in_lua.lua
|
|
||||||
|
|
||||||
def __init__(self, name: str, lua: LuaRuntime):
|
def __init__(self, name: str, lua: LuaRuntime):
|
||||||
self.loaded = False
|
self.loaded = False
|
||||||
self._event_waiters = []
|
self._event_waiters = []
|
||||||
@ -81,25 +79,13 @@ class MP:
|
|||||||
self.log.debug("request MP.GetServerVersion()")
|
self.log.debug("request MP.GetServerVersion()")
|
||||||
return ev.call_event("_get_BeamMP_version")[0]
|
return ev.call_event("_get_BeamMP_version")[0]
|
||||||
|
|
||||||
def _reg_ev(self):
|
|
||||||
for event in self._event_waiters:
|
|
||||||
self.RegisterEvent(*event)
|
|
||||||
|
|
||||||
def RegisterEvent(self, event_name: str, function_name: str) -> None:
|
def RegisterEvent(self, event_name: str, function_name: str) -> None:
|
||||||
self.log.debug("request MP.RegisterEvent()")
|
self.log.debug("request MP.RegisterEvent()")
|
||||||
if not self.loaded:
|
ev.register_event(event_name, function_name, lua=self._lua)
|
||||||
self.log.debug("MP.RegisterEvent: plugin not loaded, waiting...")
|
|
||||||
self._event_waiters.append([event_name, function_name])
|
|
||||||
return
|
|
||||||
event_func = self._lua.globals()[function_name]
|
|
||||||
if not event_func:
|
|
||||||
self.log.warning(f"Can't register '{event_name}': not found function: '{function_name}'")
|
|
||||||
return
|
|
||||||
ev.register_event(event_name, event_func, lua=function_name)
|
|
||||||
if event_name not in self._local_events:
|
if event_name not in self._local_events:
|
||||||
self._local_events.update({str(event_name): [event_func]})
|
self._local_events.update({str(event_name): [function_name]})
|
||||||
else:
|
else:
|
||||||
self._local_events[event_name].append(event_func)
|
self._local_events[event_name].append(function_name)
|
||||||
self.log.debug("Register ok (local)")
|
self.log.debug("Register ok (local)")
|
||||||
|
|
||||||
def CreateEventTimer(self, event_name: str, interval_ms: int, strategy: int = None):
|
def CreateEventTimer(self, event_name: str, interval_ms: int, strategy: int = None):
|
||||||
@ -120,13 +106,20 @@ class MP:
|
|||||||
self.log.debug(f"Calling local lua event: '{event_name}'")
|
self.log.debug(f"Calling local lua event: '{event_name}'")
|
||||||
funcs_data = []
|
funcs_data = []
|
||||||
if event_name in self._local_events.keys():
|
if event_name in self._local_events.keys():
|
||||||
for func in self._local_events[event_name]:
|
for func_name in self._local_events[event_name]:
|
||||||
try:
|
try:
|
||||||
funcs_data.append(func(*args))
|
func = self._lua.globals()[func_name]
|
||||||
|
if not func:
|
||||||
|
self.log.warning(f"Cannot trigger local event: '{func_name}' not found!")
|
||||||
|
continue
|
||||||
|
fd = func(*args)
|
||||||
|
funcs_data.append(fd)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.log.error(f'Error while calling "{event_name}"; In function: "{func}"')
|
# TODO: i18n
|
||||||
|
self.log.error(f'Error while calling lua event "{event_name}"; In function: "{func_name}"')
|
||||||
self.log.exception(e)
|
self.log.exception(e)
|
||||||
else:
|
else:
|
||||||
|
# TODO: i18n
|
||||||
self.log.warning(f"Event {event_name} does not exist, maybe ev.call_lua_event() or MP.Trigger<>Event()?. "
|
self.log.warning(f"Event {event_name} does not exist, maybe ev.call_lua_event() or MP.Trigger<>Event()?. "
|
||||||
f"Just skipping it...")
|
f"Just skipping it...")
|
||||||
|
|
||||||
@ -272,7 +265,7 @@ class MP:
|
|||||||
return self._lua.table_from(client.identifiers)
|
return self._lua.table_from(client.identifiers)
|
||||||
return self._lua.table()
|
return self._lua.table()
|
||||||
|
|
||||||
def Set(self, *args):
|
def Set(self, *_):
|
||||||
self.log.debug("request Set")
|
self.log.debug("request Set")
|
||||||
self.log.warning("KuiToi cannot support this: MP.Set()")
|
self.log.warning("KuiToi cannot support this: MP.Set()")
|
||||||
|
|
||||||
@ -636,7 +629,7 @@ class LuaPluginsLoader:
|
|||||||
lua = LuaRuntime(encoding=config.enc, source_encoding=config.enc, unpack_returned_tuples=True)
|
lua = LuaRuntime(encoding=config.enc, source_encoding=config.enc, unpack_returned_tuples=True)
|
||||||
lua_globals = lua.globals()
|
lua_globals = lua.globals()
|
||||||
lua_globals.printRaw = lua.globals().print
|
lua_globals.printRaw = lua.globals().print
|
||||||
lua_globals.exit = lambda x: self.log.info(f"{name}: You can't disable server..")
|
lua_globals.exit = lambda x: self.log.info(f"KuiToi: You can't disable server..")
|
||||||
mp = MP(name, lua)
|
mp = MP(name, lua)
|
||||||
lua_globals.MP = mp
|
lua_globals.MP = mp
|
||||||
lua_globals.print = mp._print
|
lua_globals.print = mp._print
|
||||||
@ -648,7 +641,7 @@ class LuaPluginsLoader:
|
|||||||
lua_globals.package.path += f';{p0};{p1}'
|
lua_globals.package.path += f';{p0};{p1}'
|
||||||
with open("modules/PluginsLoader/add_in.lua", "r") as f:
|
with open("modules/PluginsLoader/add_in.lua", "r") as f:
|
||||||
lua.execute(f.read())
|
lua.execute(f.read())
|
||||||
self.lua_plugins.update({name: {"lua": lua, "ok": False, "th": None, "stop_th": None}})
|
self.lua_plugins.update({name: {"lua": lua, "ok": False}})
|
||||||
plugin_path = os.path.join(self.plugins_dir, name)
|
plugin_path = os.path.join(self.plugins_dir, name)
|
||||||
for file in os.listdir(plugin_path):
|
for file in os.listdir(plugin_path):
|
||||||
path = f"plugins/{name}/{file}"
|
path = f"plugins/{name}/{file}"
|
||||||
@ -660,7 +653,6 @@ class LuaPluginsLoader:
|
|||||||
self.log.error(f"Cannot load lua plugin from `{path}`: {e}")
|
self.log.error(f"Cannot load lua plugin from `{path}`: {e}")
|
||||||
try:
|
try:
|
||||||
lua_globals.MP.loaded = True
|
lua_globals.MP.loaded = True
|
||||||
lua_globals.MP._reg_ev()
|
|
||||||
lua_globals.MP.TriggerLocalEvent("onInit")
|
lua_globals.MP.TriggerLocalEvent("onInit")
|
||||||
lua_globals.onInit()
|
lua_globals.onInit()
|
||||||
self.lua_plugins[name]['ok'] = True
|
self.lua_plugins[name]['ok'] = True
|
||||||
@ -672,8 +664,8 @@ class LuaPluginsLoader:
|
|||||||
|
|
||||||
def unload(self, _):
|
def unload(self, _):
|
||||||
self.log.debug("Unloading lua plugins")
|
self.log.debug("Unloading lua plugins")
|
||||||
for k, data in self.lua_plugins.items():
|
for name, data in self.lua_plugins.items():
|
||||||
if data['ok']:
|
if data['ok']:
|
||||||
self.log.debug(f"Unloading lua plugin: {k}")
|
self.log.info(f"Unloading lua plugin: {name}")
|
||||||
for k, v in data['lua'].globals().MP._event_timers.items():
|
for _, timer in data['lua'].globals().MP._event_timers.items():
|
||||||
v.stop()
|
timer.stop()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user