mirror of
https://github.com/TriM-Organization/Musicreater.git
synced 2026-01-26 21:51:47 +00:00
230 lines
7.0 KiB
Python
230 lines
7.0 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
存放有关BDX结构操作的内容
|
||
"""
|
||
|
||
"""
|
||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||
Copyright © 2025 Eilles & bgArray
|
||
|
||
开源相关声明请见 仓库根目录下的 License.md
|
||
Terms & Conditions: License.md in the root directory
|
||
"""
|
||
|
||
# 睿乐组织 开发交流群 861684859
|
||
# Email TriM-Organization@hotmail.com
|
||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||
|
||
from typing import List
|
||
|
||
from ..constants import x, y, z
|
||
from ..subclass import MineCommand
|
||
from .common import bottem_side_length_of_smallest_square_bottom_box
|
||
|
||
BDX_MOVE_KEY = {
|
||
"x": [b"\x0f", b"\x0e", b"\x1c", b"\x14", b"\x15"],
|
||
"y": [b"\x11", b"\x10", b"\x1d", b"\x16", b"\x17"],
|
||
"z": [b"\x13", b"\x12", b"\x1e", b"\x18", b"\x19"],
|
||
}
|
||
"""key存储了方块移动指令的数据,其中可以用key[x|y|z][0|1]来表示xyz的减或增
|
||
而key[][2+]是用来增加指定数目的"""
|
||
|
||
|
||
def bdx_move(axis: str, value: int):
|
||
if value == 0:
|
||
return b""
|
||
if abs(value) == 1:
|
||
return BDX_MOVE_KEY[axis][0 if value == -1 else 1]
|
||
|
||
pointer = sum(
|
||
[
|
||
value != -1,
|
||
value < -1 or value > 1,
|
||
value < -128 or value > 127,
|
||
value < -32768 or value > 32767,
|
||
]
|
||
)
|
||
|
||
return BDX_MOVE_KEY[axis][pointer] + value.to_bytes(
|
||
2 ** (pointer - 2), "big", signed=True
|
||
)
|
||
|
||
|
||
def form_command_block_in_BDX_bytes(
|
||
command: str,
|
||
particularValue: int,
|
||
impluse: int = 0,
|
||
condition: bool = False,
|
||
needRedstone: bool = True,
|
||
tickDelay: int = 0,
|
||
customName: str = "",
|
||
executeOnFirstTick: bool = False,
|
||
trackOutput: bool = True,
|
||
) -> bytes:
|
||
"""
|
||
使用指定参数生成指定的指令方块放置指令项
|
||
|
||
Parameters
|
||
------------
|
||
command: str
|
||
指令
|
||
particularValue: int
|
||
方块特殊值,即朝向
|
||
: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参数覆写
|
||
impluse: int (0|1|2)
|
||
方块类型
|
||
0脉冲 1循环 2连锁
|
||
condition: bool
|
||
是否有条件
|
||
needRedstone: bool
|
||
是否需要红石
|
||
tickDelay: int
|
||
执行延时
|
||
customName: str
|
||
悬浮字
|
||
lastOutput: str
|
||
命令方块的上次输出字符串,注意此处需要留空
|
||
executeOnFirstTick: bool
|
||
是否启用首刻执行(循环指令方块是否激活后立即执行,若为False,则从激活时起延迟后第一次执行)
|
||
trackOutput: bool
|
||
是否启用命令方块输出
|
||
|
||
Returns
|
||
---------
|
||
bytes
|
||
用以生成 bdx 结构的字节码
|
||
"""
|
||
block = b"\x24" + particularValue.to_bytes(2, byteorder="big", signed=False)
|
||
|
||
for i in [
|
||
impluse.to_bytes(4, byteorder="big", signed=False),
|
||
bytes(command, encoding="utf-8") + b"\x00",
|
||
bytes(customName, encoding="utf-8") + b"\x00",
|
||
bytes("", encoding="utf-8") + b"\x00",
|
||
tickDelay.to_bytes(4, byteorder="big", signed=True),
|
||
executeOnFirstTick.to_bytes(1, byteorder="big"),
|
||
trackOutput.to_bytes(1, byteorder="big"),
|
||
condition.to_bytes(1, byteorder="big"),
|
||
needRedstone.to_bytes(1, byteorder="big"),
|
||
]:
|
||
block += i
|
||
return block
|
||
|
||
|
||
def commands_to_BDX_bytes(
|
||
commands_list: List[MineCommand],
|
||
max_height: int = 64,
|
||
):
|
||
"""
|
||
指令列表转换为用以生成 bdx 结构的字节码
|
||
|
||
Parameters
|
||
------------
|
||
commands: list[tuple[str, int]]
|
||
指令列表,每个元素为 (指令, 延迟)
|
||
max_height: int
|
||
生成结构最大高度
|
||
|
||
Returns
|
||
---------
|
||
tuple[bool, bytes, int] or tuple[bool, str]
|
||
成功与否,成功返回 (True, 未经过压缩的源, 结构占用大小),失败返回 (False, str失败原因)
|
||
"""
|
||
|
||
_sideLength = bottem_side_length_of_smallest_square_bottom_box(
|
||
len(commands_list), max_height
|
||
)
|
||
_bytes = b""
|
||
|
||
y_forward = True
|
||
z_forward = True
|
||
|
||
now_y = 0
|
||
now_z = 0
|
||
now_x = 0
|
||
|
||
for command in commands_list:
|
||
_bytes += form_command_block_in_BDX_bytes(
|
||
command.command_text,
|
||
(
|
||
(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 - 1))
|
||
)
|
||
else 5
|
||
)
|
||
),
|
||
impluse=2,
|
||
condition=command.conditional,
|
||
needRedstone=False,
|
||
tickDelay=command.delay,
|
||
customName=command.annotation_text,
|
||
executeOnFirstTick=False,
|
||
trackOutput=True,
|
||
)
|
||
|
||
# (1 if y_forward else 0) if ( # 如果y+则向上,反之向下
|
||
# ((now_y != 0) and (not y_forward)) # 如果不是y轴上首个方块
|
||
# or (y_forward and (now_y != (max_height - 1))) # 如果不是y轴上末端方块
|
||
# ) else ( # 否则,即是y轴末端或首个方块
|
||
# (3 if z_forward else 2) if ( # 如果z+则向z轴正方向,反之负方向
|
||
# ((now_z != 0) and (not z_forward)) # 如果不是z轴上的首个方块
|
||
# or (z_forward and (now_z != _sideLength - 1)) # 如果不是z轴上的末端方块
|
||
# ) else 5 # 否则,则要面向x轴正方向
|
||
# )
|
||
|
||
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 += BDX_MOVE_KEY[x][1]
|
||
now_x += 1
|
||
else:
|
||
_bytes += BDX_MOVE_KEY[z][int(z_forward)]
|
||
|
||
else:
|
||
_bytes += BDX_MOVE_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],
|
||
)
|