From 69f47c08328bbedd7adf2aac94e9807f590748ee Mon Sep 17 00:00:00 2001 From: wling Date: Thu, 15 Feb 2024 20:48:43 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=F0=9F=8E=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__init__.py" | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git "a/plugin_market/\345\272\223-\345\237\272\346\234\254\347\273\204\344\273\266API/__init__.py" "b/plugin_market/\345\272\223-\345\237\272\346\234\254\347\273\204\344\273\266API/__init__.py" index 761fc1f1..465fcad7 100644 --- "a/plugin_market/\345\272\223-\345\237\272\346\234\254\347\273\204\344\273\266API/__init__.py" +++ "b/plugin_market/\345\272\223-\345\237\272\346\234\254\347\273\204\344\273\266API/__init__.py" @@ -1,6 +1,5 @@ -from tooldelta import Plugin, PluginAPI, plugins, Frame - import json, time +from tooldelta import Plugin, PluginAPI, plugins, Frame def find_key_from_value(dic, val): # A bad method! @@ -55,7 +54,7 @@ def getScore(self, scoreboardNameToGet: str, targetNameToGet: str) -> int: return result[targetNameToGet][scoreboardNameToGet] except KeyError as err: raise Exception("Failed to get score: %s" % str(err)) - + def getPos(self, targetNameToGet: str, timeout: float | int = 1) -> dict: """ 获取租赁服内玩家坐标的函数 @@ -93,7 +92,7 @@ def getPos(self, targetNameToGet: str, timeout: float | int = 1) -> dict: return list(result.values())[0] else: return result[targetNameToGet] - + def getItem(self, targetName: str, itemName: str, itemSpecialID: int = -1) -> int: "获取玩家背包内物品数量: 目标选择器, 物品ID, 特殊值 = 所有" if (targetName not in self.game_ctrl.allplayers) and (targetName != self.game_ctrl.bot_name) and (not targetName.startswith("@a")): @@ -105,7 +104,7 @@ def getItem(self, targetName: str, itemName: str, itemSpecialID: int = -1) -> in return 0 else: return int(result.OutputMessages[0].Parameters[1]) - + def getTarget(self, sth: str, timeout: bool | int = 5) -> list: "获取符合目标选择器实体的列表" if not sth.startswith("@"): @@ -124,7 +123,7 @@ def getBlockTile(self, x: int, y: int, z: int): return "air" else: return res.OutputMessages[0].Parameters[4].strip("%tile.").strip(".name") - + def waitMsg(self, who: str, timeout: int = 30, exc = None): active_basic_api: ActivatePluginAPI = active_basic_apis[0] """ @@ -152,12 +151,12 @@ def waitMsg(self, who: str, timeout: int = 30, exc = None): raise exc else: return None - + def getPosXYZ(self, player, timeout = 30) -> tuple[float, float, float]: "获取玩家坐标的X, Y, Z值" res = self.getPos(player, timeout = timeout)["position"] return res["x"], res["y"], res["z"] - + def sendresultcmd(self, cmd, timeout = 30): "返回命令执行是否成功" res = self.game_ctrl.sendwscmd(cmd, True, timeout).SuccessCount @@ -182,8 +181,8 @@ def on_player_message(self, player: str, msg: str): if player in self.waitmsg_req: self.waitmsg_result[player] = msg self.waitmsg_req.remove(player) - + def on_player_leave(self, player: str): if player in self.waitmsg_req: self.waitmsg_result[player] = EXC_PLAYER_LEAVE - self.waitmsg_req.remove(player) \ No newline at end of file + self.waitmsg_req.remove(player) From c3eb02f05d5d3b60c97533f2af6552a95e8f6352 Mon Sep 17 00:00:00 2001 From: wling Date: Thu, 15 Feb 2024 20:49:19 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=F0=9F=94=A7=20=E6=AD=A4=E9=80=89=E9=A1=B9?= =?UTF-8?q?=E4=BE=9D=E4=B8=AA=E4=BA=BA=E5=96=9C=E5=A5=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 1822b586..9e9bd34f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,6 +4,5 @@ "editor.defaultFormatter": "ms-python.black-formatter" }, "python.languageServer": "Pylance", - "python.analysis.typeCheckingMode": "off", - "python.analysis.autoImportCompletions": false + "python.analysis.typeCheckingMode": "off" } From e14b5fa527ae4b0a72d971536931e3d05d9f29cf Mon Sep 17 00:00:00 2001 From: wling Date: Thu, 15 Feb 2024 20:50:30 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=93=A6=20=E6=96=B0=E5=A2=9E=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E5=92=8C=E6=B3=A8=E5=85=A5=E5=BC=8F=E6=8E=A5=E5=85=A5?= =?UTF-8?q?=E6=AD=BB=E4=BA=A1=E6=97=B6=E9=97=B4=E5=92=8C=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tooldelta/__init__.py | 7 + tooldelta/color_print.py | 5 +- tooldelta/launch_cli.py | 7 +- tooldelta/packets.py | 30 ++-- tooldelta/plugin_load/__init__.py | 11 +- .../plugin_load/injected_plugin/__init__.py | 14 ++ .../plugin_load/injected_plugin/movent.py | 170 ++++++++++++++++-- 7 files changed, 205 insertions(+), 39 deletions(-) diff --git a/tooldelta/__init__.py b/tooldelta/__init__.py index 7f1a9615..9e56a3b2 100644 --- a/tooldelta/__init__.py +++ b/tooldelta/__init__.py @@ -1,4 +1,5 @@ from colorama import init + # 初始化 colorama 库 init(autoreset=True) # for installing libs in debug mode @@ -21,6 +22,8 @@ execute_player_join, execute_player_left, execute_repeat, + execute_init, + execute_death_message, ) # 整个系统由三个部分组成 @@ -468,6 +471,7 @@ def process_text_packet(self, pkt: dict, plugin_grp: PluginGroup): killer = pkt["Parameters"][1] else: killer = None + asyncio.run(execute_death_message(pkt["Parameters"][0],killer)) plugin_grp.execute_player_death( pkt["Parameters"][0], killer, @@ -524,6 +528,9 @@ def Inject(self): self.linked_frame.on_plugin_err ) Builtins.createThread(asyncio.run, (execute_repeat(),)) + Print.print_inf("正在执行初始化注入式函数init任务") + asyncio.run(execute_init()) + Print.print_suc("初始化注入式函数init任务执行完毕") self.inject_welcome() def inject_welcome(self): diff --git a/tooldelta/color_print.py b/tooldelta/color_print.py index f47c9c54..06093031 100644 --- a/tooldelta/color_print.py +++ b/tooldelta/color_print.py @@ -37,7 +37,7 @@ class _Print: ["g", "#DDD605"], ["r", "/"] ] - + def __call__(self, text: str): self.print_inf(text) @@ -128,6 +128,9 @@ def print_suc(self, text: str, **print_kwargs): def print_war(self, text: str, **print_kwargs): self.print_with_info(f"§6{text}", self.INFO_WARN, **print_kwargs) + def print_load(self, text: str, **print_kwargs): + self.print_with_info(f"§d{text}", self.INFO_LOAD, **print_kwargs) + def fmt_info(self, text: str, info: str = "§f 信息 "): setNextColor = "§r" if "\n" in text: diff --git a/tooldelta/launch_cli.py b/tooldelta/launch_cli.py index 6b1b348e..7304f7d6 100644 --- a/tooldelta/launch_cli.py +++ b/tooldelta/launch_cli.py @@ -482,7 +482,8 @@ def packet_handler_parent(self, pkt_type, pkt): self.packet_handler(pkt_type, pkt) def init_all_functions(self): - def sendcmd(cmd, waitForResp = False, timeout = 30): + + def sendcmd(cmd: str, waitForResp: bool = False, timeout: int = 30): if waitForResp: res = self.omega.send_player_command_need_response(cmd, timeout) if res is None: @@ -491,7 +492,8 @@ def sendcmd(cmd, waitForResp = False, timeout = 30): else: self.omega.send_player_command_omit_response(cmd) return b"" - def sendwscmd(cmd, waitForResp = False, timeout = 30): + + def sendwscmd(cmd: str, waitForResp: bool = False, timeout: int = 30): if waitForResp: res = self.omega.send_websocket_command_need_response(cmd, timeout) if res is None: @@ -500,6 +502,7 @@ def sendwscmd(cmd, waitForResp = False, timeout = 30): else: self.omega.send_websocket_command_omit_response(cmd) return b"" + def sendwocmd(cmd: str): self.omega.send_settings_command(cmd) def sendPacket(pktID: int, pkt: str): diff --git a/tooldelta/packets.py b/tooldelta/packets.py index 81b4fb7f..d98e5d5b 100644 --- a/tooldelta/packets.py +++ b/tooldelta/packets.py @@ -188,21 +188,21 @@ class SubPacket_CmdOutputMsg: Success: bool Message: str Parameters: list[str] - def __init__(this, pkt: dict): - this.Success = pkt["Success"] - this.Parameters = pkt["Parameters"] - this.Message = pkt["Message"] + def __init__(self, pkt: dict): + self.Success = pkt["Success"] + self.Parameters = pkt["Parameters"] + self.Message = pkt["Message"] class SubPacket_CmdOrigin: Origin: int UUID: str RequestID: str PlayerUniqueID: int - def __init__(this, pkt: dict): - this.Origin = pkt["Origin"] - this.UUID = pkt["UUID"] - this.RequestID = pkt["RequestID"] - this.PlayerUniqueID = pkt["PlayerUniqueID"] + def __init__(self, pkt: dict): + self.Origin = pkt["Origin"] + self.UUID = pkt["UUID"] + self.RequestID = pkt["RequestID"] + self.PlayerUniqueID = pkt["PlayerUniqueID"] class Packet_CommandOutput: CommandOrigin: SubPacket_CmdOrigin @@ -210,9 +210,9 @@ class Packet_CommandOutput: SuccessCount: int OutputMessages: list[SubPacket_CmdOutputMsg] as_dict: dict - def __init__(this, pkt: dict): - this.as_dict = pkt - this.CommandOrigin = SubPacket_CmdOrigin(pkt["CommandOrigin"]) - this.OutputMessages = [SubPacket_CmdOutputMsg(imsg) for imsg in pkt["OutputMessages"]] - this.SuccessCount = pkt["SuccessCount"] - this.OutputType = pkt["OutputType"] + def __init__(self, pkt: dict): + self.as_dict = pkt + self.CommandOrigin = SubPacket_CmdOrigin(pkt["CommandOrigin"]) + self.OutputMessages = [SubPacket_CmdOutputMsg(imsg) for imsg in pkt["OutputMessages"]] + self.SuccessCount = pkt["SuccessCount"] + self.OutputType = pkt["OutputType"] diff --git a/tooldelta/plugin_load/__init__.py b/tooldelta/plugin_load/__init__.py index c6d06031..4ffe5c40 100644 --- a/tooldelta/plugin_load/__init__.py +++ b/tooldelta/plugin_load/__init__.py @@ -66,10 +66,7 @@ def read_all_plugins(self): dotcs_plugin.read_plugin_from_old(self, dotcs_module_env) classic_plugin.read_plugin_from_new(self, {}) asyncio.run(injected_plugin.load_plugin(self)) - Print.print_inf("正在执行初始化函数init任务") - asyncio.run(injected_plugin.execute_init()) - Print.print_suc("初始化函数init任务执行完毕") def add_broadcast_listener(self, evt_name: str): "将下面的方法作为一个广播事件接收器" @@ -293,6 +290,7 @@ def processPacketFunc(self, pktID: int, pkt: dict): # NOTE 快捷导入插件函数(待增加) + from .injected_plugin.movent import ( sendcmd, sendfbcmd, @@ -304,7 +302,12 @@ def processPacketFunc(self, pktID: int, pkt: dict): get_all_player, getTarget, rawText, - is_op + is_op, + getPos, + get_robotname, + countdown, + getBlockTile, + getTickingAreaList, ) from .injected_plugin import player_message, player_join, player_left, repeat, init diff --git a/tooldelta/plugin_load/injected_plugin/__init__.py b/tooldelta/plugin_load/injected_plugin/__init__.py index ea503667..0f71be13 100644 --- a/tooldelta/plugin_load/injected_plugin/__init__.py +++ b/tooldelta/plugin_load/injected_plugin/__init__.py @@ -11,6 +11,7 @@ player_message_funcs = {} player_join_funcs = {} player_left_funcs = {} +player_death_funcs = {} repeat_funcs = {} init_plugin_funcs = {} @@ -38,6 +39,13 @@ def decorator(func): return decorator +def player_death(priority=None): + + def decorator(func): + player_death_funcs[func] = priority + return func + + return decorator def init(priority=None): def decorator(func): @@ -98,10 +106,16 @@ async def execute_repeat(): # 并发执行所有任务 await asyncio.gather(*tasks) + # 处理玩家消息并执行插件 async def execute_player_message(playername, message): await execute_asyncio_task(player_message_funcs, playername, message) + +async def execute_death_message(playername,killer): + await execute_asyncio_task(player_death_funcs, playername, killer) + + async def execute_player_join(playername): await execute_asyncio_task(player_join_funcs, playername) diff --git a/tooldelta/plugin_load/injected_plugin/movent.py b/tooldelta/plugin_load/injected_plugin/movent.py index 500451d5..6ccd901a 100644 --- a/tooldelta/plugin_load/injected_plugin/movent.py +++ b/tooldelta/plugin_load/injected_plugin/movent.py @@ -1,48 +1,61 @@ +from typing import Any from tooldelta.color_print import Print +import ujson as json +import time +from tooldelta.packets import Packet_CommandOutput, PacketIDS +from typing import Callable frame = None game_control = None -def check_avaliable(sth): + +def check_avaliable(sth) -> None: if sth is None: raise AttributeError(f"无法使用 {sth.__class__.__name__}, 因为其还未被初始化") -def set_frame(my_frame): + +def set_frame(my_frame: object) -> Callable[[object], None]: # 只有在系统启动后才能获得有效的 frame global frame, game_control frame = my_frame game_control = my_frame.get_game_control() -def sendcmd(*arg): + +def sendcmd( + cmd: str, waitForResp: bool = False, timeout: int = 30 +) -> Callable[[str, bool, int], bytes | Packet_CommandOutput]: check_avaliable(game_control) - game_control.sendcmd(*arg) + return game_control.sendcmd(cmd=cmd, waitForResp=waitForResp, timeout=timeout) -def sendwscmd(*arg): +def sendwscmd( + cmd: str, waitForResp: bool = False, timeout: int = 30 +) -> Callable[[str, bool, int], bytes | Packet_CommandOutput]: check_avaliable(game_control) - game_control.sendwscmd(*arg) + return game_control.sendwscmd(cmd=cmd, waitForResp=waitForResp, timeout=timeout) -def sendwocmd(*arg): +def sendwocmd(cmd: str) -> Callable[[str], None]: check_avaliable(game_control) - game_control.sendwocmd(*arg) + game_control.sendwocmd(cmd=cmd) -def sendPacket(*arg): +def sendPacket(pktID: int, pkt: str) -> Callable[[int,str], None]: check_avaliable(game_control) - game_control.sendPacket(*arg) + game_control.sendPacket(pktID=pktID, pkt=pkt) -def sendPacketJson(*arg): +def sendPacketJson(pktID: int, pkt: str) -> Callable[[int ,str], None]: # tip: 和sendPacket已经是同一个东西了 check_avaliable(game_control) - game_control.sendPacketJson(*arg) + game_control.sendPacketJson(pktID=pktID, pkt=pkt) -def sendfbcmd(*arg): +def sendfbcmd(cmd: str) -> Callable[[str], None]: # 在除FastBuilder外的其他启动器上不可用 check_avaliable(game_control) - game_control.sendfbcmd(*arg) + game_control.sendfbcmd(cmd=cmd) + def rawText(playername: str, text: str): """ @@ -74,12 +87,13 @@ def tellrawText(playername: str, title: str | None = None, text: str = ""): ) ) -def get_all_player(): + +def get_all_player() -> list: check_avaliable(game_control) - Print.print_suc(game_control.allplayers) return game_control.allplayers -def is_op(playername: str) ->bool: + +def is_op(playername: str) -> bool: check_avaliable(game_control) return frame.launcher.is_op(playername) @@ -99,3 +113,125 @@ def getTarget(sth: str, timeout: bool | int = 5) -> list: return result.split(", ") else: return [] + + +def find_key_from_value(dic: dict, val: Any) -> Any | None: + # A bad method! + for k, v in dic.items(): + if v == val: + return k + + +def get_robotname() -> str: + check_avaliable(game_control) + return game_control.bot_name + + +def getPos(targetNameToGet: str, timeout: float | int = 5) -> dict: + check_avaliable(game_control) + """ + 获取租赁服内玩家坐标的函数 + 参数: + targetNameToGet: str -> 玩家名称 + 返回: dict -> 获取结果 + 包含了["x"], ["y"], ["z"]: float, ["dimension"](维度): int 和["yRot"]: float + """ + if ( + (targetNameToGet not in get_all_player()) + and (targetNameToGet != game_control.bot_name) + and (not targetNameToGet.startswith("@a")) + ): + raise Exception("Player not found.") + result = game_control.sendwscmd("/querytarget " + targetNameToGet, True, timeout) + if result.OutputMessages[0].Success == False: + raise Exception( + f"Failed to get the position: {result.OutputMessages[0].Parameters[0]}" + ) + parameter = result.OutputMessages[0].Parameters[0] + if isinstance(parameter, str): + resultList = json.loads(parameter) + else: + resultList = parameter + result = {} + for i in resultList: + targetName = find_key_from_value(game_control.players_uuid, i["uniqueId"]) + x = i["position"]["x"] if i["position"]["x"] >= 0 else i["position"]["x"] - 1 + y = i["position"]["y"] - 1.6200103759765 + z = i["position"]["z"] if i["position"]["z"] >= 0 else i["position"]["z"] - 1 + position = { + "x": float("%.2f" % x), + "y": float("%.2f" % y), + "z": float("%.2f" % z), + } + dimension = i["dimension"] + yRot = i["yRot"] + result[targetName] = { + "dimension": dimension, + "position": position, + "yRot": yRot, + } + if targetNameToGet == "@a": + return result + else: + if len(result) != 1: + raise Exception("Failed to get the position.") + if targetNameToGet.startswith("@a"): + return list(result.values())[0] + else: + return result[targetNameToGet] + + +def countdown(delay: int | float, msg: str = None) -> None: + """ + 控制台显示倒计时的函数 + + 参数: + delay: int | float -> 倒计时时间(秒) + msg: str -> 倒计时运行时显示的说明 + 返回: 无返回值 + """ + if msg is None: + msg = "Countdown" + delayStart = time.time() + delayStop = delayStart + delay + while delay >= 0: + if delay >= 0: + delay = delayStop - time.time() + else: + delay = 0 + Print.print_inf("%s: %.2fs" % (msg, delay), end="\r") + time.sleep(0.01) + print("",end="\n") + + +def getBlockTile(x: int, y: int, z: int) -> str: + "获取指定坐标的方块的ID" + res = sendwscmd(f"/testforblock {x} {y} {z} air", True) + if res.SuccessCount: + return "air" + else: + print(res.OutputMessages[0].Parameters) + return res.OutputMessages[0].Parameters[4].strip("%tile.").strip(".name") + + +def getTickingAreaList() -> dict: + result = {} + resultList = sendcmd("/tickingarea list all-dimensions", True).OutputMessages + if resultList[0].Success == False: + return result + for tickareaData in resultList[1].Message.split("%dimension.dimensionName")[1:]: + tickareaDimension = tickareaData.split(": \n")[0] + tickareaList = tickareaData.split(": \n")[1].split("\n") + for tickarea in tickareaList: + if not tickarea: + continue + tickareaName = tickarea.split("- ", 1)[1].split(": ", 1)[0] + tickareaPos = { + "start": tickarea.split(" ")[2:5], + "end": tickarea.split(" ")[6:9], + } + tickareaPos["start"].pop(1) + tickareaPos["end"].pop(1) + result[tickareaName] = {"dimension": tickareaDimension} + result[tickareaName].update(tickareaPos) + return result From a31730f45dac02a926f8b7ed6ae8b7e4973ffb8c Mon Sep 17 00:00:00 2001 From: wling Date: Thu, 15 Feb 2024 20:59:48 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=F0=9F=93=A6=20=E6=96=B0=E5=A2=9E=E6=AD=BB?= =?UTF-8?q?=E4=BA=A1=E8=BF=94=E5=9B=9E=E4=B8=8E=E6=9B=B4=E6=96=B0=E4=BD=9C?= =?UTF-8?q?=E8=80=85=E4=BF=A1=E6=81=AF=E4=B8=8E=E7=89=88=E6=9C=AC=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugin_market/market_tree.json | 188 ++++++++++-------- .../__init__.py" | 4 +- .../__init__.py" | 97 +++++++++ .../__init__.py" | 188 ++++++++++++++++++ 4 files changed, 388 insertions(+), 89 deletions(-) create mode 100644 "plugin_market/\346\255\273\344\272\241\350\277\224\345\233\236/__init__.py" create mode 100644 "plugin_market/\347\273\264\345\272\246\344\274\240\351\200\201/__init__.py" diff --git a/plugin_market/market_tree.json b/plugin_market/market_tree.json index 11f00d32..6ad0ac66 100644 --- a/plugin_market/market_tree.json +++ b/plugin_market/market_tree.json @@ -5,96 +5,110 @@ "DownloadRefURL": "https://mirror.ghproxy.com/raw.githubusercontent.com/ToolDelta/ToolDelta/main/plugin_market", "DirectoryFileURL": "https://mirror.ghproxy.com/raw.githubusercontent.com/ToolDelta/ToolDelta/main/plugin_market/directory.json", "MarketPlugins": { - "自定义聊天栏菜单": { - "author": "SuperScript", - "version": "0.0.1", - "description": "自定义聊天栏菜单触发词触发的指令, 方便简洁", - "limit_launcher": null, - "pre-plugins": { - "聊天栏菜单": "0.0.3" - }, - "plugin-type": "classic" + "自定义聊天栏菜单": { + "author": "SuperScript", + "version": "0.0.1", + "description": "自定义聊天栏菜单触发词触发的指令, 方便简洁", + "limit_launcher": null, + "pre-plugins": { + "聊天栏菜单": "0.0.3" }, - "控制台执行MCFB指令": { - "author": "SuperScript", - "version": "0.0.2", - "description": "可以在控制台让机器人执行指令, 特殊指令等", - "limit_launcher": null, - "pre-plugins": {}, - "plugin-type": "classic" + "plugin-type": "classic" + }, + "控制台执行MCFB指令": { + "author": "SuperScript", + "version": "0.0.2", + "description": "可以在控制台让机器人执行指令, 特殊指令等", + "limit_launcher": null, + "pre-plugins": {}, + "plugin-type": "classic" + }, + "@玩家": { + "author": "wling", + "version": "0.0.2", + "description": "让@更有效果!", + "limit_launcher": null, + "pre-plugins": {}, + "plugin-type": "injected" + }, + "井字棋": { + "author": "SuperScript/wling", + "version": "0.0.2", + "description": "娱乐小游戏: 3x3井字棋", + "limit_launcher": null, + "pre-plugins": {}, + "plugin-type": "injected" + }, + "清空末影箱": { + "author": "wling", + "version": "0.0.1", + "description": "还在担心玩家在末影箱藏小东西吗?直接清空末影箱!", + "limit_launcher": null, + "pre-plugins": {}, + "plugin-type": "injected" + }, + "简易建造": { + "author": "SuperScript", + "version": "0.0.1", + "description": "使用一些更简便的方法建造服务器", + "limit_launcher": null, + "pre-plugins": { + "聊天栏菜单": "0.0.4", + "库-基本组件API": "0.0.1" }, - "@玩家": { - "author": "wling", - "version": "0.0.2", - "description": "让@更有效果!", - "limit_launcher": null, - "pre-plugins": { - }, - "plugin-type": "injected" + "plugin-type": "classic" + }, + "封禁系统": { + "author": "SuperScript", + "version": "0.0.1", + "description": "服内有大哥或者熊孩子? 更方便地ban掉! 同时也是一个前置插件.", + "limit_launcher": null, + "pre-plugins": { + "聊天栏菜单": "0.0.4" }, - "井字棋": { - "author": "SuperScript/wling", - "version": "0.0.1", - "description": "娱乐小游戏: 3x3井字棋", - "limit_launcher": null, - "pre-plugins": {}, - "plugin-type": "injected" + "plugin-type": "classic" + }, + "库-基本组件API": { + "author": "SuperScript", + "version": "0.0.1", + "description": "所有使用基本组件API的插件的前置", + "limit_launcher": null, + "pre-plugins": {}, + "plugin-type": "classic" + }, + "库-世界交互": { + "author": "SuperScript", + "version": "0.0.1", + "description": "所有使用世界交互的插件的前置", + "limit_launcher": null, + "pre-plugins": { + "聊天栏菜单": "0.0.1" }, - "清空末影箱": { - "author": "wling", - "version": "0.0.1", - "description": "还在担心玩家在末影箱藏小东西吗?直接清空末影箱!", - "limit_launcher": null, - "pre-plugins": { - }, - "plugin-type": "injected" - }, - "简易建造": { - "author": "SuperScript", - "version": "0.0.1", - "description": "使用一些更简便的方法建造服务器", - "limit_launcher": null, - "pre-plugins": { - "聊天栏菜单": "0.0.4", - "库-基本组件API": "0.0.1" - }, - "plugin-type": "classic" - }, - "封禁系统": { - "author": "SuperScript", - "version": "0.0.1", - "description": "服内有大哥或者熊孩子? 更方便地ban掉! 同时也是一个前置插件.", - "limit_launcher": null, - "pre-plugins": { - "聊天栏菜单": "0.0.4" - }, - "plugin-type": "classic" - }, - "库-基本组件API": { - "author": "SuperScript", - "version": "0.0.1", - "description": "所有使用基本组件API的插件的前置", - "limit_launcher": null, - "pre-plugins": {}, - "plugin-type": "classic" - }, - "库-世界交互": { - "author": "SuperScript", - "version": "0.0.1", - "description": "所有使用世界交互的插件的前置", - "limit_launcher": null, - "pre-plugins": { - "聊天栏菜单": "0.0.1" - }, - "plugin-type": "classic" - }, - "聊天栏菜单": { - "author": "SuperScript", - "version": "0.0.4", - "description": "所有使用到聊天栏菜单的组件的前置组件", - "limit_launcher": null, - "pre-plugins": {}, - "plugin-type": "classic" - } + "plugin-type": "classic" + }, + "聊天栏菜单": { + "author": "SuperScript", + "version": "0.0.4", + "description": "所有使用到聊天栏菜单的组件的前置组件", + "limit_launcher": null, + "pre-plugins": {}, + "plugin-type": "classic" + }, + "死亡返回": { + "author": "wling/7912", + "version": "0.0.1", + "description": "死了啊?没事,哥们给你记着,让我帮你返回吧!", + "limit_launcher": null, + "pre-plugins": { "维度传送": "0.0.1" }, + "plugin-type": "injected" + }, + "维度传送": { + "author": "SuperScript", + "version": "0.0.1", + "description": "作用如其名,跨纬度传送,谁都爱", + "limit_launcher": null, + "pre-plugins": {}, + "plugin-type": "injected" + } } } \ No newline at end of file diff --git "a/plugin_market/\344\272\225\345\255\227\346\243\213/__init__.py" "b/plugin_market/\344\272\225\345\255\227\346\243\213/__init__.py" index 050c9f51..efe61771 100644 --- "a/plugin_market/\344\272\225\345\255\227\346\243\213/__init__.py" +++ "b/plugin_market/\344\272\225\345\255\227\346\243\213/__init__.py" @@ -2,8 +2,8 @@ __plugin_meta__ = { "name": "井字棋", - "version": "1.0", - "author": "SuperScript", + "version": "0.0.2", + "author": "SuperScript/wling", } class JZQStage: def __init__(self): diff --git "a/plugin_market/\346\255\273\344\272\241\350\277\224\345\233\236/__init__.py" "b/plugin_market/\346\255\273\344\272\241\350\277\224\345\233\236/__init__.py" new file mode 100644 index 00000000..aa842edb --- /dev/null +++ "b/plugin_market/\346\255\273\344\272\241\350\277\224\345\233\236/__init__.py" @@ -0,0 +1,97 @@ +import os, time +from genericpath import isfile +from logging import config +from traceback import print_tb +from tooldelta.plugin_load.injected_plugin import player_death +from 维度传送 import tp +from tooldelta.plugin_load import player_message, tellrawText, getPos +import ujson as json + +__plugin_meta__ = { + "name": "死亡返回", + "version": "0.0.1", + "author": "wling/7912", +} + + +LOG_DEATH_TIME = 30 # 记录最小频率 (秒) +plugin_path = r"插件配置文件/死亡返回" +config_path = plugin_path + r"/死亡位置.json" +os.makedirs(plugin_path, exist_ok=True) +if os.path.isfile(config_path): + os.makedirs(config_path, exist_ok=True) + with open(config_path, "w", encoding="utf-8") as f: + json.dump("{}", f, indent=4, ensure_ascii=False) + + +def translateDim(dimension): + if dimension == 0: + return "主世界" + if dimension == 1: + return "地狱" + if dimension == 2: + return "末地" + raise ValueError("维度只能是0, 1或2.") + + +@player_message +async def _(playername, msg): + if msg == ".backdeath": + with open(config, "r", encoding="utf-8") as f: + data = json.loads(f) + if playername not in data: + tellrawText('@a[name="%s"]' % playername, "§l§4ERROR§r", "§c未找到记录.") + return + deathData = data[playername] + tp( + '@a[name="%s"]' % playername, + x=deathData["position"]["x"], + y=deathData["position"]["y"], + z=deathData["position"]["z"], + dimension=deathData["dimension"], + ) + tellrawText( + '@a[name="%s"]' % playername, + "§l死亡点记录§r", + "已传送到上次死亡点: [§l%s§r, (§l%s§r, §l%s§r, §l%s§r)]." + % ( + translateDim(deathData["dimension"]), + deathData["position"]["x"], + deathData["position"]["y"], + deathData["position"]["z"], + ), + ) + data[playername] = deathData + with open(config_path, "w", encoding="utf-8") as f: + json.dump(data, f, indent=4, ensure_ascii=False) + + +@player_death() +async def _(playername): + deathTime = int(time.time()) + with open(config, "r", encoding="utf-8") as f: + data = json.loads(f) + if playername not in data: + data[playername] = {} + deathData_old = data[playername] + if deathData_old: + deathTimeDelta = deathTime - deathData_old["time"] + if deathTimeDelta < LOG_DEATH_TIME: + tellrawText( + '@a[name="%s"]' % playername, + "§l§4ERROR§r", + "§c时间间隔过短, 未保存此次记录. (冷却时间: §l%d§r§cs)" + % (LOG_DEATH_TIME - deathTimeDelta), + ) + return + + deathData = getPos(f'@a[name="{playername}"]') + deathData["time"] = deathTime + data[playername] = deathData + with open(config_path, "w", encoding="utf-8") as f: + json.dump(data, f, indent=4, ensure_ascii=False) + tellrawText( + f'@a[name="{playername}"]', + "§l死亡点记录§r", + f"已记录死亡点: [§l{translateDim(deathData['dimension'])}§r, (§l{deathData['position']['x']}§r, §l{deathData['position']['y']}§r, §l{deathData['position']['z']}§r)], 输入§l.backdeath§r返回.", + ) diff --git "a/plugin_market/\347\273\264\345\272\246\344\274\240\351\200\201/__init__.py" "b/plugin_market/\347\273\264\345\272\246\344\274\240\351\200\201/__init__.py" new file mode 100644 index 00000000..04a556e7 --- /dev/null +++ "b/plugin_market/\347\273\264\345\272\246\344\274\240\351\200\201/__init__.py" @@ -0,0 +1,188 @@ +import asyncio +from tooldelta.plugin_load import init, sendcmd, countdown, getTickingAreaList +from tooldelta import Print +from tooldelta.plugin_load.injected_plugin.movent import ( + get_robotname, + getBlockTile, + getPos, + getTarget, +) + +__plugin_meta__ = { + "name": "维度传送", + "version": "0.0.1", + "author": "wling/7912", +} + +def tp(target, *, x, y, z, dimension): + if dimension == 0: + sendcmd( + f"/execute @e[type=armor_stand, name=td_overworld, c=1] ~ ~ ~ /tp {target} {x} {y} {z}" + ) + return + if dimension == 1: + sendcmd( + f"/execute @e[type=armor_stand, name=td_the_nether, c=1] ~ ~ ~ /tp {target} {x} {y} {z}" + ) + return + if dimension == 2: + sendcmd( + f"/execute @e[type=armor_stand, name=td_the_end, c=1] ~ ~ ~ /tp {target} {x} {y} {z}" + ) + return + raise ValueError("dimension参数仅可以是0, 1或2.") + + +@init() +async def _() -> None: + Print.print_load("§e正在配置跨维度传送.") + robotDim = getPos(get_robotname())["dimension"] + if robotDim != 0: + Print.print_load("§e机器人不在主世界, 正在传到主世界.") + while getPos(get_robotname())["dimension"] != 0: + sendcmd("/tp @r", True) + countdown(5, "等待世界加载") + Print.print_war("§e机器人不在主世界, 正在重新传到主世界.") + sendcmd("/tp @s 77912 1 77912", True) + await asyncio.sleep(3) + robotDim = getPos(get_robotname())["dimension"] + if getBlockTile(77912, 0, 77912) != "seaLantern": + sendcmd("/fill 77904 0 77904 77919 5 77919 sealantern 0 hollow") + if robotDim == 1: + if getBlockTile(77905, 1, 77905) != "portal": + sendcmd("/setblock 77905 1 77905 portal") + sendcmd("/tp @s 77905 0 77905") + cout = 0 + while getPos(get_robotname())["dimension"] != 0: + await asyncio.sleep(0.1) + if cout == 5: # 试错次数 + Print.print_err("§c无法将机器人传到主世界.") + return + if robotDim == 2: + if getBlockTile(77905, 1, 77905) != "end_portal": + sendcmd("/setblock 77905 1 77905 end_portal") + sendcmd("/tp @s 77905 0 77905") + cout = 0 + while getPos(get_robotname())["dimension"] != 0: + await asyncio.sleep(0.1) + if cout == 5: # 试错次数 + Print.print_err("§c无法将机器人传到主世界.") + return + sendcmd("/tp @s 100000 100000 100000", True) + Print.print_suc("§a成功将机器人传到主世界.") + Print.print_load("§e检测常加载区块数量.") + tickareaList = getTickingAreaList() + tickareaAvaliableNum = 10 - len(tickareaList) + for tickareaName in ["td_overworld", "td_the_nether", "td_the_end"]: + if tickareaName in tickareaList: + tickareaAvaliableNum += 1 + else: + countdown(5, "等待世界加载") + + if tickareaAvaliableNum < 3: + Print.print_err("§c可创建的常加载区块数量不够.") + return + + for dimension in range(3): + if dimension == 0: + if "td_the_end" not in tickareaList: + Print.print_load("§e主世界常加载不存在, 正在添加.") + sendcmd("/tickingarea add 77904 0 77904 77919 0 77919 td_overworld") + sendcmd("/tp @s 77912 1 77912", True) + await asyncio.sleep(2) + if getBlockTile(77912, 0, 77912) != "seaLantern": + sendcmd("/fill 77904 0 77904 77919 5 77919 sealantern 0 hollow") + if not getTarget("@e[type=armor_stand, name=td_overworld]"): + Print.print_load("§e主世界盔甲架不存在, 正在生成.") + if getBlockTile(77912, 0, 77912) != "seaLantern": + sendcmd("/fill 77904 0 77904 77919 5 77919 sealantern 0 hollow") + sendcmd("/summon armor_stand td_overworld 77912 1 77912") + await asyncio.sleep(1) + elif dimension == 1: + if "td_the_nether" not in tickareaList: + Print.print_load("§e地狱常加载不存在, 正在添加.") + sendcmd("/tp @s 77912 1 77912", True) + await asyncio.sleep(2) + if getBlockTile(77905, 1, 77905) != "portal": + sendcmd("/setblock 77905 1 77905 portal") + await asyncio.sleep(1) + sendcmd("/tp @s 77905 0 77905") + while getPos(get_robotname())["dimension"] != 1: + pass + await asyncio.sleep(1) + await asyncio.sleep(1) + sendcmd("/tickingarea add 77904 0 77904 77919 0 77919 td_the_nether") + await asyncio.sleep(1) + sendcmd("/tp @s 77912 1 77912", True) + await asyncio.sleep(1) + if getBlockTile(77912, 0, 77912) != "seaLantern": + sendcmd("/fill 77904 0 77904 77919 5 77919 sealantern 0 hollow") + if not getTarget("@e[type=armor_stand, name=td_the_nether]"): + Print.print_load("§e地狱盔甲架不存在, 正在生成.") + if getPos(get_robotname())["dimension"] == 0: + sendcmd("/tp @s 77912 1 77912", True) + await asyncio.sleep(2) + if getBlockTile(77905, 1, 77905) != "portal": + sendcmd("/setblock 77905 1 77905 portal") + await asyncio.sleep(1) + sendcmd("/tp @s 77905 1 77905") + await asyncio.sleep(1) + sendcmd("/tp @s 77905 2 77905") + await asyncio.sleep(1) + sendcmd("/tp @s 77905 1 77905") + await asyncio.sleep(1) + while getPos(get_robotname())["dimension"] != 1: + pass + await asyncio.sleep(1) + await asyncio.sleep(2) + sendcmd("/tp @s 77912 1 77912", True) + await asyncio.sleep(2) + if getBlockTile(77912, 0, 77912) != "seaLantern": + sendcmd("/fill 77904 0 77904 77919 5 77919 sealantern 0 hollow") + sendcmd("/summon armor_stand td_the_nether 77912 1 77912") + if getPos(get_robotname())["dimension"] == 1: + sendcmd("/tp @s @e[type=armor_stand, name=td_overworld]", True) + while getPos(get_robotname())["dimension"] != 0: + pass + await asyncio.sleep(1) + if dimension == 2: + if "td_the_end" not in tickareaList: + Print.print_load("§e末地常加载不存在, 正在添加.") + sendcmd("/tp @s 77912 1 77912", True) + await asyncio.sleep(2) + if getBlockTile(77918, 1, 77918) != "end_portal": + sendcmd("/setblock 77918 1 77918 end_portal") + await asyncio.sleep(1) + sendcmd("/tp @s 77918 0 77918") + while getPos(get_robotname())["dimension"] != 2: + pass + await asyncio.sleep(1) + await asyncio.sleep(1) + sendcmd("/tickingarea add 77904 0 77904 77919 0 77919 td_the_end") + await asyncio.sleep(1) + sendcmd("/tp @s 77912 1 77912", True) + await asyncio.sleep(2) + if getBlockTile(77912, 0, 77912) != "seaLantern": + sendcmd("/fill 77904 0 77904 77919 5 77919 sealantern 0 hollow") + if not getTarget("@e[type=armor_stand, name=td_the_end]"): + Print.print_load("§e末地盔甲架不存在, 正在生成.") + if getPos(get_robotname())["dimension"] == 0: + sendcmd("/tp @s 77912 1 77912", True) + await asyncio.sleep(1) + if getBlockTile(77918, 1, 77918) != "end_portal": + sendcmd("/setblock 77918 1 77918 end_portal") + await asyncio.sleep(1) + sendcmd("/tp @s 77918 0 77918") + while getPos(get_robotname())["dimension"] != 2: + pass + await asyncio.sleep(1) + await asyncio.sleep(1) + sendcmd("/tp @s 77912 1 77912", True) + await asyncio.sleep(2) + if getBlockTile(77912, 0, 77912) != "seaLantern": + sendcmd("/fill 77904 0 77904 77919 5 77919 sealantern 0 hollow") + sendcmd("/summon armor_stand td_the_end 77912 1 77912") + if getPos(get_robotname())["dimension"] == 2: + sendcmd("/tp @s @e[type=armor_stand, name=td_overworld]", True) + + Print.print_suc("§a成功配置跨维度传送.") From df171d599a2d37d76ece6a548feb1d80fcc201c1 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 15 Feb 2024 16:31:40 +0000 Subject: [PATCH 5/5] [AUTO] Generate Directory JSON --- plugin_market/directory.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugin_market/directory.json b/plugin_market/directory.json index b30f73e4..14132a0b 100644 --- a/plugin_market/directory.json +++ b/plugin_market/directory.json @@ -32,6 +32,12 @@ "库-世界交互": [ "__init__.py" ], + "维度传送": [ + "__init__.py" + ], + "死亡返回": [ + "__init__.py" + ], "库-基本组件API": [ "__init__.py" ]