This commit is contained in:
EillesWan 2023-04-29 21:32:16 +08:00
commit 5d48fcd96a
6 changed files with 260 additions and 263 deletions

View File

@ -29,7 +29,7 @@ class MSCTBaseException(Exception):
super().__init__(*args) super().__init__(*args)
def miao( def miao(
self, self,
): ):
for i in self.args: for i in self.args:
print(i + "喵!") print(i + "喵!")
@ -81,7 +81,7 @@ class NotDefineTempoError(MidiFormatException):
class ChannelOverFlowError(MidiFormatException): class ChannelOverFlowError(MidiFormatException):
"""一个midi中含有过多的通道""" """一个midi中含有过多的通道"""
def __init__(self, max_channel = 16, *args): def __init__(self, max_channel=16, *args):
"""一个midi中含有过多的通道""" """一个midi中含有过多的通道"""
super().__init__("含有过多的通道(数量应≤{}".format(max_channel), *args) super().__init__("含有过多的通道(数量应≤{}".format(max_channel), *args)

View File

@ -20,17 +20,17 @@ Copyright © 2023 all the developers of Musicreater
Terms & Conditions: ../License.md Terms & Conditions: ../License.md
""" """
import mido
import brotli
import json import json
import uuid
import shutil import shutil
import uuid
from typing import TypeVar, Union
import brotli
import mido
from .utils import *
from .exceptions import * from .exceptions import *
from .instConstants import * from .instConstants import *
from .utils import *
from typing import TypeVar, Union
T = TypeVar("T") # Declare type variable T = TypeVar("T") # Declare type variable
VM = TypeVar("VM", mido.MidiFile, None) # void mido VM = TypeVar("VM", mido.MidiFile, None) # void mido
@ -43,7 +43,7 @@ DEFAULT_PROGRESSBAR_STYLE = (
class SingleNote: class SingleNote:
def __init__( def __init__(
self, instrument: int, pitch: int, velocity: int, startTime: int, lastTime: int self, instrument: int, pitch: int, velocity: int, startTime: int, lastTime: int
): ):
"""用于存储单个音符的类 """用于存储单个音符的类
:param instrument 乐器编号 :param instrument 乐器编号
@ -216,7 +216,7 @@ class midiConvert:
@staticmethod @staticmethod
def __Inst2soundID_withX( def __Inst2soundID_withX(
instrumentID: int, instrumentID: int,
): ):
""" """
返回midi的乐器ID对应的我的世界乐器名对于音域转换算法如下 返回midi的乐器ID对应的我的世界乐器名对于音域转换算法如下
@ -278,10 +278,10 @@ class midiConvert:
return str(int(int(score / 20) / 60)) + ":" + str(int(int(score / 20) % 60)) return str(int(int(score / 20) / 60)) + ":" + str(int(int(score / 20) % 60))
def __form_progress_bar( def __form_progress_bar(
self, self,
max_score: int, max_score: int,
scoreboard_name: str, scoreboard_name: str,
progressbar_style: tuple = DEFAULT_PROGRESSBAR_STYLE, progressbar_style: tuple = DEFAULT_PROGRESSBAR_STYLE,
) -> list: ) -> list:
""" """
生成进度条 生成进度条
@ -466,10 +466,10 @@ class midiConvert:
return result return result
def _toCmdList_m1( def _toCmdList_m1(
self, self,
scoreboard_name: str = "mscplay", scoreboard_name: str = "mscplay",
MaxVolume: float = 1.0, MaxVolume: float = 1.0,
speed: float = 1.0, speed: float = 1.0,
) -> list: ) -> list:
""" """
使用Dislink Sforza的转换思路将midi转换为我的世界命令列表 使用Dislink Sforza的转换思路将midi转换为我的世界命令列表
@ -525,7 +525,7 @@ class midiConvert:
+ str(nowscore) + str(nowscore)
+ "}" + "}"
+ f"] ~ ~ ~ playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg.velocity / 128} " + f"] ~ ~ ~ playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg.velocity / 128} "
f"{2 ** ((msg.note - 60 - _X) / 12)}" f"{2 ** ((msg.note - 60 - _X) / 12)}"
) )
commands += 1 commands += 1
if len(singleTrack) != 0: if len(singleTrack) != 0:
@ -535,10 +535,10 @@ class midiConvert:
# 原本这个算法的转换效果应该和上面的算法相似的 # 原本这个算法的转换效果应该和上面的算法相似的
def _toCmdList_m2( def _toCmdList_m2(
self, self,
scoreboard_name: str = "mscplay", scoreboard_name: str = "mscplay",
MaxVolume: float = 1.0, MaxVolume: float = 1.0,
speed: float = 1.0, speed: float = 1.0,
) -> list: ) -> list:
""" """
使用神羽和金羿的转换思路将midi转换为我的世界命令列表 使用神羽和金羿的转换思路将midi转换为我的世界命令列表
@ -597,7 +597,7 @@ class midiConvert:
) )
elif (msg.type == "note_on" and msg.velocity == 0) or ( elif (msg.type == "note_on" and msg.velocity == 0) or (
msg.type == "note_off" msg.type == "note_off"
): ):
channels[msg.channel].append(("NoteE", msg.note, microseconds)) channels[msg.channel].append(("NoteE", msg.note, microseconds))
@ -660,7 +660,7 @@ class midiConvert:
.replace(")", r"}") .replace(")", r"}")
) )
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} " + f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} "
f"{2 ** ((msg[1] - 60 - _X) / 12)}" f"{2 ** ((msg[1] - 60 - _X) / 12)}"
) )
cmdAmount += 1 cmdAmount += 1
@ -671,10 +671,10 @@ class midiConvert:
return [tracks, cmdAmount, maxScore] return [tracks, cmdAmount, maxScore]
def _toCmdList_m3( def _toCmdList_m3(
self, self,
scoreboard_name: str = "mscplay", scoreboard_name: str = "mscplay",
MaxVolume: float = 1.0, MaxVolume: float = 1.0,
speed: float = 1.0, speed: float = 1.0,
) -> list: ) -> list:
""" """
使用金羿的转换思路将midi转换为我的世界命令列表 使用金羿的转换思路将midi转换为我的世界命令列表
@ -720,7 +720,7 @@ class midiConvert:
if msg.time != 0: if msg.time != 0:
try: try:
microseconds += ( microseconds += (
msg.time * tempo / self.midi.ticks_per_beat / 1000 msg.time * tempo / self.midi.ticks_per_beat / 1000
) )
# print(microseconds) # print(microseconds)
except NameError: except NameError:
@ -728,10 +728,10 @@ class midiConvert:
raise NotDefineTempoError("计算当前分数时出错 未定义参量 Tempo") raise NotDefineTempoError("计算当前分数时出错 未定义参量 Tempo")
else: else:
microseconds += ( microseconds += (
msg.time msg.time
* mido.midifiles.midifiles.DEFAULT_TEMPO * mido.midifiles.midifiles.DEFAULT_TEMPO
/ self.midi.ticks_per_beat / self.midi.ticks_per_beat
) / 1000 ) / 1000
if msg.is_meta: if msg.is_meta:
if msg.type == "set_tempo": if msg.type == "set_tempo":
@ -759,7 +759,7 @@ class midiConvert:
) )
elif (msg.type == "note_on" and msg.velocity == 0) or ( elif (msg.type == "note_on" and msg.velocity == 0) or (
msg.type == "note_off" msg.type == "note_off"
): ):
channels[msg.channel][track_no].append( channels[msg.channel][track_no].append(
("NoteE", msg.note, microseconds) ("NoteE", msg.note, microseconds)
@ -825,7 +825,7 @@ class midiConvert:
.replace(")", r"}") .replace(")", r"}")
) )
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} " + f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} "
f"{2 ** ((msg[1] - 60 - _X) / 12)}" f"{2 ** ((msg[1] - 60 - _X) / 12)}"
) )
cmdAmount += 1 cmdAmount += 1
@ -837,10 +837,10 @@ class midiConvert:
# 简单的单音填充 # 简单的单音填充
def _toCmdList_m4( def _toCmdList_m4(
self, self,
scoreboard_name: str = "mscplay", scoreboard_name: str = "mscplay",
MaxVolume: float = 1.0, MaxVolume: float = 1.0,
speed: float = 1.0, speed: float = 1.0,
) -> list: ) -> list:
""" """
使用金羿的转换思路将midi转换为我的世界命令列表并使用完全填充算法优化音感 使用金羿的转换思路将midi转换为我的世界命令列表并使用完全填充算法优化音感
@ -893,7 +893,7 @@ class midiConvert:
) )
elif (msg.type == "note_on" and msg.velocity == 0) or ( elif (msg.type == "note_on" and msg.velocity == 0) or (
msg.type == "note_off" msg.type == "note_off"
): ):
channels[msg.channel].append(("NoteE", msg.note, microseconds)) channels[msg.channel].append(("NoteE", msg.note, microseconds))
@ -1009,7 +1009,7 @@ class midiConvert:
+ str(score_now) + str(score_now)
+ "}" + "}"
+ f"] ~ ~ ~ playsound {soundID} @s ~ ~{1 / every_note[4] - 1} ~ " + f"] ~ ~ ~ playsound {soundID} @s ~ ~{1 / every_note[4] - 1} ~ "
f"{note.velocity * (0.7 if CheckFirstChannel else 0.9)} {2 ** ((note.pitch - 60 - _X) / 12)}" f"{note.velocity * (0.7 if CheckFirstChannel else 0.9)} {2 ** ((note.pitch - 60 - _X) / 12)}"
) )
cmdAmount += 1 cmdAmount += 1
@ -1018,10 +1018,10 @@ class midiConvert:
return [tracks, cmdAmount, maxScore] return [tracks, cmdAmount, maxScore]
def _toCmdList_withDelay_m1( def _toCmdList_withDelay_m1(
self, self,
MaxVolume: float = 1.0, MaxVolume: float = 1.0,
speed: float = 1.0, speed: float = 1.0,
player: str = "@a", player: str = "@a",
) -> list: ) -> list:
""" """
使用Dislink Sforza的转换思路将midi转换为我的世界命令列表并输出每个音符之后的延迟 使用Dislink Sforza的转换思路将midi转换为我的世界命令列表并输出每个音符之后的延迟
@ -1061,13 +1061,13 @@ class midiConvert:
tracks[now_tick].append( tracks[now_tick].append(
self.execute_cmd_head.format(player) self.execute_cmd_head.format(player)
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg.velocity / 128} " + f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg.velocity / 128} "
f"{2 ** ((msg.note - 60 - _X) / 12)}" f"{2 ** ((msg.note - 60 - _X) / 12)}"
) )
except KeyError: except KeyError:
tracks[now_tick] = [ tracks[now_tick] = [
self.execute_cmd_head.format(player) self.execute_cmd_head.format(player)
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg.velocity / 128} " + f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg.velocity / 128} "
f"{2 ** ((msg.note - 60 - _X) / 12)}" f"{2 ** ((msg.note - 60 - _X) / 12)}"
] ]
results = [] results = []
@ -1090,10 +1090,10 @@ class midiConvert:
return [results, max(all_ticks)] return [results, max(all_ticks)]
def _toCmdList_withDelay_m2( def _toCmdList_withDelay_m2(
self, self,
MaxVolume: float = 1.0, MaxVolume: float = 1.0,
speed: float = 1.0, speed: float = 1.0,
player: str = "@a", player: str = "@a",
) -> list: ) -> list:
""" """
使用神羽和金羿的转换思路将midi转换为我的世界命令列表并输出每个音符之后的延迟 使用神羽和金羿的转换思路将midi转换为我的世界命令列表并输出每个音符之后的延迟
@ -1137,7 +1137,7 @@ class midiConvert:
for msg in self.midi: for msg in self.midi:
try: try:
microseconds += ( microseconds += (
msg.time * 1000 msg.time * 1000
) # 任何人都tm不要动这里这里循环方式不是track所以这里的计时方式不一样 ) # 任何人都tm不要动这里这里循环方式不是track所以这里的计时方式不一样
# print(microseconds) # print(microseconds)
@ -1146,7 +1146,7 @@ class midiConvert:
raise NotDefineTempoError("计算当前分数时出错 未定义参量 Tempo") raise NotDefineTempoError("计算当前分数时出错 未定义参量 Tempo")
else: else:
microseconds += ( microseconds += (
msg.time * 1000 msg.time * 1000
) # 任何人都tm不要动这里这里循环方式不是track所以这里的计时方式不一样 ) # 任何人都tm不要动这里这里循环方式不是track所以这里的计时方式不一样
if msg.is_meta: if msg.is_meta:
@ -1169,7 +1169,7 @@ class midiConvert:
) )
elif (msg.type == "note_on" and msg.velocity == 0) or ( elif (msg.type == "note_on" and msg.velocity == 0) or (
msg.type == "note_off" msg.type == "note_off"
): ):
channels[msg.channel].append(("NoteE", msg.note, microseconds)) channels[msg.channel].append(("NoteE", msg.note, microseconds))
@ -1223,13 +1223,13 @@ class midiConvert:
tracks[score_now].append( tracks[score_now].append(
self.execute_cmd_head.format(player) self.execute_cmd_head.format(player)
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} " + f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} "
f"{2 ** ((msg[1] - 60 - _X) / 12)}" f"{2 ** ((msg[1] - 60 - _X) / 12)}"
) )
except KeyError: except KeyError:
tracks[score_now] = [ tracks[score_now] = [
self.execute_cmd_head.format(player) self.execute_cmd_head.format(player)
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} " + f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} "
f"{2 ** ((msg[1] - 60 - _X) / 12)}" f"{2 ** ((msg[1] - 60 - _X) / 12)}"
] ]
all_ticks = list(tracks.keys()) all_ticks = list(tracks.keys())
@ -1254,10 +1254,10 @@ class midiConvert:
return [results, max(all_ticks)] return [results, max(all_ticks)]
def _toCmdList_withDelay_m3( def _toCmdList_withDelay_m3(
self, self,
MaxVolume: float = 1.0, MaxVolume: float = 1.0,
speed: float = 1.0, speed: float = 1.0,
player: str = "@a", player: str = "@a",
) -> list: ) -> list:
""" """
使用金羿的转换思路将midi转换为我的世界命令列表并输出每个音符之后的延迟 使用金羿的转换思路将midi转换为我的世界命令列表并输出每个音符之后的延迟
@ -1303,7 +1303,7 @@ class midiConvert:
if msg.time != 0: if msg.time != 0:
try: try:
microseconds += ( microseconds += (
msg.time * tempo / self.midi.ticks_per_beat / 1000 msg.time * tempo / self.midi.ticks_per_beat / 1000
) )
# print(microseconds) # print(microseconds)
except NameError: except NameError:
@ -1311,10 +1311,10 @@ class midiConvert:
raise NotDefineTempoError("计算当前分数时出错 未定义参量 Tempo") raise NotDefineTempoError("计算当前分数时出错 未定义参量 Tempo")
else: else:
microseconds += ( microseconds += (
msg.time msg.time
* mido.midifiles.midifiles.DEFAULT_TEMPO * mido.midifiles.midifiles.DEFAULT_TEMPO
/ self.midi.ticks_per_beat / self.midi.ticks_per_beat
) / 1000 ) / 1000
if msg.is_meta: if msg.is_meta:
if msg.type == "set_tempo": if msg.type == "set_tempo":
@ -1342,7 +1342,7 @@ class midiConvert:
) )
elif (msg.type == "note_on" and msg.velocity == 0) or ( elif (msg.type == "note_on" and msg.velocity == 0) or (
msg.type == "note_off" msg.type == "note_off"
): ):
channels[msg.channel][track_no].append( channels[msg.channel][track_no].append(
("NoteE", msg.note, microseconds) ("NoteE", msg.note, microseconds)
@ -1400,13 +1400,13 @@ class midiConvert:
tracks[score_now].append( tracks[score_now].append(
self.execute_cmd_head.format(player) self.execute_cmd_head.format(player)
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} " + f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} "
f"{2 ** ((msg[1] - 60 - _X) / 12)}" f"{2 ** ((msg[1] - 60 - _X) / 12)}"
) )
except KeyError: except KeyError:
tracks[score_now] = [ tracks[score_now] = [
self.execute_cmd_head.format(player) self.execute_cmd_head.format(player)
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} " + f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} "
f"{2 ** ((msg[1] - 60 - _X) / 12)}" f"{2 ** ((msg[1] - 60 - _X) / 12)}"
] ]
all_ticks = list(tracks.keys()) all_ticks = list(tracks.keys())
@ -1432,13 +1432,13 @@ class midiConvert:
return [results, max(all_ticks)] return [results, max(all_ticks)]
def to_mcpack( def to_mcpack(
self, self,
method: int = 1, method: int = 1,
volume: float = 1.0, volume: float = 1.0,
speed: float = 1.0, speed: float = 1.0,
progressbar: Union[bool, tuple] = None, progressbar: Union[bool, tuple] = None,
scoreboard_name: str = "mscplay", scoreboard_name: str = "mscplay",
isAutoReset: bool = False, isAutoReset: bool = False,
) -> tuple: ) -> tuple:
""" """
使用method指定的转换算法将midi转换为我的世界mcpack格式的包 使用method指定的转换算法将midi转换为我的世界mcpack格式的包
@ -1466,7 +1466,7 @@ class midiConvert:
# 写入manifest.json # 写入manifest.json
if not os.path.exists(f"{self.output_path}/temp/manifest.json"): if not os.path.exists(f"{self.output_path}/temp/manifest.json"):
with open( with open(
f"{self.output_path}/temp/manifest.json", "w", encoding="utf-8" f"{self.output_path}/temp/manifest.json", "w", encoding="utf-8"
) as f: ) as f:
f.write( f.write(
'{\n "format_version": 1,\n "header": {\n "description": "' '{\n "format_version": 1,\n "header": {\n "description": "'
@ -1483,7 +1483,7 @@ class midiConvert:
) )
else: else:
with open( with open(
f"{self.output_path}/temp/manifest.json", "r", encoding="utf-8" f"{self.output_path}/temp/manifest.json", "r", encoding="utf-8"
) as manifest: ) as manifest:
data = json.loads(manifest.read()) data = json.loads(manifest.read())
data["header"][ data["header"][
@ -1507,9 +1507,9 @@ class midiConvert:
"function mscplay/track" + str(cmdlist.index(track) + 1) + "\n" "function mscplay/track" + str(cmdlist.index(track) + 1) + "\n"
) )
with open( with open(
f"{self.output_path}/temp/functions/mscplay/track{cmdlist.index(track) + 1}.mcfunction", f"{self.output_path}/temp/functions/mscplay/track{cmdlist.index(track) + 1}.mcfunction",
"w", "w",
encoding="utf-8", encoding="utf-8",
) as f: ) as f:
f.write("\n".join(track)) f.write("\n".join(track))
index_file.writelines( index_file.writelines(
@ -1520,12 +1520,12 @@ class midiConvert:
+ scoreboard_name + scoreboard_name
+ " 1\n", + " 1\n",
( (
"scoreboard players reset @a[scores={" "scoreboard players reset @a[scores={"
+ scoreboard_name + scoreboard_name
+ "=" + "="
+ str(maxscore + 20) + str(maxscore + 20)
+ "..}]" + "..}]"
+ f" {scoreboard_name}\n" + f" {scoreboard_name}\n"
) )
if isAutoReset if isAutoReset
else "", else "",
@ -1538,18 +1538,18 @@ class midiConvert:
# 改这一行没🐎 # 改这一行没🐎
if progressbar is True: if progressbar is True:
with open( with open(
f"{self.output_path}/temp/functions/mscplay/progressShow.mcfunction", f"{self.output_path}/temp/functions/mscplay/progressShow.mcfunction",
"w", "w",
encoding="utf-8", encoding="utf-8",
) as f: ) as f:
f.writelines( f.writelines(
"\n".join(self.__form_progress_bar(maxscore, scoreboard_name)) "\n".join(self.__form_progress_bar(maxscore, scoreboard_name))
) )
else: else:
with open( with open(
f"{self.output_path}/temp/functions/mscplay/progressShow.mcfunction", f"{self.output_path}/temp/functions/mscplay/progressShow.mcfunction",
"w", "w",
encoding="utf-8", encoding="utf-8",
) as f: ) as f:
f.writelines( f.writelines(
"\n".join( "\n".join(
@ -1573,13 +1573,13 @@ class midiConvert:
return True, maxlen, maxscore return True, maxlen, maxscore
def to_mcpack_with_delay( def to_mcpack_with_delay(
self, self,
method: int = 1, method: int = 1,
volume: float = 1.0, volume: float = 1.0,
speed: float = 1.0, speed: float = 1.0,
progressbar: Union[bool, tuple] = False, progressbar: Union[bool, tuple] = False,
player: str = "@a", player: str = "@a",
max_height: int = 64, max_height: int = 64,
): ):
""" """
使用method指定的转换算法将midi转换为mcstructure结构文件后打包成mcpack文件 使用method指定的转换算法将midi转换为mcstructure结构文件后打包成mcpack文件
@ -1646,14 +1646,14 @@ class midiConvert:
struct, size, end_pos = commands_to_structure(command_list, max_height - 1) struct, size, end_pos = commands_to_structure(command_list, max_height - 1)
with open( with open(
os.path.abspath( os.path.abspath(
os.path.join( os.path.join(
self.output_path, self.output_path,
"temp/structures/", "temp/structures/",
f"{self.mid_file_name}_main.mcstructure", f"{self.mid_file_name}_main.mcstructure",
) )
), ),
"wb+", "wb+",
) as f: ) as f:
struct.dump(f) struct.dump(f)
@ -1680,14 +1680,14 @@ class midiConvert:
) )
with open( with open(
os.path.abspath( os.path.abspath(
os.path.join( os.path.join(
self.output_path, self.output_path,
"temp/structures/", "temp/structures/",
f"{self.mid_file_name}_start.mcstructure", f"{self.mid_file_name}_start.mcstructure",
) )
), ),
"wb+", "wb+",
) as f: ) as f:
struct_a.dump(f) struct_a.dump(f)
@ -1702,14 +1702,14 @@ class midiConvert:
) )
with open( with open(
os.path.abspath( os.path.abspath(
os.path.join( os.path.join(
self.output_path, self.output_path,
"temp/structures/", "temp/structures/",
f"{self.mid_file_name}_pgb.mcstructure", f"{self.mid_file_name}_pgb.mcstructure",
) )
), ),
"wb+", "wb+",
) as f: ) as f:
pgb_struct.dump(f) pgb_struct.dump(f)
@ -1730,25 +1730,25 @@ class midiConvert:
) )
with open( with open(
os.path.abspath( os.path.abspath(
os.path.join( os.path.join(
self.output_path, self.output_path,
"temp/structures/", "temp/structures/",
f"{self.mid_file_name}_reset.mcstructure", f"{self.mid_file_name}_reset.mcstructure",
) )
), ),
"wb+", "wb+",
) as f: ) as f:
struct_a.dump(f) struct_a.dump(f)
del struct_a, pgb_struct del struct_a, pgb_struct
index_file.write( index_file.write(
f"structure load {self.mid_file_name}_reset ~{pgbSize[0]+2} ~ ~1\n" f"structure load {self.mid_file_name}_reset ~{pgbSize[0] + 2} ~ ~1\n"
) )
index_file.write( index_file.write(
f"structure load {self.mid_file_name}_main ~{pgbSize[0]+2} ~1 ~1\n" f"structure load {self.mid_file_name}_main ~{pgbSize[0] + 2} ~1 ~1\n"
) )
else: else:
@ -1768,12 +1768,12 @@ class midiConvert:
return True, len(command_list), max_delay return True, len(command_list), max_delay
def to_mcstructure_file_with_delay( def to_mcstructure_file_with_delay(
self, self,
method: int = 1, method: int = 1,
volume: float = 1.0, volume: float = 1.0,
speed: float = 1.0, speed: float = 1.0,
player: str = "@a", player: str = "@a",
max_height: int = 64, max_height: int = 64,
): ):
""" """
使用method指定的转换算法将midi转换为mcstructure结构文件 使用method指定的转换算法将midi转换为mcstructure结构文件
@ -1802,25 +1802,25 @@ class midiConvert:
struct, size, end_pos = commands_to_structure(cmd_list, max_height - 1) struct, size, end_pos = commands_to_structure(cmd_list, max_height - 1)
with open( with open(
os.path.abspath( os.path.abspath(
os.path.join(self.output_path, f"{self.mid_file_name}.mcstructure") os.path.join(self.output_path, f"{self.mid_file_name}.mcstructure")
), ),
"wb+", "wb+",
) as f: ) as f:
struct.dump(f) struct.dump(f)
return True, size, max_delay return True, size, max_delay
def to_BDX_file( def to_BDX_file(
self, self,
method: int = 1, method: int = 1,
volume: float = 1.0, volume: float = 1.0,
speed: float = 1.0, speed: float = 1.0,
progressbar: Union[bool, tuple] = False, progressbar: Union[bool, tuple] = False,
scoreboard_name: str = "mscplay", scoreboard_name: str = "mscplay",
isAutoReset: bool = False, isAutoReset: bool = False,
author: str = "Eilles", author: str = "Eilles",
max_height: int = 64, max_height: int = 64,
): ):
""" """
使用method指定的转换算法将midi转换为BDX结构文件 使用method指定的转换算法将midi转换为BDX结构文件
@ -1845,17 +1845,17 @@ class midiConvert:
os.makedirs(self.output_path) os.makedirs(self.output_path)
with open( with open(
os.path.abspath( os.path.abspath(
os.path.join(self.output_path, f"{self.mid_file_name}.bdx") os.path.join(self.output_path, f"{self.mid_file_name}.bdx")
), ),
"w+", "w+",
) as f: ) as f:
f.write("BD@") f.write("BD@")
_bytes = ( _bytes = (
b"BDX\x00" b"BDX\x00"
+ author.encode("utf-8") + author.encode("utf-8")
+ b" & Musicreater\x00\x01command_block\x00" + b" & Musicreater\x00\x01command_block\x00"
) )
commands = [] commands = []
@ -1882,14 +1882,14 @@ class midiConvert:
[ [
(i, 0) (i, 0)
for i in ( for i in (
self.__form_progress_bar(maxScore, scoreboard_name) self.__form_progress_bar(maxScore, scoreboard_name)
# 此处是对于仅有 True 的参数和自定义参数的判断 # 此处是对于仅有 True 的参数和自定义参数的判断
# 改这一行没🐎 # 改这一行没🐎
if progressbar is True if progressbar is True
else self.__form_progress_bar( else self.__form_progress_bar(
maxScore, scoreboard_name, progressbar maxScore, scoreboard_name, progressbar
)
) )
)
], ],
max_height - 1, max_height - 1,
) )
@ -1905,24 +1905,24 @@ class midiConvert:
_bytes += cmdBytes _bytes += cmdBytes
with open( with open(
os.path.abspath( os.path.abspath(
os.path.join(self.output_path, f"{self.mid_file_name}.bdx") os.path.join(self.output_path, f"{self.mid_file_name}.bdx")
), ),
"ab+", "ab+",
) as f: ) as f:
f.write(brotli.compress(_bytes + b"XE")) f.write(brotli.compress(_bytes + b"XE"))
return True, total_count, maxScore, size, finalPos return True, total_count, maxScore, size, finalPos
def to_BDX_file_with_delay( def to_BDX_file_with_delay(
self, self,
method: int = 1, method: int = 1,
volume: float = 1.0, volume: float = 1.0,
speed: float = 1.0, speed: float = 1.0,
progressbar: Union[bool, tuple] = False, progressbar: Union[bool, tuple] = False,
player: str = "@a", player: str = "@a",
author: str = "Eilles", author: str = "Eilles",
max_height: int = 64, max_height: int = 64,
): ):
""" """
使用method指定的转换算法将midi转换为BDX结构文件 使用method指定的转换算法将midi转换为BDX结构文件
@ -1949,17 +1949,17 @@ class midiConvert:
os.makedirs(self.output_path) os.makedirs(self.output_path)
with open( with open(
os.path.abspath( os.path.abspath(
os.path.join(self.output_path, f"{self.mid_file_name}.bdx") os.path.join(self.output_path, f"{self.mid_file_name}.bdx")
), ),
"w+", "w+",
) as f: ) as f:
f.write("BD@") f.write("BD@")
_bytes = ( _bytes = (
b"BDX\x00" b"BDX\x00"
+ author.encode("utf-8") + author.encode("utf-8")
+ b" & Musicreater\x00\x01command_block\x00" + b" & Musicreater\x00\x01command_block\x00"
) )
# 此处是对于仅有 True 的参数和自定义参数的判断 # 此处是对于仅有 True 的参数和自定义参数的判断
@ -2009,17 +2009,17 @@ class midiConvert:
_bytes += cmdBytes _bytes += cmdBytes
with open( with open(
os.path.abspath( os.path.abspath(
os.path.join(self.output_path, f"{self.mid_file_name}.bdx") os.path.join(self.output_path, f"{self.mid_file_name}.bdx")
), ),
"ab+", "ab+",
) as f: ) as f:
f.write(brotli.compress(_bytes + b"XE")) f.write(brotli.compress(_bytes + b"XE"))
return True, len(cmdlist), max_delay, size, finalPos return True, len(cmdlist), max_delay, size, finalPos
def toDICT( def toDICT(
self, self,
) -> dict: ) -> dict:
""" """
使用金羿的转换思路将midi转换为字典 使用金羿的转换思路将midi转换为字典
@ -2062,9 +2062,9 @@ class midiConvert:
raise NotDefineTempoError("计算当前分数时出错 未定义参量 Tempo") raise NotDefineTempoError("计算当前分数时出错 未定义参量 Tempo")
else: else:
microseconds += ( microseconds += (
msg.time msg.time
* mido.midifiles.midifiles.DEFAULT_TEMPO * mido.midifiles.midifiles.DEFAULT_TEMPO
/ self.midi.ticks_per_beat / self.midi.ticks_per_beat
) )
if msg.is_meta: if msg.is_meta:
@ -2093,7 +2093,7 @@ class midiConvert:
) )
elif (msg.type == "note_on" and msg.velocity == 0) or ( elif (msg.type == "note_on" and msg.velocity == 0) or (
msg.type == "note_off" msg.type == "note_off"
): ):
channels[msg.channel][track_no].append( channels[msg.channel][track_no].append(
("NoteE", msg.note, microseconds) ("NoteE", msg.note, microseconds)

View File

@ -1,6 +1,6 @@
import math import math
import os import os
from typing import Union
from TrimMCStruct import Structure, Block, TAG_Long, TAG_Byte from TrimMCStruct import Structure, Block, TAG_Long, TAG_Byte
bdx_key = { bdx_key = {
@ -26,11 +26,11 @@ def bdx_move(axis: str, value: int):
[ [
1 if i else 0 1 if i else 0
for i in ( for i in (
value != -1, value != -1,
value < -1 or value > 1, value < -1 or value > 1,
value < -128 or value > 127, value < -128 or value > 127,
value < -32768 or value > 32767, value < -32768 or value > 32767,
) )
] ]
) )
@ -62,15 +62,15 @@ def compress_zipfile(sourceDir, outFilename, compression=8, exceptFile=None):
def form_command_block_in_BDX_bytes( def form_command_block_in_BDX_bytes(
command: str, command: str,
particularValue: int, particularValue: int,
impluse: int = 0, impluse: int = 0,
condition: bool = False, condition: bool = False,
needRedstone: bool = True, needRedstone: bool = True,
tickDelay: int = 0, tickDelay: int = 0,
customName: str = "", customName: str = "",
executeOnFirstTick: bool = False, executeOnFirstTick: bool = False,
trackOutput: bool = True, trackOutput: bool = True,
): ):
""" """
使用指定项目返回指定的指令方块放置指令项 使用指定项目返回指定的指令方块放置指令项
@ -142,8 +142,8 @@ def bottem_side_length_of_smallest_square_bottom_box(total: int, maxHeight: int)
def commands_to_BDX_bytes( def commands_to_BDX_bytes(
commands: list, commands: list,
max_height: int = 64, max_height: int = 64,
): ):
""" """
:param commands: 指令列表(指令, 延迟) :param commands: 指令列表(指令, 延迟)
@ -175,13 +175,13 @@ def commands_to_BDX_bytes(
cmd, cmd,
(1 if y_forward else 0) (1 if y_forward else 0)
if ( if (
((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 - 1)) or (z_forward and (now_z != _sideLength - 1))
) )
else 5, else 5,
impluse=impluse, impluse=impluse,
@ -203,7 +203,7 @@ def commands_to_BDX_bytes(
now_z += 1 if z_forward else -1 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 < 0) and (not z_forward)
): ):
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
@ -227,7 +227,7 @@ def commands_to_BDX_bytes(
def form_note_block_in_NBT_struct( def form_note_block_in_NBT_struct(
note: int, coordinate: tuple, instrument: str = "note.harp", powered: bool = False note: int, coordinate: tuple, instrument: str = "note.harp", powered: bool = False
): ):
"""生成音符盒方块 """生成音符盒方块
:param note: `int`(0~24) :param note: `int`(0~24)
@ -262,7 +262,7 @@ def form_note_block_in_NBT_struct(
def form_repeater_in_NBT_struct( def form_repeater_in_NBT_struct(
delay: int, facing: int delay: int, facing: int
): ):
"""生成中继器方块 """生成中继器方块
:param powered: :param powered:
@ -270,7 +270,7 @@ def form_repeater_in_NBT_struct(
:param facing: :param facing:
:param delay: 1~4 :param delay: 1~4
:return Block()""" :return Block()"""
return Block( return Block(
"minecraft", "minecraft",
"unpowered_repeater", "unpowered_repeater",
@ -280,17 +280,18 @@ def form_repeater_in_NBT_struct(
}, },
) )
def form_command_block_in_NBT_struct( def form_command_block_in_NBT_struct(
command: str, command: str,
coordinate: tuple, coordinate: tuple,
particularValue: int, particularValue: int,
impluse: int = 0, impluse: int = 0,
condition: bool = False, condition: bool = False,
alwaysRun: bool = True, alwaysRun: bool = True,
tickDelay: int = 0, tickDelay: int = 0,
customName: str = "", customName: str = "",
executeOnFirstTick: bool = False, executeOnFirstTick: bool = False,
trackOutput: bool = True, trackOutput: bool = True,
): ):
""" """
使用指定项目返回指定的指令方块结构 使用指定项目返回指定的指令方块结构
@ -372,9 +373,10 @@ def form_command_block_in_NBT_struct(
compability_version=17959425, compability_version=17959425,
) )
def commands_to_structure( def commands_to_structure(
commands: list, commands: list,
max_height: int = 64, max_height: int = 64,
): ):
""" """
:param commands: 指令列表(指令, 延迟) :param commands: 指令列表(指令, 延迟)
@ -406,14 +408,14 @@ def commands_to_structure(
coordinate=coordinate, coordinate=coordinate,
particularValue=(1 if y_forward else 0) particularValue=(1 if y_forward else 0)
if ( if (
((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 ( else (
(3 if z_forward else 2) (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 - 1)) or (z_forward and (now_z != _sideLength - 1))
) )
else 5 else 5
), ),
@ -437,7 +439,7 @@ def commands_to_structure(
now_z += 1 if z_forward else -1 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 < 0) and (not z_forward)
): ):
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
@ -452,4 +454,3 @@ def commands_to_structure(
), ),
(now_x, now_y, now_z), (now_x, now_y, now_z),
) )

View File

@ -1,30 +1,22 @@
import shutil import shutil
import os import os
from rich.console import Console
from rich.progress import track
console = Console()
# find the full path of .egg-info folder def main():
egg_info = [i for i in os.listdir() if i.endswith(".egg-info")][0] with console.status("Find the full path of .egg-info folder"):
print(egg_info) egg_info: list = []
for file in os.listdir():
if os.path.isfile(file) and file.endswith(".egg-info"):
egg_info.append(file)
console.print(file)
for file in track(["build", "dist", "logs", *egg_info], description="Deleting files"):
if os.path.isdir(file) and os.access(file, os.W_OK):
shutil.rmtree(file)
# remove build, dist, logs, TrimLog.egg-info folders
try:
shutil.rmtree("build")
except FileNotFoundError:
pass
try: if __name__ == "__main__":
shutil.rmtree("dist") main()
except FileNotFoundError:
pass
try:
shutil.rmtree(egg_info)
except FileNotFoundError:
pass
try:
shutil.rmtree("logs")
except FileNotFoundError:
pass
print("Cleaned up!")

View File

@ -1,3 +1,3 @@
python setup.py sdist bdist_wheel python -m build
python -m twine upload dist/* python -m twine upload dist/*
python clean_update.py python clean_update.py

4
upload.sh Normal file
View File

@ -0,0 +1,4 @@
#!/usr/bin/env bash
python -m build
python -m twine upload dist/*
python clean_update.py