mirror of
https://github.com/TriM-Organization/Musicreater.git
synced 2024-11-11 01:27:35 +08:00
史诗级更新!支持导出mcstructure库,更改部分API和文档,修改了部分代码格式,新增红乐测试
This commit is contained in:
parent
b758a2f967
commit
4874ace92d
1
.gitignore
vendored
1
.gitignore
vendored
@ -10,6 +10,7 @@
|
|||||||
*.mcpack
|
*.mcpack
|
||||||
*.bdx
|
*.bdx
|
||||||
*.json
|
*.json
|
||||||
|
*.mcstructure
|
||||||
|
|
||||||
# Byte-compiled / optimized
|
# Byte-compiled / optimized
|
||||||
__pycache__/
|
__pycache__/
|
||||||
|
@ -19,8 +19,6 @@ Terms & Conditions: ../License.md
|
|||||||
|
|
||||||
from .main import *
|
from .main import *
|
||||||
|
|
||||||
__version__ = "0.4.0"
|
__version__ = "0.5.0"
|
||||||
__all__ = []
|
__all__ = []
|
||||||
__author__ = (("金羿", "Eilles Wan"), ("诸葛亮与八卦阵", "bgArray"))
|
__author__ = (("金羿", "Eilles Wan"), ("诸葛亮与八卦阵", "bgArray"), ("鸣凤鸽子", "MingFengPigeon"))
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ class MSCTBaseException(Exception):
|
|||||||
"""音·创库版本的所有错误均继承于此"""
|
"""音·创库版本的所有错误均继承于此"""
|
||||||
|
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
|
"""音·创库版本的所有错误均继承于此"""
|
||||||
super().__init__(*args)
|
super().__init__(*args)
|
||||||
|
|
||||||
def miao(
|
def miao(
|
||||||
@ -37,37 +38,65 @@ class MSCTBaseException(Exception):
|
|||||||
raise self
|
raise self
|
||||||
|
|
||||||
|
|
||||||
class CrossNoteError(MSCTBaseException):
|
class MidiFormatException(MSCTBaseException):
|
||||||
"""同通道下同音符交叉出现所产生的错误"""
|
"""音·创库版本的所有MIDI格式错误均继承于此"""
|
||||||
|
|
||||||
pass
|
def __init__(self, *args):
|
||||||
|
"""音·创库版本的所有MIDI格式错误均继承于此"""
|
||||||
|
super().__init__("MIDI格式错误", *args)
|
||||||
class NotDefineTempoError(MSCTBaseException):
|
|
||||||
"""没有Tempo设定导致时间无法计算的错误"""
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class MidiDestroyedError(MSCTBaseException):
|
class MidiDestroyedError(MSCTBaseException):
|
||||||
"""Midi文件损坏"""
|
"""Midi文件损坏"""
|
||||||
|
|
||||||
pass
|
def __init__(self, *args):
|
||||||
|
"""Midi文件损坏"""
|
||||||
|
super().__init__("MIDI文件损坏:无法读取MIDI文件", *args)
|
||||||
|
|
||||||
|
|
||||||
class ChannelOverFlowError(MSCTBaseException):
|
class CommandFormatError(RuntimeError):
|
||||||
"""一个midi中含有过多的通道(数量应≤16)"""
|
"""指令格式与目标格式不匹配而引起的错误"""
|
||||||
|
|
||||||
pass
|
def __init__(self, *args):
|
||||||
|
"""指令格式与目标格式不匹配而引起的错误"""
|
||||||
|
super().__init__("指令格式不匹配", *args)
|
||||||
|
|
||||||
|
|
||||||
class NotDefineProgramError(MSCTBaseException):
|
class CrossNoteError(MidiFormatException):
|
||||||
|
"""同通道下同音符交叉出现所产生的错误"""
|
||||||
|
|
||||||
|
def __init__(self, *args):
|
||||||
|
"""同通道下同音符交叉出现所产生的错误"""
|
||||||
|
super().__init__("同通道下同音符交叉", *args)
|
||||||
|
|
||||||
|
|
||||||
|
class NotDefineTempoError(MidiFormatException):
|
||||||
|
"""没有Tempo设定导致时间无法计算的错误"""
|
||||||
|
|
||||||
|
def __init__(self, *args):
|
||||||
|
"""没有Tempo设定导致时间无法计算的错误"""
|
||||||
|
super().__init__("在曲目开始时没有声明Tempo(未指定拍长)", *args)
|
||||||
|
|
||||||
|
|
||||||
|
class ChannelOverFlowError(MidiFormatException):
|
||||||
|
"""一个midi中含有过多的通道"""
|
||||||
|
|
||||||
|
def __init__(self, max_channel = 16, *args):
|
||||||
|
"""一个midi中含有过多的通道"""
|
||||||
|
super().__init__("含有过多的通道(数量应≤{})".format(max_channel), *args)
|
||||||
|
|
||||||
|
|
||||||
|
class NotDefineProgramError(MidiFormatException):
|
||||||
"""没有Program设定导致没有乐器可以选择的错误"""
|
"""没有Program设定导致没有乐器可以选择的错误"""
|
||||||
|
|
||||||
pass
|
def __init__(self, *args):
|
||||||
|
"""没有Program设定导致没有乐器可以选择的错误"""
|
||||||
|
super().__init__("未指定演奏乐器", *args)
|
||||||
|
|
||||||
|
|
||||||
class ZeroSpeedError(MSCTBaseException):
|
class ZeroSpeedError(MidiFormatException):
|
||||||
"""以0作为播放速度的错误"""
|
"""以0作为播放速度的错误"""
|
||||||
|
|
||||||
pass
|
def __init__(self, *args):
|
||||||
|
"""以0作为播放速度的错误"""
|
||||||
|
super().__init__("播放速度为0", *args)
|
||||||
|
@ -176,4 +176,25 @@ percussion_instrument_list = {
|
|||||||
77: ("note.xylophone", 4),
|
77: ("note.xylophone", 4),
|
||||||
78: ("note.xylophone", 4),
|
78: ("note.xylophone", 4),
|
||||||
79: ("note.bell", 4),
|
79: ("note.bell", 4),
|
||||||
80: ("note.bell", 4), }
|
80: ("note.bell", 4),
|
||||||
|
}
|
||||||
|
|
||||||
|
instrument_to_blocks_list = {
|
||||||
|
"note.bass": ("planks",),
|
||||||
|
"note.snare": ("sand",),
|
||||||
|
"note.hat": ("glass",),
|
||||||
|
"note.bd": ("stone",),
|
||||||
|
"note.bell": ("gold_block",),
|
||||||
|
"note.flute": ("clay",),
|
||||||
|
"note.chime": ("packed_ice",),
|
||||||
|
"note.guitar": ("wool",),
|
||||||
|
"note.xylobone": ("bone_block",),
|
||||||
|
"note.iron_xylophone": ("iron_block",),
|
||||||
|
"note.cow_bell": ("soul_sand",),
|
||||||
|
"note.didgeridoo": ("pumpkin",),
|
||||||
|
"note.bit": ("emerald_block",),
|
||||||
|
"note.banjo": ("hay_block",),
|
||||||
|
"note.pling": ("glowstone",),
|
||||||
|
"note.bassattack": ("command_block",), # 无法找到此音效
|
||||||
|
"note.harp": ("glass",),
|
||||||
|
}
|
||||||
|
@ -1,35 +1,38 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
功能测试 若非已知 请勿更改
|
||||||
|
此文件仅供功能测试,并非实际调用的文件
|
||||||
|
请注意,此处的文件均为测试使用
|
||||||
|
不要更改 不要更改 不要更改
|
||||||
|
请注意这里的一切均需要其原作者更改
|
||||||
|
这里用于放置一些新奇的点子
|
||||||
|
用于测试
|
||||||
|
不要更改 不要更改 不要更改!
|
||||||
|
"""
|
||||||
|
|
||||||
# 音·创 开发交流群 861684859
|
# 音·创 开发交流群 861684859
|
||||||
|
# Email TriM-Organization@hotmail.com
|
||||||
# 版权所有 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray") & 鸣凤鸽子("MingFengPigeon")
|
# 版权所有 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray") & 鸣凤鸽子("MingFengPigeon")
|
||||||
# 若需使用或借鉴 请依照 Apache 2.0 许可证进行许可
|
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
音·创 库版 (Musicreater Package Version)
|
音·创 (Musicreater)
|
||||||
是一款免费开源的针对《我的世界:基岩版》的midi音乐转换库
|
是一款免费开源的针对《我的世界》的midi音乐转换库
|
||||||
注意!除了此源文件以外,任何属于此仓库以及此项目的文件均依照Apache许可证进行许可
|
Musicreater (音·创)
|
||||||
Musicreater pkgver (Package Version 音·创 库版)
|
A free open source library used for convert midi file into formats that is suitable for **Minecraft**.
|
||||||
A free open source library used for convert midi file into formats that is suitable for **Minecraft: Bedrock Edition**.
|
|
||||||
Note! Except for this source file, all the files in this repository and this project are licensed under Apache License 2.0
|
|
||||||
|
|
||||||
Copyright 2022 all the developers of Musicreater
|
版权所有 © 2023 音·创 开发者
|
||||||
|
Copyright © 2023 all the developers of Musicreater
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the 'License');
|
开源相关声明请见 ../License.md
|
||||||
you may not use this file except in compliance with the License.
|
Terms & Conditions: ../License.md
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an 'AS IS' BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _toCmdList_m1(
|
def _toCmdList_m1(
|
||||||
self,
|
self,
|
||||||
scoreboardname: str = "mscplay",
|
scoreboardname: str = "mscplay",
|
||||||
@ -91,10 +94,6 @@ def _toCmdList_m1(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ============================
|
# ============================
|
||||||
|
|
||||||
|
|
||||||
@ -102,10 +101,6 @@ def _toCmdList_m1(
|
|||||||
|
|
||||||
import mido
|
import mido
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class NoteMessage:
|
class NoteMessage:
|
||||||
def __init__(self, channel, pitch, velocity, startT, lastT, midi, now_bpm, change_bpm=None):
|
def __init__(self, channel, pitch, velocity, startT, lastT, midi, now_bpm, change_bpm=None):
|
||||||
self.channel = channel
|
self.channel = channel
|
||||||
@ -213,5 +208,98 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ============================
|
||||||
|
|
||||||
|
|
||||||
|
from typing import Union
|
||||||
|
from .utils import x,y,z,bottem_side_length_of_smallest_square_bottom_box,form_note_block_in_NBT_struct,form_repeater_in_NBT_struct
|
||||||
|
|
||||||
|
# 不要用 没写完
|
||||||
|
def delay_to_note_blocks(
|
||||||
|
baseblock: str = "stone",
|
||||||
|
position_forward: Union(x, y, z) = z,
|
||||||
|
max_height: int = 64,
|
||||||
|
):
|
||||||
|
"""传入音符,生成以音符盒存储的红石音乐
|
||||||
|
:param:
|
||||||
|
baseblock: 中继器的下垫方块
|
||||||
|
position_forward: 结构延长方向
|
||||||
|
:return 是否生成成功
|
||||||
|
"""
|
||||||
|
|
||||||
|
from TrimMCStruct import Structure, Block
|
||||||
|
|
||||||
|
_sideLength = bottem_side_length_of_smallest_square_bottom_box(
|
||||||
|
len(commands), max_height
|
||||||
|
)
|
||||||
|
|
||||||
|
struct = Structure(
|
||||||
|
(_sideLength, max_height, _sideLength), # 声明结构大小
|
||||||
|
)
|
||||||
|
|
||||||
|
log = print
|
||||||
|
|
||||||
|
startpos = [0,0,0]
|
||||||
|
|
||||||
|
|
||||||
|
# 1拍 x 2.5 rt
|
||||||
|
def placeNoteBlock():
|
||||||
|
for i in notes:
|
||||||
|
error = True
|
||||||
|
try:
|
||||||
|
struct.set_block(
|
||||||
|
[startpos[0], startpos[1] + 1, startpos[2]],
|
||||||
|
form_note_block_in_NBT_struct(height2note[i[0]], instrument),
|
||||||
|
)
|
||||||
|
struct.set_block(startpos, Block("universal_minecraft", instuments[i[0]][1]),)
|
||||||
|
error = False
|
||||||
|
except ValueError:
|
||||||
|
log("无法放置音符:" + str(i) + "于" + str(startpos))
|
||||||
|
struct.set_block(Block("universal_minecraft", baseblock), startpos)
|
||||||
|
struct.set_block(
|
||||||
|
Block("universal_minecraft", baseblock),
|
||||||
|
[startpos[0], startpos[1] + 1, startpos[2]],
|
||||||
|
)
|
||||||
|
finally:
|
||||||
|
if error is True:
|
||||||
|
log("无法放置音符:" + str(i) + "于" + str(startpos))
|
||||||
|
struct.set_block(Block("universal_minecraft", baseblock), startpos)
|
||||||
|
struct.set_block(
|
||||||
|
Block("universal_minecraft", baseblock),
|
||||||
|
[startpos[0], startpos[1] + 1, startpos[2]],
|
||||||
|
)
|
||||||
|
delay = int(i[1] * speed + 0.5)
|
||||||
|
if delay <= 4:
|
||||||
|
startpos[0] += 1
|
||||||
|
struct.set_block(
|
||||||
|
form_repeater_in_NBT_struct(delay, "west"),
|
||||||
|
[startpos[0], startpos[1] + 1, startpos[2]],
|
||||||
|
)
|
||||||
|
struct.set_block(Block("universal_minecraft", baseblock), startpos)
|
||||||
|
else:
|
||||||
|
for j in range(int(delay / 4)):
|
||||||
|
startpos[0] += 1
|
||||||
|
struct.set_block(
|
||||||
|
form_repeater_in_NBT_struct(4, "west"),
|
||||||
|
[startpos[0], startpos[1] + 1, startpos[2]],
|
||||||
|
)
|
||||||
|
struct.set_block(Block("universal_minecraft", baseblock), startpos)
|
||||||
|
if delay % 4 != 0:
|
||||||
|
startpos[0] += 1
|
||||||
|
struct.set_block(
|
||||||
|
form_repeater_in_NBT_struct(delay % 4, "west"),
|
||||||
|
[startpos[0], startpos[1] + 1, startpos[2]],
|
||||||
|
)
|
||||||
|
struct.set_block(Block("universal_minecraft", baseblock), startpos)
|
||||||
|
startpos[0] += posadder[0]
|
||||||
|
startpos[1] += posadder[1]
|
||||||
|
startpos[2] += posadder[2]
|
||||||
|
|
||||||
|
# e = True
|
||||||
|
try:
|
||||||
|
placeNoteBlock()
|
||||||
|
# e = False
|
||||||
|
except: # ValueError
|
||||||
|
log("无法放置方块了,可能是因为区块未加载叭")
|
||||||
|
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,9 @@
|
|||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
|
from typing import Union
|
||||||
|
from TrimMCStruct import Structure, Block, TAG_Long, TAG_Byte
|
||||||
|
|
||||||
key = {
|
bdx_key = {
|
||||||
"x": [b"\x0f", b"\x0e", b"\x1c", b"\x14", b"\x15"],
|
"x": [b"\x0f", b"\x0e", b"\x1c", b"\x14", b"\x15"],
|
||||||
"y": [b"\x11", b"\x10", b"\x1d", b"\x16", b"\x17"],
|
"y": [b"\x11", b"\x10", b"\x1d", b"\x16", b"\x17"],
|
||||||
"z": [b"\x13", b"\x12", b"\x1e", b"\x18", b"\x19"],
|
"z": [b"\x13", b"\x12", b"\x1e", b"\x18", b"\x19"],
|
||||||
@ -18,7 +20,7 @@ def bdx_move(axis: str, value: int):
|
|||||||
if value == 0:
|
if value == 0:
|
||||||
return b""
|
return b""
|
||||||
if abs(value) == 1:
|
if abs(value) == 1:
|
||||||
return key[axis][0 if value == -1 else 1]
|
return bdx_key[axis][0 if value == -1 else 1]
|
||||||
|
|
||||||
pointer = sum(
|
pointer = sum(
|
||||||
[
|
[
|
||||||
@ -32,7 +34,9 @@ def bdx_move(axis: str, value: int):
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
return key[axis][pointer] + value.to_bytes(2 ** (pointer - 2), "big", signed=True)
|
return bdx_key[axis][pointer] + value.to_bytes(
|
||||||
|
2 ** (pointer - 2), "big", signed=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def compress_zipfile(sourceDir, outFilename, compression=8, exceptFile=None):
|
def compress_zipfile(sourceDir, outFilename, compression=8, exceptFile=None):
|
||||||
@ -112,8 +116,7 @@ def form_command_block_in_BDX_bytes(
|
|||||||
|
|
||||||
:return:str
|
:return:str
|
||||||
"""
|
"""
|
||||||
block = b"\x24" + \
|
block = b"\x24" + particularValue.to_bytes(2, byteorder="big", signed=False)
|
||||||
particularValue.to_bytes(2, byteorder="big", signed=False)
|
|
||||||
|
|
||||||
for i in [
|
for i in [
|
||||||
impluse.to_bytes(4, byteorder="big", signed=False),
|
impluse.to_bytes(4, byteorder="big", signed=False),
|
||||||
@ -138,7 +141,7 @@ def bottem_side_length_of_smallest_square_bottom_box(total: int, maxHeight: int)
|
|||||||
return math.ceil(math.sqrt(math.ceil(total / maxHeight)))
|
return math.ceil(math.sqrt(math.ceil(total / maxHeight)))
|
||||||
|
|
||||||
|
|
||||||
def to_BDX_bytes(
|
def commands_to_BDX_bytes(
|
||||||
commands: list,
|
commands: list,
|
||||||
max_height: int = 64,
|
max_height: int = 64,
|
||||||
):
|
):
|
||||||
@ -178,7 +181,7 @@ def to_BDX_bytes(
|
|||||||
else (3 if z_forward else 2)
|
else (3 if z_forward else 2)
|
||||||
if (
|
if (
|
||||||
((now_z != 0) and (not z_forward))
|
((now_z != 0) and (not z_forward))
|
||||||
or (z_forward and (now_z != _sideLength))
|
or (z_forward and (now_z != _sideLength - 1))
|
||||||
)
|
)
|
||||||
else 5,
|
else 5,
|
||||||
impluse=impluse,
|
impluse=impluse,
|
||||||
@ -204,15 +207,13 @@ def to_BDX_bytes(
|
|||||||
):
|
):
|
||||||
now_z -= 1 if z_forward else -1
|
now_z -= 1 if z_forward else -1
|
||||||
z_forward = not z_forward
|
z_forward = not z_forward
|
||||||
_bytes += key[x][1]
|
_bytes += bdx_key[x][1]
|
||||||
now_x += 1
|
now_x += 1
|
||||||
else:
|
else:
|
||||||
|
_bytes += bdx_key[z][int(z_forward)]
|
||||||
_bytes += key[z][int(z_forward)]
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
_bytes += bdx_key[y][int(y_forward)]
|
||||||
_bytes += key[y][int(y_forward)]
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
_bytes,
|
_bytes,
|
||||||
@ -225,6 +226,60 @@ def to_BDX_bytes(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def form_note_block_in_NBT_struct(
|
||||||
|
note: int, coordinate: tuple, instrument: str = "note.harp", powered: bool = False
|
||||||
|
):
|
||||||
|
"""生成音符盒方块
|
||||||
|
:param note: `int`(0~24)
|
||||||
|
音符的音高
|
||||||
|
:param coordinate: `tuple[int,int,int]`
|
||||||
|
此方块所在之相对坐标
|
||||||
|
:param instrument: `str`
|
||||||
|
音符盒的乐器
|
||||||
|
:param powered: `bool`
|
||||||
|
是否已被激活
|
||||||
|
:return Block
|
||||||
|
"""
|
||||||
|
|
||||||
|
return Block(
|
||||||
|
"minecraft",
|
||||||
|
"noteblock",
|
||||||
|
{
|
||||||
|
"instrument": instrument.replace("note.", ""),
|
||||||
|
"note": note,
|
||||||
|
"powered": powered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"block_entity_data": {
|
||||||
|
"note": TAG_Byte(note),
|
||||||
|
"id": "noteblock",
|
||||||
|
"x": coordinate[0],
|
||||||
|
"y": coordinate[1],
|
||||||
|
"z": coordinate[2],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def form_repeater_in_NBT_struct(
|
||||||
|
delay: int, facing: int
|
||||||
|
):
|
||||||
|
"""生成中继器方块
|
||||||
|
:param powered:
|
||||||
|
:param locked:
|
||||||
|
:param facing:
|
||||||
|
:param delay: 1~4
|
||||||
|
:return Block()"""
|
||||||
|
|
||||||
|
return Block(
|
||||||
|
"minecraft",
|
||||||
|
"unpowered_repeater",
|
||||||
|
{
|
||||||
|
"repeater_delay": delay,
|
||||||
|
"direction": facing,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
def form_command_block_in_NBT_struct(
|
def form_command_block_in_NBT_struct(
|
||||||
command: str,
|
command: str,
|
||||||
coordinate: tuple,
|
coordinate: tuple,
|
||||||
@ -281,42 +336,43 @@ def form_command_block_in_NBT_struct(
|
|||||||
|
|
||||||
:return:str
|
:return:str
|
||||||
"""
|
"""
|
||||||
from TrimMCStruct import Block, TAG_Long
|
|
||||||
block = Block(
|
return Block(
|
||||||
"minecraft",
|
"minecraft",
|
||||||
"command_block" if impluse == 0 else (
|
"command_block"
|
||||||
"repeating_command_block" if impluse == 1 else "chain_command_block"),
|
if impluse == 0
|
||||||
states={"conditional_bit": condition,
|
else ("repeating_command_block" if impluse == 1 else "chain_command_block"),
|
||||||
"facing_direction": particularValue},
|
states={"conditional_bit": condition, "facing_direction": particularValue},
|
||||||
extra_data={
|
extra_data={
|
||||||
'Command': command,
|
"block_entity_data": {
|
||||||
'CustomName': customName,
|
"Command": command,
|
||||||
'ExecuteOnFirstTick': executeOnFirstTick,
|
"CustomName": customName,
|
||||||
'LPCommandMode': 0,
|
"ExecuteOnFirstTick": executeOnFirstTick,
|
||||||
'LPCondionalMode': False,
|
"LPCommandMode": 0,
|
||||||
'LPRedstoneMode': False,
|
"LPCondionalMode": False,
|
||||||
'LastExecution': TAG_Long(0),
|
"LPRedstoneMode": False,
|
||||||
'LastOutput': '',
|
"LastExecution": TAG_Long(0),
|
||||||
'LastOutputParams': [],
|
"LastOutput": "",
|
||||||
'SuccessCount': 0,
|
"LastOutputParams": [],
|
||||||
'TickDelay': tickDelay,
|
"SuccessCount": 0,
|
||||||
'TrackOutput': trackOutput,
|
"TickDelay": tickDelay,
|
||||||
'Version': 25,
|
"TrackOutput": trackOutput,
|
||||||
'auto': alwaysRun,
|
"Version": 25,
|
||||||
'conditionMet': False, # 是否已经满足条件
|
"auto": alwaysRun,
|
||||||
'conditionalMode': condition,
|
"conditionMet": False, # 是否已经满足条件
|
||||||
'id': 'CommandBlock',
|
"conditionalMode": condition,
|
||||||
'isMovable': True,
|
"id": "CommandBlock",
|
||||||
'powered': False, # 是否已激活
|
"isMovable": True,
|
||||||
'x': coordinate[0],
|
"powered": False, # 是否已激活
|
||||||
'y': coordinate[1],
|
"x": coordinate[0],
|
||||||
'z': coordinate[2],
|
"y": coordinate[1],
|
||||||
|
"z": coordinate[2],
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
compability_version=17959425,
|
||||||
)
|
)
|
||||||
return block
|
|
||||||
|
|
||||||
|
def commands_to_structure(
|
||||||
def to_structure(
|
|
||||||
commands: list,
|
commands: list,
|
||||||
max_height: int = 64,
|
max_height: int = 64,
|
||||||
):
|
):
|
||||||
@ -325,8 +381,6 @@ def to_structure(
|
|||||||
:param max_height: 生成结构最大高度
|
:param max_height: 生成结构最大高度
|
||||||
:return 成功与否,成功返回(结构类,结构占用大小),失败返回(False,str失败原因)
|
:return 成功与否,成功返回(结构类,结构占用大小),失败返回(False,str失败原因)
|
||||||
"""
|
"""
|
||||||
# 导入库
|
|
||||||
from TrimMCStruct import Structure
|
|
||||||
|
|
||||||
_sideLength = bottem_side_length_of_smallest_square_bottom_box(
|
_sideLength = bottem_side_length_of_smallest_square_bottom_box(
|
||||||
len(commands), max_height
|
len(commands), max_height
|
||||||
@ -345,7 +399,8 @@ def to_structure(
|
|||||||
|
|
||||||
for cmd, delay in commands:
|
for cmd, delay in commands:
|
||||||
coordinate = (now_x, now_y, now_z)
|
coordinate = (now_x, now_y, now_z)
|
||||||
struct.set_block(coordinate,
|
struct.set_block(
|
||||||
|
coordinate,
|
||||||
form_command_block_in_NBT_struct(
|
form_command_block_in_NBT_struct(
|
||||||
command=cmd,
|
command=cmd,
|
||||||
coordinate=coordinate,
|
coordinate=coordinate,
|
||||||
@ -354,12 +409,14 @@ def to_structure(
|
|||||||
((now_y != 0) and (not y_forward))
|
((now_y != 0) and (not y_forward))
|
||||||
or (y_forward and (now_y != (max_height - 1)))
|
or (y_forward and (now_y != (max_height - 1)))
|
||||||
)
|
)
|
||||||
else (3 if z_forward else 2)
|
else (
|
||||||
|
(3 if z_forward else 2)
|
||||||
if (
|
if (
|
||||||
((now_z != 0) and (not z_forward))
|
((now_z != 0) and (not z_forward))
|
||||||
or (z_forward and (now_z != _sideLength))
|
or (z_forward and (now_z != _sideLength - 1))
|
||||||
)
|
)
|
||||||
else 5,
|
else 5
|
||||||
|
),
|
||||||
impluse=2,
|
impluse=2,
|
||||||
condition=False,
|
condition=False,
|
||||||
alwaysRun=True,
|
alwaysRun=True,
|
||||||
@ -367,7 +424,8 @@ def to_structure(
|
|||||||
customName="",
|
customName="",
|
||||||
executeOnFirstTick=False,
|
executeOnFirstTick=False,
|
||||||
trackOutput=True,
|
trackOutput=True,
|
||||||
))
|
),
|
||||||
|
)
|
||||||
|
|
||||||
now_y += 1 if y_forward else -1
|
now_y += 1 if y_forward else -1
|
||||||
|
|
||||||
@ -387,9 +445,11 @@ def to_structure(
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
struct,
|
struct,
|
||||||
[
|
(
|
||||||
now_x + 1,
|
now_x + 1,
|
||||||
max_height if now_x or now_z else now_y,
|
max_height if now_x or now_z else now_y,
|
||||||
_sideLength if now_x else now_z,
|
_sideLength if now_x else now_z,
|
||||||
],
|
),
|
||||||
|
(now_x, now_y, now_z),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img width="128" height="128" src="https://s1.ax1x.com/2022/05/06/Ouhghj.md.png">
|
<img width="128" height="128" src="https://gitee.com/TriM-Organization/Musicreater/raw/master/resources/msctIcon.ico">
|
||||||
</img>
|
</img>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<img width="128" height="128" src="https://s1.ax1x.com/2022/05/06/Ouhghj.md.png" >
|
<img width="128" height="128" src="https://s1.ax1x.com/2022/05/06/Ouhghj.md.png" >
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 align="center">a free open-source library of converting midi files into *Minecraft* formats.</h3>
|
<h3 align="center">a free open-source library of converting midi files into _Minecraft_ formats.</h3>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://forthebadge.com/images/badges/built-with-love.svg">
|
<img src="https://forthebadge.com/images/badges/built-with-love.svg">
|
||||||
|
@ -15,8 +15,10 @@
|
|||||||
```python
|
```python
|
||||||
import Musicreater # 导入转换库
|
import Musicreater # 导入转换库
|
||||||
|
|
||||||
|
old_execute_format = False # 指定是否使用旧的execute指令语法(即1.18及以前的《我的世界:基岩版》语法)
|
||||||
|
|
||||||
# 首先新建转换对象。
|
# 首先新建转换对象。
|
||||||
conversion = Musicreater.midiConvert()
|
conversion = Musicreater.midiConvert(enable_old_exe_format = old_execute_format)
|
||||||
# 值得注意的是,一个转换对象可以转换多个文件。
|
# 值得注意的是,一个转换对象可以转换多个文件。
|
||||||
# 也就是在实例化的时候不进行对文件的绑定。
|
# 也就是在实例化的时候不进行对文件的绑定。
|
||||||
# 如果有调试需要,可以在实例化时传入参数 debug = True
|
# 如果有调试需要,可以在实例化时传入参数 debug = True
|
||||||
@ -26,10 +28,9 @@ conversion = Musicreater.midiConvert()
|
|||||||
# 地址都为字符串类型,不能传入文件流
|
# 地址都为字符串类型,不能传入文件流
|
||||||
midi_path = "./where/you/place/.midi/files.mid"
|
midi_path = "./where/you/place/.midi/files.mid"
|
||||||
output_folder = "./where/you/want2/convert/into/"
|
output_folder = "./where/you/want2/convert/into/"
|
||||||
old_execute_format = False # 指定是否使用旧的execute指令语法(即1.18及以前的《我的世界:基岩版》语法)
|
|
||||||
|
|
||||||
# 设定基本转换参数
|
# 设定基本转换参数
|
||||||
conversion.convert(midi_path,output_folder,old_execute_format)
|
conversion.convert(midi_path,output_folder)
|
||||||
|
|
||||||
# 进行转换并接受输出,具体的参数均在代码之文档中有相关说明
|
# 进行转换并接受输出,具体的参数均在代码之文档中有相关说明
|
||||||
method_id = 3 # 指定使用的转换算法
|
method_id = 3 # 指定使用的转换算法
|
||||||
|
24
example.py
24
example.py
@ -20,8 +20,6 @@ import os
|
|||||||
import Musicreater
|
import Musicreater
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 获取midi列表
|
# 获取midi列表
|
||||||
midi_path = input(f"请输入MIDI路径:")
|
midi_path = input(f"请输入MIDI路径:")
|
||||||
|
|
||||||
@ -46,9 +44,6 @@ fileFormat = int(input(f"请输入输出格式[BDX(1) 或 MCPACK(0)]:").lower(
|
|||||||
playerFormat = int(input(f"请选择播放方式[计分板(1) 或 延迟(0)]:").lower())
|
playerFormat = int(input(f"请选择播放方式[计分板(1) 或 延迟(0)]:").lower())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 真假字符串判断
|
# 真假字符串判断
|
||||||
def bool_str(sth: str) -> bool:
|
def bool_str(sth: str) -> bool:
|
||||||
try:
|
try:
|
||||||
@ -61,6 +56,7 @@ def bool_str(sth: str) -> bool:
|
|||||||
else:
|
else:
|
||||||
raise ValueError("布尔字符串啊?")
|
raise ValueError("布尔字符串啊?")
|
||||||
|
|
||||||
|
|
||||||
debug = False
|
debug = False
|
||||||
|
|
||||||
if os.path.exists("./demo_config.json"):
|
if os.path.exists("./demo_config.json"):
|
||||||
@ -75,40 +71,40 @@ else:
|
|||||||
# 提示语 检测函数 错误提示语
|
# 提示语 检测函数 错误提示语
|
||||||
for args in [
|
for args in [
|
||||||
(
|
(
|
||||||
f'输入音量:',
|
f"输入音量:",
|
||||||
float,
|
float,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
f'输入播放速度:',
|
f"输入播放速度:",
|
||||||
float,
|
float,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
f'是否启用进度条:',
|
f"是否启用进度条:",
|
||||||
bool_str,
|
bool_str,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
f'计分板名称:',
|
f"计分板名称:",
|
||||||
str,
|
str,
|
||||||
)
|
)
|
||||||
if playerFormat == 1
|
if playerFormat == 1
|
||||||
else (
|
else (
|
||||||
f'玩家选择器:',
|
f"玩家选择器:",
|
||||||
str,
|
str,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
f'是否自动重置计分板:',
|
f"是否自动重置计分板:",
|
||||||
bool_str,
|
bool_str,
|
||||||
)
|
)
|
||||||
if playerFormat == 1
|
if playerFormat == 1
|
||||||
else (),
|
else (),
|
||||||
(
|
(
|
||||||
f'作者名称:',
|
f"作者名称:",
|
||||||
str,
|
str,
|
||||||
)
|
)
|
||||||
if fileFormat == 1
|
if fileFormat == 1
|
||||||
else (),
|
else (),
|
||||||
(
|
(
|
||||||
f'最大结构高度:',
|
f"最大结构高度:",
|
||||||
int,
|
int,
|
||||||
)
|
)
|
||||||
if fileFormat == 1
|
if fileFormat == 1
|
||||||
@ -117,7 +113,7 @@ else:
|
|||||||
if args:
|
if args:
|
||||||
prompts.append(args[1](input(args[0])))
|
prompts.append(args[1](input(args[0])))
|
||||||
|
|
||||||
conversion = Musicreater.midiConvert(debug)
|
conversion = Musicreater.midiConvert(debug=debug)
|
||||||
|
|
||||||
|
|
||||||
print(f"正在处理 {midi_path} :")
|
print(f"正在处理 {midi_path} :")
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
|
|
||||||
from Musicreater import midiConvert
|
from Musicreater import midiConvert
|
||||||
|
|
||||||
conversion = midiConvert()
|
conversion = midiConvert(enable_old_exe_format=False)
|
||||||
conversion.convert(input("midi path:"),input("out path:"))
|
conversion.convert(input("midi路径:"), input("输出路径:"))
|
||||||
conversion.to_mcstructure_file_with_delay(3,)
|
|
||||||
|
conversion.to_mcstructure_file_with_delay(
|
||||||
|
3,
|
||||||
|
)
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
Brotli>=1.0.9
|
Brotli>=1.0.9
|
||||||
mido>=1.2.10
|
mido>=1.2.10
|
||||||
TrimMCStruct>=0.0.5.5
|
TrimMCStruct>=0.0.5.6
|
Loading…
Reference in New Issue
Block a user