From 16be83ea29d78c533598d1b7e143b5bb0901c377 Mon Sep 17 00:00:00 2001 From: Eilles Wan Date: Sun, 19 Feb 2023 02:25:00 +0000 Subject: [PATCH 01/10] update README.md. Signed-off-by: Eilles Wan --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 345157b..d29b847 100644 --- a/README.md +++ b/README.md @@ -91,14 +91,20 @@ -------------------------------------------- -NOT AN OFFICIAL MINECRAFT PRODUCT. - -NOT APPROVED BY OR ASSOCIATED WITH MOJANG OR MICROSOFT. - 此项目并非一个官方 《我的世界》(*Minecraft*)项目 此项目不隶属或关联于 Mojang Studios 或 微软 +此项目亦不与 网易 相关 + +“Minecraft”是 Mojang Synergies AB 的商标,此项目中所有对于“我的世界”、“Minecraft”等相关称呼均为引用性使用 + +* 上文提及的 网易 公司,指代的是在中国大陆运营《我的世界:中国版》的上海网之易网络科技发展有限公司 + +NOT AN OFFICIAL MINECRAFT PRODUCT. + +NOT APPROVED BY OR ASSOCIATED WITH MOJANG OR MICROSOFT. + From bd329082c24d377a5c59d56b75b53f2baec4934b Mon Sep 17 00:00:00 2001 From: EillesWan Date: Sun, 5 Mar 2023 18:58:05 +0800 Subject: [PATCH 02/10] =?UTF-8?q?=E8=BF=99=E4=B8=8D=E6=98=AF=E6=9C=80?= =?UTF-8?q?=E7=BB=88=E7=89=88=E6=9C=AC=EF=BC=8C=E8=AF=B7=E4=B8=8D=E8=A6=81?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Musicreater/__init__.py | 8 ++-- Musicreater/exceptions.py | 14 +++--- Musicreater/main.py | 32 +++++++++----- Musicreater/utils.py | 91 ++++++++++++++++++++++++++++++++++++++- README.md | 4 +- requirements.txt | 3 +- 6 files changed, 126 insertions(+), 26 deletions(-) diff --git a/Musicreater/__init__.py b/Musicreater/__init__.py index 6473b31..b13efda 100644 --- a/Musicreater/__init__.py +++ b/Musicreater/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """一个简单的我的世界音频转换库 -音·创 库版 (Musicreater) +音·创 (Musicreater) 是一款免费开源的针对《我的世界》的midi音乐转换库 Musicreater(音·创) A free open source library used for convert midi file into formats that is suitable for **Minecraft**. @@ -12,14 +12,14 @@ Copyright © 2023 all the developers of Musicreater Terms & Conditions: ../License.md """ -# 音·创 开发交流群 861684859 -# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com +# 睿穆组织 开发交流群 861684859 +# Email TriM-Organization@hotmail.com # 版权所有 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray") & 鸣凤鸽子("MingFengPigeon") # 若需转载或借鉴 许可声明请查看仓库目录下的 License.md from .main import * -__version__ = "0.3.2" +__version__ = "0.3.3" __all__ = [] __author__ = (("金羿", "Eilles Wan"), ("诸葛亮与八卦阵", "bgArray")) diff --git a/Musicreater/exceptions.py b/Musicreater/exceptions.py index bc68d22..9db92b9 100644 --- a/Musicreater/exceptions.py +++ b/Musicreater/exceptions.py @@ -1,17 +1,17 @@ # -*- coding: utf-8 -*- -# 音·创 开发交流群 861684859 -# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com +# 睿穆组织 开发交流群 861684859 +# Email TriM-Organization@hotmail.com # 版权所有 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray") & 鸣凤鸽子("MingFengPigeon") # 若需转载或借鉴 许可声明请查看仓库目录下的 License.md -""" -音·创 库版 (Musicreater Package Version) -是一款免费开源的针对《我的世界:基岩版》的midi音乐转换库 -Musicreater pkgver (Package Version 音·创 库版) -A free open source library used for convert midi file into formats that is suitable for **Minecraft: Bedrock Edition**. +"""一个简单的我的世界音频转换库 +音·创 (Musicreater) +是一款免费开源的针对《我的世界》的midi音乐转换库 +Musicreater(音·创) +A free open source library used for convert midi file into formats that is suitable for **Minecraft**. 版权所有 © 2023 音·创 开发者 Copyright © 2023 all the developers of Musicreater diff --git a/Musicreater/main.py b/Musicreater/main.py index 6fc6d40..d1d3bd7 100644 --- a/Musicreater/main.py +++ b/Musicreater/main.py @@ -2,7 +2,7 @@ # 音·创 开发交流群 861684859 -# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com +# Email TriM-Organization@hotmail.com # 版权所有 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray") & 鸣凤鸽子("MingFengPigeon") # 若需转载或借鉴 许可声明请查看仓库目录下的 License.md @@ -1471,7 +1471,17 @@ class midiConvert: :param player: 玩家选择器,默认为`@a` :return 成功与否,成功返回(True,未经过压缩的源,结构占用大小),失败返回(False,str失败原因) """ - pass + cmdlist, max_delay = self.methods_byDelay[method - 1]( + volume, + speed, + player, + ) + + if not os.path.exists(self.outputPath): + os.makedirs(self.outputPath) + + + def to_BDX_file( self, @@ -1552,9 +1562,9 @@ class midiConvert: max_height - 1, ) _bytes += pgbBytes - _bytes += move(y, -pgbNowPos[1]) - _bytes += move(z, -pgbNowPos[2]) - _bytes += move(x, 2) + _bytes += bdx_move(y, -pgbNowPos[1]) + _bytes += bdx_move(z, -pgbNowPos[2]) + _bytes += bdx_move(x, 2) size[0] += 2 + pgbSize[0] size[1] = max(size[1], pgbSize[1]) @@ -1632,14 +1642,14 @@ class midiConvert: 1, customName="初始化进度条", ) - _bytes += move(z, 2) + _bytes += bdx_move(z, 2) _bytes += form_command_block_in_BDX_bytes( r"scoreboard players add {} {} 1".format(player, scb_name), 1, 1, customName="显示进度条并加分", ) - _bytes += move(y, 1) + _bytes += bdx_move(y, 1) pgbBytes, pgbSize, pgbNowPos = to_BDX_bytes( [ (i, 0) @@ -1648,15 +1658,15 @@ class midiConvert: max_height - 1, ) _bytes += pgbBytes - _bytes += move(y, -1 - pgbNowPos[1]) - _bytes += move(z, -2 - pgbNowPos[2]) - _bytes += move(x, 2) + _bytes += bdx_move(y, -1 - pgbNowPos[1]) + _bytes += bdx_move(z, -2 - pgbNowPos[2]) + _bytes += bdx_move(x, 2) _bytes += form_command_block_in_BDX_bytes( r"scoreboard players reset {} {}".format(player, scb_name), 1, customName="置零进度条", ) - _bytes += move(y, 1) + _bytes += bdx_move(y, 1) size[0] += 2 + pgbSize[0] size[1] = max(size[1], pgbSize[1]) size[2] = max(size[2], pgbSize[2]) diff --git a/Musicreater/utils.py b/Musicreater/utils.py index 229d99b..434eeea 100644 --- a/Musicreater/utils.py +++ b/Musicreater/utils.py @@ -14,7 +14,7 @@ y = "y" z = "z" -def move(axis: str, value: int): +def bdx_move(axis: str, value: int): if value == 0: return b"" if abs(value) == 1: @@ -220,3 +220,92 @@ def to_BDX_bytes( ], [now_x, now_y, now_z], ) + +def to_structure( + commands: list, + max_height: int = 64, +): + """ + :param commands: 指令列表(指令, 延迟) + :param max_height: 生成结构最大高度 + :return 成功与否,成功返回(True,未经过压缩的源,结构占用大小),失败返回(False,str失败原因) + """ + # 导入库 + from mcstructure import Block, Structure + + _sideLength = bottem_side_length_of_smallest_square_bottom_box(len(commands), max_height) + + struct = Structure( + (_sideLength, max_height, _sideLength), # 声明结构大小 + ) + + y_forward = True + z_forward = True + + now_y = 0 + now_z = 0 + now_x = 0 + + for cmd, delay in commands: + impluse = 2 + condition = False + needRedstone = False + tickDelay = delay + customName = "" + executeOnFirstTick = False + trackOutput = True + _bytes += form_command_block_in_BDX_bytes( + cmd, + (1 if y_forward else 0) + if ( + ((now_y != 0) and (not y_forward)) + or (y_forward and (now_y != (max_height - 1))) + ) + else (3 if z_forward else 2) + if ( + ((now_z != 0) and (not z_forward)) + or (z_forward and (now_z != _sideLength)) + ) + else 5, + impluse=impluse, + condition=condition, + needRedstone=needRedstone, + tickDelay=tickDelay, + customName=customName, + executeOnFirstTick=executeOnFirstTick, + trackOutput=trackOutput, + ) + + now_y += 1 if y_forward else -1 + + if ((now_y >= max_height) and y_forward) or ((now_y < 0) and (not y_forward)): + now_y -= 1 if y_forward else -1 + + y_forward = not y_forward + + now_z += 1 if z_forward else -1 + + if ((now_z > _sideLength) and z_forward) or ( + (now_z < 0) and (not z_forward) + ): + now_z -= 1 if z_forward else -1 + z_forward = not z_forward + _bytes += key[x][1] + now_x += 1 + else: + + _bytes += key[z][int(z_forward)] + + else: + + _bytes += key[y][int(y_forward)] + + return ( + _bytes, + [ + now_x + 1, + max_height if now_x or now_z else now_y, + _sideLength if now_x else now_z, + ], + [now_x, now_y, now_z], + ) \ No newline at end of file diff --git a/README.md b/README.md index 345157b..e9c34ba 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@

-[![][Bilibili: 凌云金羿]](https://space.bilibili.com/397369002/) +[![][Bilibili: 金羿ELS]](https://space.bilibili.com/397369002/) [![][Bilibili: 诸葛亮与八卦阵]](https://space.bilibili.com/604072474) [![CodeStyle: black]](https://github.com/psf/black) [![][python]](https://www.python.org/) @@ -103,7 +103,7 @@ NOT APPROVED BY OR ASSOCIATED WITH MOJANG OR MICROSOFT. -[Bilibili: 凌云金羿]: https://img.shields.io/badge/Bilibili-%E5%87%8C%E4%BA%91%E9%87%91%E7%BE%BF-00A1E7?style=for-the-badge +[Bilibili: 金羿ELS]: https://img.shields.io/badge/Bilibili-%E5%87%8C%E4%BA%91%E9%87%91%E7%BE%BF-00A1E7?style=for-the-badge [Bilibili: 诸葛亮与八卦阵]: https://img.shields.io/badge/Bilibili-%E8%AF%B8%E8%91%9B%E4%BA%AE%E4%B8%8E%E5%85%AB%E5%8D%A6%E9%98%B5-00A1E7?style=for-the-badge [CodeStyle: black]: https://img.shields.io/badge/code%20style-black-121110.svg?style=for-the-badge [python]: https://img.shields.io/badge/python-3.6-AB70FF?style=for-the-badge diff --git a/requirements.txt b/requirements.txt index 70abd76..68153c0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ Brotli>=1.0.9 -mido>=1.2.10 \ No newline at end of file +mido>=1.2.10 +mcstructure \ No newline at end of file From 7cc70d69483199eb99feeb6d251f1a8eb15bc099 Mon Sep 17 00:00:00 2001 From: EillesWan Date: Sat, 11 Mar 2023 18:23:40 +0800 Subject: [PATCH 03/10] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=83=A8=E5=88=86?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/库的生成与功能文档.md | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/docs/库的生成与功能文档.md b/docs/库的生成与功能文档.md index 91bdb93..685ba25 100644 --- a/docs/库的生成与功能文档.md +++ b/docs/库的生成与功能文档.md @@ -10,28 +10,38 @@ # 库的简单调用 -参见[magicDemo.py的相关部分](../magicDemo.py#L436),使用此库进行MIDI转换非常简单。 +参见[example.py的相关部分](../example.py#L120),使用此库进行MIDI转换非常简单。 ```python -import msctPkgver # 导入转换库 +import Musicreater # 导入转换库 # 首先新建转换对象。 -conversion = msctPkgver.midiConvert() +conversion = Musicreater.midiConvert() # 值得注意的是,一个转换对象可以转换多个文件。 # 也就是在实例化的时候不进行对文件的绑定。 # 如果有调试需要,可以在实例化时传入参数 debug = True -# 如:conversion = msctPkgver.midiConvert(debug=True) +# 如:conversion = Musicreater.midiConvert(debug=True) # 设置输入输出地址,并指定execute指令语法 # 地址都为字符串类型,不能传入文件流 midi_path = "./where/you/place/.midi/files.mid" output_folder = "./where/you/want2/convert/into/" old_execute_format = False # 指定是否使用旧的execute指令语法(即1.18及以前的《我的世界:基岩版》语法) + +# 设定基本转换参数 conversion.convert(midi_path,output_folder,old_execute_format) -# 进行转换并接受输出,具体的参数均在文档中有相关说明 -method_id = 2 # 指定使用的转换算法 -convertion_result = conversion.tomcpack(method_id,*prompts) +# 进行转换并接受输出,具体的参数均在代码之文档中有相关说明 +method_id = 3 # 指定使用的转换算法 + +# 使用计分板播放器,转换为附加包文件 +convertion_result = conversion.to_mcpack(method_id,*prompts) + +# 使用计分板播放器,转换为BDX结构文件 +convertion_result = conversion.to_BDX_file(method_id,*prompts) + +# 使用延迟播放器,转换为BDX结构文件 +convertion_result = conversion.to_BDX_file_with_delay(method_id,*prompts) # 转换结果是一个元组。 # 若其转换成功,则前三位必为 From a07f723d7c6f4e8cc125d75dd634228f102741f8 Mon Sep 17 00:00:00 2001 From: EillesWan Date: Sun, 12 Mar 2023 14:35:23 +0800 Subject: [PATCH 04/10] =?UTF-8?q?=E8=BF=99=E6=94=B9=E4=BA=86=E4=B8=8D?= =?UTF-8?q?=E5=95=A6=EF=BC=8C=E4=B8=80=E4=BB=A3=E4=B8=80=E4=BB=A3=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E6=9C=89=E4=B8=AA=E9=AC=BC=E7=94=A8=EF=BC=8C=E4=BB=80?= =?UTF-8?q?=E4=B9=88=E9=83=BD=E6=B2=A1=E5=8F=98=E5=98=9B=EF=BC=9B=E6=88=91?= =?UTF-8?q?=E5=B8=A6=E7=9A=84=E6=98=AF=E4=BB=80=E4=B9=88=E9=98=9F=E5=95=8A?= =?UTF-8?q?=EF=BC=8C=E6=88=91=E5=B8=A6=E7=9A=84=E6=98=AF=E7=9D=BF=E7=A9=86?= =?UTF-8?q?=E5=95=8A=EF=BC=8C=E5=85=88=E6=8A=8A=E8=BF=99=E4=B8=AA=E7=90=86?= =?UTF-8?q?=E5=BF=B5=E6=90=9E=E6=87=82=E5=98=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Musicreater/main.py | 2 ++ Musicreater/utils.py | 63 ++++++++++++++++++++++++++++++++++++++++++++ README.md | 22 +++++++++++++--- requirements.txt | 1 - 4 files changed, 84 insertions(+), 4 deletions(-) diff --git a/Musicreater/main.py b/Musicreater/main.py index d1d3bd7..c2ae62e 100644 --- a/Musicreater/main.py +++ b/Musicreater/main.py @@ -1479,6 +1479,8 @@ class midiConvert: if not os.path.exists(self.outputPath): os.makedirs(self.outputPath) + + diff --git a/Musicreater/utils.py b/Musicreater/utils.py index 434eeea..a3ddaa1 100644 --- a/Musicreater/utils.py +++ b/Musicreater/utils.py @@ -221,6 +221,69 @@ def to_BDX_bytes( [now_x, now_y, now_z], ) + +def form_command_block_in_NBT_struct( + command: str, + particularValue: int, + impluse: int = 0, + condition: bool = False, + needRedstone: bool = True, + tickDelay: int = 0, + customName: str = "", + executeOnFirstTick: bool = False, + trackOutput: bool = True, +): + """ + 使用指定项目返回指定的指令方块结构 + :param command: `str` + 指令 + :param particularValue: + 方块特殊值,即朝向 + :0 下 无条件 + :1 上 无条件 + :2 z轴负方向 无条件 + :3 z轴正方向 无条件 + :4 x轴负方向 无条件 + :5 x轴正方向 无条件 + :6 下 无条件 + :7 下 无条件 + + :8 下 有条件 + :9 上 有条件 + :10 z轴负方向 有条件 + :11 z轴正方向 有条件 + :12 x轴负方向 有条件 + :13 x轴正方向 有条件 + :14 下 有条件 + :14 下 有条件 + 注意!此处特殊值中的条件会被下面condition参数覆写 + :param impluse: `int 0|1|2` + 方块类型 + 0脉冲 1循环 2连锁 + :param condition: `bool` + 是否有条件 + :param needRedstone: `bool` + 是否需要红石 + :param tickDelay: `int` + 执行延时 + :param customName: `str` + 悬浮字 + lastOutput: `str` + 上次输出字符串,注意此处需要留空 + :param executeOnFirstTick: `bool` + 执行第一个已选项(循环指令方块是否激活后立即执行,若为False,则从激活时起延迟后第一次执行) + :param trackOutput: `bool` + 是否输出 + + :return:str + """ + from mcstructure import Block + block = Block("minecraft:command_block") + + return block + + + def to_structure( commands: list, max_height: int = 64, diff --git a/README.md b/README.md index 6dc83a5..9378849 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,27 @@ -

音·创 Musicreater

+ +

+ 音·创 Musicreater +

- + +

一款免费开源的 《我的世界》 MIDI音乐转换库。

- + + + Fork me on Gitee + +

+ + + [![][Bilibili: 金羿ELS]](https://space.bilibili.com/397369002/) [![][Bilibili: 诸葛亮与八卦阵]](https://space.bilibili.com/604072474) [![CodeStyle: black]](https://github.com/psf/black) @@ -18,6 +29,11 @@ [![][license]](LICENSE) [![][release]](../../releases) +[![GiteeStar](https://gitee.com/TriM-Organization/Musicreater/badge/star.svg?theme=gray)](https://gitee.com/TriM-Organization/Musicreater/stargazers) +[![GiteeFork](https://gitee.com/TriM-Organization/Musicreater/badge/fork.svg?theme=gray)](https://gitee.com/TriM-Organization/Musicreater/members) +[![GitHub Repo stars](https://img.shields.io/github/stars/TriM-Organization/Musicreater?color=white&logo=GitHub&style=plastic)](https://github.com/TriM-Organization/Musicreater/stargazers) +[![GitHub Repo Forks](https://img.shields.io/github/forks/TriM-Organization/Musicreater?color=white&logo=GitHub&style=plastic)](https://github.com/TriM-Organization/Musicreater/forks) + 简体中文🇨🇳 | [English🇬🇧](README_EN.md) diff --git a/requirements.txt b/requirements.txt index 68153c0..11e2979 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,2 @@ Brotli>=1.0.9 mido>=1.2.10 -mcstructure \ No newline at end of file From fb4cd07dc6d6953e3a2557cdca9f1fc6ad216ae8 Mon Sep 17 00:00:00 2001 From: EillesWan Date: Sun, 12 Mar 2023 17:43:52 +0800 Subject: [PATCH 05/10] =?UTF-8?q?=E6=96=B0=E5=A2=9EMCSTRUCTURE=E7=BB=93?= =?UTF-8?q?=E6=9E=84=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/mcstructure文件结构.md | 172 ++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 docs/mcstructure文件结构.md diff --git a/docs/mcstructure文件结构.md b/docs/mcstructure文件结构.md new file mode 100644 index 0000000..d6d468d --- /dev/null +++ b/docs/mcstructure文件结构.md @@ -0,0 +1,172 @@ + +**此文档译自https://wiki.bedrock.dev/nbt/mcstructure.html** + +# `.MCSTRUCTURE`文件结构 + +mcstructure 文件是未经压缩的 [NBT 文件](https://wiki.vg/NBT#Specification),也正如《我的世界:基岩版》的所有 NBT 文件一样,其皆以小端字节序(又称小端序)存储。以下是此类文件的 NBT 标签结构: + + + +[nbt-tag-types]: https://static.wikia.nocookie.net/minecraft_zh_gamepedia/images/d/d0/Nbtsheet.png/revision/latest +[int]: https://foruda.gitee.com/images/1678607417066876136/a1771588_9911226.png +[string]: https://foruda.gitee.com/images/1678607425650690164/1a6315b0_9911226.png +[list]: https://foruda.gitee.com/images/1678607435868247552/890a21c3_9911226.png +[compound]: https://foruda.gitee.com/images/1678607445511007209/448e8cec_9911226.png + +![Integer][int] 整型 `format_version`: 当前总为 `1` + +![List][list] 列表 `size`: 整数列表,用于表示结构大小 +- ![Integer][int] 整型: 结构X轴长 +- ![Integer][int] 整型: 结构Y轴长 +- ![Integer][int] 整型: 结构Z轴长 + +![Compound][compound] 复合 `structure`: 实际存储结构的数据组 + +- ![List][list] 列表 `block_indices`: 结构中存储的方块索引。包含两个列表,第一个为实际方块数据,第二个列表对应第一个列表中的方块之内含层(second layer)的方块数据。每一个方块都以一个整型数据,即在方块池(palette)(详见下文)中的索引下标(index),的形式存储。方块的存储是一维列表,将结构中每个方块依照从 Z 轴到 Y 轴到 X 轴且沿轴正方向的顺序一字排开形成列表。例如,若结构大小为 `[2,3,4]`,则每一层(即包括内含层也是一样的顺序)的24个方块(这个数量是由结构大小决定的,即结构尺寸的乘积)分别对应着如下相对坐标位置的方块:`[(0,0,0), (0,0,1), (0,0,2), (0,0,3), (0,1,0), (0,1,1), (0,1,2), (0,1,3), (0,2,0), (0,2,1), (0,2,2), (0,2,3), (1,0,0), (1,0,1), (1,0,2), (1,0,3), (1,1,0), (1,1,1), (1,1,2), (1,1,3), (1,2,0), (1,2,1), (1,2,2), (1,2,3)]`。若索引下标为 `-1` 则表示此处无方块(即对应“结构空位”),则此处在结构加载时就会保留其原有方块。在我们用结构方块保存结构时这种现象会发生,同时方块的内含层中也大多是无方块的。同时,两个层的方块共享一个方块池 + +- - ![List][list] of ![Integer][int] 整型列表: 首层(primary layer)方块列表 +- - ![List][list] of ![Integer][int] 整型列表: 内含层方块列表。此层通常为空,但若您存储的是《白蛇传》中的水漫金山场景就另当别论了 + +- ![List][list] of ![Compound][compound] 复合列表 `entities`: 以 NBT 存储的实体列表,其存储格式与在地图文件中存储实体的形式一致。类似 `Pos` 与 `UniqueID` 这样的独立于不同世界中的标签亦会被保存下来,但是《我的世界》加载这样的标签时会将它们覆写为实际值 + +- ![Compound][compound] 复合 `palette`: 理论上可以包含多种不同名字的方块池(palette),似乎这样设计是可能要支持以后的对于同一种结构的变体形态。但可惜的是,目前游戏内仅保存和加载名称为 `default` 的方块池 + +- - ![Compound][compound] 复合 `自定名称` : 单方块池(目前名称别自定,自定了没用,只能是 `default`) + +- - - ![List][list] 列表 `block_palette`: 方块及其状态(Block State)之列表,即包含了方块索引中那些索引下标(index)所指代之方块 +- - - - ![Compound][compound] 复合: 单方块及其状态 +- - - - - ![String][string] 字符串 `name`: 方块ID(identifier),形如 `minecraft:planks` +- - - - - ![Compound][compound] 复合 `states`: 方块之状态(state),以键值对的形式出现。例如:`wood_type:"acacia"`、`bite_counter:3`、`open_bit:1b`。其值将转换为 NBT 可接受的类型,如在游戏内枚举出的值(enum values)将转换为字符串(string)、标量(scalar numbers)将被转换为整型(integer)、布尔值(boolean values)会被转为字节型(byte) +- - - - - ![Integer][int] 整型 `version`: 兼容版本(Compatibility versioning number)(当前此文撰写时,对应的版本号是 `17959425`,对应游戏版本 1.19) + +- - - ![Compound][compound] 复合 `block_position_data`: 包含结构中各个方块的附加数据(additional data),每一个键(key)皆为`block_indices` 中的下标索引(index),表示其对应的方块,数据类型当然为整型(integer)。此处不会保有多层方块的指代,难道你见过草方块里包含着一个指令方块的吗? + +- - - - ![Compound][compound] 复合 `方块索引(index)值`: 单方块附加数据(additional block data)以方块之方块索引而对应着此方块 + +- - - - - ![Compound][compound] 复合 `block_entity_data`: 以 NBT 存储方块实体数据(block entity data),其存储格式与在地图文件中存储实体的形式一致。同上述实体标签的理,其位置标签(position tag)亦会被保存下来,但是《我的世界》加载这样的标签时会将它们覆写为实际值。不过这时候也不会有其他什么东西跟这玩意手拉手出现了 *\>译注:此处原文为No other objects seem to exist adjacent to this one at this time.应该是说,与`entities`那么多其他的独立于各个世界的标签相比,在方块实体中的算少的了* + +![List][list] 列表 `structure_world_origin`: 结构最初保存时的起始点坐标(position),以三个整型(integer)组成的列表的形式出现。坐标的值即结构方块保存时的坐标加上我们在结构放开里填写的偏移数据。这个坐标用于计算(determine)加载时实体的位置。一个实体的新的绝对坐标由其原始坐标减去结构最初保存时的起始点坐标后,再加上加载起始点的坐标计算而来。 + +- ![Integer][int] 整型: 结构原 X 坐标 +- ![Integer][int] 整型: 结构原 Y 坐标 +- ![Integer][int] 整型: 结构原 Z 坐标 + +以下是一些例子(以Python的数据结构为例): + +```python +# 大小为 1x3x1 (XYZ) 的 +# 从下往上分别是一个指令方块、一个铁块和一个空气方块的 +# 结构 NBT 数据 +{ + 'format_version': TAG_Int(1, 'format_version'), + 'size': [TAG_Int(1, None), TAG_Int(3, None), TAG_Int(1, None)], + 'structure': { + 'block_indices': [ + [TAG_Int(0, None), TAG_Int(1, None), TAG_Int(2, None)], + [TAG_Int(-1, None), TAG_Int(-1, None), TAG_Int(-1, None)] + ], + 'entities': [], + 'palette': { + 'default': { + 'block_palette': [ + { + 'name': TAG_String('minecraft:command_block', 'name'), + 'states': { + 'conditional_bit': TAG_Byte(0, 'conditional_bit'), + 'facing_direction': TAG_Int(1, 'facing_direction') + }, + 'version': TAG_Int(17959425, 'version') + }, + { + 'name': TAG_String('minecraft:iron_block', 'name'), + 'states': {}, + 'version': TAG_Int(17959425, 'version') + }, + { + 'name': TAG_String('minecraft:air', 'name'), + 'states': {}, + 'version': TAG_Int(17959425, 'version') + } + ], + 'block_position_data': { + '0': { + 'Command': TAG_String('help 4', 'Command'), + 'CustomName': TAG_String('', 'CustomName'), + 'ExecuteOnFirstTick': TAG_Byte(0, 'ExecuteOnFirstTick'), + 'LPCommandMode': TAG_Int(0, 'LPCommandMode'), + 'LPCondionalMode': TAG_Byte(0, 'LPCondionalMode'), + 'LPRedstoneMode': TAG_Byte(0, 'LPRedstoneMode'), + 'LastExecution': TAG_Long(0, 'LastExecution'), + 'LastOutput': TAG_String('', 'LastOutput'), + 'LastOutputParams': [], + 'SuccessCount': TAG_Int(0, 'SuccessCount'), + 'TickDelay': TAG_Int(0, 'TickDelay'), + 'TrackOutput': TAG_Byte(1, 'TrackOutput'), + 'Version': TAG_Int(25, 'Version'), + 'auto': TAG_Byte(0, 'auto'), + 'conditionMet': TAG_Byte(0, 'conditionMet'), + 'conditionalMode': TAG_Byte(0, 'conditionalMode'), + 'id': TAG_String('CommandBlock', 'id'), + 'isMovable': TAG_Byte(1, 'isMovable'), + 'powered': TAG_Byte(0, 'powered'), + 'x': TAG_Int(1, 'x'), + 'y': TAG_Int(1, 'y'), + 'z': TAG_Int(1, 'z') + } + } + } + } + }, + 'structure_world_origin': [TAG_Int(0, None), TAG_Int(0, None), TAG_Int(0, None)], +} +``` + +```python +# 大小为 2x2x2 (XYZ) 的 +# 全是白色羊毛的 +# 结构 NBT 数据 +{ + 'format_version': TAG_Int(1, 'format_version'), + 'size': [TAG_Int(2, None), TAG_Int(2, None), TAG_Int(2, None)], + 'structure': { + 'block_indices': [ + [ + TAG_Int(0, None), + TAG_Int(0, None), + TAG_Int(0, None), + TAG_Int(0, None), + TAG_Int(0, None), + TAG_Int(0, None), + TAG_Int(0, None), + TAG_Int(0, None) + ], + [ + TAG_Int(-1, None), + TAG_Int(-1, None), + TAG_Int(-1, None), + TAG_Int(-1, None), + TAG_Int(-1, None), + TAG_Int(-1, None), + TAG_Int(-1, None), + TAG_Int(-1, None) + ] + ], + 'entities': [], + 'palette': { + 'default': { + 'block_palette': [ + { + 'name': TAG_String('minecraft:wool', 'name'), + 'states': {'color': TAG_String('white', 'color')}, + 'version': TAG_Int(17959425, 'version') + } + ], + 'block_position_data': {} + } + } + }, + 'structure_world_origin': [TAG_Int(0, None), TAG_Int(0, None), TAG_Int(0, None)] +} +``` + +源代码可参照此处,作者金羿。 \ No newline at end of file From 6ca8820fa8c4d971b33e045fb35886664e2c2d5d Mon Sep 17 00:00:00 2001 From: EillesWan Date: Sun, 12 Mar 2023 17:57:40 +0800 Subject: [PATCH 06/10] =?UTF-8?q?=E6=94=B9=E4=B8=AA=E4=B8=9C=E8=A5=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/mcstructure文件结构.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/mcstructure文件结构.md b/docs/mcstructure文件结构.md index d6d468d..ad46c7a 100644 --- a/docs/mcstructure文件结构.md +++ b/docs/mcstructure文件结构.md @@ -5,13 +5,13 @@ mcstructure 文件是未经压缩的 [NBT 文件](https://wiki.vg/NBT#Specification),也正如《我的世界:基岩版》的所有 NBT 文件一样,其皆以小端字节序(又称小端序)存储。以下是此类文件的 NBT 标签结构: - + [nbt-tag-types]: https://static.wikia.nocookie.net/minecraft_zh_gamepedia/images/d/d0/Nbtsheet.png/revision/latest -[int]: https://foruda.gitee.com/images/1678607417066876136/a1771588_9911226.png -[string]: https://foruda.gitee.com/images/1678607425650690164/1a6315b0_9911226.png -[list]: https://foruda.gitee.com/images/1678607435868247552/890a21c3_9911226.png -[compound]: https://foruda.gitee.com/images/1678607445511007209/448e8cec_9911226.png +[int]: https://foruda.gitee.com/images/1678607417066876136/a1771588_9911226.png?width=16 +[string]: https://foruda.gitee.com/images/1678607425650690164/1a6315b0_9911226.png?width=16 +[list]: https://foruda.gitee.com/images/1678607435868247552/890a21c3_9911226.png?width=16 +[compound]: https://foruda.gitee.com/images/1678607445511007209/448e8cec_9911226.png?width=16 ![Integer][int] 整型 `format_version`: 当前总为 `1` From acb347b4913f754a6629e52f7622647a3e5105ac Mon Sep 17 00:00:00 2001 From: EillesWan Date: Sun, 26 Mar 2023 19:18:00 +0800 Subject: [PATCH 07/10] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=EF=BC=8C=E5=87=8F=E5=B0=91=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E6=96=87=E6=A1=A3=EF=BC=8C=E6=8A=8A=E6=96=87=E6=A1=A3=E7=A7=BB?= =?UTF-8?q?=E5=8A=A8=E5=88=B0=E4=BA=86MCS=E5=BA=93=E9=87=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Musicreater/__init__.py | 2 +- Musicreater/utils.py | 6 +- docs/mcstructure文件结构.md | 172 ------------------------------------ requirements.txt | 1 + 4 files changed, 5 insertions(+), 176 deletions(-) delete mode 100644 docs/mcstructure文件结构.md diff --git a/Musicreater/__init__.py b/Musicreater/__init__.py index b13efda..13921f5 100644 --- a/Musicreater/__init__.py +++ b/Musicreater/__init__.py @@ -19,7 +19,7 @@ Terms & Conditions: ../License.md from .main import * -__version__ = "0.3.3" +__version__ = "0.3.4" __all__ = [] __author__ = (("金羿", "Eilles Wan"), ("诸葛亮与八卦阵", "bgArray")) diff --git a/Musicreater/utils.py b/Musicreater/utils.py index a3ddaa1..dcabe83 100644 --- a/Musicreater/utils.py +++ b/Musicreater/utils.py @@ -277,8 +277,8 @@ def form_command_block_in_NBT_struct( :return:str """ - from mcstructure import Block - block = Block("minecraft:command_block") + from TrimMCStruct import Block + block = Block("minecraft","command_block") return block @@ -294,7 +294,7 @@ def to_structure( :return 成功与否,成功返回(True,未经过压缩的源,结构占用大小),失败返回(False,str失败原因) """ # 导入库 - from mcstructure import Block, Structure + from TrimMCStruct import Block, Structure _sideLength = bottem_side_length_of_smallest_square_bottom_box(len(commands), max_height) diff --git a/docs/mcstructure文件结构.md b/docs/mcstructure文件结构.md deleted file mode 100644 index ad46c7a..0000000 --- a/docs/mcstructure文件结构.md +++ /dev/null @@ -1,172 +0,0 @@ - -**此文档译自https://wiki.bedrock.dev/nbt/mcstructure.html** - -# `.MCSTRUCTURE`文件结构 - -mcstructure 文件是未经压缩的 [NBT 文件](https://wiki.vg/NBT#Specification),也正如《我的世界:基岩版》的所有 NBT 文件一样,其皆以小端字节序(又称小端序)存储。以下是此类文件的 NBT 标签结构: - - - -[nbt-tag-types]: https://static.wikia.nocookie.net/minecraft_zh_gamepedia/images/d/d0/Nbtsheet.png/revision/latest -[int]: https://foruda.gitee.com/images/1678607417066876136/a1771588_9911226.png?width=16 -[string]: https://foruda.gitee.com/images/1678607425650690164/1a6315b0_9911226.png?width=16 -[list]: https://foruda.gitee.com/images/1678607435868247552/890a21c3_9911226.png?width=16 -[compound]: https://foruda.gitee.com/images/1678607445511007209/448e8cec_9911226.png?width=16 - -![Integer][int] 整型 `format_version`: 当前总为 `1` - -![List][list] 列表 `size`: 整数列表,用于表示结构大小 -- ![Integer][int] 整型: 结构X轴长 -- ![Integer][int] 整型: 结构Y轴长 -- ![Integer][int] 整型: 结构Z轴长 - -![Compound][compound] 复合 `structure`: 实际存储结构的数据组 - -- ![List][list] 列表 `block_indices`: 结构中存储的方块索引。包含两个列表,第一个为实际方块数据,第二个列表对应第一个列表中的方块之内含层(second layer)的方块数据。每一个方块都以一个整型数据,即在方块池(palette)(详见下文)中的索引下标(index),的形式存储。方块的存储是一维列表,将结构中每个方块依照从 Z 轴到 Y 轴到 X 轴且沿轴正方向的顺序一字排开形成列表。例如,若结构大小为 `[2,3,4]`,则每一层(即包括内含层也是一样的顺序)的24个方块(这个数量是由结构大小决定的,即结构尺寸的乘积)分别对应着如下相对坐标位置的方块:`[(0,0,0), (0,0,1), (0,0,2), (0,0,3), (0,1,0), (0,1,1), (0,1,2), (0,1,3), (0,2,0), (0,2,1), (0,2,2), (0,2,3), (1,0,0), (1,0,1), (1,0,2), (1,0,3), (1,1,0), (1,1,1), (1,1,2), (1,1,3), (1,2,0), (1,2,1), (1,2,2), (1,2,3)]`。若索引下标为 `-1` 则表示此处无方块(即对应“结构空位”),则此处在结构加载时就会保留其原有方块。在我们用结构方块保存结构时这种现象会发生,同时方块的内含层中也大多是无方块的。同时,两个层的方块共享一个方块池 - -- - ![List][list] of ![Integer][int] 整型列表: 首层(primary layer)方块列表 -- - ![List][list] of ![Integer][int] 整型列表: 内含层方块列表。此层通常为空,但若您存储的是《白蛇传》中的水漫金山场景就另当别论了 - -- ![List][list] of ![Compound][compound] 复合列表 `entities`: 以 NBT 存储的实体列表,其存储格式与在地图文件中存储实体的形式一致。类似 `Pos` 与 `UniqueID` 这样的独立于不同世界中的标签亦会被保存下来,但是《我的世界》加载这样的标签时会将它们覆写为实际值 - -- ![Compound][compound] 复合 `palette`: 理论上可以包含多种不同名字的方块池(palette),似乎这样设计是可能要支持以后的对于同一种结构的变体形态。但可惜的是,目前游戏内仅保存和加载名称为 `default` 的方块池 - -- - ![Compound][compound] 复合 `自定名称` : 单方块池(目前名称别自定,自定了没用,只能是 `default`) - -- - - ![List][list] 列表 `block_palette`: 方块及其状态(Block State)之列表,即包含了方块索引中那些索引下标(index)所指代之方块 -- - - - ![Compound][compound] 复合: 单方块及其状态 -- - - - - ![String][string] 字符串 `name`: 方块ID(identifier),形如 `minecraft:planks` -- - - - - ![Compound][compound] 复合 `states`: 方块之状态(state),以键值对的形式出现。例如:`wood_type:"acacia"`、`bite_counter:3`、`open_bit:1b`。其值将转换为 NBT 可接受的类型,如在游戏内枚举出的值(enum values)将转换为字符串(string)、标量(scalar numbers)将被转换为整型(integer)、布尔值(boolean values)会被转为字节型(byte) -- - - - - ![Integer][int] 整型 `version`: 兼容版本(Compatibility versioning number)(当前此文撰写时,对应的版本号是 `17959425`,对应游戏版本 1.19) - -- - - ![Compound][compound] 复合 `block_position_data`: 包含结构中各个方块的附加数据(additional data),每一个键(key)皆为`block_indices` 中的下标索引(index),表示其对应的方块,数据类型当然为整型(integer)。此处不会保有多层方块的指代,难道你见过草方块里包含着一个指令方块的吗? - -- - - - ![Compound][compound] 复合 `方块索引(index)值`: 单方块附加数据(additional block data)以方块之方块索引而对应着此方块 - -- - - - - ![Compound][compound] 复合 `block_entity_data`: 以 NBT 存储方块实体数据(block entity data),其存储格式与在地图文件中存储实体的形式一致。同上述实体标签的理,其位置标签(position tag)亦会被保存下来,但是《我的世界》加载这样的标签时会将它们覆写为实际值。不过这时候也不会有其他什么东西跟这玩意手拉手出现了 *\>译注:此处原文为No other objects seem to exist adjacent to this one at this time.应该是说,与`entities`那么多其他的独立于各个世界的标签相比,在方块实体中的算少的了* - -![List][list] 列表 `structure_world_origin`: 结构最初保存时的起始点坐标(position),以三个整型(integer)组成的列表的形式出现。坐标的值即结构方块保存时的坐标加上我们在结构放开里填写的偏移数据。这个坐标用于计算(determine)加载时实体的位置。一个实体的新的绝对坐标由其原始坐标减去结构最初保存时的起始点坐标后,再加上加载起始点的坐标计算而来。 - -- ![Integer][int] 整型: 结构原 X 坐标 -- ![Integer][int] 整型: 结构原 Y 坐标 -- ![Integer][int] 整型: 结构原 Z 坐标 - -以下是一些例子(以Python的数据结构为例): - -```python -# 大小为 1x3x1 (XYZ) 的 -# 从下往上分别是一个指令方块、一个铁块和一个空气方块的 -# 结构 NBT 数据 -{ - 'format_version': TAG_Int(1, 'format_version'), - 'size': [TAG_Int(1, None), TAG_Int(3, None), TAG_Int(1, None)], - 'structure': { - 'block_indices': [ - [TAG_Int(0, None), TAG_Int(1, None), TAG_Int(2, None)], - [TAG_Int(-1, None), TAG_Int(-1, None), TAG_Int(-1, None)] - ], - 'entities': [], - 'palette': { - 'default': { - 'block_palette': [ - { - 'name': TAG_String('minecraft:command_block', 'name'), - 'states': { - 'conditional_bit': TAG_Byte(0, 'conditional_bit'), - 'facing_direction': TAG_Int(1, 'facing_direction') - }, - 'version': TAG_Int(17959425, 'version') - }, - { - 'name': TAG_String('minecraft:iron_block', 'name'), - 'states': {}, - 'version': TAG_Int(17959425, 'version') - }, - { - 'name': TAG_String('minecraft:air', 'name'), - 'states': {}, - 'version': TAG_Int(17959425, 'version') - } - ], - 'block_position_data': { - '0': { - 'Command': TAG_String('help 4', 'Command'), - 'CustomName': TAG_String('', 'CustomName'), - 'ExecuteOnFirstTick': TAG_Byte(0, 'ExecuteOnFirstTick'), - 'LPCommandMode': TAG_Int(0, 'LPCommandMode'), - 'LPCondionalMode': TAG_Byte(0, 'LPCondionalMode'), - 'LPRedstoneMode': TAG_Byte(0, 'LPRedstoneMode'), - 'LastExecution': TAG_Long(0, 'LastExecution'), - 'LastOutput': TAG_String('', 'LastOutput'), - 'LastOutputParams': [], - 'SuccessCount': TAG_Int(0, 'SuccessCount'), - 'TickDelay': TAG_Int(0, 'TickDelay'), - 'TrackOutput': TAG_Byte(1, 'TrackOutput'), - 'Version': TAG_Int(25, 'Version'), - 'auto': TAG_Byte(0, 'auto'), - 'conditionMet': TAG_Byte(0, 'conditionMet'), - 'conditionalMode': TAG_Byte(0, 'conditionalMode'), - 'id': TAG_String('CommandBlock', 'id'), - 'isMovable': TAG_Byte(1, 'isMovable'), - 'powered': TAG_Byte(0, 'powered'), - 'x': TAG_Int(1, 'x'), - 'y': TAG_Int(1, 'y'), - 'z': TAG_Int(1, 'z') - } - } - } - } - }, - 'structure_world_origin': [TAG_Int(0, None), TAG_Int(0, None), TAG_Int(0, None)], -} -``` - -```python -# 大小为 2x2x2 (XYZ) 的 -# 全是白色羊毛的 -# 结构 NBT 数据 -{ - 'format_version': TAG_Int(1, 'format_version'), - 'size': [TAG_Int(2, None), TAG_Int(2, None), TAG_Int(2, None)], - 'structure': { - 'block_indices': [ - [ - TAG_Int(0, None), - TAG_Int(0, None), - TAG_Int(0, None), - TAG_Int(0, None), - TAG_Int(0, None), - TAG_Int(0, None), - TAG_Int(0, None), - TAG_Int(0, None) - ], - [ - TAG_Int(-1, None), - TAG_Int(-1, None), - TAG_Int(-1, None), - TAG_Int(-1, None), - TAG_Int(-1, None), - TAG_Int(-1, None), - TAG_Int(-1, None), - TAG_Int(-1, None) - ] - ], - 'entities': [], - 'palette': { - 'default': { - 'block_palette': [ - { - 'name': TAG_String('minecraft:wool', 'name'), - 'states': {'color': TAG_String('white', 'color')}, - 'version': TAG_Int(17959425, 'version') - } - ], - 'block_position_data': {} - } - } - }, - 'structure_world_origin': [TAG_Int(0, None), TAG_Int(0, None), TAG_Int(0, None)] -} -``` - -源代码可参照此处,作者金羿。 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 11e2979..772b6ad 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ Brotli>=1.0.9 mido>=1.2.10 +TrimMCStruct>=0.0.2 \ No newline at end of file From 48f5a975dbd60bbf00287f9ca1097830b0009529 Mon Sep 17 00:00:00 2001 From: EillesWan Date: Sun, 16 Apr 2023 19:11:55 +0800 Subject: [PATCH 08/10] =?UTF-8?q?=E9=9D=A9=E5=91=BD=E5=B0=9A=E6=9C=AA?= =?UTF-8?q?=E6=88=90=E5=8A=9F=EF=BC=9F=E4=B9=9F=E8=AE=B8=E6=98=AF=E5=BA=93?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=8C=E4=BD=86=E6=98=AF=E6=B2=A1?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E6=A3=80=E6=9F=A5=E4=BA=86=EF=BC=8C=E5=85=88?= =?UTF-8?q?=E8=B5=B0=E4=BA=86=EF=BC=88=EF=BC=88=EF=BC=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Musicreater/main.py | 9 ++- Musicreater/utils.py | 135 ++++++++++++++++++++++++----------------- example_mcstructure.py | 6 ++ requirements.txt | 2 +- 4 files changed, 92 insertions(+), 60 deletions(-) create mode 100644 example_mcstructure.py diff --git a/Musicreater/main.py b/Musicreater/main.py index c2ae62e..1cc3d47 100644 --- a/Musicreater/main.py +++ b/Musicreater/main.py @@ -155,6 +155,7 @@ class midiConvert: [ self._toCmdList_withDelay_m1, self._toCmdList_withDelay_m2, + self._toCmdList_withDelay_m3, ] ) @@ -1457,7 +1458,6 @@ class midiConvert: speed: float = 1.0, progressbar: Union[bool, tuple] = False, player: str = "@a", - author: str = "Eilles", max_height: int = 64, ): """ @@ -1480,8 +1480,13 @@ class midiConvert: if not os.path.exists(self.outputPath): os.makedirs(self.outputPath) - + struct, size = to_structure(cmdlist,max_height-1) + with open( + os.path.abspath(os.path.join(self.outputPath, f"{self.midFileName}.mcstructure")), + "wb+", + ) as f: + struct.dump(f) diff --git a/Musicreater/utils.py b/Musicreater/utils.py index dcabe83..81fa654 100644 --- a/Musicreater/utils.py +++ b/Musicreater/utils.py @@ -106,13 +106,14 @@ def form_command_block_in_BDX_bytes( lastOutput: `str` 上次输出字符串,注意此处需要留空 :param executeOnFirstTick: `bool` - 执行第一个已选项(循环指令方块是否激活后立即执行,若为False,则从激活时起延迟后第一次执行) + 首刻执行(循环指令方块是否激活后立即执行,若为False,则从激活时起延迟后第一次执行) :param trackOutput: `bool` 是否输出 :return:str """ - block = b"\x24" + particularValue.to_bytes(2, byteorder="big", signed=False) + block = b"\x24" + \ + particularValue.to_bytes(2, byteorder="big", signed=False) for i in [ impluse.to_bytes(4, byteorder="big", signed=False), @@ -147,7 +148,9 @@ def to_BDX_bytes( :return 成功与否,成功返回(True,未经过压缩的源,结构占用大小),失败返回(False,str失败原因) """ - _sideLength = bottem_side_length_of_smallest_square_bottom_box(len(commands), max_height) + _sideLength = bottem_side_length_of_smallest_square_bottom_box( + len(commands), max_height + ) _bytes = b"" y_forward = True @@ -196,7 +199,7 @@ def to_BDX_bytes( now_z += 1 if z_forward else -1 - if ((now_z > _sideLength) and z_forward) or ( + if ((now_z >= _sideLength) and z_forward) or ( (now_z < 0) and (not z_forward) ): now_z -= 1 if z_forward else -1 @@ -224,10 +227,11 @@ def to_BDX_bytes( def form_command_block_in_NBT_struct( command: str, + coordinate: tuple, particularValue: int, impluse: int = 0, condition: bool = False, - needRedstone: bool = True, + alwaysRun: bool = True, tickDelay: int = 0, customName: str = "", executeOnFirstTick: bool = False, @@ -237,6 +241,8 @@ def form_command_block_in_NBT_struct( 使用指定项目返回指定的指令方块结构 :param command: `str` 指令 + :param coordinate: `tuple[int,int,int]` + 此方块所在之相对坐标 :param particularValue: 方块特殊值,即朝向 :0 下 无条件 @@ -262,28 +268,54 @@ def form_command_block_in_NBT_struct( 0脉冲 1循环 2连锁 :param condition: `bool` 是否有条件 - :param needRedstone: `bool` - 是否需要红石 + :param alwaysRun: `bool` + 是否始终执行 :param tickDelay: `int` 执行延时 :param customName: `str` 悬浮字 - lastOutput: `str` - 上次输出字符串,注意此处需要留空 :param executeOnFirstTick: `bool` - 执行第一个已选项(循环指令方块是否激活后立即执行,若为False,则从激活时起延迟后第一次执行) + 首刻执行(循环指令方块是否激活后立即执行,若为False,则从激活时起延迟后第一次执行) :param trackOutput: `bool` 是否输出 :return:str """ - from TrimMCStruct import Block - block = Block("minecraft","command_block") - + from TrimMCStruct import Block, TAG_Long + block = Block( + "minecraft", + "command_block" if impluse == 0 else ( + "repeating_command_block" if impluse == 1 else "chain_command_block"), + states={"conditional_bit": condition, + "facing_direction": particularValue}, + extra_data={ + 'Command': command, + 'CustomName': customName, + 'ExecuteOnFirstTick': executeOnFirstTick, + 'LPCommandMode': 0, + 'LPCondionalMode': False, + 'LPRedstoneMode': False, + 'LastExecution': TAG_Long(0), + 'LastOutput': '', + 'LastOutputParams': [], + 'SuccessCount': 0, + 'TickDelay': tickDelay, + 'TrackOutput': trackOutput, + 'Version': 25, + 'auto': alwaysRun, + 'conditionMet': False, # 是否已经满足条件 + 'conditionalMode': condition, + 'id': 'CommandBlock', + 'isMovable': True, + 'powered': False, # 是否已激活 + 'x': coordinate[0], + 'y': coordinate[1], + 'z': coordinate[2], + } + ) return block - def to_structure( commands: list, max_height: int = 64, @@ -291,12 +323,14 @@ def to_structure( """ :param commands: 指令列表(指令, 延迟) :param max_height: 生成结构最大高度 - :return 成功与否,成功返回(True,未经过压缩的源,结构占用大小),失败返回(False,str失败原因) + :return 成功与否,成功返回(结构类,结构占用大小),失败返回(False,str失败原因) """ # 导入库 - from TrimMCStruct import Block, Structure + from TrimMCStruct import Structure - _sideLength = bottem_side_length_of_smallest_square_bottom_box(len(commands), max_height) + _sideLength = bottem_side_length_of_smallest_square_bottom_box( + len(commands), max_height + ) struct = Structure( (_sideLength, max_height, _sideLength), # 声明结构大小 @@ -310,34 +344,30 @@ def to_structure( now_x = 0 for cmd, delay in commands: - impluse = 2 - condition = False - needRedstone = False - tickDelay = delay - customName = "" - executeOnFirstTick = False - trackOutput = True - _bytes += form_command_block_in_BDX_bytes( - cmd, - (1 if y_forward else 0) - if ( - ((now_y != 0) and (not y_forward)) - or (y_forward and (now_y != (max_height - 1))) - ) - else (3 if z_forward else 2) - if ( - ((now_z != 0) and (not z_forward)) - or (z_forward and (now_z != _sideLength)) - ) - else 5, - impluse=impluse, - condition=condition, - needRedstone=needRedstone, - tickDelay=tickDelay, - customName=customName, - executeOnFirstTick=executeOnFirstTick, - trackOutput=trackOutput, - ) + coordinate = (now_x, now_y, now_z) + struct.set_block(coordinate, + form_command_block_in_NBT_struct( + command=cmd, + coordinate=coordinate, + particularValue=(1 if y_forward else 0) + if ( + ((now_y != 0) and (not y_forward)) + or (y_forward and (now_y != (max_height - 1))) + ) + else (3 if z_forward else 2) + if ( + ((now_z != 0) and (not z_forward)) + or (z_forward and (now_z != _sideLength)) + ) + else 5, + impluse=2, + condition=False, + alwaysRun=True, + tickDelay=delay, + customName="", + executeOnFirstTick=False, + trackOutput=True, + )) now_y += 1 if y_forward else -1 @@ -348,27 +378,18 @@ def to_structure( now_z += 1 if z_forward else -1 - if ((now_z > _sideLength) and z_forward) or ( + if ((now_z >= _sideLength) and z_forward) or ( (now_z < 0) and (not z_forward) ): now_z -= 1 if z_forward else -1 z_forward = not z_forward - _bytes += key[x][1] now_x += 1 - else: - - _bytes += key[z][int(z_forward)] - - else: - - _bytes += key[y][int(y_forward)] return ( - _bytes, + struct, [ now_x + 1, max_height if now_x or now_z else now_y, _sideLength if now_x else now_z, ], - [now_x, now_y, now_z], - ) \ No newline at end of file + ) diff --git a/example_mcstructure.py b/example_mcstructure.py new file mode 100644 index 0000000..3f8af86 --- /dev/null +++ b/example_mcstructure.py @@ -0,0 +1,6 @@ + +from Musicreater import midiConvert + +conversion = midiConvert() +conversion.convert(input("midi path:"),input("out path:")) +conversion.to_mcstructure_file_with_delay(3,) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 772b6ad..0331a85 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ Brotli>=1.0.9 mido>=1.2.10 -TrimMCStruct>=0.0.2 \ No newline at end of file +TrimMCStruct>=0.0.5 \ No newline at end of file From a9ec7582a94c056f4428618bdd155f47f6b22655 Mon Sep 17 00:00:00 2001 From: EillesWan Date: Sun, 16 Apr 2023 19:12:10 +0800 Subject: [PATCH 09/10] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Musicreater/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Musicreater/__init__.py b/Musicreater/__init__.py index 13921f5..a42b215 100644 --- a/Musicreater/__init__.py +++ b/Musicreater/__init__.py @@ -19,7 +19,7 @@ Terms & Conditions: ../License.md from .main import * -__version__ = "0.3.4" +__version__ = "0.4.0" __all__ = [] __author__ = (("金羿", "Eilles Wan"), ("诸葛亮与八卦阵", "bgArray")) From b758a2f967737d32ef7d98d5ad952767d6dd64ca Mon Sep 17 00:00:00 2001 From: EillesWan Date: Sun, 16 Apr 2023 19:14:13 +0800 Subject: [PATCH 10/10] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 0331a85..b7afb8f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ Brotli>=1.0.9 mido>=1.2.10 -TrimMCStruct>=0.0.5 \ No newline at end of file +TrimMCStruct>=0.0.5.5 \ No newline at end of file