diff --git a/docs/cn/multilanguage/example.json b/docs/cn/multilanguage/example.json new file mode 100644 index 0000000..f745560 --- /dev/null +++ b/docs/cn/multilanguage/example.json @@ -0,0 +1,48 @@ +{ + "": "基础阶段", + "hello": "来自KuiToi服务器的问候!", + "config_path": "使用{}进行配置。", + "init_ok": "初始化完成。", + "start": "服务器已启动!", + "stop": "服务器已停止!", + + "": "服务器认证", + "auth_need_key": "需要BeamMP密钥才能启动!", + "auth_empty_key": "BeamMP密钥为空!", + "auth_cannot_open_browser": "无法打开浏览器:{}", + "auth_use_link": "使用此链接:{}", + + "": "GUI阶段", + "GUI_yes": "是", + "GUI_no": "否", + "GUI_ok": "确定", + "GUI_cancel": "取消", + "GUI_need_key_message": "需要BeamMP密钥才能启动!\n是否在浏览器中打开链接以获取密钥?", + "GUI_enter_key_message": "请输入密钥:", + "GUI_cannot_open_browser": "无法打开浏览器。\n请使用此链接:{}", + + "": "Web阶段", + "web_start": "WebAPI已启动{}(CTRL+C停止)", + + "": "命令:man", + "man_message_man": "man - 显示COMMAND的帮助页面。\n用法:man COMMAND", + "help_message_man": "显示COMMAND的帮助页面。", + "man_for": "帮助页面", + "man_message_not_found": "man:找不到帮助页面。", + "man_command_not_found": "man:找不到\"{}\"命令!", + + "": "命令:help", + "man_message_help": "help - 显示命令的名称和简短描述。\n用法:help [--raw]\n命令`help`列出所有可用的命令,并为每个命令提供简短描述。", + "help_message_help": "显示命令的名称和简短描述。", + "help_command": "命令", + "help_message": "文本", + "help_message_not_found": "无文本", + + "": "命令:stop", + "man_message_stop": "stop - 关闭服务器。\n用法:stop", + "help_message_stop": "关闭服务器。", + + "": "命令:exit", + "man_message_exit": "exit - 关闭服务器。\n用法:exit", + "help_message_exit": "关闭服务器。" +} \ No newline at end of file diff --git a/docs/cn/multilanguage/readme.md b/docs/cn/multilanguage/readme.md new file mode 100644 index 0000000..0cd9fef --- /dev/null +++ b/docs/cn/multilanguage/readme.md @@ -0,0 +1,3 @@ +# MultiLanguage - i18n支持 + +在 [example.json](./example.json) 中是 [src/modules/i18n/files/ru.json](../../../src/modules/i18n/files/ru.json) 的副本。如果你想将其翻译成以前未翻译过的语言,或者更新现有的翻译,我将很高兴接受你的拉取请求。 diff --git a/docs/cn/plugins/classes.md b/docs/cn/plugins/classes.md new file mode 100644 index 0000000..ad7eca6 --- /dev/null +++ b/docs/cn/plugins/classes.md @@ -0,0 +1,174 @@ +# 传递的类 + +## 值得一读 + +1. 什么是“*args”和“**kwargs”? -> [habr上的文章 ↗](https://habr.com/ru/companies/ruvds/articles/482464/) + +## KuiToi +_`kt = KuiToi("PluginName"")`_ + +### kt.log +_常量_\ +返回预配置的记录器 + +### kt.name +_常量_\ +返回插件名称 + +### kt.dir +_常量_\ +返回插件文件夹 + +### kt.open() +_与open()参数相同_\ +在kt.dir中打开文件 + +### kt.register_event(event_name: str, event_func: function) +_`event_name: str` -> 作为`event_func`调用的事件名称._\ +_`event_func: function` -> 要调用的函数._ + +在`event_func`中,可以传递普通函数或async - 不需要提前进行await。\ +您也可以创建自己的事件,并使用自己的名称注册任意数量的事件。 + +### kt.call_event(event_name: str, *args, **kwargs) -> list: +_`event_name: str` -> 要调用的事件名称._\ +_`*args, **kwargs` -> 要传递给函数的参数._ + +### **async** kt.call_async_event(event_name: str, *args, **kwargs) -> list: +_`event_name: str` -> 要调用的事件名称._\ +_`*args, **kwargs` -> 要传递给函数的参数._\ +_需要用`await`调用_ + +###### _建议阅读*args, **kwargs,链接在开头_ +所有事件的数据都以以下格式传递:`{"event_name": event_name, "args": args, "kwargs": kwargs}`\ +`args: list` -> 表示传递到事件中的数据数组\ +`kwargs: dict` -> 表示传递到事件中的数据字典 +数据将以数组形式从所有成功的波动中返回。 + +### kt.call_lua_event(event_name: str, *args) -> list: +_`event_name: str` -> 要调用的事件名称._\ +_`*args` -> 要传递给函数的参数._ + +添加用于向后兼容性。\ +lua函数使用直接传递参数`lua_func(*args)`进行调用。 + +### kt.get_player([pid: int], [nick: str]) -> Player | None: +_`pid: int` -> Player ID - 玩家标识符._\ +_`nick: str` -> Player Nick - 玩家昵称._ + +该方法通过其`pid`或`nick`返回玩家对象。\ +如果无法找到玩家,则返回 `None`。 + +### kt.get_players() -> List[Player] | list: + +该方法返回所有玩家的数组。\ +如果没有玩家,则数组将为空。 + +### kt.players_counter() -> int: + +该方法返回在线的玩家数量。 + +### kt.is_player_connected([pid: int], [nick: str]) -> bool: +_`pid: int` -> Player ID - 玩家标识符._\ +_`nick: str` -> Player Nick - 玩家昵称._ + +该方法通过其`pid`或`nick`返回玩家对象。 + +## Player (或 Client) +_`pl = kt.get_player()`_\ +_`pl = event_data['kwargs']['player']`_ + +### pl.log -> Logger +_常量_\ +返回预配置的记录器 + +### pl.addr -> str +_常量_\ +返回玩家的 IP 地址 + +### pl.pid -> int +### pl.cid -> int +_常量_\ +返回客户端的 ID _(pid: PlayerId = cid: ClientId)_ + +### pl.key -> str +_常量_\ +返回在身份验证期间传递的密钥 + +### pl.nick -> str +_变量_\ +从 BeamMP 服务器传递的昵称,可以更改,后果未知 + +### pl.roles -> str +_变量_\ +从 BeamMP 服务器传递的角色,可以更改(如果设置了不正确的角色,可能会发生意外情况。) + +### pl.guest -> bool +_常量_\ +返回玩家是否为游客,从 BeamMP 服务器传递 + +### pl.identifiers -> dict +_常量_\ +标识符,从 BeamMP 服务器传递。 + +### pl.ready -> bool +_常量,由核心更改_\ +返回布尔值,如果为 True-> 玩家已下载所有资源,在地图上加载 + +### pl.cars -> dict +_常量,由核心更改_\ +按类型返回汽车字典: + +```python +{ + 1: { + "packet": car_packet, + "json": car_json, + "json_ok": bool(car_json), + "snowman": snowman, + "over_spawn": (snowman and allow_snowman) or over_spawn, + "pos": { + "pos":[0,0,0], + "rvel":[0,0,0], + "rot":[0,0,0], + "vel":[0,0,0], + "tim":0, + "ping":0 + } + }, + 2: ... +} +``` +其中 `1` - car_id\ +其中 `pkt` - 未处理的从客户端收到的数据包(仅供非常有经验的用户使用)\ +其中 `json` - 以 dict 形式存储的已处理的数据包\ +其中 `json_ok` - 核心是否能够处理数据包\ +其中 `snowman` - 车辆是否为雪人\ +其中 `over_spawn` - 车辆是否超过了生成限制(通过插件允许)\ +其中 `pos` - 车辆位置(通过 UDP 传递) + +### pl.last_position -> dict +_常量,由核心更改_ +返回玩家的最后位置 + + +### **async** pl.kick([reason: str = "Kicked!"]) -> None +_`reason: str` -> 踢出理由,参数可选,默认值为 `Kicked!`_ +将玩家踢出服务器 + +### **async** pl.send_message(message: str, [to_all: bool = True]) -> None +_`message: str` -> 消息文本,不带 "Server:"_ +_`to_all: bool` -> 是否向所有人发送此消息?参数可选,默认值为 `True`_ +向玩家或所有人发送消息 + +### **async** pl.send_event(event_name: str, event_data: Any, [to_all: bool = True]) -> None +_`event_name: str` -> 要调用的事件名称_ +_`event_data: Any` -> 发送到事件的数据。_ +_`to_all: bool` -> 是否向所有人发送此消息?参数可选,默认值为 `True`_ +将事件发送到客户端。\ +如果 event_data 是 tuple、list、dict,则核心会通过 json.dumps(event_data) 将其转换为 json,然后再发送。\ +否则,数据将是字符串,不受限制; + +### **async** pl.delete_car(self, car_id: int) -> None +_`car_id: int` -> 要删除的车辆的 ID_ +删除玩家的车辆 \ No newline at end of file diff --git a/docs/cn/plugins/events_list.md b/docs/cn/plugins/events_list.md new file mode 100644 index 0000000..811ec5b --- /dev/null +++ b/docs/cn/plugins/events_list.md @@ -0,0 +1,3 @@ +# 所有可用事件列表 + +大多数事件将包含`pl = data ['kwargs'] ['player']`,可以在[这里](./classes.md)找到描述。 diff --git a/docs/cn/plugins/examples/async_example.py b/docs/cn/plugins/examples/async_example.py new file mode 100644 index 0000000..1244eda --- /dev/null +++ b/docs/cn/plugins/examples/async_example.py @@ -0,0 +1,37 @@ +import json + +try: + import KuiToi +except ImportError: + pass + +kt = KuiToi("Example") +log = kt.log +config = {"config_version": 0.1, "sql": {"enabled": False, "host": "127.0.0.1", "port": 3363, "database": "fucklua"}} +cfg_file = "config.json" + + +async def my_event_handler(event_data): + log.info(f"{event_data}") + + +async def load(): + # Инициализация плагина + with open(cfg_file, 'w') as f: + json.dump(config, f) + cgf = config + log.info(cgf) + ev.register_event("my_event", my_event_handler) + log.info("Плагин загружен успешно.") + + +async def start(): + # Запуск процессов плагина + await ev.call_async_event("my_event") + await ev.call_async_event("my_event", "Some data", data="some data too") + log.info("Плагин запустился успешно.") + + +async def unload(): + # Код завершающий все процессы + log.info("Плагин выгружен успешно.") diff --git a/docs/cn/plugins/examples/example.py b/docs/cn/plugins/examples/example.py new file mode 100644 index 0000000..536a170 --- /dev/null +++ b/docs/cn/plugins/examples/example.py @@ -0,0 +1,37 @@ +import json + +try: + import KuiToi +except ImportError: + pass + +kt = KuiToi("Example") +log = kt.log +config = {"config_version": 0.1, "sql": {"enabled": False, "host": "127.0.0.1", "port": 3363, "database": "fucklua"}} +cfg_file = "config.json" + + +def my_event_handler(event_data): + log.info(f"{event_data}") + + +def load(): + # Инициализация плагина + with open(cfg_file, 'w') as f: + json.dump(config, f) + cgf = config + log.info(cgf) + ev.register_event("my_event", my_event_handler) + log.info("Плагин загружен успешно.") + + +def start(): + # Запуск процессов плагина + ev.call_event("my_event") + ev.call_event("my_event", "Some data", data="some data too") + log.info("Плагин запустился успешно.") + + +def unload(): + # Код завершающий все процессы + log.info("Плагин выгружен успешно.") diff --git a/docs/cn/plugins/lua/example.lua b/docs/cn/plugins/lua/example.lua new file mode 100644 index 0000000..984646f --- /dev/null +++ b/docs/cn/plugins/lua/example.lua @@ -0,0 +1,27 @@ +print("example.lua") + +--CreateTimer Testing +local mytimer = MP.CreateTimer() +--.--.--.--.--.--.--. + +--GetOSName Testing +print("OS Name: "..MP.GetOSName()) +--.--.--.--.--.--.- + +--GetServerVersion Testing +local major, minor, patch = MP.GetServerVersion() +print("Server Version: "..major.."."..minor.."."..patch) +--.--.--.--.--.--.--.--.-- + +--Events Testing-- +function handleChat(player_id, player_name, message) + print("Lua handleChat:", player_id, player_name, message, "; Uptime: "..mytimer:GetCurrent()) + return 1 +end + +MP.RegisterEvent("onChatMessage", "handleChat") +--.--.--.--.--.--. + +function onInit() + print("Initializing ready!") +end diff --git a/docs/cn/plugins/lua/readme.md b/docs/cn/plugins/lua/readme.md new file mode 100644 index 0000000..6039bc6 --- /dev/null +++ b/docs/cn/plugins/lua/readme.md @@ -0,0 +1,35 @@ +# BeamMP Lua反馈支持 + +KiuToi几乎完全支持BeamMP的lua插件,所有必要的方法都已经创建,测试显示以下细节: + +在KiuToi中没有支持:`MP.Set()` + +#### Economic Rework V2.0(付费,Discord(RU):[Hlebushek](https://discordapp.com/users/449634697593749516)) + +1. 要获取`pluginPath`,需要:`debug.getinfo(1).source:gsub("\\","/")` => `debug.getinfo(1).source:gsub("\\","/"):gsub("@", "")`,因为路径返回值中包含`@`,这破坏了插件。 + +#### Cobalt Essentials V1.7.5(免费,[github ↗](https://github.com/prestonelam2003/CobaltEssentials/)) + +1. 要获取`pluginPath`,需要:`debug.getinfo(1).source:gsub("\\","/")` => `debug.getinfo(1).source:gsub("\\","/"):gsub("@", "")`,因为路径返回值中包含`@`,这破坏了插件。 +2. 必须将所有的`require()`移动到`onInit`之后。 +3. 在某些情况下,必须在函数声明之后注册`MP.RegisterEvent`,即: +```lua +--这样不正确,可能无法注册 +MP.RegisterEvent("onPlayerAuth","onPlayerAuth") +function onPlayerAuth(name, role, isGuest) + -- Some plugin code +end + +--这样就可以了 +MP.RegisterEvent("onPlayerAuth","onPlayerAuth") +``` + +### 工作原理 + +插件加载经过几个阶段: + +1. 扫描`plugins/`文件夹 +2. 如果文件夹不在PyPlugins中,并且文件夹中存在`*.lua`,则添加它,例如`plugins/LuaPlugin` +3. 然后从该文件夹中进行`lua.loadfile({filename})`(这是lua中的标准方法) +4. 最后调用事件和函数`onInit()` +5. 如果在执行`onInit()`期间没有发生错误,则可以通过`lua_plugins`命令看到这样的消息:`Lua plugins: LuaPlugin:ok` diff --git a/docs/cn/plugins/readme.md b/docs/cn/plugins/readme.md new file mode 100644 index 0000000..8d45a2d --- /dev/null +++ b/docs/cn/plugins/readme.md @@ -0,0 +1,97 @@ +# 插件系统 + +### 事件:[这里](./events_list.md) +### 类:[这里](./classes.md) + +## 使用带有“Dummy”的库 +###### (这意味着它没有服务器无法工作,但IDE将指导API) +###### (库还在开发中) + +* 使用pip:\ + `$ pip install KuiToi` +* 从源代码安装:\ + `git clone https://github.com/KuiToi/KuiToi-PyLib` + +## 示例 + +```python +try: + import KuiToi +except ImportError: + pass + +kt = KuiToi("ExamplePlugin") +log = kt.log + +def my_event_handler(event_data): + log.info(f"{event_data}") + +def load(): + # 初始化插件 + ev.register_event("my_event", my_event_handler) + log.info("插件已成功加载。") + + +def start(): + # 启动插件进程 + ev.call_event("my_event") + ev.call_event("my_event", "一些数据", data="一些数据也是") + log.info("插件已成功启动。") + + +def unload(): + # 结束所有进程的代码 + log.info("插件已成功卸载。") +``` + +您还可以在[example.py](examples/example.py)中找到更广泛的示例。 + +* 建议在`load()`后使用`open()`,否则应使用`kt.load()`-在`plugin//`文件夹中创建一个文件 +* 创建自己的事件:`kt.register_event("my_event", my_event_function)`- +* 调用事件:`kt.call_event("my_event")` +* 使用数据调用事件:`kt.call_event("my_event", data, data2=data2)` +* 基本事件:_稍后会写_ + +## 异步函数 + +支持async + +```python +try: + import KuiToi +except ImportError: + pass + +kt = KuiToi("Example") +log = kt.log + + +async def my_event_handler(event_data): + log.info(f"{event_data}") + + +async def load(): + # 初始化插件 + ev.register_event("my_event", my_event_handler) + log.info("插件已成功加载。") + + +async def start(): + # 启动插件进程 + await ev.call_async_event("my_event") + await ev.call_async_event("my_event", "一些数据", data="一些数据也是") + log.info("插件已成功启动。") + + +async def unload(): + # 结束所有进程的代码 + log.info("插件已成功卸载。") + +``` + +您还可以在[async_example.py](examples/async_example.py)中找到更广泛的示例。 + +* 创建自己的事件:`kt.register_event("my_event", my_event_function)`(在register_event中检查函数) +* 调用async事件:`kt.call_async_event("my_event")` +* 使用数据调用async事件:`kt.call_async_event("my_event", data, data2=data2)` +* 基本的async事件:_稍后会写_ diff --git a/docs/cn/setup/readme.md b/docs/cn/setup/readme.md new file mode 100644 index 0000000..4fa3988 --- /dev/null +++ b/docs/cn/setup/readme.md @@ -0,0 +1,88 @@ +# 来自 KuiToi 服务器的问候 + +## 好的,让我们开始吧 + +###### _(这里是 Linux 的命令)_ + +* 运行它需要 **Python 3.10.x**!只有这个版本才能运行,Python 3.11 不支持... +* 您可以像这样检查 Python 版本(你要在这里笑): +```bash +python3 --version # Python 3.10.6 +``` +* 克隆存储库并导航到它 +* 安装所有必需的内容 +* 然后,使用我的“脚本”,删除所有不必要的文件并移动到核心源 +```bash +git clone -b Stable https://github.com/kuitoi/KuiToi-Server.git && cd KuiToi-Server +pip install -r requirements.txt +mv ./src/ $HOME/ktsrc/ && rm -rf ./* && mv $HOME/ktsrc/* . && rm -rf $HOME/ktsrc +``` +* 这是如何检查服务器信息并启动它的方法: +```bash +python3 main.py --help # 显示所有可用命令 +python3 main.py # 启动服务器 +``` + +## 配置 + +* 启动后,将创建 `kuitoi.yaml` +* 默认情况下,它如下所示: +```yaml +!!python/object:modules.ConfigProvider.config_provider.Config +Auth: + key: null + private: true +Game: + map: gridmap_v2 + max_cars: 1 + players: 8 +Options: + debug: false + encoding: utf-8 + language: en + log_chat: true + speed_limit: 0 + use_lua: true + use_queue: false +Server: + description: Welcome to KuiToi Server! + name: KuiToi-Server + server_ip: 0.0.0.0 + server_port: 30814 +WebAPI: + enabled: false + secret_key: 3838ccb03c86cdb386b67fbfdcba62d0 + server_ip: 127.0.0.1 + server_port: 8433 +``` +### Auth + +* 如果您将 `private: false` 并且不设置 `key`,服务器将请求一个 BeamMP 密钥,没有它无法启动。 +* 输入 BeamMP 密钥后,服务器将出现在启动器列表中。 +* 您可以在此处获取密钥:[https://beammp.com/k/keys ↗](https://beammp.com/k/keys) + +### Game + +* `map` 仅为地图名称,即打开具有地图的 mod 在 `map.zip/levels` - 地图名称将在那里,那就是我们插入的地方。 +* `max_cars` - 每个玩家的最大汽车数量 +* `players` - 最大玩家数 + +### Options + +* `debug` - 是否输出调试消息(仅适用于有经验的用户,会略微降低性能) +* `encoding` - 使用哪种编码打开文件 +* `language` - 服务器将使用哪种语言启动(当前可用:en,ru) +* `log_chat` - 是否将聊天输出到控制台 +* `speed_limit` - 下载 mod 的下载速度限制(以 MB/s 为单位) +* `use_lua` - 启用 lua 支持 +* `use_queue` - 按队列下载 mod,即一次只能下载一个客户端 + +### Server + +* `description` - BeamMP 启动器的服务器描述 +* `name` - BeamMP 启动器的服务器名称 +* `server_ip` - 分配给服务器的 IP 地址(仅适用于有经验的用户,默认为 0.0.0.0) +* `server_port` - 服务器将在哪个端口上工作 + +### WebAPI +##### _文档尚未准备好_ \ No newline at end of file diff --git a/docs/cn/web/readme.md b/docs/cn/web/readme.md new file mode 100644 index 0000000..20f7f98 --- /dev/null +++ b/docs/cn/web/readme.md @@ -0,0 +1,13 @@ +# 服务器的 WebAPI + +## 可用的端点 + +* `/stop`: + * 必需参数: + * `secret_key` - 在服务器配置中指定的密钥 + + +* `/event.get` + * 这个端点还没有准备好 + * 必需参数: + * `secret_key` - 在服务器配置中指定的密钥 \ No newline at end of file