Open 9Vcc opened 1 year ago
此版本有一个传送bug,玩家在!c旁观之后飞到任意地方再次!c会再次生成玩家坐标数据,导致玩家!s时传送至玩家第二次!c时的位置 下面是修复此bug后的源码
import os import json import re from mcdreforged.api.all import * from typing import NamedTuple camera_player = 0 # 临时存储数据 temp_data_list: dict = {} DATA_FILE = 'config/gamemode_helper.json' # Reference Here Plugin class Position(NamedTuple): x: float y: float z: float # 这一部分是将 Rcon 返回的数据进行处理 def process_coordinate(text: str) -> Position: data = text[1:-1].replace('d', '').split(', ') data = [(x + 'E0').split('E') for x in data] assert len(data) == 3 return Position(*[float(e[0]) * 10 ** int(e[1]) for e in data]) def process_dimension(text: str) -> str: return text.replace(re.match(r'[\w ]+: ', text).group(), '', 1).strip('"\' ') def process_facing(text: str) -> str: data = text[1:-1].replace('f', '').split(', ') return ' '.join(data) def on_info(server: PluginServerInterface, info: Info): global camera_player if info.is_player and info.content == "!c": player_name = info.player # Rcon 是否连接并运行 if server.is_rcon_running(): if player_name not in temp_data_list.keys(): # 坐标 position = process_coordinate( re.search(r'\[.*]', server.rcon_query('data get entity {} Pos'.format(player_name))).group() ) # 面向 rotation = process_facing( re.search(r'\[.*]', server.rcon_query('data get entity {} Rotation'.format(player_name))).group() ) # 维度 dimension = process_dimension( server.rcon_query('data get entity {} Dimension'.format(player_name)) ) temp_data_list[player_name] = { "x": position.x, "y": position.y, "z": position.z, "facing": rotation, "dimension": dimension } server.execute("gamemode spectator {}".format(player_name)) else: return else: camera_player += 1 server.execute('data get entity ' + info.player) elif info.is_player and info.content == "!s": player_name = info.player if player_name in temp_data_list.keys(): player_position = temp_data_list.get(player_name) x = player_position['x'] y = player_position['y'] z = player_position['z'] facing = player_position['facing'] dimension = player_position['dimension'] server.execute(f"execute in {dimension} run tp {player_name} {x} {y} {z} {facing}") server.execute(f"gamemode survival {player_name}") del temp_data_list[player_name] # 如果没有 rcon if not info.is_player and camera_player > 0 and re.match(r'\w+ has the following entity data: ', info.content) is not None: name = info.content.split(' ')[0] position_str = re.search(r'(?<=Pos: )\[.*?]', info.content).group() dimension = re.search(r'(?<= Dimension: )(.*?),', info.content).group().replace('"', '').replace("'", '').replace(',', '') facing_str = re.search(r'(?<=Rotation: )\[.*?]', info.content).group() position = process_coordinate(position_str) rotation = process_facing(facing_str) if name not in temp_data_list.keys(): # 添加条件检查 temp_data_list[name] = { "x": position.x, "y": position.y, "z": position.z, "facing": rotation, "dimension": dimension } server.execute("gamemode spectator {}".format(name)) camera_player -= 1 # 服务器被关闭, 无论是崩溃还是正常关闭 def on_server_stop(server: PluginServerInterface, server_return_code: int): with open(DATA_FILE, 'w', encoding='utf8') as data_file: json.dump(temp_data_list, data_file, ensure_ascii=False, indent=2) # 插件被卸载 def on_unload(server: PluginServerInterface): with open(DATA_FILE, 'w', encoding='utf8') as data_file: json.dump(temp_data_list, data_file, ensure_ascii=False, indent=2) def on_load(server: PluginServerInterface, old): global temp_data_list if os.path.exists(DATA_FILE) is False: with open(DATA_FILE, 'w', encoding='utf8') as data_file: json.dump({}, data_file, ensure_ascii=False, indent=2) temp_data_list = {} elif os.path.exists(DATA_FILE): with open(DATA_FILE, 'r', encoding='utf8') as data_file: temp_data_list = json.load(data_file) server.register_help_message('!c', '切换为旁观者模式') server.register_help_message('!s', '切换回生存并回到切换为旁观者时的位置')
你可以提交pr的,这个插件真的停止维护了. 如果需要使用请使用mod版, 谢谢 Mod版:CameraMod
此版本有一个传送bug,玩家在!c旁观之后飞到任意地方再次!c会再次生成玩家坐标数据,导致玩家!s时传送至玩家第二次!c时的位置 下面是修复此bug后的源码