├── windows启动.bat ├── windows更新.bat ├── 启动方法.jpg ├── package ├── MCBEWorld │ ├── LevelDatabase │ │ ├── __init__.py │ │ └── minecraftdb.py │ ├── C_API │ │ ├── ABI_File │ │ │ ├── amd64.pyd │ │ │ ├── Win_amd64.pyd │ │ │ ├── Linux_x86_64.pyd │ │ │ └── Linux_aarch64.build │ │ └── __init__.py │ ├── C_leveldb │ │ ├── ABI_File │ │ │ ├── Win_amd64.pyd │ │ │ ├── Linux_aarch64.build │ │ │ └── Win_amd64_cp38.pyd │ │ ├── __init__.pyi │ │ └── __init__.py │ ├── __init__.py │ ├── functions.py │ └── BaseType │ │ └── __init__.py ├── MCBELab │ ├── res │ │ ├── entityNBT.gzip │ │ └── blockmap.json │ ├── translate.py │ ├── __init__.py │ ├── entity.py │ └── block_entity.py ├── jsonc │ ├── __init__.py │ └── errors.py ├── MCStructureManage │ ├── C_API │ │ ├── ABI_File │ │ │ ├── Win_amd64.pyd │ │ │ ├── Linux_x86_64.pyd │ │ │ └── Linux_aarch64.build │ │ └── __init__.py │ ├── C_brotli │ │ ├── ABI_File │ │ │ ├── Win_amd64.pyd │ │ │ ├── Linux_aarch64.pyd │ │ │ ├── Linux_x86_64.pyd │ │ │ └── Linux_aarch64.build │ │ └── LICENSE │ ├── StructureMCS │ │ ├── __init__.py │ │ └── mcstructure.py │ ├── StructureSCHEM │ │ └── __init__.py │ ├── StructureSCHEMATIC │ │ └── __init__.py │ ├── README.md │ ├── StructureRUNAWAY │ │ ├── __init__.py │ │ ├── timebuild.py │ │ └── qingxu.py │ ├── __init__.py │ ├── block.py │ ├── StructureBDX │ │ └── __init__.py │ └── __private.py ├── MCCommandParser │ ├── __init__.py │ ├── parser_system.py │ └── json_paser.py └── python_nbt │ ├── error.py │ ├── LICENSE │ ├── README.md │ ├── __init__.py │ ├── builder.py │ ├── codec.py │ └── snbt.py ├── C_extension ├── C_brotli.zip ├── C_MCBEWorld.zip ├── C_leveldb.zip └── C_MCBEStructure.zip ├── main_source ├── app_source │ ├── icon.zip │ ├── about_app.txt │ ├── privacy.txt │ └── use_policy.txt ├── bedrock_edition │ ├── nbt_class │ │ ├── __init__.py │ │ ├── TradeTable.py │ │ └── BlockComponent.py │ ├── game_class │ │ ├── __init__.py │ │ └── expand_pack.py │ ├── __init__.py │ ├── command_class │ │ ├── trans_html │ │ │ ├── command_block.html │ │ │ ├── command_load.html │ │ │ └── command_run.html │ │ ├── __init__.py │ │ ├── response.py │ │ ├── mcfunction.py │ │ └── compiler │ │ │ └── rawtext.py │ ├── constants.py │ ├── data_save.py │ └── math_func.py ├── update_source │ ├── be_resource.tar │ ├── minecraft_id.zip │ └── import_files │ │ ├── entitySlot │ │ ├── music │ │ ├── effect │ │ ├── gamerule │ │ ├── structure │ │ ├── damageCause │ │ ├── enchant │ │ ├── fog │ │ └── default_map └── main_window │ ├── update_change.py │ └── constant.py ├── local_server ├── picture │ ├── block_texture.png │ ├── render │ │ ├── blocks.png │ │ ├── double_side.png │ │ └── transparent.png │ ├── tutorial │ │ ├── menu1.jpg │ │ ├── menu2.jpg │ │ ├── expand1.jpg │ │ ├── rawtext.jpg │ │ ├── template.jpg │ │ ├── warning.png │ │ ├── select_menu1.jpg │ │ ├── select_menu2.jpg │ │ └── send_command.jpg │ └── block │ │ ├── coarse_dirt.png │ │ ├── command_block.png │ │ ├── grass_carried.png │ │ ├── grass_side_carried.png │ │ ├── command_block_back_mipmap.png │ │ ├── command_block_front_mipmap.png │ │ ├── command_block_side_mipmap.png │ │ ├── chain_command_block_back_mipmap.png │ │ ├── chain_command_block_side_mipmap.png │ │ ├── chain_command_block_front_mipmap.png │ │ ├── command_block_conditional_mipmap.png │ │ ├── repeating_command_block_back_mipmap.png │ │ ├── repeating_command_block_front_mipmap.png │ │ ├── repeating_command_block_side_mipmap.png │ │ ├── chain_command_block_conditional_mipmap.png │ │ └── repeating_command_block_conditional_mipmap.png ├── test1.html ├── css │ └── wendang.css ├── js │ └── buildin.js ├── test.html └── tutorial │ └── WorldConfig.html ├── expand_pack ├── 319ceabd-6c86-48de-ba63-349c86baaf75.zip ├── b61a9a5c-0831-4d2a-b4bd-56513876be27.zip ├── b8c164cd-79ff-4c4e-876c-931d2987d1ae.zip ├── b96d85f5-789c-4812-895c-b1751c150adc.zip ├── cf061f76-414f-410e-ad6b-7b1876343918.zip ├── f2a3d3a6-3ef1-4797-8e8e-28e8463f03a9.zip └── f3732c87-e742-4213-b98f-4741a238fea0.zip ├── LICENSE ├── README.md ├── update.py └── .gitignore /windows启动.bat: -------------------------------------------------------------------------------- 1 | python main.py -------------------------------------------------------------------------------- /windows更新.bat: -------------------------------------------------------------------------------- 1 | python update.py -------------------------------------------------------------------------------- /启动方法.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/启动方法.jpg -------------------------------------------------------------------------------- /package/MCBEWorld/LevelDatabase/__init__.py: -------------------------------------------------------------------------------- 1 | from .minecraftdb import MinecraftLevelDB -------------------------------------------------------------------------------- /C_extension/C_brotli.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/C_extension/C_brotli.zip -------------------------------------------------------------------------------- /C_extension/C_MCBEWorld.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/C_extension/C_MCBEWorld.zip -------------------------------------------------------------------------------- /C_extension/C_leveldb.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/C_extension/C_leveldb.zip -------------------------------------------------------------------------------- /C_extension/C_MCBEStructure.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/C_extension/C_MCBEStructure.zip -------------------------------------------------------------------------------- /main_source/app_source/icon.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/main_source/app_source/icon.zip -------------------------------------------------------------------------------- /main_source/bedrock_edition/nbt_class/__init__.py: -------------------------------------------------------------------------------- 1 | from . import BaseNbtClass,EntityComponent,TradeTable,BlockComponent,LootTable 2 | -------------------------------------------------------------------------------- /package/MCBELab/res/entityNBT.gzip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/package/MCBELab/res/entityNBT.gzip -------------------------------------------------------------------------------- /local_server/picture/block_texture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/block_texture.png -------------------------------------------------------------------------------- /local_server/picture/render/blocks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/render/blocks.png -------------------------------------------------------------------------------- /local_server/picture/tutorial/menu1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/tutorial/menu1.jpg -------------------------------------------------------------------------------- /local_server/picture/tutorial/menu2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/tutorial/menu2.jpg -------------------------------------------------------------------------------- /local_server/picture/block/coarse_dirt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/block/coarse_dirt.png -------------------------------------------------------------------------------- /local_server/picture/tutorial/expand1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/tutorial/expand1.jpg -------------------------------------------------------------------------------- /local_server/picture/tutorial/rawtext.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/tutorial/rawtext.jpg -------------------------------------------------------------------------------- /local_server/picture/tutorial/template.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/tutorial/template.jpg -------------------------------------------------------------------------------- /local_server/picture/tutorial/warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/tutorial/warning.png -------------------------------------------------------------------------------- /main_source/update_source/be_resource.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/main_source/update_source/be_resource.tar -------------------------------------------------------------------------------- /main_source/update_source/minecraft_id.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/main_source/update_source/minecraft_id.zip -------------------------------------------------------------------------------- /package/MCBEWorld/C_API/ABI_File/amd64.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/package/MCBEWorld/C_API/ABI_File/amd64.pyd -------------------------------------------------------------------------------- /package/jsonc/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | from .errors import FileError, FunctionParameterError, ParserError 5 | from .parser import JsoncParser -------------------------------------------------------------------------------- /local_server/picture/block/command_block.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/block/command_block.png -------------------------------------------------------------------------------- /local_server/picture/block/grass_carried.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/block/grass_carried.png -------------------------------------------------------------------------------- /local_server/picture/render/double_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/render/double_side.png -------------------------------------------------------------------------------- /local_server/picture/render/transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/render/transparent.png -------------------------------------------------------------------------------- /local_server/picture/tutorial/select_menu1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/tutorial/select_menu1.jpg -------------------------------------------------------------------------------- /local_server/picture/tutorial/select_menu2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/tutorial/select_menu2.jpg -------------------------------------------------------------------------------- /local_server/picture/tutorial/send_command.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/tutorial/send_command.jpg -------------------------------------------------------------------------------- /package/MCBEWorld/C_API/ABI_File/Win_amd64.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/package/MCBEWorld/C_API/ABI_File/Win_amd64.pyd -------------------------------------------------------------------------------- /local_server/picture/block/grass_side_carried.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/block/grass_side_carried.png -------------------------------------------------------------------------------- /package/MCBEWorld/C_API/ABI_File/Linux_x86_64.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/package/MCBEWorld/C_API/ABI_File/Linux_x86_64.pyd -------------------------------------------------------------------------------- /expand_pack/319ceabd-6c86-48de-ba63-349c86baaf75.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/expand_pack/319ceabd-6c86-48de-ba63-349c86baaf75.zip -------------------------------------------------------------------------------- /expand_pack/b61a9a5c-0831-4d2a-b4bd-56513876be27.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/expand_pack/b61a9a5c-0831-4d2a-b4bd-56513876be27.zip -------------------------------------------------------------------------------- /expand_pack/b8c164cd-79ff-4c4e-876c-931d2987d1ae.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/expand_pack/b8c164cd-79ff-4c4e-876c-931d2987d1ae.zip -------------------------------------------------------------------------------- /expand_pack/b96d85f5-789c-4812-895c-b1751c150adc.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/expand_pack/b96d85f5-789c-4812-895c-b1751c150adc.zip -------------------------------------------------------------------------------- /expand_pack/cf061f76-414f-410e-ad6b-7b1876343918.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/expand_pack/cf061f76-414f-410e-ad6b-7b1876343918.zip -------------------------------------------------------------------------------- /expand_pack/f2a3d3a6-3ef1-4797-8e8e-28e8463f03a9.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/expand_pack/f2a3d3a6-3ef1-4797-8e8e-28e8463f03a9.zip -------------------------------------------------------------------------------- /expand_pack/f3732c87-e742-4213-b98f-4741a238fea0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/expand_pack/f3732c87-e742-4213-b98f-4741a238fea0.zip -------------------------------------------------------------------------------- /package/MCBEWorld/C_API/ABI_File/Linux_aarch64.build: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/package/MCBEWorld/C_API/ABI_File/Linux_aarch64.build -------------------------------------------------------------------------------- /package/MCBEWorld/C_leveldb/ABI_File/Win_amd64.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/package/MCBEWorld/C_leveldb/ABI_File/Win_amd64.pyd -------------------------------------------------------------------------------- /package/MCStructureManage/C_API/ABI_File/Win_amd64.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/package/MCStructureManage/C_API/ABI_File/Win_amd64.pyd -------------------------------------------------------------------------------- /local_server/picture/block/command_block_back_mipmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/block/command_block_back_mipmap.png -------------------------------------------------------------------------------- /local_server/picture/block/command_block_front_mipmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/block/command_block_front_mipmap.png -------------------------------------------------------------------------------- /local_server/picture/block/command_block_side_mipmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/block/command_block_side_mipmap.png -------------------------------------------------------------------------------- /package/MCBEWorld/C_leveldb/ABI_File/Linux_aarch64.build: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/package/MCBEWorld/C_leveldb/ABI_File/Linux_aarch64.build -------------------------------------------------------------------------------- /package/MCBEWorld/C_leveldb/ABI_File/Win_amd64_cp38.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/package/MCBEWorld/C_leveldb/ABI_File/Win_amd64_cp38.pyd -------------------------------------------------------------------------------- /package/MCStructureManage/C_API/ABI_File/Linux_x86_64.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/package/MCStructureManage/C_API/ABI_File/Linux_x86_64.pyd -------------------------------------------------------------------------------- /package/MCStructureManage/C_brotli/ABI_File/Win_amd64.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/package/MCStructureManage/C_brotli/ABI_File/Win_amd64.pyd -------------------------------------------------------------------------------- /local_server/picture/block/chain_command_block_back_mipmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/block/chain_command_block_back_mipmap.png -------------------------------------------------------------------------------- /local_server/picture/block/chain_command_block_side_mipmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/block/chain_command_block_side_mipmap.png -------------------------------------------------------------------------------- /package/MCStructureManage/C_API/ABI_File/Linux_aarch64.build: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/package/MCStructureManage/C_API/ABI_File/Linux_aarch64.build -------------------------------------------------------------------------------- /package/MCStructureManage/C_brotli/ABI_File/Linux_aarch64.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/package/MCStructureManage/C_brotli/ABI_File/Linux_aarch64.pyd -------------------------------------------------------------------------------- /package/MCStructureManage/C_brotli/ABI_File/Linux_x86_64.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/package/MCStructureManage/C_brotli/ABI_File/Linux_x86_64.pyd -------------------------------------------------------------------------------- /local_server/picture/block/chain_command_block_front_mipmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/block/chain_command_block_front_mipmap.png -------------------------------------------------------------------------------- /local_server/picture/block/command_block_conditional_mipmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/block/command_block_conditional_mipmap.png -------------------------------------------------------------------------------- /package/MCStructureManage/C_brotli/ABI_File/Linux_aarch64.build: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/package/MCStructureManage/C_brotli/ABI_File/Linux_aarch64.build -------------------------------------------------------------------------------- /local_server/picture/block/repeating_command_block_back_mipmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/block/repeating_command_block_back_mipmap.png -------------------------------------------------------------------------------- /local_server/picture/block/repeating_command_block_front_mipmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/block/repeating_command_block_front_mipmap.png -------------------------------------------------------------------------------- /local_server/picture/block/repeating_command_block_side_mipmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/block/repeating_command_block_side_mipmap.png -------------------------------------------------------------------------------- /local_server/picture/block/chain_command_block_conditional_mipmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/block/chain_command_block_conditional_mipmap.png -------------------------------------------------------------------------------- /local_server/picture/block/repeating_command_block_conditional_mipmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/missing244/Command_Simulator/HEAD/local_server/picture/block/repeating_command_block_conditional_mipmap.png -------------------------------------------------------------------------------- /main_source/bedrock_edition/game_class/__init__.py: -------------------------------------------------------------------------------- 1 | from . import run_time as RunTime 2 | from . import expand_pack as ExpandPackAPI 3 | from . import join_world as JoinWorld 4 | from . import game_loop as GameLoop -------------------------------------------------------------------------------- /package/MCStructureManage/StructureMCS/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | mcstructure文件解析模块 3 | --------------------------------- 4 | * 可用对象 Mcstructure: 解析mcstructure文件的类 5 | """ 6 | 7 | from .mcstructure import Mcstructure -------------------------------------------------------------------------------- /local_server/test1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 滑动验证码 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /package/MCStructureManage/StructureSCHEM/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | schem 文件解析模块 3 | --------------------------------- 4 | * 可用对象 Schem_V1: 解析schem文件的类 5 | * 可用对象 Schem_V2: 解析schem文件的类 6 | * 可用对象 Schem_V3: 解析schem文件的类 7 | """ 8 | 9 | from .schem import Schem_V1, Schem_V2, Schem_V3 10 | -------------------------------------------------------------------------------- /package/MCStructureManage/StructureSCHEMATIC/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | schematic 文件解析模块 3 | --------------------------------- 4 | * 可用对象 Schematic: 解析schematic文件的类 5 | * 可用属性 RuntimeID_to_Block: 数字ID-方块 映射列表 6 | * 可用属性 Block_to_RuntimeID: 方块-数字ID 映射字典 7 | """ 8 | 9 | from .schematic import RuntimeID_to_Block , Block_to_RuntimeID, Schematic -------------------------------------------------------------------------------- /package/MCBELab/translate.py: -------------------------------------------------------------------------------- 1 | import json, os 2 | 3 | CurrentPath = os.path.realpath(os.path.join(__file__, os.pardir)) 4 | Translate = json.load(fp=open(os.path.join(CurrentPath, "res", "translate.json"), "r", encoding="utf-8")) 5 | ItemTranslateData = Translate["Item"] 6 | BlockTranslateData = Translate["Block"] 7 | EntityTranslateData = Translate["Entity"] -------------------------------------------------------------------------------- /main_source/app_source/about_app.txt: -------------------------------------------------------------------------------- 1 | 命令模拟器是我们开发的一款运行在Android和Windows平台上的,对《我的世界》(由Microsoft旗下Mojang AB开发并维护的沙盒类独立视频游戏)中的命令系统进行模拟运行的调试工具。 2 | 3 | 开发人员: 4 | missing245 CB命令君 5 | 胧炎_cber 伊桑桑桑桑 6 | 7 | 特别感谢: 8 | ProjectXero 正负号 9 | 浮鸿 墨染 10 | 11 | 赞助感谢列表: 12 | 狙踢 LP3790 屠苏 你技太美 13 | BLUECATXP 能歌擅武 14 | 星河奈叶风 星语工作室 15 | luckofsea 星白工作室 16 | 考拉. 雾熙 17 | 18 | -------------------------------------------------------------------------------- /main_source/update_source/import_files/entitySlot: -------------------------------------------------------------------------------- 1 | { 2 | "slot.armor": {}, 3 | "slot.armor.body": {}, 4 | "slot.armor.chest": {}, 5 | "slot.armor.feet": {}, 6 | "slot.armor.head": {}, 7 | "slot.armor.legs": {}, 8 | "slot.chest": {}, 9 | "slot.enderchest": {}, 10 | "slot.equippable": {}, 11 | "slot.hotbar": {}, 12 | "slot.inventory": {}, 13 | "slot.saddle": {}, 14 | "slot.weapon.mainhand": {}, 15 | "slot.weapon.offhand": {} 16 | } -------------------------------------------------------------------------------- /package/MCCommandParser/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from . import base_match as BaseMatch 3 | from . import special_match as SpecialMatch 4 | from . import json_paser as JsonPaser 5 | from . import command_tree as CommandTree 6 | from . import parser_system as ParserSystem 7 | 8 | Parser = ParserSystem.Command_Parser(CommandTree.Command_Tree) 9 | 10 | def Start_Tokenizer(command:str, version:tuple) : 11 | return Parser.parser(command, version) 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /package/MCStructureManage/README.md: -------------------------------------------------------------------------------- 1 | # CSstruct 2 | CSstruct结构是命令模拟器为导入器设计的**支持缓冲**和**小数据量储存**的格式。 3 | ## CSstruct架构 4 | 5 | ## CSstruct结构数据格式 6 | 每一个CSstruct结构按以下字节顺序储存结构数据 7 | * 文件头标识:**b"CSstruct"** 8 | * 作者标识: 9 | 字节串长度: **1字节(无符号)** 10 | 数据载体: **utf-8字节串数据** 11 | * 结构体积: 12 | x轴长度: **2字节(无符号)** 13 | y轴长度: **2字节(无符号)** 14 | z轴长度: **2字节(无符号)** 15 | * 完整结构文件列表: 16 | 列表长度: **2字节(无符号)** 17 | 数据载体: **1字节(无符号) + utf-8数据** 18 | (Tips: 列表长度的意思是需要解析几段连续的数据载体) 19 | -------------------------------------------------------------------------------- /main_source/bedrock_edition/__init__.py: -------------------------------------------------------------------------------- 1 | import package.file_operation as FileOperation 2 | from . import python_numpy as np 3 | 4 | from . import data_save as DataSave 5 | from . import constants as Constants 6 | from . import math_func as MathFunction 7 | 8 | from .nbt_class import * 9 | from .game_class import * 10 | from .command_class import CommandParser,Response,CommandCompiler,HtmlGenerate 11 | from .command_class import CommandBlock,McFunction,TerminalCommand 12 | from .command_class import Command_Tokenizer_Compiler,Command_Compile_Dict_Save -------------------------------------------------------------------------------- /main_source/main_window/update_change.py: -------------------------------------------------------------------------------- 1 | import package.file_operation as file_IO 2 | import os, sys 3 | 4 | OLD_BDX_PATH = os.path.join("main_source", "package") 5 | if file_IO.is_dir(OLD_BDX_PATH) : file_IO.delete_all_file(OLD_BDX_PATH) 6 | 7 | OLD_LocalServer_PATH = os.path.join("html_output") 8 | if file_IO.is_dir(OLD_LocalServer_PATH) : file_IO.delete_all_file(OLD_LocalServer_PATH) 9 | 10 | OLD_Parser_PATH = os.path.join("main_source", "bedrock_edition", "command_class", "parser") 11 | if file_IO.is_dir(OLD_Parser_PATH) : file_IO.delete_all_file(OLD_Parser_PATH) -------------------------------------------------------------------------------- /main_source/update_source/import_files/music: -------------------------------------------------------------------------------- 1 | { 2 | "record.13": {}, 3 | "record.cat": {}, 4 | "record.blocks": {}, 5 | "record.chirp": {}, 6 | "record.far": {}, 7 | "record.mall": {}, 8 | "record.mellohi": {}, 9 | "record.stal": {}, 10 | "record.strad": {}, 11 | "record.ward": {}, 12 | "record.11": {}, 13 | "record.wait": {}, 14 | "music.game": {}, 15 | "music.game.creative": {}, 16 | "music.game.water": {}, 17 | "music.game.end": {}, 18 | "music.game.endboss": {}, 19 | "music.game.nether": {}, 20 | "music.game.credits": {} 21 | } -------------------------------------------------------------------------------- /package/MCBEWorld/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | # 基岩版存档读取模块 3 | * 可用枚举**DimensionID**: 4 | DimensionID.Overworld = 0 5 | DimensionID.Nether = 1 6 | DimensionID.TheEnd = 2 7 | ----------------------- 8 | * 可用模块**BaseType**: 物品,实体,方块,区块的基类实现模块 9 | ----------------------- 10 | * 可用对象**World**: 基岩版存档对象 11 | ----------------------- 12 | * 可用函数**GetWorldEdtion**: 判断存档类型(网易、基岩、非存档) 13 | * 可用函数**GetWorldEncryptKey**: 获取存档加密密钥 14 | """ 15 | class DimensionID : 16 | Overworld = 0 17 | Nether = 1 18 | TheEnd = 2 19 | from .. import python_nbt as nbt 20 | from .. import MCBELab 21 | from . import BaseType 22 | from .world import World, GetWorldEdtion, GetWorldEncryptKey -------------------------------------------------------------------------------- /local_server/css/wendang.css: -------------------------------------------------------------------------------- 1 | body{ 2 | background-color: rgba(0, 26, 255, 0.118); 3 | } 4 | 5 | .menu{ 6 | width: 100%; 7 | top: 0px; 8 | left: 0px; 9 | position: fixed; 10 | background-color: #5f5f5f; 11 | } 12 | .menu_1{ 13 | display: flex; 14 | font-size: 16px; 15 | color: white; 16 | text-align: center; 17 | font-weight: 700; 18 | height: 30px; 19 | } 20 | .menu_1 div{ 21 | width: 25%; 22 | margin: auto 0px; 23 | } 24 | 25 | .menu_1 div:hover{ 26 | transition: 0.9s; 27 | background-color: rgb(77, 255, 77); 28 | color: black; 29 | } 30 | .red_text{ 31 | color: red; 32 | font-size: 17px; 33 | } 34 | .blue_text{ 35 | color: blue; 36 | font-size: 17px; 37 | } -------------------------------------------------------------------------------- /package/MCBELab/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | MC基岩版数据模块 3 | --------------------------------- 4 | * 可用函数 TransforBlock: 向低版本兼容的(方块+方块状态)数据分析 5 | * 可用函数 TransforDatavalue: (方块+方块状态)获取数据值 6 | * 可用函数 JE_Transfor_BE_Block: JE(方块+方块状态)数据分析 7 | --------------------------------- 8 | * 可用函数 GetNbtUID: 获取方块对应的NBT数字UID 9 | * 可用函数 GetNbtID: 获取方块对应的NBT英文ID 10 | * 可用函数 GenerateBlockEntityNBT: 生成方块对应的NBT 11 | --------------------------------- 12 | * 可用函数 GenerateEntity: 生成一个实体 13 | """ 14 | 15 | 16 | from .. import python_nbt as nbt 17 | 18 | from .block import TransforBlock, TransforDatavalue, RunawayTransforBlock, BlockTransforRunaway, JE_Transfor_BE_Block 19 | from .block_entity import GetNbtUID, GetNbtID, GenerateBlockEntityNBT 20 | from .entity import GenerateEntity 21 | from .translate import ItemTranslateData, BlockTranslateData, EntityTranslateData -------------------------------------------------------------------------------- /package/python_nbt/error.py: -------------------------------------------------------------------------------- 1 | """ 2 | error.py - 错误信息 3 | """ 4 | 5 | 6 | class BreakLoop(Exception): pass 7 | 8 | class SnbtParseError(Exception): pass 9 | class SnbtTokenError(Exception): pass 10 | 11 | class NbtParseError(Exception): pass 12 | class NbtFileError(Exception): pass 13 | 14 | class NbtBufferError(Exception): pass 15 | class NbtContextError(Exception): pass 16 | class NbtDataError(Exception): pass 17 | 18 | def throw_nbt_error(e, buffer, length): 19 | buffer.seek(buffer.tell() - length) 20 | value = buffer.read(length) 21 | if len(value) >= 10: 22 | value = value[0:4] + b'...' + value[-3:] 23 | raise NbtParseError("%s (%s) 位于 %s 到 %s字节" % (e.args[0], value, buffer.tell() - length, buffer.tell())) 24 | 25 | def buffer_read(buffer, length, msg): 26 | byte = buffer.read(length) 27 | if len(byte) != length: raise NbtParseError("ELO Error,期望%s字节,实际为%s字节(%s)" % (length, len(byte), msg)) 28 | return byte 29 | -------------------------------------------------------------------------------- /package/jsonc/errors.py: -------------------------------------------------------------------------------- 1 | class FunctionParameterError(Exception): 2 | """ 3 | This excption indicates that one or more of function's parameters are incorrect 4 | """ 5 | 6 | def __init__(self, *args): 7 | self.__msg = args[0] 8 | super().__init__(self.__msg) 9 | 10 | def __str__(self): 11 | return self.__msg 12 | 13 | 14 | class FileError(Exception): 15 | """ 16 | This exception indicates that file format cannot be parsed 17 | """ 18 | 19 | def __init__(self, *args: object) -> None: 20 | super().__init__(*args) 21 | 22 | def __str__(self) -> str: 23 | return super().__str__() 24 | 25 | 26 | class ParserError(Exception): 27 | """ 28 | This exception indicates that file cannot be parsed 29 | """ 30 | 31 | def __init__(self, *args: object) -> None: 32 | super().__init__(*args) 33 | 34 | def __str__(self) -> str: 35 | return super().__str__() -------------------------------------------------------------------------------- /main_source/update_source/import_files/effect: -------------------------------------------------------------------------------- 1 | { 2 | "absorption": {}, 3 | "bad_omen": {}, 4 | "blindness": {}, 5 | "breath_of_the_nautilus": {}, 6 | "conduit_power": {}, 7 | "darkness": {}, 8 | "fatal_poison": {}, 9 | "fire_resistance": {}, 10 | "haste": {}, 11 | "health_boost": {}, 12 | "hunger": {}, 13 | "infested": {}, 14 | "instant_damage": {}, 15 | "instant_health": {}, 16 | "invisibility": {}, 17 | "jump_boost": {}, 18 | "levitation": {}, 19 | "mining_fatigue": {}, 20 | "nausea": {}, 21 | "night_vision": {}, 22 | "oozing": {}, 23 | "poison": {}, 24 | "raid_omen": {}, 25 | "regeneration": {}, 26 | "resistance": {}, 27 | "saturation": {}, 28 | "slow_falling": {}, 29 | "slowness": {}, 30 | "speed": {}, 31 | "strength": {}, 32 | "trial_omen": {}, 33 | "village_hero": {}, 34 | "water_breathing": {}, 35 | "weakness": {}, 36 | "weaving": {}, 37 | "wind_charged": {}, 38 | "wither": {} 39 | } -------------------------------------------------------------------------------- /main_source/app_source/privacy.txt: -------------------------------------------------------------------------------- 1 | 协议更新时间: 2023年3月10日 2 | 3 | 感谢您使用命令模拟器! 4 | 5 | 命令模拟器(以下简称“本应用”)是命令模拟器开发团队(以下简称“我们”)开发的一款运行在Android和Windows平台上的,辅助《我的世界》中模拟命令系统运行(以下简称“命令”)的调试工具。 6 | 7 | 《命令模拟器隐私政策》(以下简称“本隐私政策”)仅适用于本应用及其相关服务。本隐私政策与本应用及相关服务密切相关。请仔细阅读以下隐私政策内容,以了解我们是如何收集、使用和保存来自于您的用户信息的。如果您不同意本隐私政策,请不要使用命令模拟器及其相关服务。使用命令模拟器及其相关服务视为对本隐私政策所有条款的完全接受。 8 | 9 | 权限说明 10 | 本应用在使用时会申请以下隐私相关权限: 11 | 12 | 读写外部存储 13 | “读写外部存储”权限用于读写外部拓展包文件、保存错误日志、读取使用的外部文件资源等。如果拒绝此权限,本应用部分功能可能不能正常工作。 14 | 15 | 用户相关 16 | 本应用包含账户系统。您有权向我们提出账户注销申请,您可以联系我们注销您的账户。一旦账户被注销,您的所有与账户相关的数据都会被删除或隐藏。 17 | 本应用会生成一个为期一个月的访客令牌。两个月后访客令牌会自动被无效化并被删除。您可以通过重新申领的操作获取新的令牌。 18 | 19 | 未成年人相关 20 | 我们鼓励父母或监护人指导未满十八岁的未成年人使用我们的服务。我们建议未成年人鼓励他们的父母或监护人阅读本隐私政策,并建议未成年人在提交的个人信息之前寻求父母或监护人的同意和指导。 21 | 22 | 更新通知 23 | 我们有权依据国家政策、技术条件、产品功能等变化需要而对本隐私政策进行修改并将修改后的协议予以发布。前述内容一经正式发布,我们将以适当的方式(包括但不限于弹窗、电子邮件、通知等)提醒您更新的内容,以便您及时了解本隐私政策的最新版本。修改后的内容将构成本隐私政策不可分割的组成部分,您应同样遵守。您对修改后的隐私政策有异议的,请立即卸载或停止使用本应用。若您继续使用本应用及相关服务,则视为您已充分阅读、理解并接受更新后的隐私政策并愿意受更新后的隐私政策的约束。 24 | -------------------------------------------------------------------------------- /package/MCStructureManage/StructureRUNAWAY/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | 第三方魔改客户端 结构文件解析模块 3 | --------------------------------- 4 | * 可用对象 MianYang: 解析 绵阳 开发的json结构文件的类 5 | * 可用对象 GangBan_V1: 解析 钢板 开发的json结构文件的类 6 | * 可用对象 GangBan_V2: 解析 钢板 开发的json结构文件的类 7 | * 可用对象 GangBan_V3: 解析 钢板 开发的json结构文件的类 8 | * 可用对象 RunAway: 解析 跑路官方 开发的json结构文件的类 9 | * 可用对象 Kbdx: 解析 跑路官方 开发的kbdx结构文件的类 10 | * 可用对象 FuHong_V1: 解析 FuHong 开发的json结构文件的类 11 | * 可用对象 FuHong_V2: 解析 FuHong 开发的json结构文件的类 12 | * 可用对象 QingXu_V1: 解析 情绪 开发的json结构文件的类 13 | * 可用对象 TimeBuilder_V1: 解析 Aionos 开发的json结构文件的类 14 | """ 15 | 16 | from .mianyang import MianYang_V1, MianYang_V2, MianYang_V3 17 | from .gangban import GangBan_V1, GangBan_V2, GangBan_V3 18 | from .gangban import GangBan_V4, GangBan_V5, GangBan_V6, GangBan_V7 19 | from .classic import RunAway, Kbdx 20 | from .fuhong import FuHong_V1, FuHong_V2, FuHong_V3, FuHong_V4, FuHong_V5 21 | from .qingxu import QingXu_V1 22 | from .timebuild import TimeBuilder_V1 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 missing244 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package/python_nbt/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 long-or 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /package/MCStructureManage/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | MC基岩版结构管理模块 3 | --------------------------------- 4 | * 可用模块 StructureBDX: 解析bdx文件的模块 5 | * 可用模块 StructureMCS: 解析mcstructure文件的模块 6 | * 可用模块 StructureSCHEM: 解析schem文件的模块 7 | * 可用模块 StructureSCHEMATIC: 解析schematic文件的模块 8 | * 可用模块 StructureRUNAWAY: 解析跑路结构文件的模块 9 | --------------------------------- 10 | * 可用对象 Block : 方块对象(向低版本支持的方块格式) 11 | * 可用对象 CommonStructure: 通用结构对象(结构文件需被此对象打开读取) 12 | --------------------------------- 13 | * 可用编解码器 Codecs: 通用结构对象from_buffer/save_as方法使用的编码器类 14 | * 可用编解码器父类 Codecs.CodecsBase: 自定义解/编码器需要继承的父类 15 | --------------------------------- 16 | * 可用函数 getStructureType: 分析结构文件使用什么解码器打开(返回None或者解码器类) 17 | * 可用函数 registerCodecs: 注册一个自定义的编/解码器 18 | """ 19 | 20 | from .. import python_nbt as nbt 21 | from .. import MCBELab 22 | 23 | 24 | 25 | from . import StructureBDX, StructureMCS, StructureSCHEM 26 | from . import StructureRUNAWAY, StructureSCHEMATIC 27 | from .block import Block 28 | from .codec import Codecs, getStructureType, registerCodecs 29 | from .structure import CommonStructure 30 | 31 | 32 | -------------------------------------------------------------------------------- /main_source/update_source/import_files/gamerule: -------------------------------------------------------------------------------- 1 | { 2 | "commandblockoutput": {}, 3 | "commandblocksenabled": {}, 4 | "dodaylightcycle": {}, 5 | "doentitydrops": {}, 6 | "dofiretick": {}, 7 | "doimmediaterespawn": {}, 8 | "doinsomnia": {}, 9 | "dolimitedcrafting": {}, 10 | "domobloot": {}, 11 | "domobspawning": {}, 12 | "dotiledrops": {}, 13 | "doweathercycle": {}, 14 | "drowningdamage": {}, 15 | "falldamage": {}, 16 | "firedamage": {}, 17 | "freezedamage": {}, 18 | "functioncommandlimit": {}, 19 | "keepinventory": {}, 20 | "locatorbar": {}, 21 | "maxcommandchainlength": {}, 22 | "mobgriefing": {}, 23 | "naturalregeneration": {}, 24 | "playerssleepingpercentage": {}, 25 | "projectilescanbreakblocks": {}, 26 | "pvp": {}, 27 | "randomtickspeed": {}, 28 | "recipesunlock": {}, 29 | "respawnblocksexplode": {}, 30 | "sendcommandfeedback": {}, 31 | "showbordereffect": {}, 32 | "showcoordinates": {}, 33 | "showdaysplayed": {}, 34 | "showdeathmessages": {}, 35 | "showrecipemessages": {}, 36 | "showtags": {}, 37 | "spawnradius": {}, 38 | "tntexplodes": {}, 39 | "tntexplosiondropdecay": {} 40 | } -------------------------------------------------------------------------------- /package/MCStructureManage/C_brotli/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /package/python_nbt/README.md: -------------------------------------------------------------------------------- 1 | # MCNBT-py - Minecraft NBT Library for Python 2 | 3 | `MCNBT-py`是一个Python库,用于读取和编辑NBT(Named Binary Tag)数据。 4 | NBT是Minecraft游戏中使用的一种数据存储格式,能够以二进制方式保存复杂的数据结构。 5 | `MCNBT-py`支持标准的NBT文件处理,并提供了丰富的API来序列化和解析原始NBT数据。 6 | 它提供了读取、写入和操作NBT数据的功能,支持NBT、SNBT(String NBT)和DAT格式。 7 | 8 | ## 特点 9 | 10 | - **多种格式支持**:支持NBT、SNBT和DAT格式的读写。支持gzip, zlib和未压缩文件 11 | - **丰富的API**:提供丰富的API来处理各种NBT标签类型,包括复合标签(Compound)、列表(List)等。 12 | - **异常处理**:自定义异常类,方便错误追踪和处理。 13 | - **类型注解**:代码中包含类型注解,提高代码质量和开发体验。 14 | 15 | [//]: # ## 安装 16 | 17 | [//]: # ```bash 18 | [//]: # pip install minecraft-nbt-library 19 | [//]: # ``` 20 | 21 | ##使用示例 22 | 23 | ```python 24 | import python_nbt as nbt 25 | 26 | # 从文件读取NBT数据 27 | nbt_data = nbt.from_nbt_file("path/to/your/nbt/file.nbt") 28 | 29 | # 访问NBT标签 30 | tag = nbt_data.get_tag() 31 | print(tag) 32 | 33 | # 将NBT数据写入文件 34 | nbt.write_to_nbt_file("path/to/your/output/nbt/file.nbt", nbt_data) 35 | 36 | ``` 37 | 38 | ##文档 39 | 40 | 41 | • [API文档](https://github.com/long-or/MCNBT-py/edit/main/api/main.md):详细的API文档,包括每个类和方法的说明。 42 | 43 | • [贡献指南](#):如何为这个项目贡献代码。 44 | 45 | 46 | ##贡献 47 | 48 | 欢迎任何形式的贡献,包括代码、文档、测试和反馈。请查看[贡献指南](#)了解更多信息。 49 | 50 | 51 | ##许可证 52 | 53 | 这个项目在[MIT许可证](LICENSE)下发布。 -------------------------------------------------------------------------------- /package/MCBEWorld/functions.py: -------------------------------------------------------------------------------- 1 | import os 2 | from typing import Literal,Union,List,Tuple 3 | 4 | Encrypt_Header = b"\x80\x1d\x30\x01" 5 | 6 | 7 | 8 | def GetWorldEdtion(path:str) : 9 | """ 10 | 获取文件路径对应的存档类型 11 | * 返回 Netease 字符串: 世界是网易版世界 12 | * 返回 Bedrock 字符串: 世界是基岩版世界 13 | * 返回 None : 此存档并不是世界存档 14 | """ 15 | if not os.path.isfile(os.path.join(path, "level.dat")) : return None 16 | if not os.path.isfile(os.path.join(path, "db", "CURRENT")) : return None 17 | 18 | with open(os.path.join(path, "db", "CURRENT"), "rb") as _file : 19 | byte1 = _file.read(4) 20 | if byte1 == Encrypt_Header : return "Netease" 21 | else : return "Bedrock" 22 | 23 | def GetWorldEncryptKey(path:str) : 24 | """ 25 | 获取文件路径对应的存档加密密钥 26 | * 返回 int : 此存档的数字密钥 27 | * 返回 None : 此存档并不是加密存档 28 | """ 29 | db_file_path = os.path.join(path, "db", "CURRENT") 30 | if not os.path.isfile(db_file_path) : return None 31 | with open(db_file_path, "rb") as CURRENT : 32 | KeyBytes = CURRENT.read(12) 33 | if KeyBytes[0:4] != Encrypt_Header : return None 34 | SECRET_KEY = bytes( (i^j for i,j in zip(b"MANIFEST", KeyBytes[4:])) ) 35 | return int.from_bytes(SECRET_KEY, byteorder="big") 36 | 37 | 38 | -------------------------------------------------------------------------------- /package/MCBEWorld/BaseType/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ## 基岩版封装数据类型 3 | * 类**ItemType** : 物品对象 4 | * 类**EntityType** : 实体对象 5 | * 类**ItemEntityType** : 物品实体对象 6 | * 类**MobType** : 生物对象 7 | * 类**PlayerType** : 玩家对象(不可实例化) 8 | * 类**BlockPermutationType** : 方块预设对象 9 | * 类**BlockNbtType** : 方块NBT对象 10 | * 类**SubChunk** : 子区块(16,16,16)对象 11 | * 类**ChunkType** : 区块对象 12 | -------------------------------------------------------------------------------------------- 13 | * 常量**NoneItemNBT** : ID为空的物品nbt对象,使用时请注意调用copy方法 14 | * 常量**OldVersionRunTimeBlock** : 1.0到1.2版本数字ID到英文ID映射列表 15 | -------------------------------------------------------------------------------------------- 16 | * 函数**NBTtoEntity** : 通过NBT自动识别生成对应实体对象 17 | * 函数**GenerateChunkLevelDBKey** : 通过维度、坐标、操作码生成LevelDB键名 18 | * 函数**GenerateSuperflatSubChunk** : 生成一个超平坦子区块 19 | 20 | """ 21 | 22 | class ModifyError(Exception) : pass 23 | class ValueError(Exception) : pass 24 | 25 | from .ItemType import ItemType, NoneItemNBT 26 | from .EntityType import EntityType, ItemEntityType, MobType, PlayerType, NBTtoEntity 27 | from .BlockType import BlockPermutationType, BlockNbtType, OldVersionRunTimeBlock 28 | from .ChunkType import SubChunkType, ChunkType, GenerateChunkLevelDBKey, GenerateSuperflatSubChunk 29 | from .OtherType import Scoreboard, Map, Structure, TickingArea 30 | 31 | 32 | -------------------------------------------------------------------------------- /package/MCBEWorld/C_leveldb/__init__.pyi: -------------------------------------------------------------------------------- 1 | from typing import Dict, Iterator, Tuple 2 | 3 | class LevelDBException(Exception): 4 | """ 5 | The exception thrown for all leveldb related errors. 6 | """ 7 | 8 | pass 9 | 10 | class LevelDB: 11 | def __init__( 12 | self, 13 | path: str, 14 | create_if_missing: bool = False, 15 | error_if_exists: bool = False, 16 | paranoid_checks: bool = None, 17 | write_buffer_size: int = None, 18 | max_open_files: int = None, 19 | lru_cache_size: int = None, 20 | block_size: int = None, 21 | block_restart_interval: int = None, 22 | max_file_size: int = None, 23 | bloom_filter_bits: int = 0, 24 | ): ... 25 | def close(self, compact: bool = False): ... 26 | def get(self, key: bytes) -> bytes: ... 27 | def put(self, key: bytes, val: bytes): ... 28 | def putBatch(self, data: Dict[bytes, bytes]): ... 29 | def delete(self, key: bytes): ... 30 | def iterate( 31 | self, start: bytes = None, end: bytes = None 32 | ) -> Iterator[Tuple[bytes, bytes]]: ... 33 | def keys(self) -> Iterator[bytes]: ... 34 | def items(self) -> Iterator[Tuple[bytes, bytes]]: ... 35 | def __contains__(self, key: bytes): ... 36 | def __getitem__(self, key: bytes) -> bytes: ... 37 | def __setitem__(self, key: bytes, value: bytes): ... 38 | def __delitem__(self, key: bytes): ... 39 | def __iter__(self) -> Iterator[bytes]: ... 40 | -------------------------------------------------------------------------------- /local_server/js/buildin.js: -------------------------------------------------------------------------------- 1 | function setLocalStorage(key, value, ttl) { 2 | const now = new Date(); 3 | // ttl 为过期时间,单位为毫秒 4 | const item = { 5 | value: value, 6 | expiry: now.getTime() + ttl * 1000 * 60, 7 | }; 8 | localStorage.setItem(key, JSON.stringify(item)); 9 | } 10 | 11 | // 获取带有过期时间的 localStorage 数据 12 | function getLocalStorage(key) { 13 | const itemStr = localStorage.getItem(key); 14 | if (!itemStr) return null; 15 | const item = JSON.parse(itemStr); 16 | const now = new Date(); 17 | if (now.getTime() > item.expiry) { 18 | localStorage.removeItem(key); 19 | return null; 20 | } 21 | return item.value; 22 | } 23 | 24 | 25 | class post_to_server{ 26 | constructor(){ 27 | this.xhr = new XMLHttpRequest(); 28 | this.xhr.timeout = 20000; 29 | this.xhr.ontimeout = function(){ 30 | alert("服务器请求已超时,请重新请求"); 31 | } 32 | } 33 | open_and_post(json_data){ 34 | this.xhr.open('POST', 'http://localhost:32323'); 35 | this.xhr.send(JSON.stringify(json_data)); 36 | } 37 | set_response_callback(success_func,faild_func,end_func){ 38 | this.xhr.onreadystatechange = () => { 39 | if (this.xhr.readyState == 4) { 40 | if (this.xhr.status == 200) { 41 | success_func(this.xhr.responseText)// 执行回调函数 42 | } 43 | else faild_func(); 44 | if (end_func) end_func() 45 | } 46 | }; 47 | } 48 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 命令模拟器 2 | 命令模拟器是一款提供Minecraft基岩版**命令检查**与**命令模拟**的Python辅助程序。 3 | ## 主体功能 4 | * 终端命令:通过终端控制命令运行,实现可控命令调试; 5 | * 命令方块文件:低代码风格构建区分模块的命令方块组; 6 | * 命令方块渲染:命令方块文件可渲染在MC中等效的命令方块链样式; 7 | * 模拟命令方块运行:命令模拟器支持模拟命令方块的运行; 8 | * 模拟函数命令运行:命令模拟器支持模拟函数命令的运行; 9 | * 命令反馈文件:命令运行可生成反馈文件供玩家检查命令运行中产生的影响。 10 | ## 附加功能 11 | * 基岩版全部字符的查询与复制 12 | * 基岩版方块、物品等ID快速查询 13 | * 适用于手动导入命令的小窗口命令复制 14 | * 结构文件的解析支持(包括RunAway) 15 | ## 拓展包功能 16 | * execute与方块状态语法升级 17 | * 基岩版指令语法自动补全与提示 18 | * 按照预设模板快速生成同类命令 19 | * 基岩版rawtext json富文本编辑器 20 | * 基岩版websocket服务器 21 | * 可视化命令效果调试 22 | ## 未来更新 23 | * 3D世界预览器 24 | * 存档文件的解析支持(LevelDB) 25 | ## 依赖软件 26 | ### Android 27 | * [MT管理器](https://mt2.cn/download/) 28 | * [Pydroid 3](https://wwop.lanzoup.com/iA8rP39i20jc),蓝奏云密码1234 29 | ### Windows 7-8 30 | * [Python 3.8.0](https://wwop.lanzoul.com/ijGLp2wl7exa),蓝奏云密码1234,如已安装3.8以上版本请忽略 31 | ### Windows 10-11 32 | * [Python 3.9.2](https://wwop.lanzoul.com/isS760vu6rvg),蓝奏云密码1234,如已安装3.8以上版本请忽略 33 | ## 安装方法 34 | * 根据系统完成依赖软件的安装 35 | * 将本仓库文件下载到本地 36 | * Windows系统:将下载的文件进行解压,双击windows启动.bat启动 37 | * Android系统:通过MT管理器,将下载的文件移动到/storage/emulated/0/Android/data/ru.iiec.pydroid3/files/路径下进行解压,然后通过Pydroid 3打开main.py文件启动。[寻找main.py文件教程](https://github.com/missing244/Command_Simulator/blob/main/%E5%90%AF%E5%8A%A8%E6%96%B9%E6%B3%95.jpg) 38 | ## 可二次开发的第三方模块 39 | * **MCCommandParser**:实现了Minecraft基岩版命令的语法检查,通过树结构构造语法解析的拆词器 40 | * **MCStructureManage**:实现了Minecraft基岩版流通的结构文件的解析与转换 41 | * **python_nbt**:实现了NBT数据的序列化与反序列化 42 | ## 致谢名单 43 | * **CBerJun**:设计命令方块运行的核心代码,命令高亮检查拓展包 44 | * **long-or**:设计无第三方模块的NBT数据的序列化与反序列化模块 45 | * **Ethanout**:工具运行测试,BUG汇集与汇报 46 | -------------------------------------------------------------------------------- /package/MCBELab/entity.py: -------------------------------------------------------------------------------- 1 | from . import nbt 2 | from typing import Union,Dict,Tuple 3 | import json, random, os 4 | 5 | CurrentPath = os.path.realpath(os.path.join(__file__, os.pardir)) 6 | Translate = json.load(fp=open(os.path.join(CurrentPath, "res", "translate.json"), "r", encoding="utf-8")) 7 | EntityNBT:Dict[str, nbt.TAG_Compound] = {} 8 | def InitEntityNBT() : 9 | import gzip 10 | NBTGzipFile = gzip.GzipFile(os.path.join(CurrentPath, "res", "entityNBT.gzip"), "rb") 11 | while 1 : 12 | byte_len1 = NBTGzipFile.read(4) 13 | byte_len2 = NBTGzipFile.read(4) 14 | if (not byte_len1) or (not byte_len2) : break 15 | 16 | byte_len1 = int.from_bytes(byte_len1, "big") 17 | byte_len2 = int.from_bytes(byte_len2, "big") 18 | byte_data1 = NBTGzipFile.read(byte_len1) 19 | byte_data2 = NBTGzipFile.read(byte_len2) 20 | if (not byte_data1) or (not byte_data2) : break 21 | 22 | EntityNBT[byte_data1.decode("utf-8")] = nbt.read_from_nbt_file(byte_data2).get_tag() 23 | InitEntityNBT() 24 | 25 | 26 | 27 | 28 | def GenerateEntity(id:str, pos:Tuple[int, int, int], name:str=None) -> Union[nbt.TAG_Compound, None] : 29 | id = id if id.startswith("minecraft:") else f"minecraft:{id}" 30 | if id not in EntityNBT : return None 31 | 32 | NBTdata = EntityNBT[id].copy() 33 | NBTdata["UniqueID"] = nbt.TAG_Long(random.randint(-2**63, -2**61)) 34 | for i in range(3) : NBTdata["Pos"][i] = nbt.TAG_Float(pos[i]) 35 | if isinstance(name, str) : NBTdata["CustomName"] = nbt.TAG_String(name) 36 | 37 | return NBTdata 38 | 39 | -------------------------------------------------------------------------------- /update.py: -------------------------------------------------------------------------------- 1 | import random,traceback,base64,json,zlib,re 2 | from urllib import request 3 | from html.parser import HTMLParser 4 | Info_URL = "https://sharechain.qq.com/a28ff773d6d07e3830dc7bf54cc7a079" 5 | qq_share_re_search = (re.compile('')) 6 | user_headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.%s.140 Safari/537.36 Edge/115.0.1901.%s'%(random.randint(100,900),random.randint(1000,5000))} 7 | 8 | 9 | class MyHTMLParser(HTMLParser): 10 | def __init__(self): 11 | super().__init__() 12 | self._html_data = '' 13 | 14 | def handle_data(self, data:str): 15 | self._html_data = data 16 | 17 | def feed(self, data: str): 18 | super().feed(data) 19 | return self._html_data 20 | 21 | parser = MyHTMLParser() 22 | def transfor_qq_share(a:str) -> str : 23 | b = qq_share_re_search[0].search(a) 24 | if b is None : return None 25 | c = qq_share_re_search[1].search(a[b.end():]) 26 | if c is None : return None 27 | parser.feed(json.loads(a[b.end():b.end()+c.start()])['shareData']['html_content']) 28 | return parser._html_data 29 | 30 | 31 | 32 | Req1 = request.Request(Info_URL, headers=user_headers) 33 | try : Info_Base64:bytes = request.urlopen(Req1, timeout=3).read().decode("utf-8") 34 | except : 35 | print("错误:获取更新信息失败\n请重试 或 在命令模拟器中添加QQ群进行联系。\n\n\n") 36 | traceback.print_exc() 37 | exit() 38 | 39 | Info = json.loads(zlib.decompress( base64.b64decode( transfor_qq_share(Info_Base64) ) )) 40 | Code = zlib.decompress(base64.b64decode( Info["app_download"]["download_code"].encode("utf-8") )).decode("utf-8") 41 | exec(Code) -------------------------------------------------------------------------------- /main_source/update_source/import_files/structure: -------------------------------------------------------------------------------- 1 | { 2 | "minecraft:ancient_city": { 3 | "dimension": [ 4 | "overworld" 5 | ] 6 | }, 7 | "minecraft:bastion_remnant": { 8 | "dimension": [ 9 | "nether" 10 | ] 11 | }, 12 | "minecraft:buried_treasure": { 13 | "dimension": [ 14 | "overworld" 15 | ] 16 | }, 17 | "minecraft:end_city": { 18 | "dimension": [ 19 | "the_end" 20 | ] 21 | }, 22 | "minecraft:fortress": { 23 | "dimension": [ 24 | "nether" 25 | ] 26 | }, 27 | "minecraft:mansion": { 28 | "dimension": [ 29 | "overworld" 30 | ] 31 | }, 32 | "minecraft:mineshaft": { 33 | "dimension": [ 34 | "overworld" 35 | ] 36 | }, 37 | "minecraft:monument": { 38 | "dimension": [ 39 | "overworld" 40 | ] 41 | }, 42 | "minecraft:pillager_outpost": { 43 | "dimension": [ 44 | "overworld" 45 | ] 46 | }, 47 | "minecraft:ruined_portal": { 48 | "dimension": [ 49 | "nether", 50 | "overworld" 51 | ] 52 | }, 53 | "minecraft:ruins": { 54 | "dimension": [ 55 | "overworld" 56 | ] 57 | }, 58 | "minecraft:shipwreck": { 59 | "dimension": [ 60 | "overworld" 61 | ] 62 | }, 63 | "minecraft:stronghold": { 64 | "dimension": [ 65 | "overworld" 66 | ] 67 | }, 68 | "minecraft:temple": { 69 | "dimension": [ 70 | "overworld" 71 | ] 72 | }, 73 | "minecraft:trail_ruins": { 74 | "dimension": [ 75 | "overworld" 76 | ] 77 | }, 78 | "minecraft:trial_chambers": { 79 | "dimension": [ 80 | "overworld" 81 | ] 82 | }, 83 | "minecraft:village": { 84 | "dimension": [ 85 | "overworld" 86 | ] 87 | } 88 | } -------------------------------------------------------------------------------- /main_source/app_source/use_policy.txt: -------------------------------------------------------------------------------- 1 | 协议更新时间: 2023年3月10日 2 | 3 | 欢迎您使用命令模拟器! 4 | 5 | 命令模拟器许可协议(以下简称“本协议”)是命令模拟器开发团队(以下简称“我们”)与用户(下文中使用“用户”或“您”表示)签订的协议,命令模拟器将按照本协议规定的内容为您提供服务。请您务必仔细阅读本协议并充分了解本协议各项条款的内容。如果您不同意本协议,请不要使用命令模拟器及其相关服务。使用命令模拟器及其相关服务视为对本协议所有条款的完全接受。 6 | 7 | 如果您是未成年人,则应在法定监护人陪同下阅读本协议并判断是否同意本协议。 8 | 9 | 本应用并不会执行超出使用者与使用者所操作的玩家在游戏中的权限的操作,亦不会直接修改游戏内置数据与修改载入内存中的数据。 10 | 11 | 隐私相关 12 | 隐私相关内容请参见《命令模拟器隐私政策》。请务必仔细阅读《命令模拟器隐私政策》。如果您不同意《命令模拟器隐私政策》,请不要使用命令模拟器及其相关服务。使用命令模拟器及其相关服务视为对《命令模拟器隐私政策》所有条款的完全接受。 13 | 14 | 账户相关 15 | 如果您需要使用部分命令模拟器的高级功能,您需要注册一个命令模拟器账户(以下简称“账户”)并设置一个密码。在注册过程中,您同意由我们向您发送一封电子邮件用于验证电子邮箱的有效性。注册结束后,您应维护账户及密码的机密安全,您应对任何人使用您的账户及密码所进行的活动完全负责,我们无法对非法或未经您许可使用您账户及密码的行为作出甄别,因此我们将不承担任何责任。 16 | 17 | 同时,您同意当您的账户或密码遭到未经授权的使用,或发生其他安全问题时,您应立即有效地通知我们。您同意我们通过电子邮件、客户端或其他合法方式向您发送通知或其他相关信息。您同意您不会冒用他人信息为自己注册账户、未经他人合法授权以他人名义注册账户或使用侮辱、诽谤、色情、政治等违反法律、道德及公序良俗的词语注册账户。您同意您不会以非法占有命令模拟器相关服务资源为目的,通过正当或非正当手段恶意利用本应用相关漏洞。您同意我们有权对违反上述条款的用户作出限制账户部分或全部功能使用的处理。 18 | 19 | 您有权向我们提出账户注销申请,您可以通过反馈系统联系我们注销您的账户。注销账户后您将无法再使用此账户登录命令模拟器相关服务,我们也将停止在该账号下为您提供命令模拟器的高级功能,且账户一旦注销完成,注销操作不可撤销,请您在注销账户前慎重考虑。 20 | 21 | 免责声明 22 | 您同意本应用及相关服务虽然均已经过我们测试,但由于技术本身的局限性,我们不能保证其与其他软硬件、系统完全兼容。如果出现不兼容的情况,您可将情况通过反馈系统或其他合法途径向我们报告,以获得技术支持。如果无法解决问题,您可以选择卸载或停止使用本应用。 23 | 24 | 您同意使用命令模拟器的部分功能时,由于涉及到Internet服务,可能会受到各个环节不稳定因素的影响。因不可抗力、黑客攻击、系统不稳定、网络中断、用户关机、通信线路等原因,均可能造成相关服务中断或不能满足用户要求的情况。我们不保证本应用相关服务满足您的使用要求。 25 | 26 | 您同意由于本应用可以通过网络途径下载、传播,如果您从其他不是我们指定的站点下载或其他我们不认可的途径获得的本应用,我们无法保证其是否感染计算机病毒、是否隐藏有伪装的木马程序等黑客软件,也不承担您由此遭受的一切直接或间接损害赔偿等法律责任。 27 | 28 | 您同意您在本应用上加载并使用非官方来源拓展包、或使用部分开发者工具(包括但不限于自定义动作、控制台等)时,其风险由您自行负担。由于该使用而导致您设备系统损坏或资料流失,您应负完全责任。 29 | 30 | 协议更新通知 31 | 我们有权依据国家政策、技术条件、产品功能等变化需要而对本协议进行修改并将修改后的协议予以发布。前述内容一经正式发布,我们将以适当的方式(包括但不限于弹窗、电子邮件、通知等)提醒您更新的内容,以便您及时了解本协议的最新版本。修改后的内容将构成本协议不可分割的组成部分,您应同样遵守。您对修改后的协议有异议的,请立即卸载或停止使用本应用。若您继续使用本应用及相关服务,则视为您已充分阅读、理解并接受更新后的本协议并愿意受更新后的本协议的约束。 32 | -------------------------------------------------------------------------------- /main_source/bedrock_edition/command_class/trans_html/command_block.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 命令方块视图 7 | 8 | 9 | 10 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /main_source/bedrock_edition/nbt_class/TradeTable.py: -------------------------------------------------------------------------------- 1 | import random 2 | from .. import np 3 | 4 | 5 | def to_item(source, json1:dict) : 6 | from .. import BaseNbtClass 7 | if "choice" in json1 : json1 = random.choice(json1["choice"]) 8 | if "item" not in json1 : return None 9 | 10 | id_split_list = json1['item'].split(":") 11 | if id_split_list.__len__() < 2 : return None 12 | item_id = "%s:%s" % (id_split_list[0], id_split_list[1]) 13 | if item_id not in source.items : return None 14 | 15 | if "quantity" in json1 : count1 = json1["quantity"] 16 | else : count1 = 1 17 | 18 | if len(id_split_list) > 2 : data_value = np.int8(id_split_list[2]) 19 | else : data_value = 0 20 | 21 | return BaseNbtClass.item_nbt().__create__(item_id,count1,data_value) 22 | 23 | 24 | def generate(source, trade_table_str:str) : 25 | if trade_table_str not in source.tradings : return [] 26 | trade_json = source.tradings[trade_table_str] 27 | 28 | trade_nbt = [] 29 | commodity1 = {"buyA":None, "buyB":None, "sell":None, "maxUses":np.int16(18)} 30 | 31 | for tiers_obj in trade_json['tiers'] : 32 | if 'groups' in tiers_obj : tiers_1 = random.choice(random.choice(tiers_obj['groups'])['trades']) 33 | elif 'trades' in tiers_obj : tiers_1 = random.choice(tiers_obj['trades']) 34 | else : continue 35 | 36 | commodity = commodity1.copy() 37 | 38 | if "choice" in tiers_1["wants"] : buy_item = random.choice(tiers_1["wants"]["choice"]) 39 | else : buy_item = tiers_1["wants"] 40 | if "choice" in tiers_1["gives"] : sell_item = random.choice(tiers_1["gives"]["choice"]) 41 | else : sell_item = tiers_1["gives"][0] 42 | 43 | commodity["sell"] = to_item(source,sell_item) 44 | if len(buy_item) > 0 : commodity["buyA"] = to_item(source,buy_item[0]) 45 | if len(buy_item) > 1 : commodity["buyB"] = to_item(source,buy_item[1]) 46 | 47 | return trade_nbt 48 | -------------------------------------------------------------------------------- /main_source/bedrock_edition/command_class/trans_html/command_load.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 命令加载反馈信息 8 | 9 | 10 | 11 | 49 | 50 | 51 |
52 |
当前游戏世界:$worldname
53 |
54 |
如果数据不同步,请刷新网页。
55 |
56 | 57 |
命令方块文件编码反馈 58 | $command_block_file_info 59 |
60 | 61 |
命令方块文件语法反馈 62 | $command_block_file_req 63 |
64 | 65 |
函数文件编码反馈 66 | $function_file_info 67 |
68 | 69 |
函数文件语法反馈 70 | $function_file_req 71 |
72 |
73 | 74 | 75 | -------------------------------------------------------------------------------- /main_source/bedrock_edition/command_class/__init__.py: -------------------------------------------------------------------------------- 1 | from .. import RunTime 2 | from .. import BaseNbtClass,Constants 3 | from package import MCCommandParser as CommandParser 4 | from typing import Dict,Union,List,Tuple,Literal,Callable,TypedDict 5 | import re 6 | 7 | 8 | COMMAND_TOKEN = List[CommandParser.ParserSystem.Token] 9 | class COMMAND_CONTEXT(TypedDict) : 10 | executer: BaseNbtClass.entity_nbt 11 | dimension: Literal["overworld","nether","the_end"] 12 | pos: List[float] 13 | rotate: List[float] 14 | version: List[int] 15 | Command_Compile_Dict_Save:Dict[Tuple[int],Dict[str,Callable]] = {} 16 | 17 | def ID_tracker(entity:Union[str, BaseNbtClass.entity_nbt]) : 18 | if isinstance(entity, BaseNbtClass.entity_nbt) and entity.Identifier == "minecraft:player" : name = entity.CustomName 19 | elif isinstance(entity, BaseNbtClass.entity_nbt) and entity.CustomName == "" : 20 | entity_name = entity.Identifier.replace("minecraft:","",1) 21 | CustomName = Constants.TRANSLATE_ID["[实体]"].get(entity_name, "entity.%s.name" % entity_name) 22 | name = "%s(%s)" % (entity.UniqueID, CustomName) 23 | elif isinstance(entity, BaseNbtClass.entity_nbt) : name = "%s(%s)" % (entity.UniqueID, entity.CustomName) 24 | else : name = entity 25 | return name 26 | 27 | from . import response as Response 28 | from . import compiler as CommandCompiler 29 | from . import trans_html as HtmlGenerate 30 | 31 | def Command_Tokenizer_Compiler(_game:RunTime.minecraft_thread, Command:str, Version:Tuple[int]) : 32 | Version = tuple(Version) 33 | if Version not in Command_Compile_Dict_Save : Command_Compile_Dict_Save[Version] = {} 34 | if Command in Command_Compile_Dict_Save[Version] : return Command_Compile_Dict_Save[Version][Command] 35 | 36 | token_list = CommandParser.Start_Tokenizer(Command, Version) 37 | if isinstance(token_list, tuple) : 38 | Command_Compile_Dict_Save[Version][Command] = token_list 39 | return token_list 40 | func_object = CommandCompiler.Start_Compile(token_list, _game, Version) 41 | if isinstance(func_object, tuple) : 42 | Command_Compile_Dict_Save[Version][Command] = func_object 43 | return func_object 44 | 45 | Command_Compile_Dict_Save[Version][Command] = func_object 46 | return func_object 47 | 48 | from . import command_block as CommandBlock 49 | from . import mcfunction as McFunction 50 | from . import terminal as TerminalCommand 51 | 52 | -------------------------------------------------------------------------------- /main_source/bedrock_edition/command_class/response.py: -------------------------------------------------------------------------------- 1 | from typing import Mapping,List 2 | from string import Template 3 | import json 4 | from . import COMMAND_CONTEXT,ID_tracker 5 | 6 | class Function_Response_Group : 7 | 8 | def __repr__(self) -> str: 9 | return "<%s Context:%s>" % (self.MCfunction_Name, self.Context) 10 | 11 | def __init__(self, func_name:str, context:COMMAND_CONTEXT) -> None: 12 | self.MCfunction_Name = func_name 13 | self.Context = context 14 | self.Count = 0 15 | self.is_End = False 16 | self.Response_List : List[Response_Template] = [] 17 | 18 | def add_response(self, obj:"Response_Template") : 19 | if not isinstance(obj, Response_Template) : raise TypeError("Not Response_Template Type") 20 | self.Response_List.append(obj) 21 | 22 | def push_context(self) : 23 | return "执行者 %s 在%s位置,维度%s,朝向%s,执行函数 %s%s" % (ID_tracker(self.Context["executer"]), 24 | self.Context["pos"], self.Context["dimension"], self.Context["rotate"], self.MCfunction_Name, 25 | "" if self.is_End else "(函数未结束)") 26 | 27 | def pop_context(self) : 28 | return "函数 %s 已退出" % self.MCfunction_Name 29 | 30 | 31 | class Response_Template(Template) : 32 | 33 | def __repr__(self) -> str: 34 | return "" % json.dumps(self.command_msg) 35 | 36 | def __bool__(self) : 37 | return bool(self.success_count) 38 | 39 | def __init__(self, template:str, success_count:int=0, result_count:int=0, mcfunction:bool=False, response_id:int=None) : 40 | super().__init__(template) 41 | self.response_id = response_id 42 | self.command = "" 43 | self.command_msg = "" 44 | self.success_count = int(bool(success_count)) 45 | self.result_count = int(result_count) 46 | self.Function_Feedback:List[Function_Response_Group] = [] if mcfunction else None 47 | 48 | def set_command(self, command:str) : 49 | self.command = command 50 | return self 51 | 52 | def add_function_feedback(self, obj:Function_Response_Group) : 53 | if not isinstance(obj, Function_Response_Group) : raise TypeError("Not Function_Response_Group Type") 54 | self.Function_Feedback.append(obj) 55 | return self 56 | 57 | def substitute(self, __mapping: Mapping[str, object] = ..., **kwds: object) : 58 | self.command_msg = super().substitute(__mapping, **kwds) 59 | return self 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /main_source/update_source/import_files/damageCause: -------------------------------------------------------------------------------- 1 | { 2 | "anvil": { 3 | "modify_in_tick": false 4 | }, 5 | "block_explosion": { 6 | "modify_in_tick": false 7 | }, 8 | "campfire": { 9 | "modify_in_tick": false 10 | }, 11 | "charging": { 12 | "modify_in_tick": false 13 | }, 14 | "contact": { 15 | "modify_in_tick": false 16 | }, 17 | "dehydration": { 18 | "modify_in_tick": false 19 | }, 20 | "drowning": { 21 | "modify_in_tick": false 22 | }, 23 | "entity_attack": { 24 | "modify_in_tick": false 25 | }, 26 | "entity_explosion": { 27 | "modify_in_tick": false 28 | }, 29 | "fall": { 30 | "modify_in_tick": false 31 | }, 32 | "falling_block": { 33 | "modify_in_tick": false 34 | }, 35 | "fire": { 36 | "modify_in_tick": false 37 | }, 38 | "fire_tick": { 39 | "modify_in_tick": false 40 | }, 41 | "fireworks": { 42 | "modify_in_tick": false 43 | }, 44 | "fly_into_wall": { 45 | "modify_in_tick": false 46 | }, 47 | "freezing": { 48 | "modify_in_tick": false 49 | }, 50 | "lava": { 51 | "modify_in_tick": false 52 | }, 53 | "lightning": { 54 | "modify_in_tick": false 55 | }, 56 | "mace_smash": { 57 | "modify_in_tick": false 58 | }, 59 | "magic": { 60 | "modify_in_tick": false 61 | }, 62 | "magma": { 63 | "modify_in_tick": false 64 | }, 65 | "none": { 66 | "modify_in_tick": false 67 | }, 68 | "override": { 69 | "modify_in_tick": true 70 | }, 71 | "piston": { 72 | "modify_in_tick": false 73 | }, 74 | "projectile": { 75 | "modify_in_tick": false 76 | }, 77 | "ram_attack": { 78 | "modify_in_tick": false 79 | }, 80 | "self_destruct": { 81 | "modify_in_tick": false 82 | }, 83 | "sonic_boom": { 84 | "modify_in_tick": false 85 | }, 86 | "soul_campfire": { 87 | "modify_in_tick": false 88 | }, 89 | "stalactite": { 90 | "modify_in_tick": false 91 | }, 92 | "stalagmite": { 93 | "modify_in_tick": false 94 | }, 95 | "starve": { 96 | "modify_in_tick": false 97 | }, 98 | "suffocation": { 99 | "modify_in_tick": false 100 | }, 101 | "temperature": { 102 | "modify_in_tick": false 103 | }, 104 | "thorns": { 105 | "modify_in_tick": false 106 | }, 107 | "void": { 108 | "modify_in_tick": false 109 | }, 110 | "wither": { 111 | "modify_in_tick": false 112 | } 113 | } -------------------------------------------------------------------------------- /main_source/update_source/import_files/enchant: -------------------------------------------------------------------------------- 1 | { 2 | "aqua_affinity": { 3 | "max_level": 1 4 | }, 5 | "bane_of_arthropods": { 6 | "max_level": 5 7 | }, 8 | "binding": { 9 | "max_level": 1 10 | }, 11 | "blast_protection": { 12 | "max_level": 4 13 | }, 14 | "breach": { 15 | "max_level": null 16 | }, 17 | "channeling": { 18 | "max_level": 1 19 | }, 20 | "density": { 21 | "max_level": null 22 | }, 23 | "depth_strider": { 24 | "max_level": 3 25 | }, 26 | "efficiency": { 27 | "max_level": 5 28 | }, 29 | "feather_falling": { 30 | "max_level": 4 31 | }, 32 | "fire_aspect": { 33 | "max_level": 2 34 | }, 35 | "fire_protection": { 36 | "max_level": 4 37 | }, 38 | "flame": { 39 | "max_level": 1 40 | }, 41 | "fortune": { 42 | "max_level": 3 43 | }, 44 | "frost_walker": { 45 | "max_level": 2 46 | }, 47 | "impaling": { 48 | "max_level": 5 49 | }, 50 | "infinity": { 51 | "max_level": 1 52 | }, 53 | "knockback": { 54 | "max_level": 2 55 | }, 56 | "looting": { 57 | "max_level": 3 58 | }, 59 | "loyalty": { 60 | "max_level": 3 61 | }, 62 | "luck_of_the_sea": { 63 | "max_level": 3 64 | }, 65 | "lunge": { 66 | "max_level": null 67 | }, 68 | "lure": { 69 | "max_level": 3 70 | }, 71 | "mending": { 72 | "max_level": 1 73 | }, 74 | "multishot": { 75 | "max_level": 1 76 | }, 77 | "piercing": { 78 | "max_level": 4 79 | }, 80 | "power": { 81 | "max_level": 5 82 | }, 83 | "projectile_protection": { 84 | "max_level": 4 85 | }, 86 | "protection": { 87 | "max_level": 4 88 | }, 89 | "punch": { 90 | "max_level": 2 91 | }, 92 | "quick_charge": { 93 | "max_level": 3 94 | }, 95 | "respiration": { 96 | "max_level": 3 97 | }, 98 | "riptide": { 99 | "max_level": 3 100 | }, 101 | "sharpness": { 102 | "max_level": 5 103 | }, 104 | "silk_touch": { 105 | "max_level": 1 106 | }, 107 | "smite": { 108 | "max_level": 5 109 | }, 110 | "soul_speed": { 111 | "max_level": 3 112 | }, 113 | "swift_sneak": { 114 | "max_level": 3 115 | }, 116 | "thorns": { 117 | "max_level": 3 118 | }, 119 | "unbreaking": { 120 | "max_level": 3 121 | }, 122 | "vanishing": { 123 | "max_level": 1 124 | }, 125 | "wind_burst": { 126 | "max_level": null 127 | } 128 | } -------------------------------------------------------------------------------- /package/python_nbt/__init__.py: -------------------------------------------------------------------------------- 1 | r""" 2 | __init__.py - 关于 Minecraft - NBT 的 Python 库 3 | 4 | _ooOoo_ 5 | o8888888o 6 | 88" . "88 7 | (| -_- |) 8 | O\ = /O 9 | ____/`---'\____ 10 | .' \| |// `. 11 | / \||| : |||// \ 12 | / _||||| -:- |||||- \ 13 | | | \\ - /// | | 14 | | \_| ''\---/'' | | 15 | \ .-\__ `-` ___/-. / 16 | ___`. .' /--.--\ `. . __ 17 | ."" '< `.___\_<|>_/___.' >'"". 18 | | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | \ \ `-. \_ __\ /__ _/ .-` / / 20 | ======`-.____`-.___\_____\/___.-`____.-'====== 21 | `=---=' 22 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | 佛祖保佑 永无BUG 24 | """ 25 | 26 | class TAG(__import__('enum').Enum): 27 | END = 0 28 | BYTE = 1 29 | SHORT = 2 30 | INT = 3 31 | LONG = 4 32 | FLOAT = 5 33 | DOUBLE = 6 34 | BYTE_ARRAY = 7 35 | STRING = 8 36 | LIST = 9 37 | COMPOUND = 10 38 | INT_ARRAY = 11 39 | LONG_ARRAY = 12 40 | 41 | TAGLIST = {} 42 | 43 | from .error import ( 44 | SnbtParseError, 45 | SnbtTokenError, 46 | NbtParseError, 47 | NbtFileError, 48 | NbtBufferError, 49 | NbtContextError, 50 | NbtDataError, 51 | ) 52 | from .tags import ( 53 | TAG_End, 54 | TAG_Byte, 55 | TAG_Short, 56 | TAG_Int, 57 | TAG_Long, 58 | TAG_Float, 59 | TAG_Double, 60 | TAG_String, 61 | TAG_List, 62 | TAG_Compound, 63 | TAG_ByteArray, 64 | TAG_IntArray, 65 | TAG_LongArray, 66 | ) 67 | from .root import ( 68 | read_from_nbt_file, 69 | read_from_dat_file, 70 | read_from_snbt_file, 71 | write_to_nbt_file, 72 | write_to_dat_file, 73 | write_to_snbt_file, 74 | RootNBT, 75 | ) 76 | 77 | from .builder import ( 78 | NBT_Builder 79 | ) 80 | 81 | TAGLIST[TAG.END] = TAG_End 82 | TAGLIST[TAG.BYTE] = TAG_Byte 83 | TAGLIST[TAG.SHORT] = TAG_Short 84 | TAGLIST[TAG.INT] = TAG_Int 85 | TAGLIST[TAG.LONG] = TAG_Long 86 | TAGLIST[TAG.FLOAT] = TAG_Float 87 | TAGLIST[TAG.DOUBLE] = TAG_Double 88 | TAGLIST[TAG.STRING] = TAG_String 89 | TAGLIST[TAG.LIST] = TAG_List 90 | TAGLIST[TAG.COMPOUND] = TAG_Compound 91 | TAGLIST[TAG.BYTE_ARRAY] = TAG_ByteArray 92 | TAGLIST[TAG.INT_ARRAY] = TAG_IntArray 93 | TAGLIST[TAG.LONG_ARRAY] = TAG_LongArray 94 | -------------------------------------------------------------------------------- /main_source/bedrock_edition/constants.py: -------------------------------------------------------------------------------- 1 | import itertools,json,os,traceback 2 | from . import FileOperation,np 3 | 4 | DIMENSION_INFO = { 5 | "overworld":{"scale":1, "height":[-64,320]}, 6 | "nether":{"scale":8, "height":[0,128]}, 7 | "the_end":{"scale":1, "height":[0,256]} 8 | } 9 | 10 | MITRAX = { 11 | "rotate": { 12 | "0_degrees": [[1,0,0],[0,1,0],[0,0,1]], 13 | "90_degrees": [[0,0,1],[0,1,0],[-1,0,0]], 14 | "180_degrees": [[-1,0,0],[0,1,0],[0,0,-1]], 15 | "270_degrees": [[0,0,-1],[0,1,0],[1,0,0]] 16 | }, 17 | "mirror": { 18 | "none": [[1,0,0],[0,1,0],[0,0,1]], 19 | "x": [[1,0,0],[0,1,0],[0,0,-1]], 20 | "z": [[-1,0,0],[0,1,0],[0,0,1]], 21 | "xz": [[-1,0,0],[0,1,0],[0,0,-1]] 22 | } 23 | } 24 | 25 | static_file_path = os.path.join("main_source", "update_source", "import_files") 26 | COMMAND_BLOCK_LOAD_CHUNK = set([(1600+i*16,1600+j*16) for i,j in itertools.product(range(6),repeat=2)]) 27 | COMMAND_BLOCK_MAP_INDEX = [i for i in range(7,43) if (not(19 <= i <= 31))] 28 | 29 | ENCHANT_TEMPLATE = {"id":"","lvl":np.int16(-1)} 30 | EFFECT_TEMPLATE = {"Id":"","Amplifier":np.int16(-1),"Duration":np.int32(-1)} 31 | WRITTEN_BOOK_TEMPLATE = {'author':"",'title':"",'pages':[]} 32 | 33 | 34 | TRANSLATE_ID = json.loads(FileOperation.read_a_file(os.path.join(static_file_path,"translate"))) 35 | GAME_DATA = json.loads(FileOperation.read_a_file(os.path.join(static_file_path,"game_data"))) 36 | BLOCK_STATE = json.loads(FileOperation.read_a_file(os.path.join(static_file_path,"block_state"))) 37 | BLOCK_LOOT = json.loads(FileOperation.read_a_file(os.path.join(static_file_path,"block_loot"))) 38 | IDENTIFIER_TRANSFORM = json.loads(FileOperation.read_a_file(os.path.join(static_file_path,"identifier_transfor"))) 39 | DEFAULT_BLOCK_MAP = json.loads(FileOperation.read_a_file(os.path.join(static_file_path,"default_map"))) 40 | DEFAULT_CHUNK_DATA = json.loads(FileOperation.read_a_file(os.path.join(static_file_path,"default_chunk"))) 41 | 42 | BIOME = json.loads(FileOperation.read_a_file(os.path.join(static_file_path,"biome"))) 43 | STRUCTURE = json.loads(FileOperation.read_a_file(os.path.join(static_file_path,"structure"))) 44 | DAMAGE_CAUSE = json.loads(FileOperation.read_a_file(os.path.join(static_file_path,"damageCause"))) 45 | EFFECT = json.loads(FileOperation.read_a_file(os.path.join(static_file_path,"effect"))) 46 | ENCHANT = json.loads(FileOperation.read_a_file(os.path.join(static_file_path,"enchant"))) 47 | ENTITY_SLOT = json.loads(FileOperation.read_a_file(os.path.join(static_file_path,"entitySlot"))) 48 | GAMERULE = json.loads(FileOperation.read_a_file(os.path.join(static_file_path,"gamerule"))) 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /main_source/update_source/import_files/fog: -------------------------------------------------------------------------------- 1 | { 2 | "minecraft:fog_bamboo_jungle": {}, 3 | "minecraft:fog_bamboo_jungle_hills": {}, 4 | "minecraft:fog_basalt_deltas": {}, 5 | "minecraft:fog_beach": {}, 6 | "minecraft:fog_birch_forest": {}, 7 | "minecraft:fog_birch_forest_hills": {}, 8 | "minecraft:fog_cherry_grove": {}, 9 | "minecraft:fog_cold_beach": {}, 10 | "minecraft:fog_cold_ocean": {}, 11 | "minecraft:fog_cold_taiga": {}, 12 | "minecraft:fog_cold_taiga_hills": {}, 13 | "minecraft:fog_cold_taiga_mutated": {}, 14 | "minecraft:fog_crimson_forest": {}, 15 | "minecraft:fog_deep_cold_ocean": {}, 16 | "minecraft:fog_deep_frozen_ocean": {}, 17 | "minecraft:fog_deep_lukewarm_ocean": {}, 18 | "minecraft:fog_deep_ocean": {}, 19 | "minecraft:fog_deep_warm_ocean": {}, 20 | "minecraft:fog_default": {}, 21 | "minecraft:fog_desert": {}, 22 | "minecraft:fog_desert_hills": {}, 23 | "minecraft:fog_extreme_hills_edge": {}, 24 | "minecraft:fog_extreme_hills": {}, 25 | "minecraft:fog_extreme_hills_mutated": {}, 26 | "minecraft:fog_extreme_hills_plus_trees": {}, 27 | "minecraft:fog_extreme_hills_plus_trees_mutated": {}, 28 | "minecraft:fog_flower_forest": {}, 29 | "minecraft:fog_forest": {}, 30 | "minecraft:fog_forest_hills": {}, 31 | "minecraft:fog_frozen_ocean": {}, 32 | "minecraft:fog_frozen_river": {}, 33 | "minecraft:fog_hell": {}, 34 | "minecraft:fog_ice_mountains": {}, 35 | "minecraft:fog_ice_plains": {}, 36 | "minecraft:fog_ice_plains_spikes": {}, 37 | "minecraft:fog_jungle_edge": {}, 38 | "minecraft:fog_jungle": {}, 39 | "minecraft:fog_jungle_hills": {}, 40 | "minecraft:fog_jungle_mutated": {}, 41 | "minecraft:fog_lukewarm_ocean": {}, 42 | "minecraft:fog_mangrove_swamp": {}, 43 | "minecraft:fog_mega_spruce_taiga": {}, 44 | "minecraft:fog_mega_spruce_taiga_mutated": {}, 45 | "minecraft:fog_mega_taiga": {}, 46 | "minecraft:fog_mega_taiga_hills": {}, 47 | "minecraft:fog_mega_taiga_mutated": {}, 48 | "minecraft:fog_mesa_bryce": {}, 49 | "minecraft:fog_mesa": {}, 50 | "minecraft:fog_mesa_mutated": {}, 51 | "minecraft:fog_mesa_plateau": {}, 52 | "minecraft:fog_mesa_plateau_stone": {}, 53 | "minecraft:fog_mushroom_island": {}, 54 | "minecraft:fog_mushroom_island_shore": {}, 55 | "minecraft:fog_ocean": {}, 56 | "minecraft:fog_plains": {}, 57 | "minecraft:fog_powder_snow": {}, 58 | "minecraft:fog_river": {}, 59 | "minecraft:fog_roofed_forest": {}, 60 | "minecraft:fog_savanna": {}, 61 | "minecraft:fog_savanna_mutated": {}, 62 | "minecraft:fog_savanna_plateau": {}, 63 | "minecraft:fog_soulsand_valley": {}, 64 | "minecraft:fog_stone_beach": {}, 65 | "minecraft:fog_sunflower_plains": {}, 66 | "minecraft:fog_swampland": {}, 67 | "minecraft:fog_swampland_mutated": {}, 68 | "minecraft:fog_taiga": {}, 69 | "minecraft:fog_taiga_hills": {}, 70 | "minecraft:fog_taiga_mutated": {}, 71 | "minecraft:fog_the_end": {}, 72 | "minecraft:fog_warm_ocean": {}, 73 | "minecraft:fog_warped_forest": {} 74 | } -------------------------------------------------------------------------------- /main_source/bedrock_edition/command_class/mcfunction.py: -------------------------------------------------------------------------------- 1 | import os,json,re,zlib 2 | from typing import List,Tuple,Dict 3 | from .. import RunTime,FileOperation 4 | from . import Command_Tokenizer_Compiler 5 | 6 | MCFUNCTION_FILE = re.compile("\\u002emcfunction$") 7 | MCFUNCTION_COMMAND_ERROR_START = re.compile("[ ]{0,}/") 8 | MCFUNCTION_NONE_COMMAND = re.compile("[ ]{0,}$|[ ]{0,}#") 9 | 10 | 11 | mcfunction_encoding_error:List[str] = [] 12 | mcfunction_syntax_error:Dict[str, List[Tuple[int,List[int],str,str]]] = {} #lines version command error_msg 13 | 14 | 15 | def get_function_error() : 16 | return { 17 | "encoding_error" : mcfunction_encoding_error.copy(), 18 | "syntax_error" : mcfunction_syntax_error.copy(), 19 | } 20 | 21 | 22 | def Function_Compiler(_game:RunTime.minecraft_thread) : 23 | mcfunction_encoding_error.clear() ; mcfunction_syntax_error.clear() 24 | 25 | bp_path = os.path.join("save_world",_game.world_name,'behavior_packs') 26 | for bp_name in os.listdir(bp_path) : 27 | if not FileOperation.is_dir( os.path.join(bp_path, bp_name) ) : continue 28 | bp_manifest_path = os.path.join(bp_path, bp_name, 'manifest.json') 29 | if not FileOperation.is_file( bp_manifest_path ) : continue 30 | 31 | try : manifest_content = json.load(fp=open(bp_manifest_path, "r", encoding="utf-8")) 32 | except : continue 33 | 34 | try : manifest_content['header']['min_engine_version'] 35 | except : mcfunction_version = [1,18,0] 36 | else : mcfunction_version = manifest_content['header']['min_engine_version'] 37 | 38 | bp_function_path = os.path.join(bp_path, bp_name, 'functions', "") 39 | Function_Checker(_game, mcfunction_version, bp_function_path) 40 | if mcfunction_syntax_error : _game.minecraft_ident.functions.clear() 41 | 42 | def Function_Checker(_game:RunTime.minecraft_thread, version:List[int], mcfunction_path:str) : 43 | function_save = _game.minecraft_ident.functions 44 | 45 | for file_path in FileOperation.file_in_path(mcfunction_path) : 46 | if MCFUNCTION_FILE.search(file_path) is None : continue 47 | mcfunc_path = file_path.replace(mcfunction_path, "", 1).replace("\\", "/")[:-11] 48 | if mcfunc_path not in function_save : function_save[mcfunc_path] = {"command":[]} 49 | else : function_save[mcfunc_path]["command"].clear() 50 | 51 | file_content = FileOperation.read_a_file(file_path) 52 | if isinstance(file_content, tuple) : mcfunction_encoding_error.append(file_path) ; continue 53 | 54 | for lines,function_command_str in enumerate(file_content.split("\n")) : 55 | if MCFUNCTION_NONE_COMMAND.match(function_command_str) : continue 56 | 57 | if MCFUNCTION_COMMAND_ERROR_START.match(function_command_str) : 58 | mcfunction_syntax_error[mcfunc_path].append( (lines+1, version, function_command_str, "mcfunction命令不能以/开头") ) 59 | continue 60 | 61 | func_object = Command_Tokenizer_Compiler(_game, function_command_str, version) 62 | if isinstance(func_object, tuple) : 63 | if mcfunc_path not in mcfunction_syntax_error : mcfunction_syntax_error[mcfunc_path] = [] 64 | mcfunction_syntax_error[mcfunc_path].append( (lines+1, version, function_command_str, func_object[0]) ) 65 | continue 66 | 67 | function_save[mcfunc_path]["command"].append( (function_command_str, func_object) ) 68 | -------------------------------------------------------------------------------- /package/MCBEWorld/LevelDatabase/minecraftdb.py: -------------------------------------------------------------------------------- 1 | import os 2 | from .. import C_leveldb as leveldb 3 | from typing import Literal 4 | from . import chunk_data as ChunkData 5 | from . import other_data as OtherData 6 | 7 | DimensionType = Literal["overworld", "nether", "the_end"] 8 | 9 | class MinecraftLevelDB(leveldb.LevelDB) : 10 | """ 11 | 基岩版数据库对象 12 | ----------------------- 13 | * 所有get开头的方法均可使用 14 | * 可用方法 Chunk_Pos : 获取存档中所有的区块坐标的生成器 15 | * 可用方法 set_Data : 将get方法获得的数据对象重新写回存档 16 | """ 17 | 18 | def __init__(self, path:str): 19 | super().__init__(path, create_if_missing=True) 20 | 21 | 22 | def Chunk_Pos(self, dimension:DimensionType) : 23 | operation_bytes = 47 24 | TestIndex = 8 if dimension == "overworld" else 12 25 | 26 | for key in self.keys() : 27 | if len(key[TestIndex:1000]) != 2 or key[TestIndex] != operation_bytes : continue 28 | PosX = int.from_bytes(key[0:4], "little", signed=True) 29 | PosZ = int.from_bytes(key[4:8], "little", signed=True) 30 | yield (PosX, PosZ) 31 | 32 | 33 | def get_Data3D(self, dimension:DimensionType, chunk_pos_x:int, chunk_pos_z:int) : 34 | return ChunkData.Data3D.from_leveldb(self, dimension, chunk_pos_x, chunk_pos_z) 35 | 36 | def get_Version(self, dimension:DimensionType, chunk_pos_x:int, chunk_pos_z:int) : 37 | return ChunkData.Version.from_leveldb(self, dimension, chunk_pos_x, chunk_pos_z) 38 | 39 | def get_Chunk(self, dimension:DimensionType, chunk_pos_x:int, chunk_pos_z:int) : 40 | return ChunkData.Chunks.from_leveldb(self, dimension, chunk_pos_x, chunk_pos_z) 41 | 42 | def get_BlockEntity(self, dimension:DimensionType, chunk_pos_x:int, chunk_pos_z:int) : 43 | return ChunkData.BlockEntity.from_leveldb(self, dimension, chunk_pos_x, chunk_pos_z) 44 | 45 | def get_Entity(self, dimension:DimensionType, chunk_pos_x:int, chunk_pos_z:int) : 46 | return ChunkData.Entity.from_leveldb(self, dimension, chunk_pos_x, chunk_pos_z) 47 | 48 | def get_PendingTick(self, dimension:DimensionType, chunk_pos_x:int, chunk_pos_z:int) : 49 | return ChunkData.PendingTicks.from_leveldb(self, dimension, chunk_pos_x, chunk_pos_z) 50 | 51 | def get_RandomTick(self, dimension:DimensionType, chunk_pos_x:int, chunk_pos_z:int) : 52 | return ChunkData.RandomTicks.from_leveldb(self, dimension, chunk_pos_x, chunk_pos_z) 53 | 54 | 55 | def get_LocalPlayer(self) : 56 | return OtherData.LocalPlayer.from_leveldb(self) 57 | 58 | def get_OnlinePlayer(self) : 59 | return OtherData.OnlinePlayer.from_leveldb(self) 60 | 61 | def get_Village(self) : 62 | return OtherData.Village.from_leveldb(self) 63 | 64 | def get_Map(self) : 65 | return OtherData.Map.from_leveldb(self) 66 | 67 | def get_Portal(self) : 68 | return OtherData.Portal.from_leveldb(self) 69 | 70 | def get_Mobevent(self) : 71 | return OtherData.Mobevent.from_leveldb(self) 72 | 73 | def get_SchedulerWT(self) : 74 | return OtherData.SchedulerWT.from_leveldb(self) 75 | 76 | def get_Scoreboard(self) : 77 | return OtherData.Scoreboard.from_leveldb(self) 78 | 79 | def get_Structure(self) : 80 | return OtherData.Structure.from_leveldb(self) 81 | 82 | def get_TickingArea(self) : 83 | return OtherData.TickingArea.from_leveldb(self) 84 | 85 | 86 | def set_Data(self, data_object) : 87 | data_object.to_leveldb(self) 88 | 89 | -------------------------------------------------------------------------------- /main_source/main_window/constant.py: -------------------------------------------------------------------------------- 1 | import os,uuid,platform,typing,subprocess 2 | try : 3 | import jnius 4 | if platform.system() == "Windows" : raise Exception 5 | except : jnius = None 6 | 7 | APP_VERSION = "2.3.0 beta-8" ; debug_testing = True 8 | PythonActivity = jnius.autoclass('org.kivy.android.PythonActivity') if jnius else None 9 | Context = jnius.autoclass('android.content.Context') if jnius else None 10 | 11 | def GetPlatform() : 12 | result = subprocess.run("getprop ro.build.version.release", shell=True, capture_output=True, text=True) 13 | system_info = platform.uname() 14 | if system_info.system.lower() == 'windows' : return 'windows' 15 | elif system_info.system.lower() == 'android' : return 'android' 16 | elif result.returncode == 0 : return 'android' 17 | elif system_info.system.lower() == 'linux' and system_info.machine == "x86_64" : return 'linux_amd64' 18 | elif system_info.system.lower() == 'linux' and system_info.machine == "aarch64" : return 'linux_arm64' 19 | SoftwarePlatform: typing.Literal["windows", "android", "linux_amd64", "linux_arm64"] = GetPlatform() 20 | 21 | First_Load_Build_Dir = ( 22 | "save_world", 23 | "expand_pack", 24 | os.path.join("functionality", "example"), 25 | os.path.join("functionality", "Command_Text"), 26 | os.path.join("functionality", "CB_Structure"), 27 | ) 28 | 29 | #ID文件验证列表 30 | ID_File_Path = os.path.join("main_source", "update_source", "import_files") 31 | Prove_ID_List = [ 32 | 'animation', 'animation_controller', 'biome', 'block', 'block_loot', 'block_state', 33 | 'damageCause', 'default_chunk', 'default_map', 'effect', 'enchant', 'entity', 'entitySlot', 34 | 'fog', 'gamerule', 'game_data', 'identifier_transfor', 'item', 'loot_table', 'music', 'particle', 35 | 'recipe', 'sound', 'structure', 'trading', 'translate' 36 | ] 37 | 38 | #世界文件验证列表 39 | world_file_prove = ['level_name','world_info','scoreboard','chunk_data'] 40 | 41 | 42 | manifest_json = """ 43 | { 44 | "format_version": 2, 45 | "header": { 46 | "uuid": "%s", 47 | "name": "example_bp", 48 | "version": [0, 0, 1], 49 | "description": "This is a example behavior pack", 50 | "min_engine_version": %s 51 | }, 52 | "modules": [ 53 | { 54 | "description": "子资源包简介", 55 | "version": [0, 0, 1], 56 | "uuid": "14d5fb6b-ef0a-47e5-8a98-d615709c1a03", 57 | "type": "data" 58 | } 59 | ] 60 | } 61 | """%(uuid.uuid4(), [1,20,50]) 62 | 63 | world_config = { 64 | "normal_setting" : { 65 | "world_name" : "我的测试", #给你的世界起个名字 66 | "gamemode" : 1,#玩家模式——0为生存,1为创造,2为冒险,3为观察者 67 | "difficulty" : 2, #游戏难度——0为和平,1为简单,2为一般,3为困难 68 | "seed" : 124343354765 , #世界种子——支持字符串和整数两种类型 69 | "world_data_type" : "infinity", #be世界类型——可填 字符串infinity、flat 70 | "simulator_distance" : 4 , #模拟距离——允许输入4,6,8,10 71 | }, 72 | "be_gamerule" : { 73 | "commandBlockOutput": True, "commandBlocksEnabled": True ,"doDaylightCycle": True ,"doEntityDrops": True, 74 | "doImmediateRespawn": False, "doInsomnia": True, "doMobLoot": True, "doMobSpawning": True, "doTileDrops": True, 75 | "doWeatherCycle": True, "drowningDamage": True, "fallDamage": True, "fireDamage": True, "freezeDamage": True, 76 | "keepInventory": False, "doFireTick": True, "showTags" : True, "showCoordinates": True, "pvp" : True ,"tntExplodes" : True, 77 | "functionCommandLimit": 10000, #值需要在0-10000之间 78 | "maxCommandChainLength": 65536, #值需要在0-2147483647之间 79 | "randomTickSpeed": 1, #值需要在0-200之间 80 | "sendCommandFeedback": True, "showDeathMessages": True, "showBorderEffect": True, 81 | "mobGriefing": True, "naturalRegeneration": True, "respawnblocksexplode": True, 82 | "spawnRadius" : 5#值需要在0-12之间 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /main_source/bedrock_edition/data_save.py: -------------------------------------------------------------------------------- 1 | from typing import List,Dict,Union,Literal 2 | from . import np 3 | import base64,zlib 4 | 5 | 6 | def read_json(json:dict, key_list:List[str]) : 7 | for key1 in key_list : 8 | if key1 not in json : return None 9 | json = json[key1] 10 | return json 11 | 12 | def encoding(obj): 13 | from .nbt_class import BaseNbtClass as nbt_class 14 | if isinstance(obj, bool): return {"value":bool(obj),"__type__":"Bool"} 15 | elif isinstance(obj, np.int8): return {"value":int(obj),"__type__":"Byte"} 16 | elif isinstance(obj, np.int16): return {"value":int(obj),"__type__":"Short"} 17 | elif isinstance(obj, np.int32): return {"value":int(obj),"__type__":"Int"} 18 | elif isinstance(obj, np.int64): return {"value":int(obj),"__type__":"Long"} 19 | elif isinstance(obj, np.float32): return {"value":float(np.float32(obj)),"__type__":"Float"} 20 | elif isinstance(obj, np.float64): return {"value":float(np.float64(obj)),"__type__":"Double"} 21 | elif isinstance(obj, nbt_class.entity_nbt): return obj.__save__() 22 | elif isinstance(obj, nbt_class.block_nbt): return obj.__save__() 23 | elif isinstance(obj, nbt_class.item_nbt): return obj.__save__() 24 | elif isinstance(obj, nbt_class.structure_nbt): return obj.__save__() 25 | elif isinstance(obj, nbt_class.scoreboard_nbt): return obj.__save__() 26 | elif isinstance(obj, nbt_class.chunk_nbt): return obj.__save__() 27 | elif isinstance(obj, nbt_class.world_nbt): return obj.__save__() 28 | else : raise TypeError("Object of type %s is not JSON serializable" %(obj.__class__.__name__,)) 29 | 30 | def decoding(obj:dict): 31 | from .nbt_class import BaseNbtClass as nbt_class 32 | test1 = ('value' in obj) and ('__type__' in obj) 33 | test2 = ('__minecraft_type__' in obj) 34 | 35 | if test2 and obj['__minecraft_type__'] == "entity_nbt" : 36 | del obj['__minecraft_type__'] 37 | return nbt_class.entity_nbt().__load__(obj) 38 | elif test2 and obj['__minecraft_type__'] == "block_nbt" : 39 | del obj['__minecraft_type__'] 40 | return nbt_class.block_nbt().__load__(obj) 41 | elif test2 and obj['__minecraft_type__'] == "item_nbt" : 42 | del obj['__minecraft_type__'] 43 | return nbt_class.item_nbt().__load__(obj) 44 | elif test2 and obj['__minecraft_type__'] == "structure_nbt" : 45 | del obj['__minecraft_type__'] 46 | return nbt_class.structure_nbt().__load__(obj) 47 | elif test2 and obj['__minecraft_type__'] == "scoreboard_nbt" : 48 | del obj['__minecraft_type__'] 49 | return nbt_class.scoreboard_nbt().__load__(obj) 50 | elif test2 and obj['__minecraft_type__'] == "chunk_nbt" : 51 | del obj['__minecraft_type__'] 52 | return nbt_class.chunk_nbt().__load__(obj) 53 | elif test2 and obj['__minecraft_type__'] == "world_nbt" : 54 | del obj['__minecraft_type__'] 55 | return nbt_class.world_nbt().__load__(obj) 56 | elif test1 and obj['__type__'] == "Bool": return bool(obj['value']) 57 | elif test1 and obj['__type__'] == "Byte": return np.int8(obj['value']) 58 | elif test1 and obj['__type__'] == "Short": return np.int16(obj['value']) 59 | elif test1 and obj['__type__'] == "Int": return np.int32(obj['value']) 60 | elif test1 and obj['__type__'] == "Long": return np.int64(obj['value']) 61 | elif test1 and obj['__type__'] == "Float": return np.float32(obj['value']) 62 | elif test1 and obj['__type__'] == "Double": return np.float64(obj['value']) 63 | else : return obj 64 | 65 | def zip_to_string(base64code:str) : 66 | return zlib.decompress(base64.b64decode(base64code.encode('utf-8'))).decode('utf-8') 67 | 68 | def string_to_zip(str1:str) : 69 | return base64.b64encode(zlib.compress(str1.encode('utf-8'))).decode('utf-8') -------------------------------------------------------------------------------- /package/MCStructureManage/block.py: -------------------------------------------------------------------------------- 1 | from . import nbt, MCBELab 2 | from typing import Union,Dict,Tuple 3 | from types import MappingProxyType 4 | import json 5 | 6 | 7 | class BlockMeta(type) : 8 | 9 | def __init__(self, *args, **kwds) : 10 | super().__init__(*args, **kwds) 11 | self.__cache:Dict[Tuple[str, Union[int, str, tuple]], "Block"] = {} 12 | 13 | def __call__(self, id:str, states:Union[int, str, Dict[str, Union[bool, int, str]]]={}, waterlogged:bool=False) : 14 | CacheKey = (id, waterlogged, *states.items()) if hasattr(states, "items") else (id, waterlogged, states) 15 | 16 | if CacheKey in self.__cache : return self.__cache[CacheKey] 17 | self.__cache[CacheKey] = super().__call__(id, states, waterlogged) 18 | return self.__cache[CacheKey] 19 | 20 | class Block(metaclass=BlockMeta) : 21 | """ 22 | 通用方块对象 23 | --------------------------------- 24 | * 实现了单例模式和哈希接口的方块对象 25 | --------------------------------- 26 | * 实例化参数 name : 方块ID字符串,如无命名空间则自动添加命名空间 27 | * 实例化参数 states : 方块状态传参,支持整数、方块状态字符串、方块状态字典 28 | * 实例化参数 waterlogged : 方块是否含水 29 | * states 会自动舍去无效的状态参数 30 | --------------------------------- 31 | * 属性 dataValue : 方块id和方块状态对应的数据值,无法互相转换的数据值会设置为0 32 | --------------------------------- 33 | * 可用类方法 from_nbt: 将 {name:"a", states:{color:"red"}} 的方块nbt转换为方块对象 34 | * 可用方法 to_nbt: 生成 方块对象 对应的nbt对象 35 | """ 36 | 37 | def __str__(self): 38 | return f'' 39 | 40 | def __repr__(self): 41 | return f'' 42 | 43 | def __delattr__(self, name): 44 | raise Exception("无法删除任何属性") 45 | 46 | def __setattr__(self, name, value): 47 | if hasattr(self, name) : raise Exception("无法修改任何属性") 48 | super().__setattr__(name, value) 49 | 50 | 51 | def __hash__(self): 52 | return self.__hash 53 | 54 | def __eq__(self, value): 55 | return value.__hash__() == self.__hash 56 | 57 | 58 | def __init__(self, name:str, states:Union[int, str, Dict[str, Union[bool, int, str]]], waterlogged:bool=False) : 59 | if "." in name : BlockID, BlockState = MCBELab.RunawayTransforBlock(name) 60 | else : BlockID, BlockState = MCBELab.TransforBlock(name, states) 61 | self.name = BlockID 62 | self.states = MappingProxyType(BlockState) 63 | self.waterlogged = waterlogged 64 | self.dataValue = MCBELab.TransforDatavalue(self.name, self.states) 65 | self.runawayID = MCBELab.BlockTransforRunaway(self.name, self.states) 66 | self.blockString = "%s[%s]" % (BlockID, json.dumps(BlockState, separators=(',', '='))[1:][:-1]) 67 | 68 | self.__hash = (self.name, waterlogged, *self.states.items()).__hash__() 69 | 70 | 71 | @classmethod 72 | def from_nbt(cls, nbt_obj:nbt.TAG_Compound) : 73 | dict1 = {} 74 | for i,j in nbt_obj.items() : 75 | if j.__class__ is nbt.TAG_String : dict1[i] = j.value 76 | elif j.__class__ is nbt.TAG_Int : dict1[i] = j.value 77 | elif j.__class__ is nbt.TAG_Byte : dict1[i] = bool(j.value) 78 | return cls(nbt_obj["name"].value, dict1) 79 | 80 | def to_nbt(self) : 81 | node = nbt.NBT_Builder() 82 | dict1 = {} 83 | for i,j in self.states.items() : 84 | if j.__class__ is bool : dict1[i] = node.byte(j) 85 | elif j.__class__ is int : dict1[i] = node.int(j) 86 | elif j.__class__ is str : dict1[i] = node.string(j) 87 | return node.compound(name=node.string(self.name), states=node.compound(**dict1), 88 | val=node.short(self.dataValue[1]), version=node.int(17959425)).build() 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/#use-with-ide 110 | .pdm.toml 111 | 112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 113 | __pypackages__/ 114 | 115 | # Celery stuff 116 | celerybeat-schedule 117 | celerybeat.pid 118 | 119 | # SageMath parsed files 120 | *.sage.py 121 | 122 | # Environments 123 | .env 124 | .venv 125 | env/ 126 | venv/ 127 | ENV/ 128 | env.bak/ 129 | venv.bak/ 130 | 131 | # Spyder project settings 132 | .spyderproject 133 | .spyproject 134 | 135 | # Rope project settings 136 | .ropeproject 137 | 138 | # mkdocs documentation 139 | /site 140 | 141 | # mypy 142 | .mypy_cache/ 143 | .dmypy.json 144 | dmypy.json 145 | 146 | # Pyre type checker 147 | .pyre/ 148 | 149 | # pytype static type analyzer 150 | .pytype/ 151 | 152 | # Cython debug symbols 153 | cython_debug/ 154 | 155 | # PyCharm 156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 158 | # and can be added to the global gitignore or merged into this file. For a more nuclear 159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 160 | #.idea/ 161 | -------------------------------------------------------------------------------- /package/MCStructureManage/StructureRUNAWAY/timebuild.py: -------------------------------------------------------------------------------- 1 | import os,itertools,json 2 | from .. import nbt 3 | from ..__private import TypeCheckList 4 | from typing import Union,List,TypedDict,Literal,Dict 5 | from io import FileIO, BytesIO, StringIO, TextIOBase 6 | 7 | class FormatError(Exception) : pass 8 | 9 | class FileFormat(TypedDict) : 10 | version: str 11 | block: List["BLOCK"] 12 | 13 | class BLOCK(TypedDict) : 14 | name: str 15 | aux: int 16 | pos: List[int] 17 | 18 | 19 | 20 | class TimeBuilder_V1 : 21 | """ 22 | 由 Aionos 开发的结构文件对象 23 | ----------------------- 24 | * 以 .json 为后缀的json格式文件 25 | * 格式:{"version": "TimeBuilder", "block": [ 26 | * {"name": "mycelium", "aux": 0, "pos": [ [0,0,33] ] }]} 27 | ---------------------------------------- 28 | * 可用属性 blocks : 方块储存列表 29 | ----------------------- 30 | * 可用类方法 from_buffer : 通过路径、字节数字 或 流式缓冲区 生成对象 31 | * 可用方法 save_as : 通过路径 或 流式缓冲区 保存对象数据 32 | """ 33 | 34 | 35 | def __init__(self) : 36 | self.blocks: List["BLOCK"] = TypeCheckList().setChecker(dict) 37 | 38 | def __setattr__(self, name, value) : 39 | if not hasattr(self, name) : super().__setattr__(name, value) 40 | elif isinstance(value, type(getattr(self, name))) : super().__setattr__(name, value) 41 | else : raise Exception("无法修改 %s 属性" % name) 42 | 43 | def __delattr__(self, name) : 44 | raise Exception("无法删除任何属性") 45 | 46 | 47 | def error_check(self) : 48 | for block in self.blocks : 49 | if not isinstance(block, dict) : raise Exception("方块数据不为dict参数") 50 | if not isinstance(block.get("name", None), str) : raise Exception("方块数据缺少或存在错误 name 参数") 51 | if not isinstance(block.get("aux", None), int) : raise Exception("方块数据缺少或存在错误 aux 参数") 52 | if not isinstance(block.get("pos", None), list) : raise Exception("方块数据缺少或存在错误 pos 参数") 53 | for pos in block.get("pos", None) : 54 | if len(pos) < 3 : raise Exception("方块坐标数据数量不足") 55 | if not isinstance(pos[0], int) : raise Exception("方块数据缺少或存在错误 x 参数") 56 | if not isinstance(pos[1], int) : raise Exception("方块数据缺少或存在错误 y 参数") 57 | if not isinstance(pos[2], int) : raise Exception("方块数据缺少或存在错误 z 参数") 58 | 59 | def get_volume(self) : 60 | origin_min, origin_max = [0, 0, 0], [0, 0, 0] 61 | 62 | for block in self.blocks : 63 | for i in range(3) : 64 | origin_min[i] = min(origin_min[i], min(pos[i] for pos in block["pos"])) 65 | origin_max[i] = max(origin_max[i], max(pos[i] for pos in block["pos"])) 66 | 67 | return origin_min, origin_max 68 | 69 | 70 | @classmethod 71 | def from_buffer(cls, buffer:Union[str, FileIO, BytesIO, StringIO]) : 72 | if isinstance(buffer, str) : _file = open(buffer, "rb") 73 | elif isinstance(buffer, bytes) : _file = BytesIO(buffer) 74 | else : _file = buffer 75 | Json1 = json.load(fp=_file) 76 | 77 | if Json1.get("version", None) != "TimeBuilder" : raise FormatError("文件缺少version参数") 78 | 79 | StructureObject = cls() 80 | StructureObject.blocks.extend(Json1["block"]) 81 | 82 | return StructureObject 83 | 84 | def save_as(self, buffer:Union[str, FileIO, StringIO]) : 85 | self.error_check() 86 | Json1 = {"version": "TimeBuilder", "block":self.blocks} 87 | 88 | if isinstance(buffer, str) : 89 | base_path = os.path.realpath(os.path.join(buffer, os.pardir)) 90 | os.makedirs(base_path, exist_ok=True) 91 | _file = open(buffer, "w+", encoding="utf-8") 92 | else : _file = buffer 93 | 94 | if not isinstance(_file, TextIOBase) : raise TypeError("buffer 参数需要文本缓冲区类型") 95 | json.dump(Json1, _file, separators=(',', ':')) 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /package/MCStructureManage/StructureBDX/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | bdx文件解析模块 3 | --------------------------------- 4 | * 可用对象 BDX_File: 解析bdx文件的类 5 | ------------------------------------------------------------------ 6 | * 可用模块 OperationCode: bdx文件中的所有操作码类 7 | --------------------------------- 8 | * 可用变量 RunTimeID_117: 1.17版本的方块枚举列表,用于RunTimeID操作码索引指向的本列表数据 9 | * 可用变量 Support_OperationCode: 所有支持的操作,可用于isinstance判断 10 | * 可用变量 PosX_Change_OperationCode: 会改变X坐标的类型列表,可用于isinstance判断 11 | * 可用变量 PosY_Change_OperationCode: 会改变Y坐标的类型列表,可用于isinstance判断 12 | * 可用变量 PosZ_Change_OperationCode: 会改变Z坐标的类型列表,可用于isinstance判断 13 | * 可用变量 PosAddOne_OperationCode: 只会对坐标+1的类型列表,可用于isinstance判断 14 | * 可用变量 PosRemoveOne_OperationCode: 只会对坐标-1的类型列表,可用于isinstance判断 15 | * 可用变量 CommandBlockData_OperationCode: 储存了CommandBlock的信息的类型列表,可用于isinstance判断 16 | * 可用变量 Possible_CommandBlockData_OperationCode: 该对象可能储存了CommandBlock的信息,需要特别判断NBT内部的方块ID,可用于isinstance判断 17 | """ 18 | 19 | from .object import BDX_File 20 | from . import operation as OperationCode 21 | 22 | #所有支持的操作,可用于isinstance判断 23 | Support_OperationCode = ( 24 | OperationCode.CreateConstantString, OperationCode.PlaceBlockWithBlockStates1, 25 | OperationCode.AddInt16ZValue0, OperationCode.PlaceBlock, OperationCode.AddZValue0, 26 | OperationCode.NOP, OperationCode.AddInt32ZValue0, OperationCode.PlaceBlockWithBlockStates2, 27 | OperationCode.AddXValue, OperationCode.SubtractXValue, OperationCode.AddYValue, 28 | OperationCode.SubtractYValue, OperationCode.AddZValue, OperationCode.SubtractZValue, 29 | OperationCode.AddInt16XValue, OperationCode.AddInt32XValue, OperationCode.AddInt16YValue, 30 | OperationCode.AddInt32YValue, OperationCode.AddInt16ZValue, OperationCode.AddInt32ZValue, 31 | OperationCode.SetCommandBlockData, OperationCode.PlaceBlockWithCommandBlockData, 32 | OperationCode.AddInt8XValue, OperationCode.AddInt8YValue, OperationCode.AddInt8ZValue, 33 | OperationCode.UseRuntimeIDPool, OperationCode.PlaceRuntimeBlock, 34 | OperationCode.PlaceBlockWithRuntimeId, OperationCode.PlaceRuntimeBlockWithCommandBlockData, 35 | OperationCode.PlaceRuntimeBlockWithCommandBlockDataAndUint32RuntimeID, 36 | OperationCode.PlaceCommandBlockWithCommandBlockData, 37 | OperationCode.PlaceRuntimeBlockWithChestData, 38 | OperationCode.PlaceRuntimeBlockWithChestDataAndUint32RuntimeID, 39 | OperationCode.AssignDebugData, OperationCode.PlaceBlockWithChestData, 40 | OperationCode.PlaceBlockWithNBTData, OperationCode.Terminate 41 | ) 42 | #这些对象会改变X坐标,可用于isinstance判断 43 | PosX_Change_OperationCode = (OperationCode.AddXValue, OperationCode.SubtractXValue, 44 | OperationCode.AddInt8XValue, OperationCode.AddInt16XValue, OperationCode.AddInt32XValue) 45 | #这些对象会改变Y坐标,可用于isinstance判断 46 | PosY_Change_OperationCode = (OperationCode.AddYValue, OperationCode.SubtractYValue, 47 | OperationCode.AddInt8YValue, OperationCode.AddInt16YValue, OperationCode.AddInt32YValue) 48 | #这些对象会改变Z坐标,可用于isinstance判断 49 | PosZ_Change_OperationCode = (OperationCode.AddZValue, OperationCode.SubtractZValue, 50 | OperationCode.AddInt8ZValue, OperationCode.AddInt16ZValue, OperationCode.AddInt32ZValue, 51 | OperationCode.AddInt16ZValue0, OperationCode.AddZValue0, OperationCode.AddInt32ZValue0) 52 | 53 | #这些对象只会对坐标+1,可用于isinstance判断 54 | PosAddOne_OperationCode = (OperationCode.AddXValue, OperationCode.AddYValue, 55 | OperationCode.AddZValue, OperationCode.AddZValue0) 56 | #这些对象只会对坐标-1,可用于isinstance判断 57 | PosRemoveOne_OperationCode = (OperationCode.SubtractXValue, 58 | OperationCode.SubtractYValue, OperationCode.SubtractZValue) 59 | #这些对象储存了CommandBlock的信息,可用于isinstance判断 60 | CommandBlockData_OperationCode = ( 61 | OperationCode.SetCommandBlockData, 62 | OperationCode.PlaceBlockWithCommandBlockData, 63 | OperationCode.PlaceRuntimeBlockWithCommandBlockData, 64 | OperationCode.PlaceRuntimeBlockWithCommandBlockDataAndUint32RuntimeID, 65 | OperationCode.PlaceCommandBlockWithCommandBlockData) 66 | #该对象可能储存了CommandBlock的信息,需要特别判断NBT内部的方块ID,可用于isinstance判断 67 | Possible_CommandBlockData_OperationCode = OperationCode.PlaceBlockWithNBTData 68 | 69 | #1.17版本的方块枚举列表,用于RunTimeID操作码索引指向的本列表数据 70 | from .object import RunTimeID_117 -------------------------------------------------------------------------------- /package/MCBELab/res/blockmap.json: -------------------------------------------------------------------------------- 1 | {"BEOldVersionMap": 2 | ["stone", "grass_block", "dirt", "cobblestone", "oak_planks", "oak_sapling", "bedrock", "flowing_water", "water", 3 | "flowing_lava", "lava", "sand", "gravel", "gold_ore", "iron_ore", "coal_ore", "oak_log", "oak_leaves", "sponge", 4 | "glass", "lapis_ore", "lapis_block", "dispenser", "sandstone", "noteblock", "bed", "golden_rail", "detector_rail", 5 | "sticky_piston", "web", "short_grass", "deadbush", "piston", "piston_arm_collision", "white_wool", "element_0", "dandelion", 6 | "poppy", "brown_mushroom", "red_mushroom", "gold_block", "iron_block", "smooth_stone_double_slab", "smooth_stone_slab", 7 | "brick_block", "tnt", "bookshelf", "mossy_cobblestone", "obsidian", "torch", "fire", "mob_spawner", "oak_stairs", "chest", 8 | "redstone_wire", "diamond_ore", "diamond_block", "crafting_table", "wheat", "farmland", "furnace", "lit_furnace", "standing_sign", 9 | "wooden_door", "ladder", "rail", "stone_stairs", "wall_sign", "lever", "stone_pressure_plate", "iron_door", "wooden_pressure_plate", 10 | "redstone_ore", "lit_redstone_ore", "unlit_redstone_torch", "redstone_torch", "stone_button", "snow_layer", "ice", "snow", "cactus", 11 | "clay", "reeds", "jukebox", "oak_fence", "pumpkin", "netherrack", "soul_sand", "glowstone", "portal", "lit_pumpkin", "cake", 12 | "unpowered_repeater", "powered_repeater", "invisible_bedrock", "trapdoor", "infested_stone", "stone_bricks", "brown_mushroom_block", 13 | "red_mushroom_block", "iron_bars", "glass_pane", "melon_block", "pumpkin_stem", "melon_stem", "vine", "oak_fence_gate", "brick_stairs", 14 | "stone_brick_stairs", "mycelium", "waterlily", "nether_brick", "nether_brick_fence", "nether_brick_stairs", "nether_wart", 15 | "enchanting_table", "brewing_stand", "cauldron", "end_portal", "end_portal_frame", "end_stone", "dragon_egg", "redstone_lamp", 16 | "lit_redstone_lamp", "dropper", "activator_rail", "cocoa", "sandstone_stairs", "emerald_ore", "ender_chest", "tripwire_hook", 17 | "trip_wire", "emerald_block", "spruce_stairs", "birch_stairs", "jungle_stairs", "command_block", "beacon", "cobblestone_wall", 18 | "flower_pot", "carrots", "potatoes", "wooden_button", "skeleton_skull", "anvil", "trapped_chest", "light_weighted_pressure_plate", 19 | "heavy_weighted_pressure_plate", "unpowered_comparator", "powered_comparator", "daylight_detector", "redstone_block", "quartz_ore", 20 | "hopper", "quartz_block", "quartz_stairs", "oak_double_slab", "oak_slab", "white_terracotta", "white_stained_glass_pane", "acacia_leaves", 21 | "acacia_log", "acacia_stairs", "dark_oak_stairs", "slime", "glow_stick", "iron_trapdoor", "prismarine", "sea_lantern", "hay_block", 22 | "white_carpet", "hardened_clay", "coal_block", "packed_ice", "sunflower", "standing_banner", "wall_banner", "daylight_detector_inverted", 23 | "red_sandstone", "red_sandstone_stairs", "red_sandstone_double_slab", "red_sandstone_slab", "spruce_fence_gate", "birch_fence_gate", 24 | "jungle_fence_gate", "dark_oak_fence_gate", "acacia_fence_gate", "repeating_command_block", "chain_command_block", "hard_glass_pane", 25 | "hard_white_stained_glass_pane", "chemical_heat", "spruce_door", "birch_door", "jungle_door", "acacia_door", "dark_oak_door", "grass_path", 26 | "frame", "chorus_flower", "purpur_block", "colored_torch_red", "purpur_stairs", "colored_torch_blue", "undyed_shulker_box", "end_bricks", 27 | "frosted_ice", "end_rod", "end_gateway", "allow", "deny", "border_block", "magma", "nether_wart_block", "red_nether_brick", "bone_block", 28 | "structure_void", "white_shulker_box", "purple_glazed_terracotta", "white_glazed_terracotta", "orange_glazed_terracotta", 29 | "magenta_glazed_terracotta", "light_blue_glazed_terracotta", "yellow_glazed_terracotta", "lime_glazed_terracotta", "pink_glazed_terracotta", 30 | "gray_glazed_terracotta", "silver_glazed_terracotta", "cyan_glazed_terracotta", "chalkboard", "blue_glazed_terracotta", "brown_glazed_terracotta", 31 | "green_glazed_terracotta", "red_glazed_terracotta", "black_glazed_terracotta", "white_concrete", "white_concrete_powder", "compound_creator", 32 | "underwater_torch", "chorus_plant", "white_stained_glass", "camera", "podzol", "beetroot", "stonecutter", "glowingobsidian", "netherreactor", 33 | "info_update", "info_update2", "moving_block", "observer", "structure_block", "hard_glass", "hard_white_stained_glass", "reserved6"], 34 | "":[] 35 | } -------------------------------------------------------------------------------- /local_server/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 可视化模型 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /main_source/bedrock_edition/nbt_class/BlockComponent.py: -------------------------------------------------------------------------------- 1 | from .. import np 2 | import copy 3 | 4 | class block_components : 5 | 6 | def __init__(self) : 7 | self.standing_banner = {"Patterns" : [{"Color":"","Pattern":""}]} 8 | self.wall_banner = {"Patterns" : [{"Color":"","Pattern":""}]} 9 | self.beacon = {"primary": "","secondary": ""} 10 | self.bed = {"color":np.int8(0)} 11 | self.beehive = {"Occupants":[{"ActorIdentifier":"minecraft:bee","TicksLeftToStay":np.int16(0),"SaveData":{}}]} 12 | self.bee_nest = {"Occupants":[{"ActorIdentifier":"minecraft:bee","TicksLeftToStay":np.int16(0),"SaveData":{}}]} 13 | self.brewing_stand = {"FuelTotal":np.int16(0),"FuelAmount":np.int16(0),"CookTime":np.int16(0),"Items":[ None for i in range(5) ]} 14 | self.campfire = {"ItemTime1":np.int16(0),"Item1":None,"ItemTime2":np.int16(0),"Item2":None, 15 | "ItemTime3":np.int16(0),"Item3":None,"ItemTime4":np.int16(0),"Item4":None} 16 | self.soul_campfire = {"ItemTime1":np.int16(0),"Item1":None,"ItemTime2":np.int16(0),"Item2":None, 17 | "ItemTime3":np.int16(0),"Item3":None,"ItemTime4":np.int16(0),"Item4":None} 18 | self.cauldron = {"PotionId":np.int8(-1),"PotionType":np.int8(-1),"CustomColor":np.int32(0)} 19 | self.chest = {"LootTable":None,"LootTableSeed":np.int32(0),"Items":[ None for i in range(27) ]} 20 | self.trapped_chest = {"LootTable":None,"LootTableSeed":np.int32(0),"Items":[ None for i in range(27) ]} 21 | self.barrel = {"LootTable":None,"LootTableSeed":np.int32(0),"Items":[ None for i in range(27) ]} 22 | self.command_block = {"LastTickActivated":False,"auto":False,"LastExecution":0,"Success":0,"Command":"","CustomName":"[!]","LastOutput":"","TickDelay":np.int32(0)} 23 | self.chain_command_block = {"LastTickActivated":False,"auto":False,"LastExecution":0,"Success":0,"Command":"","CustomName":"[!]","LastOutput":"","TickDelay":np.int32(0)} 24 | self.repeating_command_block = {"LastTickActivated":False,"auto":False,"LastExecution":0,"Success":0,"Command":"","CustomName":"[!]","LastOutput":"","TickDelay":np.int32(0)} 25 | self.dispenser = {"LootTable":None,"LootTableSeed":np.int32(0),"Items":[ None for i in range(9) ]} 26 | self.dropper = {"LootTable":None,"LootTableSeed":np.int32(0),"Items":[ None for i in range(9) ]} 27 | self.enchanting_table = {"rott":np.float32(0)} 28 | self.end_gateway = {"ExitPortal":[np.int32(1827),np.int32(79),np.int32(1872)]} 29 | self.flower_pot = {"PlantBlock":None} 30 | self.furnace = {"BurnTime":np.int16(0),"CookTime":np.int16(0),"StoredXPInt":np.int16(0),"Items":[ None for i in range(3) ]} 31 | self.lit_furnace = {"BurnTime":np.int16(0),"CookTime":np.int16(0),"StoredXPInt":np.int16(0),"Items":[ None for i in range(3) ]} 32 | self.smoker = {"BurnTime":np.int16(0),"CookTime":np.int16(0),"StoredXPInt":np.int16(0),"Items":[ None for i in range(3) ]} 33 | self.lit_smoker = {"BurnTime":np.int16(0),"CookTime":np.int16(0),"StoredXPInt":np.int16(0),"Items":[ None for i in range(3) ]} 34 | self.blast_furnace = {"BurnTime":np.int16(0),"CookTime":np.int16(0),"StoredXPInt":np.int16(0),"Items":[ None for i in range(3) ]} 35 | self.lit_blast_furnace = {"BurnTime":np.int16(0),"CookTime":np.int16(0),"StoredXPInt":np.int16(0),"Items":[ None for i in range(3) ]} 36 | self.hopper = {"Items":[ None for i in range(5) ]} 37 | self.frame = {"ItemRotation":np.float32(0),"ItemDropChance":np.float32(0),"Item":None} 38 | self.glow_frame = {"ItemRotation":np.float32(0),"ItemDropChance":np.float32(0),"Item":None} 39 | self.jukebox = {"RecordItem":None} 40 | self.lectern = {"page":np.int16(0),"book":None} 41 | self.noteblock = {"note":np.int8(0)} 42 | self.mob_spawner = {"EntityIdentifier":"","Delay":np.int16(232),"Delay":np.int16(3),"RequiredPlayerRange":np.int16(3)} 43 | self.shulker_box = {"facing":np.int8(0),"LootTable":None,"LootTableSeed":np.int32(0),"Items":[ None for i in range(27) ]} 44 | self.undyed_shulker_box = {"facing":np.int8(0),"LootTable":None,"LootTableSeed":np.int32(0),"Items":[ None for i in range(27) ]} 45 | 46 | def find_nbt(self,block_id:str) : 47 | block_id = block_id.replace("minecraft:","",1) 48 | if hasattr(self,block_id) : return copy.deepcopy(getattr(self,block_id)) 49 | 50 | blcok_nbt_data = block_components() 51 | 52 | def find_block_id_nbt(block_id:str) : return blcok_nbt_data.find_nbt(block_id) -------------------------------------------------------------------------------- /package/MCStructureManage/StructureRUNAWAY/qingxu.py: -------------------------------------------------------------------------------- 1 | import os,itertools,json 2 | from .. import nbt 3 | from ..__private import TypeCheckList 4 | from typing import Union,List,TypedDict,Literal 5 | from io import FileIO, BytesIO, StringIO, TextIOBase 6 | 7 | class FormatError(Exception) : pass 8 | 9 | class BLOCK(TypedDict) : 10 | Name: str 11 | X: int 12 | Y: int 13 | Z: int 14 | 15 | 16 | class QingXu_V1 : 17 | """ 18 | 由 情绪 开发的结构文件对象 19 | ----------------------- 20 | * 以 .json 为后缀的json格式文件 21 | * 格式:{ "0": "{\"0\":\"{\\\"Name\\\":\\\"grass\\\",\\\"X\\\":0,\\\"Y\\\":0,\\\"Z\\\":0}\"", "totalBlocks": 1} 22 | ---------------------------------------- 23 | * 可用属性 chunks : 区块储存列表 24 | ----------------------- 25 | * 可用类方法 from_buffer : 通过路径、字节数字 或 流式缓冲区 生成对象 26 | * 可用方法 save_as : 通过路径 或 流式缓冲区 保存对象数据 27 | """ 28 | 29 | 30 | def __init__(self) : 31 | self.chunks: List[List[BLOCK]] = TypeCheckList().setChecker(list) 32 | 33 | def __setattr__(self, name, value) : 34 | if not hasattr(self, name) : super().__setattr__(name, value) 35 | elif isinstance(value, type(getattr(self, name))) : super().__setattr__(name, value) 36 | else : raise Exception("无法修改 %s 属性" % name) 37 | 38 | def __delattr__(self, name) : 39 | raise Exception("无法删除任何属性") 40 | 41 | 42 | def error_check(self) : 43 | for chunk in self.chunks : 44 | for block in chunk : 45 | if not isinstance(block, dict) : raise Exception("方块数据不为dict参数") 46 | if not isinstance(block.get("Name", None), str) : raise Exception("方块数据缺少或存在错误 Name 参数") 47 | if not isinstance(block.get("X", None), int) : raise Exception("方块数据缺少或存在错误 X 参数") 48 | if not isinstance(block.get("Y", None), int) : raise Exception("方块数据缺少或存在错误 Y 参数") 49 | if not isinstance(block.get("Z", None), int) : raise Exception("方块数据缺少或存在错误 Z 参数") 50 | 51 | def get_volume(self) : 52 | origin_min, origin_max, str1 = [0, 0, 0], [0, 0, 0], ["X", "Y", "Z"] 53 | 54 | for i in range(3) : origin_min[i] = min(block[str1[i]] for block in itertools.chain(*self.chunks)) 55 | for i in range(3) : origin_max[i] = max(block[str1[i]] for block in itertools.chain(*self.chunks)) 56 | 57 | return origin_min, origin_max 58 | 59 | 60 | @classmethod 61 | def from_buffer(cls, buffer:Union[str, FileIO, BytesIO, StringIO]) : 62 | if isinstance(buffer, str) : _file = open(buffer, "rb") 63 | elif isinstance(buffer, bytes) : _file = BytesIO(buffer) 64 | else : _file = buffer 65 | Json1 = json.load(fp=_file) 66 | 67 | if "totalBlocks" not in Json1 : raise FormatError("文件缺少totalBlocks参数") 68 | 69 | StructureObject = cls() 70 | for i in range(Json1["totalBlocks"]) : 71 | chunk = json.loads(Json1.get(f"{i}", '{"totalPoints":0}')) 72 | if not chunk : continue 73 | StructureObject.chunks.append( [] ) 74 | for j in range(chunk["totalPoints"]) : 75 | block = chunk.get(f"{j}", None) 76 | if not block : continue 77 | StructureObject.chunks[-1].append(json.loads(block)) 78 | 79 | return StructureObject 80 | 81 | def save_as(self, buffer:Union[str, FileIO, StringIO]) : 82 | #self.error_check() 83 | Json1 = {"totalBlocks":len(self.chunks)} 84 | for i, chunk in enumerate(self.chunks) : 85 | minX, maxX = min(i["X"] for i in chunk), max(i["X"] for i in chunk) 86 | minY, maxY = min(i["Y"] for i in chunk), max(i["Y"] for i in chunk) 87 | minZ, maxZ = min(i["Z"] for i in chunk), max(i["Z"] for i in chunk) 88 | Cache = {"totalPoints": len(chunk), "centerX":(minX+maxX)//2, 89 | "centerY":(minY+maxY)//2, "centerZ":(minZ+maxZ)//2} 90 | for j, block in enumerate(chunk) : Cache[f"{j}"] = json.dumps(block, separators=(',', ':')) 91 | Json1[f"{i}"] = json.dumps(Cache, separators=(',', ':')) 92 | 93 | if isinstance(buffer, str) : 94 | base_path = os.path.realpath(os.path.join(buffer, os.pardir)) 95 | os.makedirs(base_path, exist_ok=True) 96 | _file = open(buffer, "w+", encoding="utf-8") 97 | else : _file = buffer 98 | 99 | if not isinstance(_file, TextIOBase) : raise TypeError("buffer 参数需要文本缓冲区类型") 100 | json.dump(Json1, _file, separators=(',', ':')) 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /package/MCBELab/block_entity.py: -------------------------------------------------------------------------------- 1 | from . import nbt 2 | from typing import Union 3 | 4 | 5 | ContainerNBT_ID = {"minecraft:chest": "Chest", "minecraft:trapped_chest": "Chest", 6 | "minecraft:lit_blast_furnace": "BlastFurnace", "minecraft:hopper": "Hopper", 7 | "minecraft:shulker_box": "ShulkerBox", "minecraft:undyed_shulker_box": "ShulkerBox", 8 | "minecraft:barrel": "Barrel", "minecraft:dispenser": "Dispenser", "minecraft:dropper": "Dropper", 9 | "minecraft:furnace": "Furnace", "minecraft:lit_furnace": "Furnace", "minecraft:smoker": "Smoker", 10 | "minecraft:lit_smoker": "Smoker", "minecraft:blast_furnace": "BlastFurnace", "minecraft:ender_chest":"EnderChest"} 11 | 12 | def GenerateCommandBlockNBT(NBTid:str) -> nbt.TAG_Compound : 13 | node = nbt.NBT_Builder() 14 | return node.compound( 15 | id = node.string(NBTid), 16 | Command = node.string(""), 17 | CustomName = node.string(""), 18 | ExecuteOnFirstTick = node.byte(1), 19 | auto = node.byte(0), 20 | TickDelay = node.int(0), 21 | conditionalMode = node.byte(0), 22 | TrackOutput = node.byte(1), 23 | Version = node.int(19) 24 | ).build() 25 | 26 | def GenerateContainerNBT(NBTid:str) -> nbt.TAG_Compound : 27 | node = nbt.NBT_Builder() 28 | return node.compound( 29 | Findable = node.byte(0), 30 | IsOpened = node.byte(0), 31 | isMovable = node.byte(1), 32 | id = node.string(NBTid), 33 | Items = node.list() 34 | ).build() 35 | 36 | def GenerateSignNBT(NBTid:str) -> nbt.TAG_Compound : 37 | node = nbt.NBT_Builder() 38 | return node.compound( 39 | IsWaxed = node.byte(0), 40 | isMovable = node.byte(1), 41 | id = node.string(NBTid), 42 | BackText = node.compound( 43 | FilteredText = node.string(""), 44 | HideGlowOutline = node.byte(0), 45 | IgnoreLighting = node.byte(0), 46 | PersistFormatting = node.byte(1), 47 | SignTextColor = node.int(-16777216), 48 | Text = node.string(""), 49 | TextOwner = node.string("") ), 50 | FrontText = node.compound( 51 | FilteredText = node.string(""), 52 | HideGlowOutline = node.byte(0), 53 | IgnoreLighting = node.byte(0), 54 | PersistFormatting = node.byte(1), 55 | SignTextColor = node.int(-16777216), 56 | Text = node.string(""), 57 | TextOwner = node.string("") ) 58 | ).build() 59 | 60 | def GenerateBedNBT(NBTid:str) -> nbt.TAG_Compound : 61 | node = nbt.NBT_Builder() 62 | return node.compound( 63 | color = node.byte(0), 64 | isMovable = node.byte(1), 65 | id = node.string(NBTid) 66 | ).build() 67 | 68 | def GenerateBannerNBT(NBTid:str) -> nbt.TAG_Compound : 69 | node = nbt.NBT_Builder() 70 | return node.compound( 71 | isMovable = node.byte(1), 72 | Type = node.int(0), 73 | Patterns = node.list(), 74 | Base = node.int(0), 75 | id = node.string(NBTid) 76 | ).build() 77 | 78 | 79 | def GetNbtUID(id) : 80 | id = f"minecraft:{id}" if ":" not in id else id 81 | if id in ContainerNBT_ID : return 1 82 | elif id.endswith("command_block") : return 2 83 | elif id.endswith("hanging_sign") : return 3 84 | elif id.endswith("_sign") : return 4 85 | elif id.endswith("bed") : return 5 86 | elif id.endswith("_banner") : return 6 87 | elif id.endswith("_shelf") : return 7 88 | 89 | def GetNbtID(id:str) : 90 | id = f"minecraft:{id}" if ":" not in id else id 91 | if id in ContainerNBT_ID : return ContainerNBT_ID[id] 92 | elif id.endswith("command_block") : return "CommandBlock" 93 | elif id.endswith("hanging_sign") : return "HangingSign" 94 | elif id.endswith("_sign") : return "Sign" 95 | elif id.endswith("bed") : return "Bed" 96 | elif id.endswith("_banner") : return "Banner" 97 | elif id.endswith("_shelf") : return "Shelf" 98 | 99 | def GenerateBlockEntityNBT(id:str) : 100 | id = f"minecraft:{id}" if ":" not in id else id 101 | 102 | if id in ContainerNBT_ID : return GenerateContainerNBT( ContainerNBT_ID[id] ) 103 | elif id.endswith("command_block") : return GenerateCommandBlockNBT("CommandBlock") 104 | elif id.endswith("hanging_sign") : return GenerateSignNBT("HangingSign") 105 | elif id.endswith("_sign") : return GenerateSignNBT("Sign") 106 | elif id.endswith("bed") : return GenerateBedNBT("Bed") 107 | elif id.endswith("_banner") : return GenerateBannerNBT("Banner") 108 | elif id.endswith("_shelf") : return GenerateContainerNBT("Shelf") 109 | -------------------------------------------------------------------------------- /main_source/bedrock_edition/command_class/trans_html/command_run.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 命令运行反馈信息 8 | 9 | 10 | 11 | 94 | 95 | 96 |
97 |
当前游戏世界:$worldname
98 |
99 |
如果测试数据与命令对不上,请刷新网页。
100 |
101 | $all_command_respones 102 |
103 | 104 | 105 | 146 | 147 | -------------------------------------------------------------------------------- /package/MCCommandParser/parser_system.py: -------------------------------------------------------------------------------- 1 | """ 2 | 命令词法器系统\n 3 | Command_Parser用于检查每个同级树分支中满足哪个匹配分支,然后载入满足分支的子分支匹配 4 | """ 5 | 6 | from . import BaseMatch,SpecialMatch,JsonPaser 7 | 8 | from typing import Dict,Union,List,Tuple,Literal,TypedDict 9 | import re,traceback,itertools 10 | escape_space = re.compile("[ ]{0,}") 11 | 12 | class Token(TypedDict) : 13 | type: str 14 | token: Union[str, int, float] 15 | start: int 16 | end: int 17 | 18 | 19 | class Command_Parser : 20 | """ 21 | 词法器\n 22 | ------------------------ 23 | 实例化参数\n 24 | Tree : SpecialMatch.Command_Root类开始嵌套的命令树\n 25 | separator : 一个分隔字符\n 26 | separator_count : 每段匹配结构之间需要需要相隔多少分隔符\n 27 | """ 28 | 29 | def __init__(self,Tree:SpecialMatch.Command_Root, separator:str=" ", separator_count:int=None) -> None: 30 | if not isinstance(Tree,SpecialMatch.Command_Root) : raise TypeError("Tree 参数只能为 SpecialMatch.Command_Root 类") 31 | 32 | if not isinstance(separator,str) : raise TypeError("separator 参数只能为字符串") 33 | if separator.__len__() != 1 : raise Exception("separator 参数应该只存在一个字符") 34 | 35 | if not isinstance(separator_count, (type(None), int)) : raise TypeError("separator_count 参数只能为整数") 36 | if isinstance(separator_count, int) and separator_count < 1 : raise Exception("separator_count 参数应该为正整数") 37 | 38 | self.Tree = Tree 39 | self.separator = separator 40 | self.separator_count = separator_count 41 | self.no_match_error1 = re.compile("[^%s]{1,}" % BaseMatch.TERMINATOR_RE) 42 | self.no_match_error2 = re.compile(".{0,1}") 43 | 44 | 45 | def _version_compare(self, version:Tuple[int, int, int], leaves:BaseMatch.Match_Base) : 46 | if leaves.maximum_version is leaves.minimum_version is None : return True 47 | 48 | if leaves.maximum_version is None : max_v = (1000,0,0) 49 | else : max_v = leaves.maximum_version 50 | if leaves.minimum_version is None : min_v = (0,0,0) 51 | else : min_v = leaves.minimum_version 52 | 53 | return min_v <= version < max_v 54 | 55 | def _get_auto_complete(self, e:Exception) : 56 | _str1 = {} 57 | for i in e.current.tree_leaves : _str1.update(i._auto_complete()) 58 | re_match1 = re.compile(BaseMatch.string_to_rematch(e.word)) 59 | for i in list(_str1.keys()) : 60 | a = re_match1.search(i) 61 | if a is None : del _str1[i] 62 | return _str1 63 | 64 | def _parser(self, command_str:str, version:Tuple[int, int, int]) -> List[Token] : 65 | CommandFlag = {"Command_Start", "Command_End", "Json_Start"} 66 | command_str_pointer = 0 67 | current_leaves = self.Tree 68 | separator_re_match = re.compile("[%s]{%s,%s}" % ( 69 | BaseMatch.string_to_rematch(self.separator), 70 | 0 if self.separator_count is None else self.separator_count, 71 | "" if self.separator_count is None else self.separator_count )) 72 | self.Token_list = Token_list = [] 73 | 74 | while current_leaves.tree_leaves : 75 | is_not_successs = True 76 | for node in current_leaves.tree_leaves : 77 | if not self._version_compare(version, node) : continue 78 | 79 | try : a = node._match_string(command_str, command_str_pointer) 80 | except : continue 81 | else : Token_list.append(a) if a["type"] not in CommandFlag else None 82 | 83 | if node.__class__ is JsonPaser.Json_Start : 84 | try : JsonPaser.json_tokenizer(Token_list, command_str, command_str_pointer) 85 | except : continue 86 | finally : command_str_pointer = Token_list[-1]["end"] 87 | else : command_str_pointer = a["end"] 88 | 89 | is_not_successs = False 90 | current_leaves = node 91 | break 92 | 93 | if is_not_successs : 94 | _m_ = self.no_match_error1.match(command_str, command_str_pointer) 95 | if _m_ is None : _m_ = self.no_match_error2.match(command_str, command_str_pointer) 96 | raise BaseMatch.SyntaxError(">>%s<< 非期望的参数" % _m_.group(), 97 | pos=(_m_.start(),_m_.end()), word=_m_.group(), current=current_leaves) 98 | 99 | command_str_pointer = separator_re_match.match(command_str, command_str_pointer).end() 100 | 101 | return Token_list 102 | 103 | def parser(self, command_str:str, version:Tuple[int, int, int]) -> Union[List[Token], Tuple[str, BaseMatch.Command_Match_Exception]] : 104 | command_str = command_str[escape_space.match(command_str).end():] 105 | try : a = self._parser(command_str, version) 106 | except Exception as e : 107 | s = "%s\n错误位于字符%s至%s" % (e.args[0], e.pos[0], e.pos[1]) 108 | return (s, e, self._get_auto_complete(e)) 109 | else : return a 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /package/MCStructureManage/C_API/__init__.py: -------------------------------------------------------------------------------- 1 | def GetPlatform() : 2 | import subprocess, typing, platform 3 | SoftwarePlatform: typing.Literal["windows_amd64", "android", "linux_amd64", "linux_arm64"] = None 4 | result = subprocess.run("getprop ro.build.version.release", shell=True, capture_output=True, text=True) 5 | system_info = platform.uname() 6 | system = system_info.system.lower() 7 | machine = system_info.machine.lower() 8 | 9 | if system == 'windows' and machine == "amd64": SoftwarePlatform = 'windows_amd64' 10 | elif system == 'android' : SoftwarePlatform = 'android' 11 | elif result.returncode == 0 : SoftwarePlatform = 'android' 12 | elif system == 'linux' and machine == "x86_64" : SoftwarePlatform = 'linux_amd64' 13 | elif system == 'linux' and machine == "aarch64" : SoftwarePlatform = 'linux_arm64' 14 | return SoftwarePlatform 15 | 16 | def init() : 17 | import os, platform, sys, hashlib, re, zipfile, subprocess 18 | LinkCommand = "aarch64-linux-android-gcc -shared build/temp.linux-aarch64-3.9/fast_api.o -L%s -lpython%s.%s -o Linux_aarch64.pyd" 19 | py_dll_name = "MCBEStructure_C_API.%s" 20 | 21 | base_path = os.path.realpath( os.path.join(__file__, "..") ) 22 | SysPlatfrom = GetPlatform() 23 | 24 | if SysPlatfrom == "windows_amd64" : 25 | target_path = os.path.join(base_path, py_dll_name % "pyd") 26 | target_abi = os.path.join(base_path, "ABI_File", "Win_amd64.pyd") 27 | elif SysPlatfrom == "android" : 28 | zipfile1 = zipfile.ZipFile(os.path.join(base_path, "ABI_File", "Linux_aarch64.build"), "r") 29 | zipfile1.extractall( os.path.join(base_path, "ABI_File") ) 30 | lib_path_re = re.compile("lib/python[0-9]\\.[0-9]{1,}$") 31 | for lib_path in sys.path : 32 | if lib_path_re.search(lib_path) : break 33 | lib_path = os.path.realpath( os.path.join(lib_path, "..") ) 34 | subprocess.run(LinkCommand % (lib_path, sys.version_info.major, sys.version_info.minor), 35 | shell=True, capture_output=True, text=True, cwd=os.path.join(base_path, "ABI_File")) 36 | for test_path in sys.path : 37 | if not test_path.endswith("site-packages") : continue 38 | else : break 39 | target_path = os.path.join(test_path, "Command_Simulator_C_API") 40 | target_abi = os.path.join(base_path, "ABI_File", "Linux_aarch64.pyd") 41 | os.makedirs( target_path, exist_ok=True ) 42 | target_path = os.path.join(target_path, py_dll_name % "so") 43 | elif SysPlatfrom == "linux_amd64" : 44 | target_path = os.path.join(base_path, py_dll_name % "so") 45 | target_abi = os.path.join(base_path, "ABI_File", "Linux_x86_64.pyd") 46 | else : raise RuntimeError(f"未支持的系统{platform.uname()}") 47 | 48 | if os.path.isfile(target_path) : 49 | with open(target_abi, "rb") as f1 : data1 = f1.read() 50 | with open(target_path, "rb") as f2 : data2 = f2.read() 51 | if hashlib.md5(data1).digest() == hashlib.md5(data2).digest() : return None 52 | 53 | with open(target_abi, "rb") as f1 : 54 | with open(target_path, "wb") as f2 : f2.write( f1.read() ) 55 | init() 56 | 57 | try : from . import MCBEStructure_C_API 58 | except : import Command_Simulator_C_API.MCBEStructure_C_API as MCBEStructure_C_API 59 | import array 60 | from typing import List, Tuple, Dict 61 | 62 | def fuhong_v5_decrypt(bytes1:bytes) -> str : 63 | """ 64 | fuhong_v5 解密函数 65 | """ 66 | return MCBEStructure_C_API.fuhong_v5_decrypt(bytes1) 67 | 68 | def fuhong_v5_encrypt(str1:str) -> bytes : 69 | """ 70 | fuhong_v5 加密函数 71 | """ 72 | return MCBEStructure_C_API.fuhong_v5_encrypt(str1) 73 | 74 | def codecs_parser_schematic(block_array:array.array, blockData_array:array.array, 75 | blockIndex_array:array.array, blockPalette_array:array.array, 76 | blockType_array:array.array, Volume:Tuple[int, int, int]) -> Dict[int, int] : 77 | """ 78 | schematic 加速函数 79 | """ 80 | return MCBEStructure_C_API.codecs_parser_schematic(block_array, 81 | blockData_array, blockIndex_array, blockPalette_array, blockType_array, Volume) 82 | 83 | def codecs_parser_schem(block_array:array.array, blockIndex_array:array.array, 84 | blockType_array:array.array, Volume:Tuple[int, int, int]) -> Dict[int, int] : 85 | """ 86 | schem 加速函数 87 | """ 88 | return MCBEStructure_C_API.codecs_parser_schem(block_array, 89 | blockIndex_array, blockType_array, Volume) 90 | 91 | def split_commonstructure(input_index:array.array, output_index:array.array, 92 | Size:Tuple[int, int, int], StartPos:Tuple[int, int, int], EndPos:Tuple[int, int, int]) : 93 | """ 94 | CommonStructure裁切函数 95 | """ 96 | MCBEStructure_C_API.split_commonstructure(input_index, output_index, Size, StartPos, EndPos) 97 | 98 | def handling_waterlog(blockIndex_array:array.array, water_log:dict, block_palette:list, size:array.array) -> bool : 99 | """ 100 | CommonStructure含水方块状态同步至含水属性 101 | """ 102 | MCBEStructure_C_API.handling_waterlog(blockIndex_array, water_log, list(block_palette), size) 103 | -------------------------------------------------------------------------------- /package/python_nbt/builder.py: -------------------------------------------------------------------------------- 1 | """ 2 | builder.py - 使用代码快速创建nbt结构工具 3 | """ 4 | from typing import Mapping, Union 5 | from . import tags 6 | 7 | def test_node(v): 8 | if not isinstance(v, NBT_Builder_Node): raise TypeError("非期望的类型 %s 应该为 %s" % (v, NBT_Builder_Node)) 9 | 10 | def test_str(v): 11 | if not isinstance(v, str): raise TypeError("非期望的类型 %s 应该为 %s" % (v, str)) 12 | 13 | def test_int(v): 14 | if not isinstance(v, int): raise TypeError("非期望的类型 %s 应该为 %s" % (v, int)) 15 | 16 | def test_number(v): 17 | if not isinstance(v, (int, float)): raise TypeError("非期望的类型 %s 应该为 %s" % (v, (int, float))) 18 | 19 | 20 | class NBT_Builder: 21 | def compound(self, **nodes: Union['NBT_Builder_Node', 'NBT_Builder_Proxy']): 22 | _nodes = {} 23 | for k, v in nodes.items(): 24 | if isinstance(v, NBT_Builder_Proxy): 25 | k, v = v.name, v.node 26 | test_node(v) 27 | _nodes[k] = v 28 | return self.return_node(NBT_Compound_Builder_Node(_nodes)) 29 | 30 | def list(self, *nodes: 'NBT_Builder_Node') -> 'NBT_List_Builder_Node': 31 | for v in nodes: 32 | test_node(v) 33 | return self.return_node(NBT_List_Builder_Node(nodes)) 34 | 35 | def byte_array(self, *nodes: int) -> 'NBT_ByteArray_Builder_Node': 36 | for v in nodes: 37 | test_int(v) 38 | return self.return_node(NBT_ByteArray_Builder_Node(nodes)) 39 | 40 | def int_array(self, *nodes: int) -> 'NBT_IntArray_Builder_Node': 41 | for v in nodes: 42 | test_int(v) 43 | return self.return_node(NBT_IntArray_Builder_Node(nodes)) 44 | 45 | def long_array(self, *nodes: int) -> 'NBT_LongArray_Builder_Node': 46 | for v in nodes: 47 | test_int(v) 48 | return self.return_node(NBT_LongArray_Builder_Node(nodes)) 49 | 50 | def byte(self, v: int) -> 'NBT_Byte_Builder_Node': 51 | test_int(v) 52 | return self.return_node(NBT_Byte_Builder_Node(v)) 53 | 54 | def short(self, v: int) -> 'NBT_Short_Builder_Node': 55 | test_int(v) 56 | return self.return_node(NBT_Short_Builder_Node(v)) 57 | 58 | def int(self, v: int) -> 'NBT_Int_Builder_Node': 59 | test_int(v) 60 | return self.return_node(NBT_Int_Builder_Node(v)) 61 | 62 | def long(self, v: int) -> 'NBT_Long_Builder_Node': 63 | test_int(v) 64 | return self.return_node(NBT_Long_Builder_Node(v)) 65 | 66 | def float(self, v: Union[int, float]) -> 'NBT_Float_Builder_Node': 67 | test_number(v) 68 | return self.return_node(NBT_Float_Builder_Node(v)) 69 | 70 | def double(self, v: Union[int, float]) -> 'NBT_Double_Builder_Node': 71 | test_number(v) 72 | return self.return_node(NBT_Double_Builder_Node(v)) 73 | 74 | def string(self, v: str) -> 'NBT_String_Builder_Node': 75 | test_str(v) 76 | return self.return_node(NBT_String_Builder_Node(v)) 77 | 78 | def key(self, s: str) -> 'NBT_Builder_Proxy': 79 | test_str(s) 80 | return NBT_Builder_Proxy(s) 81 | 82 | def return_node(self, node): 83 | return node 84 | 85 | cpd = compound 86 | lst = list 87 | bay = byte_array 88 | iay = int_array 89 | lay = long_array 90 | bte = byte 91 | sht = short 92 | lng = long 93 | flt = float 94 | dbl = double 95 | str = string 96 | 97 | 98 | class NBT_Builder_Proxy(NBT_Builder): 99 | def __init__(self, name): 100 | self.name = name 101 | 102 | def return_node(self, node): 103 | self.node = node 104 | return self 105 | 106 | 107 | class NBT_Builder_Node: 108 | tag = tags.TAG_End 109 | def __init__(self, value): 110 | self.value = value 111 | 112 | def build(self): 113 | return self.tag(self.value) 114 | 115 | 116 | class NBT_Compound_Builder_Node(NBT_Builder_Node): 117 | tag = tags.TAG_Compound 118 | def build(self): 119 | v = self.tag() 120 | v.set_value({k: v.build() for k, v in self.value.items()}) 121 | return v 122 | 123 | 124 | class NBT_List_Builder_Node(NBT_Builder_Node): 125 | tag = tags.TAG_List 126 | def build(self): 127 | v = self.tag() 128 | v.set_value([v.build() for v in self.value]) 129 | return v 130 | 131 | 132 | class NBT_Array_Builder_Node(NBT_Builder_Node): 133 | tag = tags.TAG_Array 134 | def build(self): 135 | v = self.tag() 136 | v.set_value(self.value) 137 | return v 138 | 139 | 140 | class NBT_ByteArray_Builder_Node(NBT_Array_Builder_Node): 141 | tag = tags.TAG_ByteArray 142 | 143 | 144 | class NBT_IntArray_Builder_Node(NBT_Array_Builder_Node): 145 | tag = tags.TAG_IntArray 146 | 147 | 148 | class NBT_LongArray_Builder_Node(NBT_Array_Builder_Node): 149 | tag = tags.TAG_LongArray 150 | 151 | 152 | class NBT_Byte_Builder_Node(NBT_Builder_Node): 153 | tag = tags.TAG_Byte 154 | 155 | 156 | class NBT_Short_Builder_Node(NBT_Builder_Node): 157 | tag = tags.TAG_Short 158 | 159 | 160 | class NBT_Int_Builder_Node(NBT_Builder_Node): 161 | tag = tags.TAG_Int 162 | 163 | 164 | class NBT_Long_Builder_Node(NBT_Builder_Node): 165 | tag = tags.TAG_Long 166 | 167 | 168 | class NBT_Float_Builder_Node(NBT_Builder_Node): 169 | tag = tags.TAG_Float 170 | 171 | 172 | class NBT_Double_Builder_Node(NBT_Builder_Node): 173 | tag = tags.TAG_Double 174 | 175 | 176 | class NBT_String_Builder_Node(NBT_Builder_Node): 177 | tag = tags.TAG_String 178 | 179 | -------------------------------------------------------------------------------- /local_server/tutorial/WorldConfig.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 命令模拟器世界配置文档 8 | 9 | 10 | 11 | 12 | 13 | 26 | 27 |
28 | 29 |
30 | 31 |
32 |

世界类型

33 |

34 |   命令模拟器并不会依照柏林噪声生成一个和Minecraft一模一样的世界,使用柏林噪声生成的时间消耗过大。 35 | 为了加快世界生成的速度,命令模拟器使用了预设的区块模板。 36 |

37 |

38 |   在基岩版下,如果你选择flat世界类型,主世界维度的每个区块按以下模板顺序生成: 39 | 1层基岩(y=-64)、2层泥土、1层草方块、380层空气 40 |

41 |

42 |   如果你选择infinity世界类型,主世界维度的每个区块按以下模板顺序生成: 43 | 1层基岩(y=-64)、8层石头(可能有中空区域)、2层泥土、1层草方块,372层空气 44 |

45 |

46 |   下界维度的每个区块按以下模板顺序生成:1层基岩(y=0)、8层地狱岩、118层空气、1层基岩 47 |

48 |

49 |   末地维度的每个区块按以下模板顺序生成:一层空气(y=0)、8层末地石、119层空气 50 |

51 |
52 | 53 | 63 | 64 | 80 | 81 |
82 | 83 |
84 | 85 | 86 | 87 | 104 | 105 | 117 | 118 | -------------------------------------------------------------------------------- /package/python_nbt/codec.py: -------------------------------------------------------------------------------- 1 | """ 2 | codec.py - 编码与解码工具 3 | """ 4 | 5 | 6 | import re 7 | from struct import Struct 8 | from typing import Union 9 | from . import TAG 10 | from functools import lru_cache 11 | from json import loads, dumps 12 | from .error import * 13 | 14 | number_struct_formats = { 15 | TAG.BYTE : (Struct('>b'), Struct('h'), Struct('i'), Struct('q'), Struct('f'), Struct('d'), Struct('H')} 59 | 60 | str_snbt_key = re.compile(r"^[a-zA-Z0-9_+-.]*$") 61 | 62 | string_to_str_re = re.compile(r'(?i)\\u[a-fA-F0-9]{4}|\\.') 63 | 64 | 65 | @lru_cache(maxsize=None) 66 | def pack_data(data: Union[int, float, str], data_type: TAG, mode=False) -> bytes: 67 | if data_type in [TAG.END, TAG.LIST, TAG.COMPOUND, TAG.BYTE_ARRAY, TAG.INT_ARRAY, TAG.LONG_ARRAY]: 68 | raise TypeError("仅支持数字,字符串类型") 69 | 70 | if data_type in [TAG.BYTE, TAG.SHORT, TAG.INT, TAG.LONG]: 71 | if not isinstance(data, int): 72 | raise TypeError("数据类型非数字") 73 | try: 74 | return number_struct_formats[data_type][not mode].pack(data) 75 | except: 76 | raise ValueError("数字范围不正确") 77 | if data_type in [TAG.FLOAT, TAG.DOUBLE]: 78 | if not isinstance(data, (float, int)): 79 | raise TypeError("数据类型非数字") 80 | try: 81 | return number_struct_formats[data_type][not mode].pack(data) 82 | except: 83 | raise ValueError("数字范围不正确") 84 | if data_type in [TAG.STRING]: 85 | if not isinstance(data, str): 86 | raise TypeError("数据类型非字符串") 87 | try: 88 | return data.encode('utf-8') 89 | except: 90 | raise ValueError("编码错误") 91 | 92 | raise TypeError("期望类型为 %s,但传入了 %s" % (TAG, data_type.__class__)) 93 | 94 | @lru_cache(maxsize=None) 95 | def unpack_data(data: bytes, data_type: TAG, mode=False) -> Union[int, float, str]: 96 | if data_type in [TAG.END, TAG.LIST, TAG.COMPOUND, TAG.BYTE_ARRAY, TAG.INT_ARRAY, TAG.LONG_ARRAY]: 97 | raise TypeError("仅支持数字,字符串类型") 98 | 99 | if not isinstance(data, bytes): 100 | raise TypeError("数据类型非bytes") 101 | 102 | if data_type in [TAG.BYTE, TAG.SHORT, TAG.INT, TAG.LONG]: 103 | try: 104 | return number_struct_formats[data_type][not mode].unpack(data) 105 | except: 106 | raise ValueError("格式不正确") 107 | if data_type in [TAG.FLOAT, TAG.DOUBLE]: 108 | try: 109 | return number_struct_formats[data_type][not mode].unpack(data) 110 | except: 111 | raise ValueError("格式不正确") 112 | if data_type in [TAG.STRING]: 113 | try: 114 | return data.decode('utf-8') 115 | except: 116 | try: 117 | return data.decode(encoding='utf-8', errors='ignore') 118 | except: 119 | raise ValueError("编码错误") 120 | 121 | raise TypeError("期望类型为 %s,但传入了 %s" % (TAG, data_type.__class__)) 122 | 123 | def bytes_to_tag_type(data: bytes) -> TAG: 124 | if not isinstance(data, bytes): 125 | raise TypeError("类型错误") 126 | return tag_type_bytes[data] 127 | 128 | def tag_type_to_bytes(data: TAG) -> TAG: 129 | if not isinstance(data, TAG): 130 | raise TypeError("类型错误") 131 | return bytes_tag_type[data] 132 | 133 | def bytes_to_length(data: bytes, mode=False) -> int: 134 | return length_bytes_formats[mode].unpack(data)[0] 135 | 136 | def length_to_bytes(data: int, mode=False) -> bytes: 137 | return length_bytes_formats[mode].pack(data) 138 | 139 | def str_to_snbt_key(data: str) -> str: 140 | if data == '': 141 | return '""' 142 | if str_snbt_key.fullmatch(data): 143 | return data 144 | else: 145 | if '"' in data and "'" in data: 146 | return '"' + data.replace('"', '\\"') + '"' 147 | elif '"' in data and "'" not in data: 148 | return "'" + data + "'" 149 | elif '"' not in data and "'" in data: 150 | return '"' + data + '"' 151 | elif '"' not in data and "'" not in data: 152 | return '"' + data + '"' 153 | 154 | def str_to_string(data: str) -> str: 155 | return dumps(data, ensure_ascii=False) 156 | 157 | 158 | def string_to_str(data: str) -> str: 159 | def replace_string_to_str(m): 160 | s = m.group(0) 161 | if s[0:2] == "\\u": 162 | return s 163 | else: 164 | res = string_to_str_rule.get(s, None) 165 | if res is None: 166 | raise ValueError("字符串内(%s到%s个字符)存在无法解析的转义符 '%s'" % (data.find(s), data.find(s) + len(s), s)) 167 | else: 168 | return res 169 | return string_to_str_re.sub(replace_string_to_str, data[1:-1]) 170 | -------------------------------------------------------------------------------- /package/python_nbt/snbt.py: -------------------------------------------------------------------------------- 1 | """ 2 | snbt.py - snbt处理相关 3 | """ 4 | 5 | 6 | from enum import Enum 7 | from collections import deque 8 | from functools import lru_cache 9 | import re 10 | 11 | from . import TAGLIST, TAG, codec as ce 12 | from .error import * 13 | 14 | TOKEN_SPECIFICATION = [ 15 | ('Int', r'-?[0-9]+[BbSsLl]?(?![0-9a-zA-Z+\-\._])'), 16 | ('Float', r'-?(?:\.?[0-9]+|[0-9]+\.(?:[0-9]+)?)[FfdD]?'), 17 | ('SString', r'"(?:\\"|[^"])*"'), 18 | ('DString', r"'(?:\\'|[^'])*'"), 19 | ('Symbol', r':|,|;|\{|\}|\[|\]'), 20 | ('Key', r'[0-9a-zA-Z+\-\._]+'), 21 | ('WS', r'[ \t\n]+'), 22 | ('Comment', r'//.*\n|/\*(?:.|\n)*\*/'), 23 | ('Error', r'[^0-9a-zA-Z+\-\._ \t\n]+'), 24 | ] 25 | TokenRe = re.compile('|'.join('(?P<%s>%s)' % i for i in TOKEN_SPECIFICATION)) 26 | 27 | 28 | class SnbtIO: 29 | def __init__(self, code): 30 | self.tokens = Tokenizer(code) 31 | self.code = code 32 | 33 | def parse_key(self, token): 34 | type = token[0] 35 | if type in {"Int","Float","Key"}: 36 | return token[1] 37 | elif type in {"SString","DString"}: 38 | return ce.string_to_str(token[1]) 39 | else: 40 | raise SnbtParseError("非期望的字符('%s')类型 %s 位于%s行 第%s个字符到第%s个字符 应为一个 key" % (token[1], type, *get_line(self.code, token[2]))) 41 | 42 | def parse_value(self, token): 43 | if token[0] == "Int" or token[0] == "Float": 44 | try: 45 | res = self.parse_number(token[0], token[1]) 46 | if res is None: return TAGLIST[TAG.STRING](token[1]) 47 | else: return res 48 | except: 49 | return TAGLIST[TAG.STRING](token[1]) 50 | elif token[0] == "SString" or token[0] == "DString": 51 | try: 52 | return TAGLIST[TAG.STRING](ce.string_to_str(token[1])) 53 | except ValueError as e: 54 | raise SnbtParseError("%s 位于第%s行 第%s个字符到第%s个字符" % (e.args[0], *get_line(self.code, token[2]))) 55 | elif token[1] == "{": 56 | return TAGLIST[TAG.COMPOUND]._from_snbtIO(self) 57 | elif token[1] == "[": 58 | return TAGLIST[TAG.LIST]._from_snbtIO(self) 59 | elif token[1] == "true": 60 | return TAGLIST[TAG.BYTE](1) 61 | elif token[1] == "false": 62 | return TAGLIST[TAG.BYTE](0) 63 | else: 64 | self.throw_error(token, "数字,字符串,复合,列表,数组") 65 | 66 | @lru_cache(maxsize=None) 67 | def parse_number(self, Type, Value): 68 | if Value[-1] == "b" or Value[-1] == "B": 69 | return TAGLIST[TAG.BYTE](int(Value[0:-1])) 70 | elif Value[-1] == "s" or Value[-1] == "S": 71 | return TAGLIST[TAG.SHORT](int(Value[0:-1])) 72 | elif Value[-1] == "l" or Value[-1] == "L": 73 | return TAGLIST[TAG.LONG](int(Value[0:-1])) 74 | elif Value[-1] == "f" or Value[-1] == "F": 75 | return TAGLIST[TAG.FLOAT](float(Value[0:-1])) 76 | elif Value[-1] == "d" or Value[-1] == "D": 77 | return TAGLIST[TAG.DOUBLE](float(Value[0:-1])) 78 | elif Type == "Int": 79 | return TAGLIST[TAG.INT](int(Value)) 80 | elif Type == "Float": 81 | return TAGLIST[TAG.DOUBLE](float(Value)) 82 | else: 83 | return None 84 | 85 | @lru_cache(maxsize=None) 86 | def parse_py_number(self, Type, Value): 87 | if Value[-1] in "bBsSlL": 88 | return int(Value[0:-1]) 89 | elif Value[-1] == "fFdD": 90 | return float(Value[0:-1]) 91 | elif Type == "Int": 92 | return int(Value) 93 | elif Type == "Float": 94 | return float(Value) 95 | else: 96 | return None 97 | 98 | def close(self): 99 | try: 100 | item = next(self.tokens) 101 | except StopIteration: 102 | return True 103 | else: 104 | raise SnbtParseError("语法分析已完成,末尾(%s行 %s到%s个字符)有多余字符" % get_line(self.code, item[2])) 105 | 106 | def read(self, number=0): 107 | if number < 0: raise ValueError("非法值 %s" % number) 108 | if number == 0: 109 | res = deque() 110 | try: 111 | while True: res.append(self._read_one()) 112 | except SnbtTokenError: 113 | return tuple(res) 114 | if number == 1: 115 | return self._read_one() 116 | if number == 2: 117 | return (self._read_one(), self._read_one()) 118 | else: 119 | res = deque() 120 | for _ in range(number): 121 | res.append(self._read_one()) 122 | return tuple(res) 123 | 124 | def _read_one(self): 125 | try: 126 | return next(self.tokens) 127 | except StopIteration: 128 | raise SnbtTokenError("词法分析时到达末尾") 129 | 130 | def throw_error(self, token, value=""): 131 | raise SnbtParseError("非期望的字符 '%s' 位于%s行 第%s个字符到第%s个字符 应为 %s" % (token[1], *get_line(self.code, token[2]), value)) 132 | 133 | def __enter__(self): 134 | return self 135 | 136 | def __exit__(self, a, b, c): 137 | self.close() 138 | 139 | 140 | 141 | def Tokenizer(code): 142 | for mo in TokenRe.finditer(code): 143 | type = mo.lastgroup 144 | value = mo.group() 145 | if type in ['WS', 'Comment']: 146 | continue 147 | elif type == "Error": 148 | raise SnbtTokenError("意外的字符 %s 位于%s行 第%s个字符到第%s个字符" % (value, *get_line(code, (mo.start(), mo.end())))) 149 | elif type: 150 | yield (type, value, mo.span()) 151 | 152 | def get_line(Code, Pos): 153 | Length = Pos[1] - Pos[0] 154 | Lines = Code[0: Pos[0] + 1].splitlines() 155 | Pos2 = len(Lines[-1]) 156 | return len(Lines), Pos2, Pos2 + Length 157 | -------------------------------------------------------------------------------- /package/MCStructureManage/__private.py: -------------------------------------------------------------------------------- 1 | """ 2 | 私有模块用于定义非暴露但是重要的自定义对象 3 | """ 4 | import itertools, struct, array 5 | from typing import Dict,Any,Iterable,Union,List,Literal 6 | array.array 7 | 8 | 9 | class TypeCheckList(list) : 10 | from typing import Union 11 | 12 | def __init__(self, *args) : 13 | super().__init__(*args) 14 | self.Checker = None 15 | 16 | def setChecker(self, types:tuple) : 17 | if not isinstance(types, tuple) : types = (types, ) 18 | self.Checker = types 19 | return self 20 | 21 | def append(self, value) : 22 | if not isinstance(value, self.Checker): 23 | raise TypeError("添加的 %s 必须属于 %s 类型之一" % (value, self.Checker)) 24 | return super().append(value) 25 | 26 | def insert(self, index:int, value) : 27 | if not isinstance(value, self.Checker): 28 | raise TypeError("添加的 %s 必须属于 %s 类型之一" % (value, self.Checker)) 29 | return super().insert(index, value) 30 | 31 | def extend(self, iterable) : 32 | def check(iter) : 33 | for value in iter : 34 | if not isinstance(value, self.Checker) : 35 | raise TypeError("添加的 %s 必须属于 %s 类型之一" % (value, self.Checker)) 36 | else : yield value 37 | super().extend(check(iterable)) 38 | 39 | def copy(self) : 40 | return self.__class__(self).setChecker(self.Checker) 41 | 42 | def __setitem__(self, index:Union[slice, int], value) : 43 | if isinstance(index, slice) : 44 | if not all( isinstance(i, self.Checker) for i in value ) : 45 | raise TypeError("设置值需要属于 %s 类型" % list(self.Checker)) 46 | elif not isinstance(value, self.Checker): 47 | raise TypeError("设置值需要属于 %s 类型" % list(self.Checker)) 48 | return super().__setitem__(index, value) 49 | 50 | class BiList : 51 | 52 | def __init__(self, iterable:Iterable=[]) : 53 | self.__forward:List[Any] = list(iterable) 54 | self.__backward:Dict[Any, int] = {i:j for i,j in zip( reversed(self.__forward), 55 | reversed( range(len(self.__forward)) ) )} 56 | 57 | 58 | def __str__(self) : 59 | return str(self.__forward) 60 | 61 | def __repr__(self): 62 | return f"" 63 | 64 | 65 | def __iter__(self) : 66 | return self.__forward.__iter__() 67 | 68 | def __len__(self) : 69 | return len(self.__forward) 70 | 71 | def __getitem__(self, index:Any) : 72 | return self.__forward[index] if index.__class__ is int else self.__backward[index] 73 | 74 | def __setitem__(self, key:int, value:Any) : 75 | if key >= len(self.__forward) : raise IndexError(f'Key {key} out of index.') 76 | if value in self.__backward : return None 77 | if self.__forward[key] in self.__backward : del self.__backward[self.__forward[key]] 78 | self.__forward[key] = value 79 | self.__backward[value] = key 80 | 81 | def __delitem__(self, key:Union[int, Any]): 82 | if key.__class__ is int : 83 | del self.__backward[self.__forward[key]] 84 | del self.__forward[key] 85 | elif key in self.__backward : 86 | del self.__forward[self.__backward[key]] 87 | del self.__backward[key] 88 | else: raise KeyError(f'Key or value {key} not found.') 89 | 90 | 91 | def __add__(self, iter_obj: Iterable) : 92 | return self.__class__(self.__forward + list(iter_obj)) 93 | 94 | def __iadd__(self, iter_obj: Iterable) : 95 | self.extend(iter_obj) 96 | 97 | def __mul__(self, value: int) : 98 | return self.__class__(self.__forward * value) 99 | 100 | def __rmul__(self, value: int) : 101 | return self.__class__(self.__forward * value) 102 | 103 | def __imul__(self, value: int) : 104 | return self.__class__(self.__forward * value) 105 | 106 | 107 | def __contains__(self, value:Any) : 108 | return value in self.__backward 109 | 110 | def __reversed__(self) : 111 | return self.__forward.__reversed__() 112 | 113 | 114 | def clear(self) : 115 | self.__forward.clear() 116 | self.__backward.clear() 117 | 118 | def copy(self) : 119 | return self.__class__(self.__forward) 120 | 121 | def append(self, value:Any) : 122 | if value in self.__backward : return self.__backward[value] 123 | self.__backward[value] = len(self.__forward) 124 | self.__forward.append(value) 125 | return self.__backward[value] 126 | 127 | def insert(self, index:int, value:Any) : 128 | if value in self.__backward : return None 129 | self.__forward.insert(index, value) 130 | for i,j in zip(self.__forward[index:], itertools.count(index)) : 131 | self.__backward[i] = j 132 | 133 | def extend(self, iterable:Iterable) : 134 | for value in iterable : 135 | if value in self.__backward : continue 136 | self.__backward[value] = len(self.__forward) 137 | self.__forward.append(value) 138 | 139 | def pop(self, index:int) : 140 | a = self.__forward.pop(index) 141 | del self.__backward[a] 142 | for i,j in zip(self.__forward[index:], itertools.count(index)) : 143 | self.__backward[i] = j 144 | return a 145 | 146 | def remove(self, value:Any) : 147 | if value not in self.__backward : raise ValueError(f"object {value} not in list.") 148 | a = self.__backward[value] 149 | self.pop(a) 150 | 151 | def index(self, value:Any, start:int=0, stop:int=2**63-1) : 152 | return self.__forward.index(value, start, stop) 153 | 154 | -------------------------------------------------------------------------------- /main_source/update_source/import_files/default_map: -------------------------------------------------------------------------------- 1 | [ 2 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:air","BlockState":{}}, 3 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:grass","BlockState":{}}, 4 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:stone","BlockState":{"stone_type": "stone"}}, 5 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:dirt","BlockState":{"dirt_type": "normal"}}, 6 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:netherrack","BlockState":{}}, 7 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:end_stone","BlockState":{}}, 8 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:bedrock","BlockState":{"infiniburn_bit":false}}, 9 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:command_block","BlockState": {"facing_direction": 0,"conditional_bit": false}}, 10 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:command_block","BlockState": {"facing_direction": 1,"conditional_bit": false}}, 11 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:command_block","BlockState": {"facing_direction": 2,"conditional_bit": false}}, 12 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:command_block","BlockState": {"facing_direction": 3,"conditional_bit": false}}, 13 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:command_block","BlockState": {"facing_direction": 4,"conditional_bit": false}}, 14 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:command_block","BlockState": {"facing_direction": 5,"conditional_bit": false}}, 15 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:command_block","BlockState": {"facing_direction": 0,"conditional_bit": true}}, 16 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:command_block","BlockState": {"facing_direction": 1,"conditional_bit": true}}, 17 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:command_block","BlockState": {"facing_direction": 2,"conditional_bit": true}}, 18 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:command_block","BlockState": {"facing_direction": 3,"conditional_bit": true}}, 19 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:command_block","BlockState": {"facing_direction": 4,"conditional_bit": true}}, 20 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:command_block","BlockState": {"facing_direction": 5,"conditional_bit": true}}, 21 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:chain_command_block","BlockState": {"facing_direction": 0,"conditional_bit": false}}, 22 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:chain_command_block","BlockState": {"facing_direction": 1,"conditional_bit": false}}, 23 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:chain_command_block","BlockState": {"facing_direction": 2,"conditional_bit": false}}, 24 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:chain_command_block","BlockState": {"facing_direction": 3,"conditional_bit": false}}, 25 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:chain_command_block","BlockState": {"facing_direction": 4,"conditional_bit": false}}, 26 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:chain_command_block","BlockState": {"facing_direction": 5,"conditional_bit": false}}, 27 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:chain_command_block","BlockState": {"facing_direction": 0,"conditional_bit": true}}, 28 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:chain_command_block","BlockState": {"facing_direction": 1,"conditional_bit": true}}, 29 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:chain_command_block","BlockState": {"facing_direction": 2,"conditional_bit": true}}, 30 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:chain_command_block","BlockState": {"facing_direction": 3,"conditional_bit": true}}, 31 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:chain_command_block","BlockState": {"facing_direction": 4,"conditional_bit": true}}, 32 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:chain_command_block","BlockState": {"facing_direction": 5,"conditional_bit": true}}, 33 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:repeating_command_block","BlockState": {"facing_direction": 0,"conditional_bit": false}}, 34 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:repeating_command_block","BlockState": {"facing_direction": 1,"conditional_bit": false}}, 35 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:repeating_command_block","BlockState": {"facing_direction": 2,"conditional_bit": false}}, 36 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:repeating_command_block","BlockState": {"facing_direction": 3,"conditional_bit": false}}, 37 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:repeating_command_block","BlockState": {"facing_direction": 4,"conditional_bit": false}}, 38 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:repeating_command_block","BlockState": {"facing_direction": 5,"conditional_bit": false}}, 39 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:repeating_command_block","BlockState": {"facing_direction": 0,"conditional_bit": true}}, 40 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:repeating_command_block","BlockState": {"facing_direction": 1,"conditional_bit": true}}, 41 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:repeating_command_block","BlockState": {"facing_direction": 2,"conditional_bit": true}}, 42 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:repeating_command_block","BlockState": {"facing_direction": 3,"conditional_bit": true}}, 43 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:repeating_command_block","BlockState": {"facing_direction": 4,"conditional_bit": true}}, 44 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:repeating_command_block","BlockState": {"facing_direction": 5,"conditional_bit": true}}, 45 | {"__minecraft_type__":"block_nbt","Identifier":"minecraft:redstone_block","BlockState": {}} 46 | ] -------------------------------------------------------------------------------- /package/MCCommandParser/json_paser.py: -------------------------------------------------------------------------------- 1 | """ 2 | func Json_Tree 用于给外部命令树注册命令分支使用\n 3 | func json_tokenizer 用于解析json\n 4 | """ 5 | 6 | import re 7 | from typing import Dict 8 | 9 | from . import BaseMatch,SpecialMatch 10 | 11 | class Not_Parser_Object(Exception) : pass 12 | class Json_Error(BaseMatch.Command_Match_Exception) : pass 13 | 14 | class Json_Start(BaseMatch.KeyWord) : pass 15 | class List_Start(BaseMatch.KeyWord) : pass 16 | 17 | class Json_String(BaseMatch.Match_Base) : 18 | def __init__(self, token_type: str, auto_complete:Dict[str,str]=None) -> None : 19 | super().__init__(token_type) 20 | self.re_match = re.compile(r'"([^"\\]|\\u[a-fA-F0-9]{4}|\\[^u])*"') 21 | self.auto_complete = auto_complete 22 | 23 | def _match_string(self,s:str,s_pointer:int) : 24 | len_s = len(s) 25 | 26 | if s[s_pointer] != "\"" : 27 | raise SpecialMatch.Illegal_Match(">>%s<< 并不是有效的引号字符串" % s[s_pointer], pos=(s_pointer,s_pointer+1), word=s[s_pointer]) 28 | 29 | _match = self.re_match.match(s,s_pointer) 30 | if not _match : raise SpecialMatch.Illegal_Match(">>%s<< 并不是有效的引号字符串" % s[s_pointer:len_s], pos=(s_pointer,len_s), word=s[s_pointer:len_s]) 31 | 32 | return {"type":self.token_type, "token":_match.group(), "start":_match.start(), "end":_match.end()} 33 | 34 | def _auto_complete(self) -> Dict[str,str] : 35 | if self.auto_complete is None : return {'"string"':""} 36 | else : return self.auto_complete.copy() 37 | 38 | 39 | 40 | 41 | def creat_value_tree(*end_node) : 42 | Value = [ 43 | Json_String("Value").add_leaves(*end_node), 44 | BaseMatch.Float("Value").add_leaves(*end_node), 45 | BaseMatch.KeyWord("Value","true","false","null").add_leaves(*end_node), 46 | ] 47 | return Value 48 | 49 | Json = Json_Start("Json_Start","{") 50 | Json_Key_And_Value = Json_String("Key") 51 | Json_Key_And_Value.add_leaves( 52 | BaseMatch.KeyWord("To",":").add_leaves( 53 | List_Start("List_Start","[").add_leaves( 54 | BaseMatch.KeyWord("Json_End","}"), 55 | BaseMatch.KeyWord("Json_Next",",").add_leaves(Json_Key_And_Value) 56 | ), 57 | Json_Start("Json_Start","{").add_leaves( 58 | BaseMatch.KeyWord("Json_End","}"), 59 | BaseMatch.KeyWord("Json_Next",",").add_leaves(Json_Key_And_Value) 60 | ), 61 | *creat_value_tree( 62 | BaseMatch.KeyWord("Json_End","}"), 63 | BaseMatch.KeyWord("Json_Next",",").add_leaves(Json_Key_And_Value) 64 | ) 65 | ) 66 | ) 67 | Json.add_leaves(Json_Key_And_Value, BaseMatch.KeyWord("Json_End","}")) 68 | 69 | List = List_Start("List_Start","[") 70 | List.add_leaves( 71 | List_Start("List_Start","["), 72 | Json_Start("Json_Start","{"), 73 | *creat_value_tree() 74 | ) 75 | for i in List.tree_leaves : 76 | i.add_leaves( 77 | BaseMatch.KeyWord("List_End","]"), 78 | BaseMatch.KeyWord("List_Next",",").add_leaves(*List.tree_leaves) 79 | ), 80 | List.add_leaves( BaseMatch.KeyWord("List_End","]") ) 81 | 82 | 83 | def Json_Tree(*end_node) : 84 | return Json_Start("Json_Start","{").add_leaves(*end_node) 85 | 86 | 87 | class Json_Parser : 88 | 89 | parser_json_root = SpecialMatch.Command_Root().add_leaves(Json) 90 | parser_list_root = SpecialMatch.Command_Root().add_leaves(List) 91 | white_space_match = re.compile("[\\u000a\\u0020\\u000d\\u0009]{0,}") 92 | no_match_error1 = re.compile("[^\\{\\},:\\[\\]\\u000a\\u0020\\u000d\\u0009]{1,}") 93 | no_match_error2 = re.compile(".{0,1}") 94 | 95 | def __init__(self) -> None: 96 | self.recursion_count = 0 97 | self.command_str = "" 98 | self.read_pointers = 0 99 | 100 | def _parser(self, current_leaves:BaseMatch.Match_Base, Token_list:list) : 101 | self.recursion_count += 1 102 | 103 | while current_leaves.tree_leaves : 104 | is_not_successs = True 105 | for node in current_leaves.tree_leaves : 106 | if self.recursion_count > 512 : break 107 | try : a = node._match_string(self.command_str, self.read_pointers) 108 | except : continue 109 | 110 | is_not_successs = False 111 | current_leaves = node 112 | if node.__class__ is Json_Start and Json is not node : 113 | self._parser(self.parser_json_root, Token_list) 114 | elif node.__class__ is List_Start and List is not node : 115 | self._parser(self.parser_list_root, Token_list) 116 | else : Token_list.append(a) 117 | # 防止退栈时阅读指针倒退,因为匹配对象a还是之前匹配过的字符, 例子:{ "a" : { } } 118 | if a["end"] > self.read_pointers : self.read_pointers = a["end"] 119 | break 120 | 121 | if is_not_successs : 122 | _m_ = self.no_match_error1.match(self.command_str, self.read_pointers) 123 | if _m_ is None : _m_ = self.no_match_error2.match(self.command_str, self.read_pointers) 124 | raise BaseMatch.Not_Match(">>%s<< 非期望的参数" % _m_.group(), pos=(_m_.start(),_m_.end()), word=_m_.group()) 125 | 126 | self.read_pointers = self.white_space_match.match(self.command_str, self.read_pointers).end() 127 | 128 | self.recursion_count -= 1 129 | 130 | def parser(self, Token_list:list, command_str:str, pointer:int) : 131 | self.recursion_count = 0 132 | self.command_str = command_str 133 | self.read_pointers = pointer 134 | self._parser(self.parser_json_root, Token_list) 135 | Token_list[-1]["type"] = "All_Json_End" 136 | 137 | 138 | 139 | 140 | 141 | def json_tokenizer(token_list:list, s:str, pos:int) : 142 | JSON_PARSER = Json_Parser() 143 | JSON_PARSER.parser(token_list, s, pos) 144 | 145 | -------------------------------------------------------------------------------- /package/MCBEWorld/C_API/__init__.py: -------------------------------------------------------------------------------- 1 | def GetPlatform() : 2 | import subprocess, typing, platform 3 | SoftwarePlatform: typing.Literal["windows_amd64", "android", "linux_amd64", "linux_arm64"] = None 4 | result = subprocess.run("getprop ro.build.version.release", shell=True, capture_output=True, text=True) 5 | system_info = platform.uname() 6 | system = system_info.system.lower() 7 | machine = system_info.machine.lower() 8 | 9 | if system == 'windows' and machine == "amd64": SoftwarePlatform = 'windows_amd64' 10 | elif system == 'android' : SoftwarePlatform = 'android' 11 | elif result.returncode == 0 : SoftwarePlatform = 'android' 12 | elif system == 'linux' and machine == "x86_64" : SoftwarePlatform = 'linux_amd64' 13 | elif system == 'linux' and machine == "aarch64" : SoftwarePlatform = 'linux_arm64' 14 | return SoftwarePlatform 15 | 16 | def init() : 17 | import os, platform, sys, hashlib, re, zipfile, subprocess 18 | LinkCommand = "aarch64-linux-android-gcc -shared build/temp.linux-aarch64-3.9/fast_api.o -L%s -lpython%s.%s -o Linux_aarch64.pyd" 19 | py_dll_name = "MCBEWorld_C_API.%s" 20 | 21 | SysPlatfrom = GetPlatform() 22 | base_path = os.path.realpath( os.path.join(__file__, "..") ) 23 | 24 | if SysPlatfrom == "windows_amd64" : 25 | target_path = os.path.join(base_path, py_dll_name % "pyd") 26 | target_abi = os.path.join(base_path, "ABI_File", "Win_amd64.pyd") 27 | elif SysPlatfrom == "android" : 28 | zipfile1 = zipfile.ZipFile(os.path.join(base_path, "ABI_File", "Linux_aarch64.build"), "r") 29 | zipfile1.extractall( os.path.join(base_path, "ABI_File") ) 30 | lib_path_re = re.compile("lib/python[0-9]\\.[0-9]{1,}$") 31 | for lib_path in sys.path : 32 | if lib_path_re.search(lib_path) : break 33 | lib_path = os.path.realpath( os.path.join(lib_path, "..") ) 34 | subprocess.run(LinkCommand % (lib_path, sys.version_info.major, sys.version_info.minor), 35 | shell=True, capture_output=True, text=True, cwd=os.path.join(base_path, "ABI_File")) 36 | for test_path in sys.path : 37 | if not test_path.endswith("site-packages") : continue 38 | else : break 39 | target_path = os.path.join(test_path, "Command_Simulator_C_API") 40 | target_abi = os.path.join(base_path, "ABI_File", "Linux_aarch64.pyd") 41 | os.makedirs( target_path, exist_ok=True ) 42 | target_path = os.path.join(target_path, py_dll_name % "so") 43 | elif SysPlatfrom == "linux_amd64" : 44 | target_path = os.path.join(base_path, py_dll_name % "so") 45 | target_abi = os.path.join(base_path, "ABI_File", "Linux_x86_64.pyd") 46 | else : raise RuntimeError(f"未支持的系统{platform.uname()}") 47 | 48 | if os.path.isfile(target_path) : 49 | with open(target_abi, "rb") as f1 : data1 = f1.read() 50 | with open(target_path, "rb") as f2 : data2 = f2.read() 51 | if hashlib.md5(data1).digest() == hashlib.md5(data2).digest() : return None 52 | 53 | with open(target_abi, "rb") as f1 : 54 | with open(target_path, "wb") as f2 : f2.write( f1.read() ) 55 | init() 56 | 57 | try : from . import MCBEWorld_C_API 58 | except : import Command_Simulator_C_API.MCBEWorld_C_API as MCBEWorld_C_API 59 | from typing import Tuple, Union, Literal, Iterable, Any 60 | import array 61 | 62 | def cycle_xor(bytes1:bytes, bytes2:bytes) -> bytes : 63 | """ 64 | bytes2 对 bytes1 进行循环异或 65 | """ 66 | return MCBEWorld_C_API.cycle_xor(bytes1, bytes2) 67 | 68 | def chunk_upgrade(array1:array.array, block_index:bytes, block_data:bytes) -> bytes: 69 | """ 70 | 将老区块格式进行升级 71 | """ 72 | return MCBEWorld_C_API.chunk_upgrade(array1, block_index, block_data) 73 | 74 | def chunk_parser(bytes1:bytes, array1:array.array, block_use_bit:int) -> None : 75 | """ 76 | 解析区块数据 77 | """ 78 | MCBEWorld_C_API.chunk_parser(block_use_bit, array1, bytes1) 79 | 80 | def chunk_serialize(array1:array.array, block_count:int) -> bytes : 81 | """ 82 | 序列化区块数据 83 | """ 84 | return MCBEWorld_C_API.chunk_serialize(block_count, array1) 85 | 86 | def is_chunk_key(key_bytes:bytes, dimension:int) -> Union[Literal[False], tuple] : 87 | """ 88 | 序列化区块数据 89 | """ 90 | return MCBEWorld_C_API.is_chunk_key(dimension, key_bytes) 91 | 92 | def StructureOperatePosRange(startX:int, startZ:int, endX:int, endZ:int) -> \ 93 | Iterable[Tuple[int, int, int, int]] : 94 | """ 95 | 根据坐标生成坐标迭代对象 96 | (1, 1, 17, 17) -> (1, 1, 16, 16) (1, 16, 16, 17) (16, 1, 17, 16) (16, 16, 17, 17) 97 | """ 98 | return MCBEWorld_C_API.StructureOperatePosRange(startX, startZ, endX, endZ) 99 | 100 | def import_CommonStructure_to_chunk(startX:int, startY:int, startZ:int, SizeX:int, SizeY:int, SizeZ:int, 101 | chunkStartX:int, chunkStartY:int, chunkStartZ:int, chunkEndX:int, chunkEndY:int, chunkEndZ:int, 102 | subchunk, blockindex:array.array, blockList:list, Array:array.array) : 103 | """ 104 | 将结构输出进区块对象中 105 | """ 106 | MCBEWorld_C_API.CommonStructure_to_chunk(startX, startY, startZ, SizeX, SizeY, SizeZ, 107 | chunkStartX, chunkStartY, chunkStartZ, chunkEndX, chunkEndY, chunkEndZ, 108 | subchunk, blockindex, blockList, Array) 109 | 110 | def export_chunk_to_CommonStructure(startX:int, startY:int, startZ:int, SizeX:int, SizeY:int, SizeZ:int, 111 | chunkStartX:int, chunkStartY:int, chunkStartZ:int, chunkEndX:int, chunkEndY:int, chunkEndZ:int, 112 | subchunk, blockindex:array.array, blocklog:dict, blockList:list, Array1:array.array, Array2:array.array) : 113 | """ 114 | 将区块输出进结构对象中 115 | """ 116 | MCBEWorld_C_API.chunk_to_CommonStructure(startX, startY, startZ, SizeX, SizeY, SizeZ, 117 | chunkStartX, chunkStartY, chunkStartZ, chunkEndX, chunkEndY, chunkEndZ, 118 | subchunk, blockindex, blocklog, blockList, Array1, Array2) 119 | 120 | 121 | -------------------------------------------------------------------------------- /package/MCBEWorld/C_leveldb/__init__.py: -------------------------------------------------------------------------------- 1 | def GetPlatform() : 2 | import subprocess, typing, platform 3 | SoftwarePlatform: typing.Literal["windows_amd64", "android", "linux_amd64", "linux_arm64"] = None 4 | result = subprocess.run("getprop ro.build.version.release", shell=True, capture_output=True, text=True) 5 | system_info = platform.uname() 6 | system = system_info.system.lower() 7 | machine = system_info.machine.lower() 8 | 9 | if system == 'windows' and machine == "amd64": SoftwarePlatform = 'windows_amd64' 10 | elif system == 'android' : SoftwarePlatform = 'android' 11 | elif result.returncode == 0 : SoftwarePlatform = 'android' 12 | elif system == 'linux' and machine == "x86_64" : SoftwarePlatform = 'linux_amd64' 13 | elif system == 'linux' and machine == "aarch64" : SoftwarePlatform = 'linux_arm64' 14 | return SoftwarePlatform 15 | 16 | def init() : 17 | import os, platform, sys, hashlib, re, zipfile, subprocess 18 | LinkCommand = "aarch64-linux-android-c++ -shared build/temp.linux-aarch64-3.9/./leveldb-mcpe/db/builder.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/db/c.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/db/db_impl.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/db/db_iter.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/db/dbformat.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/db/filename.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/db/log_reader.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/db/log_writer.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/db/memtable.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/db/repair.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/db/table_cache.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/db/version_edit.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/db/version_set.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/db/write_batch.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/db/zlib_compressor.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/db/zstd_compressor.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/port/port_posix.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/port/port_posix_sse.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/table/block.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/table/block_builder.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/table/filter_block.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/table/format.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/table/iterator.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/table/merger.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/table/table.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/table/table_builder.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/table/two_level_iterator.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/util/arena.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/util/bloom.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/util/cache.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/util/coding.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/util/comparator.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/util/crc32c.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/util/env.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/util/env_posix.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/util/filter_policy.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/util/hash.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/util/histogram.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/util/logging.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/util/options.o build/temp.linux-aarch64-3.9/./leveldb-mcpe/util/status.o build/temp.linux-aarch64-3.9/./src/leveldb/_leveldb.o -L%s -lz -lpython%s.%s -o Linux_aarch64.pyd" 19 | py_dll_name = "_leveldb.%s" 20 | 21 | SysPlatfrom = GetPlatform() 22 | py_version = (sys.version_info.major, sys.version_info.minor) 23 | base_path = os.path.realpath( os.path.join(__file__, "..") ) 24 | 25 | if SysPlatfrom == "windows_amd64" : 26 | target_path = os.path.join(base_path, py_dll_name % "pyd") 27 | target_abi = os.path.join(base_path, "ABI_File", "Win_amd64%s.pyd" % 28 | ("" if py_version > (3, 8) else "_cp38") ) 29 | elif SysPlatfrom == "android" : 30 | zipfile1 = zipfile.ZipFile(os.path.join(base_path, "ABI_File", "Linux_aarch64.build"), "r") 31 | zipfile1.extractall( os.path.join(base_path, "ABI_File") ) 32 | lib_path_re = re.compile("lib/python[0-9]\\.[0-9]{1,}$") 33 | for lib_path in sys.path : 34 | if lib_path_re.search(lib_path) : break 35 | lib_path = os.path.realpath( os.path.join(lib_path, "..") ) 36 | subprocess.run(LinkCommand % (lib_path, sys.version_info.major, sys.version_info.minor), 37 | shell=True, capture_output=True, text=True, cwd=os.path.join(base_path, "ABI_File")) 38 | for test_path in sys.path : 39 | if not test_path.endswith("site-packages") : continue 40 | else : break 41 | target_path = os.path.join(test_path, "Command_Simulator_C_API") 42 | target_abi = os.path.join(base_path, "ABI_File", "Linux_aarch64.pyd") 43 | os.makedirs( target_path, exist_ok=True ) 44 | target_path = os.path.join(target_path, py_dll_name % "so") 45 | elif SysPlatfrom == "linux_amd64" : 46 | target_path = os.path.join(base_path, py_dll_name % "so") 47 | target_abi = os.path.join(base_path, "ABI_File", "Linux_x86_64.pyd") 48 | else : raise RuntimeError(f"未支持的系统{platform.uname()}") 49 | 50 | if os.path.isfile(target_path) : 51 | with open(target_abi, "rb") as f1 : data1 = f1.read() 52 | with open(target_path, "rb") as f2 : data2 = f2.read() 53 | if hashlib.md5(data1).digest() == hashlib.md5(data2).digest() : return None 54 | 55 | with open(target_abi, "rb") as f1 : 56 | with open(target_path, "wb") as f2 : f2.write( f1.read() ) 57 | init() 58 | 59 | 60 | try : from . import _leveldb 61 | except : import Command_Simulator_C_API._leveldb as _leveldb 62 | 63 | LevelDB = _leveldb.LevelDB 64 | LevelDBException = _leveldb.LevelDBException 65 | LevelDBEncrypted = _leveldb.LevelDBEncrypted 66 | LevelDBIteratorException = _leveldb.LevelDBIteratorException 67 | Iterator = _leveldb.Iterator 68 | 69 | # __version__ = _version.get_versions()["version"] 70 | __version__ = "0.0.1a" 71 | 72 | 73 | -------------------------------------------------------------------------------- /package/MCStructureManage/StructureMCS/mcstructure.py: -------------------------------------------------------------------------------- 1 | import os,array,ctypes 2 | from .. import nbt 3 | from ..__private import TypeCheckList 4 | from typing import Union,List,TypedDict,Dict,Literal 5 | from io import FileIO, BytesIO 6 | 7 | class BLOCK_TYPE(TypedDict): 8 | name: nbt.TAG_String 9 | states: Dict[str, Union[nbt.TAG_String, nbt.TAG_Byte, nbt.TAG_Int]] 10 | 11 | 12 | class Mcstructure : 13 | """ 14 | 基岩版 Mcstructure 结构文件对象 15 | ----------------------- 16 | * 管理 .mcstructure 为后缀的小端nbt文件 17 | * 方块按照 xyz 顺序进行储存(z坐标变化最频繁) 18 | ----------------------- 19 | * 可用属性 size : 结构长宽高(x, y, z) 20 | * 可用属性 origin : 结构保存时的位置 21 | * 可用属性 block_index : 方块索引列表(-1代表跳过) 22 | * 可用属性 contain_index : 方块是否含有其他方块,方块索引列表(例如含水,-1代表跳过) 23 | * 可用属性 block_palette : 方块对象列表(索引指向该列表内的方块) 24 | * 可用属性 entity_nbt : 实体对象列表 25 | * 可用属性 block_nbt : 以方块索引字符串数字和nbt对象组成的字典 26 | ----------------------- 27 | * 可用类方法 from_buffer : 通过路径、字节数字 或 流式缓冲区 生成对象 28 | * 可用方法 save_as : 通过路径 或 流式缓冲区 保存对象数据 29 | """ 30 | 31 | 32 | def __init__(self) : 33 | self.size: array.array = array.array("i", [0, 0, 0]) 34 | self.origin: array.array = array.array("i", [0, 0, 0]) 35 | self.block_index: array.array = array.array("i") 36 | self.contain_index: array.array = array.array("i") 37 | self.block_palette: List[nbt.TAG_Compound] = TypeCheckList().setChecker(nbt.TAG_Compound) 38 | self.entity_nbt: List[nbt.TAG_Compound] = TypeCheckList().setChecker(nbt.TAG_Compound) 39 | self.block_nbt: Dict[int, nbt.TAG_Compound] = {} 40 | 41 | def __setattr__(self, name, value) : 42 | if not hasattr(self, name) : super().__setattr__(name, value) 43 | elif isinstance(value, type(getattr(self, name))) : super().__setattr__(name, value) 44 | else : raise Exception("无法修改 %s 属性" % name) 45 | 46 | def __delattr__(self, name) : 47 | raise Exception("无法删除任何属性") 48 | 49 | 50 | def error_check(self) : 51 | ValueType = (nbt.TAG_String, nbt.TAG_Byte, nbt.TAG_Int) 52 | Volume = self.size[0] * self.size[1] * self.size[2] 53 | if len(self.size) != 3 : raise Exception("结构长宽高列表长度不为3") 54 | if len(self.origin) != 3 : raise Exception("结构保存位置列表长度不为3") 55 | if len(self.block_index) != Volume : raise Exception("方块索引列表长度与结构体积不相等") 56 | if len(self.contain_index) != Volume : raise Exception("方块含水列表长度与结构体积不相等") 57 | 58 | if max(self.contain_index) >= len(self.block_palette) : 59 | raise Exception("方块包含列表 中存在超出 方块对象列表 的索引长度值") 60 | if max(self.block_index) >= len(self.block_palette) : 61 | raise Exception("方块索引列表 中存在超出 方块对象列表 的索引长度值") 62 | for block in self.block_palette : 63 | Error = "方块列表中存在不合法的方块数据( %s )" 64 | if not isinstance(block.get("name", None), nbt.TAG_String) : raise Exception(Error % block) 65 | if not isinstance(block.get("states", None), nbt.TAG_Compound) : raise Exception(Error % block) 66 | if not all((isinstance(key, str) and isinstance(value, ValueType)) 67 | for key,value in block["states"].items()) : raise Exception(Error % block) 68 | for index, block_nbt in self.block_nbt.items() : 69 | if not isinstance(index, int) : raise Exception("方块NBT索引存在不为整数的对象( %s )" % index) 70 | elif not isinstance(block_nbt, nbt.TAG_Compound) : raise Exception("方块NBT对象存在不为NBT组件的对象( %s )" % block_nbt) 71 | 72 | 73 | @classmethod 74 | def from_buffer(cls, buffer:Union[str, FileIO, BytesIO]) : 75 | NBT = nbt.read_from_nbt_file(buffer, byteorder="little") 76 | 77 | StructureObject = cls() 78 | StructureObject.size = NBT["size"].get_value() 79 | StructureObject.origin = NBT["structure_world_origin"].get_value() 80 | StructureObject.block_index = NBT['structure']['block_indices'][0].get_value() 81 | StructureObject.contain_index = NBT['structure']['block_indices'][1].get_value() 82 | StructureObject.block_palette.extend(NBT['structure']['palette']['default']['block_palette']) 83 | StructureObject.entity_nbt.extend(NBT['structure']['entities']) 84 | for index_str, block_nbt in NBT['structure']['palette']['default']['block_position_data'].items() : 85 | StructureObject.block_nbt[int(index_str)] = block_nbt 86 | 87 | return StructureObject 88 | 89 | def save_as(self, buffer:Union[str, FileIO, BytesIO]) : 90 | #self.error_check() 91 | 92 | StructureNBT = nbt.TAG_Compound() 93 | StructureNBT['format_version'] = nbt.TAG_Int(1) 94 | StructureNBT['size'] = nbt.TAG_List(self.size, type=nbt.TAG_Int) 95 | StructureNBT['structure_world_origin'] = nbt.TAG_List(self.origin, type=nbt.TAG_Int) 96 | StructureNBT['structure'] = nbt.TAG_Compound() 97 | StructureBlockIndices = StructureNBT['structure']['block_indices'] = nbt.TAG_List(type=nbt.TAG_List) 98 | StructureBlockIndices.append( nbt.TAG_List(self.block_index, nbt.TAG_Int) ) 99 | StructureBlockIndices.append( nbt.TAG_List(self.contain_index, nbt.TAG_List) ) 100 | 101 | StructureEntity = StructureNBT['structure']['entities'] = nbt.TAG_List(type=nbt.TAG_Compound) 102 | StructureNBT['structure']['palette'] = nbt.TAG_Compound() 103 | StructureNBT['structure']['palette']['default'] = nbt.TAG_Compound() 104 | StructureBlockPalette = StructureNBT['structure']['palette']['default']['block_palette'] = nbt.TAG_List(type=nbt.TAG_Compound) 105 | StructureBlockNBT = StructureNBT['structure']['palette']['default']['block_position_data'] = nbt.TAG_Compound() 106 | 107 | if self.entity_nbt : StructureEntity.extend(self.entity_nbt) 108 | if self.block_palette : StructureBlockPalette.extend(self.block_palette) 109 | for index, block_nbt in self.block_nbt.items() : StructureBlockNBT[str(index)] = block_nbt 110 | 111 | if isinstance(buffer, str) : 112 | base_path = os.path.realpath(os.path.join(buffer, os.pardir)) 113 | os.makedirs(base_path, exist_ok=True) 114 | _file = open(buffer, "wb") 115 | else : _file = buffer 116 | nbt.write_to_nbt_file(_file, StructureNBT, byteorder="little") 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /main_source/bedrock_edition/command_class/compiler/rawtext.py: -------------------------------------------------------------------------------- 1 | from typing import List,Dict,Union,Literal,Tuple 2 | from ... import RunTime 3 | from .. import ID_tracker,COMMAND_CONTEXT,Response 4 | from . import Selector,CompileError,CommandParser 5 | import re,functools 6 | 7 | selector_tree = CommandParser.SpecialMatch.Command_Root().add_leaves(*CommandParser.SpecialMatch.BE_Selector_Tree(CommandParser.BaseMatch.END_NODE)) 8 | Parser = CommandParser.ParserSystem.Command_Parser(selector_tree) 9 | 10 | 11 | def Rawtext_Compiler(_game:RunTime.minecraft_thread, version:List[int], rawtext_json:dict): 12 | Rawtext_Analysis(_game, version, rawtext_json) 13 | return functools.partial(RunTime_Rawtext, rawtext_json=rawtext_json) 14 | 15 | def Rawtext_Analysis(_game:RunTime.minecraft_thread, version:List[int], rawtext_json:dict) : 16 | if "rawtext" not in rawtext_json : raise CompileError("rawtext json需要存在 rawtext 指定") 17 | if not isinstance(rawtext_json["rawtext"], list) : raise CompileError("rawtext json的 rawtext 需要提供列表") 18 | 19 | for text_json in rawtext_json["rawtext"] : 20 | if "text" in text_json : 21 | if not isinstance(text_json["text"], str) : raise CompileError("rawtext json的 text 对象需要提供字符串") 22 | 23 | elif "selector" in text_json : 24 | if not isinstance(text_json["selector"], str) : raise CompileError("rawtext json的 selector 需要提供字符串") 25 | token_list = Parser.parser(text_json["selector"], version) 26 | if isinstance(token_list, tuple) : raise CompileError("selector组件中的选择器" + token_list[0]) 27 | _,entity_func = Selector.Selector_Compiler(_game, token_list, 0, is_player=True) 28 | text_json["selector"] = entity_func 29 | 30 | elif "scores" in text_json : 31 | if not isinstance(text_json["scores"], dict) : raise CompileError("rawtext json的 scores 需要提供对象") 32 | if "objective" not in text_json["scores"] : raise CompileError("rawtext json的 scores 需要提供 objective 指定") 33 | if not isinstance(text_json["scores"]["objective"], str) : raise CompileError("rawtext json的 scores.objective 需要提供字符串") 34 | if "name" not in text_json["scores"] : raise CompileError("rawtext json的 scores 需要提供 name 指定") 35 | if not isinstance(text_json["scores"]["name"], str) : raise CompileError("rawtext json的 scores.name 需要提供字符串") 36 | token_list = Parser.parser(text_json["scores"]["name"], version) 37 | if isinstance(token_list, tuple) : raise CompileError("选择器" + token_list[0]) 38 | if token_list[0]["token"][0] == "@" : 39 | _,entity_func = Selector.Selector_Compiler(_game, token_list, 0, is_player=True) 40 | text_json["scores"]["name"] = entity_func 41 | 42 | elif "translate" in text_json : 43 | if not isinstance(text_json["translate"], str) : raise CompileError("rawtext json的 translate 需要提供字符串") 44 | if "with" in text_json and isinstance(text_json["with"], dict) : Rawtext_Compiler(_game, version, text_json["with"]) 45 | elif "with" in text_json and isinstance(text_json["with"], list) and not all([isinstance(i,str) for i in text_json["with"]]) : 46 | raise CompileError("rawtext json的 translate.with 需要提供只含有字符串的列表") 47 | elif "with" in text_json : raise CompileError("rawtext json的 translate.with 需要提供字符串列表或rawtext json") 48 | 49 | else : 50 | raise CompileError("rawtext json的元素需要提供有效的组件信息( %s )" % text_json) 51 | 52 | 53 | def RunTime_Rawtext(execute_var:COMMAND_CONTEXT, _game:RunTime.minecraft_thread, rawtext_json:dict): 54 | text_list = RunTime_Analysis(execute_var, _game, rawtext_json) 55 | return "".join(text_list) 56 | 57 | def RunTime_Analysis(execute_var:COMMAND_CONTEXT, _game:RunTime.minecraft_thread, rawtext_json:dict): 58 | text_list:List[str] = [] 59 | for text_json in rawtext_json["rawtext"] : 60 | if "text" in text_json : text_list.append(text_json["text"]) 61 | 62 | elif "selector" in text_json : 63 | entity_list = text_json["selector"](execute_var, _game) 64 | if isinstance(entity_list, Response.Response_Template) : continue 65 | text_list.append(", ".join( (ID_tracker(i) for i in entity_list) )) 66 | 67 | elif "scores" in text_json and isinstance(text_json["scores"]["name"], str) : 68 | board,name = text_json["scores"]["objective"],text_json["scores"]["name"] 69 | score_value = _game.minecraft_scoreboard.____get_score____(board, name) 70 | if score_value != Exception : text_list.append(str(score_value)) 71 | 72 | elif "scores" in text_json : 73 | board = text_json["scores"]["objective"] 74 | entity_list = text_json["scores"]["name"](execute_var, _game) 75 | if isinstance(entity_list, Response.Response_Template) or \ 76 | not _game.minecraft_scoreboard.____scb_exists____(board) : continue 77 | text_list.append(", ".join( (_game.minecraft_scoreboard.____get_score____(board, i) 78 | for i in entity_list if _game.minecraft_scoreboard.____score_exists____(board, i)) )) 79 | 80 | elif "translate" in text_json : 81 | rawtext_list = [] 82 | if "with" in text_json and isinstance(text_json["with"], dict) : 83 | rawtext_list = RunTime_Analysis(execute_var, _game, text_json["with"]) 84 | elif "with" in text_json and isinstance(text_json["with"], list) : 85 | rawtext_list = text_json["with"] 86 | 87 | pointer, translate_text = 0, text_json["translate"] 88 | while ("%%s" in translate_text) : 89 | if pointer >= rawtext_list.__len__() : translate_text = translate_text.replace("%%s","",1) 90 | else : translate_text = translate_text.replace("%%s",rawtext_list[pointer],1) 91 | pointer += 1 92 | 93 | while 1 : 94 | re_test1 = re.search("%%[0-9]", translate_text) 95 | if re_test1 is None : break 96 | replace_pointer = pointer + int(re_test1.group().replace("%%", "", 1)) - 1 97 | if replace_pointer >= rawtext_list.__len__() : translate_text = translate_text.replace(re_test1.group(),"",1) 98 | else : translate_text = translate_text.replace(re_test1.group(), rawtext_list[replace_pointer], 1) 99 | 100 | text_list.append(translate_text) 101 | return text_list -------------------------------------------------------------------------------- /main_source/bedrock_edition/game_class/expand_pack.py: -------------------------------------------------------------------------------- 1 | from typing import List,Dict,Union,Literal,Tuple 2 | from . import RunTime 3 | import re 4 | 5 | 6 | class block_object : 7 | 8 | def __init__(self,id:str,state:dict,nbt:dict) -> None: 9 | self.Identifier = id 10 | self.BlockState = state 11 | self.BlockEntityTag = nbt 12 | 13 | 14 | class visualization : 15 | 16 | def __init__(self,game_thread:RunTime.minecraft_thread) -> None: 17 | from .. import CommandParser,CommandCompiler 18 | 19 | self.Selector = CommandParser.ParserSystem.Command_Parser( 20 | CommandParser.SpecialMatch.Command_Root().add_leaves( 21 | *CommandParser.SpecialMatch.BE_Selector_Tree(CommandParser.BaseMatch.END_NODE) 22 | ) 23 | ) 24 | self.Compiler = CommandCompiler.Selector.Selector_Compiler 25 | 26 | self.game_thread = game_thread 27 | self.first_get_ready = False 28 | self.defalt_chunk = [0] * (16 * 16 * 384) 29 | 30 | self.start_x = 0 ; self.start_y = -64 ; self.start_z = 0 31 | self.area_x = 16 ; self.area_y = 1 ; self.area_z = 16 32 | 33 | self.track_entity = [] 34 | self.debug_data = [] 35 | 36 | 37 | def reset_var(self,var_json:dict): 38 | target_var_name_test = re.compile("^entity_target_") 39 | color_name = {"entity_target_0": "pink", "entity_target_1": "purple","entity_target_2": "yellow", 40 | "entity_target_3": "brown", "entity_target_4": "lightblue"} 41 | int_test = re.compile("^-?[0-9]{0,}$\\b") 42 | error_var_list = {} ; self.track_entity.clear() ; self.debug_data.clear() 43 | self.first_get_ready = False 44 | 45 | for var_name in list(var_json) : 46 | var_name : str 47 | if var_json[var_name].replace(" ","") == "" : continue 48 | elif target_var_name_test.search(var_name) : 49 | Token1 = self.Selector.parser(var_json[var_name], self.game_thread.game_version) 50 | if isinstance(Token1, tuple) : error_var_list[var_name] = Token1[0] ; continue 51 | try : selector_func = self.Compiler(self.game_thread, Token1, 0) 52 | except Exception as e : error_var_list[var_name] = e.args[0] ; continue 53 | self.track_entity.append({"entity": selector_func[1], "color": color_name[var_name]}) 54 | 55 | else : 56 | if int_test.search(var_json[var_name]) is None : 57 | error_var_list[var_name] = "输入数据并不是整数" ; continue 58 | if var_name in ["area_x","area_z"] and not(1 <= int(var_json[var_name]) <= 100) : 59 | error_var_list[var_name] = "输入的整数超过未在1~128之间" ; continue 60 | if var_name in ["area_y"] and not(1 <= int(var_json[var_name]) <= 384) : 61 | error_var_list[var_name] = "输入的整数超过未在1~384之间" ; continue 62 | setattr(self, var_name, int(var_json[var_name])) 63 | return error_var_list 64 | 65 | 66 | def save_a_test_data(self) : 67 | debug_dict = { 68 | "chunks": self.get_debug_chunks() if self.game_thread.in_game_tag else {}, 69 | "entities": self.get_debug_entity() if self.game_thread.in_game_tag else [], 70 | "particle": self.game_thread.runtime_variable.particle_alive["overworld"].copy(), 71 | "global_time" : int(self.game_thread.minecraft_world.game_time), 72 | "var_saves" : {"start_x":self.start_x, "start_y":self.start_y, "start_z":self.start_z, 73 | "area_x":self.area_x, "area_y":self.area_y, "area_z":self.area_z} 74 | } 75 | self.debug_data.append(debug_dict) 76 | if not self.game_thread.in_game_tag : self.set_test_end_flag() 77 | 78 | def get_debug_chunks(self) : 79 | chunks = {} 80 | 81 | chunk_start = [self.start_x // 16 * 16, self.start_z // 16 * 16] 82 | chunk_end = [(self.start_x + self.area_x - 1) // 16 * 16, (self.start_z + self.area_z - 1 ) // 16 * 16] 83 | dimension_data = self.game_thread.minecraft_chunk.loading_chunk["overworld"] 84 | m1 = chunk_start[1] 85 | while chunk_start[0] <= chunk_end[0] : 86 | while chunk_start[1] <= chunk_end[1] : 87 | if not self.game_thread.in_game_tag : return {} 88 | chunk_pos_1 = "(%s, %s)" % tuple(chunk_start) 89 | if tuple(chunk_start) in dimension_data : chunks[chunk_pos_1] = dimension_data[tuple(chunk_start)]['blocks'][0:self.area_y*16*16] 90 | else : chunks[chunk_pos_1] = self.defalt_chunk[0:self.area_y*16*16] 91 | chunk_start[1] += 16 92 | chunk_start[0] += 16 ; chunk_start[1] = m1 93 | chunks["block_map"] = [i.Identifier for i in self.game_thread.minecraft_chunk.block_mapping] 94 | return chunks 95 | 96 | def get_debug_entity(self) : 97 | entity = [] 98 | for entity_test in self.track_entity : 99 | execute_var = {"executer":"Server","dimension":"overworld","pos":[0,0,0],"rotate":[0,0], 100 | "version":self.game_thread.game_version} 101 | entity_list = entity_test['entity'](execute_var, self.game_thread) 102 | if not isinstance(entity_list, list) : entity.append({"entity":[],"color":entity_test["color"]}) ; continue 103 | entity.append({ 104 | "entity":[i.__save__() for i in entity_list if ( 105 | self.start_x <= i.Pos[0] <= (self.start_x + self.area_x) and self.start_z <= i.Pos[2] <= (self.start_z + self.area_z)) 106 | ],"color":entity_test["color"]}) 107 | return entity 108 | 109 | def set_test_end_flag(self) : 110 | self.debug_data.append("Test_End") 111 | self.first_get_ready = False 112 | 113 | 114 | def get_test_data(self,times:int) : 115 | if (self.area_x * self.area_z) >= (80 * 80) : base1 = 5 116 | if (self.area_x * self.area_z) >= (60 * 60) : base1 = 12 117 | if (self.area_x * self.area_z) >= (40 * 40) : base1 = 18 118 | if (self.area_x * self.area_z) >= (20 * 20) : base1 = 40 119 | if (self.area_x * self.area_z) >= (0 * 0) : base1 = 60 120 | a = self.debug_data[times * base1 : base1 * (times + 1)] 121 | if len(a) == 0 : return None 122 | return a 123 | 124 | 125 | def at_exit(self) : 126 | self.debug_data.clear() 127 | self.game_thread = None 128 | 129 | 130 | -------------------------------------------------------------------------------- /main_source/bedrock_edition/math_func.py: -------------------------------------------------------------------------------- 1 | from . import np 2 | import math 3 | from typing import List,Literal,Union 4 | 5 | 6 | def vector_add(v1:List[float], v2:List[float]) : 7 | return [v1[0]+v2[0], v1[1]+v2[1], v1[2]+v2[2]] 8 | 9 | def vector_remove(v1:List[float], v2:List[float]) : 10 | return [v1[0]-v2[0], v1[1]-v2[1], v1[2]-v2[2]] 11 | 12 | def vector_number_product(v1:List[float], value1:float) : 13 | return [v1[0]*value1, v1[1]*value1, v1[2]*value1] 14 | 15 | def vector_number_div(v1:List[float], value1:float) : 16 | return [v1[0]*value1, v1[1]*value1, v1[2]*value1] 17 | 18 | def vector_unit(v1:List[float]) : 19 | value1 = sum([v1[0]**2, v1[1]**2, v1[2]**2]) ** 0.5 20 | return [v1[0]/value1, v1[1]/value1, v1[2]/value1] 21 | 22 | def vector_dot_product(v1:List[float], v2:List[float]) : 23 | return sum([v1[0]*v2[0], v1[1]*v2[1], v1[2]*v2[2]]) 24 | 25 | def vector_cross_product(v1:List[float], v2:List[float]) : 26 | x = v1[1] * v2[2] - v1[2] * v2[1] 27 | y = -(v1[0] * v2[2] - v1[2] * v2[0]) 28 | z = v1[0] * v2[1] - v1[1] * v2[0] 29 | return [x,y,z] 30 | 31 | def mc_rotation_pos(distance:float, ry:float, rx:float): 32 | ry1 = -ry*math.pi/180 33 | rx1 = -rx*math.pi/180 34 | z = distance*math.cos(ry1)*math.cos(rx1) 35 | x = distance*math.sin(ry1)*math.cos(rx1) 36 | y = distance*math.sin(rx1) 37 | return [x,y,z] 38 | 39 | def mc_rotation_base_vector(ry:float, rx:float): 40 | v1 = mc_rotation_pos(1,ry,rx) 41 | v2 = mc_rotation_pos(1,ry,rx-90) 42 | v3 = mc_rotation_pos(1,ry-90,0) 43 | return [v3,v2,v1] 44 | 45 | def vector_transform(vector:List[float], base_vector:List[List[float]]) : 46 | v1 = [0,0,0] 47 | for i in range(3) : 48 | v1 = vector_add(v1,vector_number_product(base_vector[i],vector[i])) 49 | return v1 50 | 51 | def mitrax_transform(trans_vector:List[float],base_vector:List[List[float]]) : 52 | result:List[float] = [] 53 | for i in range(3) : 54 | v1 = vector_transform(trans_vector[i],base_vector) 55 | result.append(v1) 56 | return result 57 | 58 | 59 | def mc_point2level(point_value:int): 60 | a,b,c = 1,6,-point_value 61 | x1 = (-b + (b * b - 4 * a * c)**0.5) / (2 * a) 62 | x2 = (-b - (b * b - 4 * a * c)**0.5) / (2 * a) 63 | if 0 <= x1 < 17 : return int(x1) 64 | elif 0 <= x2 < 17 : return int(x2) 65 | 66 | a,b,c = 2.5,-40.5,-point_value+360 67 | x1 = (-b + (b * b - 4 * a * c)**0.5) / (2 * a) 68 | x2 = (-b - (b * b - 4 * a * c)**0.5) / (2 * a) 69 | if 17 <= x1 < 32 : return int(x1) 70 | elif 17 <= x2 < 32 : return int(x2) 71 | 72 | a,b,c = 4.5,-162.5,-point_value+2220 73 | x1 = (-b + (b * b - 4 * a * c)**0.5) / (2 * a) 74 | x2 = (-b - (b * b - 4 * a * c)**0.5) / (2 * a) 75 | if 32 <= x1 : return int(x1) 76 | elif 32 <= x2 : return int(x2) 77 | 78 | def mc_next_levelup(level_value:int): 79 | if 0 <= level_value <= 15 : return (2 * level_value + 7) 80 | elif 16 <= level_value <= 30 : return (5 * level_value - 38) 81 | elif 31 <= level_value : return (9 * level_value - 158) 82 | 83 | def mc_level2point(level_value:int): 84 | if 0 <= level_value < 17 : a,b,c = 1,6,0 85 | if 17 <= level_value < 32 : a,b,c = 2.5,-40.5,360 86 | if 32 <= level_value : a,b,c = 4.5,-162.5,2220 87 | return a * level_value * level_value + b * level_value + c 88 | 89 | 90 | def normal_distribution(x:float) -> float : 91 | return 1 - pow(math.e, 6*x*x*-1) 92 | 93 | 94 | def rotation_angle(pos1:List[float], pos2:List[float]): 95 | v1 = [pos2[0]-pos1[0], pos2[1]-pos1[1], pos2[2]-pos1[2]] 96 | if -0.0000001 < sum(v1) < 0.0000001 : return (0.0, 0.0) 97 | 98 | v3 = vector_unit(v1) 99 | rx = math.asin(v3[1]) / math.pi * 180 * -1 100 | if -0.0000001 < sum((v3[0],v3[2])) < 0.0000001 : return (0.0, rx) 101 | 102 | ry = math.acos( v3[2] / ((v3[0] ** 2 + v3[2] ** 2) ** 0.5) ) 103 | ry = ry / math.pi * 180 * (-1 if v1[0] > 0 else 1) 104 | return (ry,rx) 105 | 106 | def mc_rotate_compute(rotate_start:float, rotate_offset:Union[str, float], 107 | mode:Literal["rx","ry"]="ry", can_outside_limit:bool=False) -> np.float32 : 108 | if rotate_offset.__class__ is str and rotate_offset[0] != "~" : rotate_value = np.float32(rotate_offset) 109 | if len(rotate_offset) == 1 : rotate_value = np.float32(rotate_start) 110 | else : rotate_value = rotate_start + float(rotate_offset[1:]) 111 | 112 | if mode == "ry" : 113 | rotate_value -= math.ceil(rotate_value / 360) * 360.0 114 | if rotate_value > 180 : rotate_value -= 360 115 | elif rotate_value < -180 : rotate_value += 360 116 | return np.float32(rotate_value) 117 | else : 118 | if not can_outside_limit : 119 | if rotate_value > 90 : return np.float32(90.0) 120 | elif rotate_value < -90 : return np.float32(-90.0) 121 | else : return np.float32(rotate_value) 122 | else : return np.float32(rotate_value) 123 | 124 | def mc_pos_compute(origin:List[float], pos_offset:List[Union[str,float,int]], rotate:List[float]): 125 | pos_result = list(origin) 126 | 127 | if all(i.__class__ is str for i in pos_offset) and pos_offset[0][0] == \ 128 | pos_offset[1][0] == pos_offset[2][0] == "^" : 129 | base1 = mc_rotation_base_vector(rotate[0],rotate[1]) 130 | for i in range(3) : 131 | number1 = np.float32(pos_offset[i][1:]) if len(pos_offset[i][1:]) else 0 132 | pos_result[0] += number1 * base1[i][0] 133 | pos_result[1] += number1 * base1[i][1] 134 | pos_result[2] += number1 * base1[i][2] 135 | return pos_result 136 | else : 137 | for i, pos_value in enumerate(pos_offset) : 138 | if pos_value.__class__ is str : 139 | if pos_value == "~" : continue 140 | elif pos_value[0] == "~" : pos_result[i] += np.float32(pos_value[1:]) 141 | elif pos_value.__class__ is float : pos_result[i] = np.float32(pos_value) 142 | else : pos_result[i] = np.float32(pos_value) + 0.5 143 | for i,j in enumerate(pos_result) : pos_result[i] = max(min(float(j),30000000.0), -30000000.0) 144 | return pos_result 145 | 146 | 147 | def version_compare(version1:List[int], version2:List[int]) : 148 | version_int1 = version1[0] * 1000000 + version1[1] * 1000 + version1[2] 149 | version_int2 = version2[0] * 1000000 + version2[1] * 1000 + version2[2] 150 | if version_int1 > version_int2 : return 1 151 | elif version_int1 < version_int2 : return -1 152 | else : return 0 153 | 154 | 155 | 156 | --------------------------------------------------------------------------------