From 813186bef9b1f4e15a36c9f7e25db8a6b00947d0 Mon Sep 17 00:00:00 2001 From: EillesWan Date: Fri, 7 Oct 2022 16:49:47 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BF=AB=E5=A5=BD=E4=BA=86=EF=BC=8C=E4=B8=8D?= =?UTF-8?q?=E6=80=A5=E4=B8=8D=E6=80=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- demo_convert.py | 3 + docs/功能使用说明.md | 139 ++++++++++++++-- msctPkgver/exceptions.py | 69 ++++++++ msctPkgver/magicmain.py | 40 +---- msctPkgver/main.py | 333 ++++++++++++++++++--------------------- 5 files changed, 351 insertions(+), 233 deletions(-) create mode 100644 msctPkgver/exceptions.py diff --git a/demo_convert.py b/demo_convert.py index 254febf..986d6f6 100644 --- a/demo_convert.py +++ b/demo_convert.py @@ -103,6 +103,9 @@ while True: + + + if os.path.isdir(midipath): for i in os.listdir(midipath): if i.lower().endswith('.mid'): diff --git a/docs/功能使用说明.md b/docs/功能使用说明.md index a1047dd..ef5e971 100644 --- a/docs/功能使用说明.md +++ b/docs/功能使用说明.md @@ -16,7 +16,7 @@ 0. 安装 Python3.6+ - 首先需要下载Python的安装包 + 首先需要下载Python的安装包,最好是 *Python3.8*,因为作者就用的是这个版本 > [下载64位Python安装包](https://www.python.org/ftp/python/3.8.10/python-3.8.10-amd64.exe) > [下载32位Python安装包](https://www.python.org/ftp/python/3.8.10/python-3.8.10.exe) @@ -46,27 +46,31 @@ 打开了终端之后,请在终端中输入以下指令 - `pip install mido -i https://mirrors.aliyun.com/pypi/simple/` - - `pip install brotli -i https://mirrors.aliyun.com/pypi/simple/` + ```bash + pip install mido -i https://mirrors.aliyun.com/pypi/simple/ + pip install brotli -i https://mirrors.aliyun.com/pypi/simple/ + ``` 安装成功后您可能会见到类似下图的提示: +### 本工具的下载与使用 -2. 下载本代码库以及演示程序 +0. 下载本代码库以及演示程序 - 若您使用git,请直接克隆本仓库: - `git clone -b pkgver https://gitee.com/EillesWan/Musicreater.git` + ```bash + git clone -b pkgver https://gitee.com/EillesWan/Musicreater.git + ``` - 若您不使用git,可以在[*码云*(Gitee)](https://gitee.com/EillesWan/Musicreater.git)或[*GitHub*](https://github.com/EillesWan/Musicreater.git)下载zip包,或者[加入QQ群聊861684859](https://jq.qq.com/?_wv=1027&k=hpeRxrYr),在群文件中获取。 -3. 开始使用 +1. 开始使用 在目录下打开终端,例如,打开命令行,请进入到目录下,在地址框内输入`cmd`: @@ -75,10 +79,10 @@ 执行以下命令:(选择你需要的) - `python demo_convert.py` - - `python demo_convert_bdx_byDelay.py` - + ```bash + python demo_convert.py + python demo_convert_bdx_byDelay.py + ``` ### 补充错误说明 @@ -94,7 +98,116 @@ 感谢群友Mono帮我们发现这个问题 -2. 参数补充说明 +## Linux操作系统 + + +### 运行环境安装 + +0. 安装并检验Python运行环境 + + 一般的Linux发行版都有安装Python环境,我们只需要保证其版本即可,理论上 ≥Python3.6 都可以运行我们的库 + + 我们可以使用 + + ```bash + python -V + ``` + + 来查看 Python 版本,如下 + + + + - 非必要环节 + + 如果你跟作者一样,觉得 Python 3.10+ 太难用很烦人的话,那真是皆大欢喜,让我们一起来回退版本吧! + + - pacman 包管理器(多用于Arch Linux上) + + 让我们先来把 python3 加入忽略升级的列表中,使用`vim`修改`/etc/pacman.conf`,在`IgnorePkg`后加上`python3` + + ```bash + sudo vim /etc/pacman.conf + ``` + + + + 然后我们开始从[Arch Achieve](https://archive.archlinux.org/packages/)上找Python的版本列表。(*这里说明一下,在Arch中,Python默认指的是Python3,而与其他某些Linux发行版中Python默认指代Python2不同,所以在Arch Achieve中也是如此。*)我这里找到的是[Python3.8.6](https://archive.archlinux.org/packages/p/python/python-3.8.6-1-x86_64.pkg.tar.zst),于是我们用`pacman`把她下载下来: + + ```bash + sudo pacman -U https://archive.archlinux.org/packages/p/python/python-3.8.6-1-x86_64.pkg.tar.zst + ``` + + + + 完美! + + 接着,我们来确认,Python自带的包管理器pip是否安装到位: + + ```bash + python -m pip # 确认pip是否安装 + # 当这个命令输入后有长段提示出现则为已经安装 + + # 如果返回如下,那么则pip尚未安装 + /usr/bin/python: No module named pip + # 可以使用如下命令来安装pip + sudo pacman -S python-pip + # 安装完成后记得验证 + python -m pip + + + # 如果还是失败,那么就需要用其他工具安装pip: + wget https://bootstrap.pypa.io/get-pip.py + sudo python get-pip.py + # 安装完成后一定要验证!!! + python -m pip + ``` + + 确认完成之后,我们来安装一下依赖库: + + ```bash + pip install mido -i https://mirrors.aliyun.com/pypi/simple/ + pip install brotli -i https://mirrors.aliyun.com/pypi/simple/ + ``` + + 安装成功后您可能会见到类似下图的提示: + + + + +### 本代码库的下载与使用 + +1. 使用Git下载本库及其示例代码 + + ```bash + git clone -b pkgver https://gitee.com/EillesWan/Musicreater.git MSCTpkgver + ``` + + 当上述命令执行成功,你会在执行此命令的所在位置发现一个名为 `MSCTpkgver` 的文件夹,其中包含的正是我们心心念念下载的本程序和示例代码。 + 而我们要运行的也正是示例代码,因此,赶快进入下载到的文件夹: + + ```bash + cd MSCTpkgver + ``` + +1. 开始使用 + + 在目录下打开终端,执行以下命令:(选择你需要的) + + ```bash + python demo_convert.py + python demo_convert_bdx_byDelay.py + ``` + + + + + + + + +# 其他说明 + +## 参数补充说明 @@ -120,7 +233,7 @@ -# 对于 进度条自定义 功能的说明 +## 对于 进度条自定义 功能的说明 因为我们提供了可以自动转换进度条的功能,因此在这里给出进度条自定义参数的详细解释。 diff --git a/msctPkgver/exceptions.py b/msctPkgver/exceptions.py new file mode 100644 index 0000000..1cd9028 --- /dev/null +++ b/msctPkgver/exceptions.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- + + +# 音·创 开发交流群 861684859 +# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com +# 版权所有 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray") & 鸣凤鸽子("MingFengPigeon") +# 若需使用或借鉴 请依照 Apache 2.0 许可证进行许可 + + +""" +音·创 库版 (Musicreater Package Version) +是一款免费开源的针对《我的世界:基岩版》的midi音乐转换库 +注意!除了此源文件以外,任何属于此仓库以及此项目的文件均依照Apache许可证进行许可 +Musicreater pkgver (Package Version 音·创 库版) +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 + + Licensed under the Apache License, Version 2.0 (the 'License'); + you may not use this file except in compliance with the License. + 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. +""" + + + + +class MSCTBaseException(Exception): + """音·创库版本的所有错误均继承于此""" + + def __init__(self, *args): + super().__init__(*args) + + def 喵(self,): + for i in self.args: + print(i+"喵!") + + def crash_it(self): + raise self + + +class CrossNoteError(MSCTBaseException): + '''同通道下同音符交叉出现所产生的错误''' + pass + + +class NotDefineTempoError(MSCTBaseException): + '''没有Tempo设定导致时间无法计算的错误''' + pass + + +class MidiDestroyedError(MSCTBaseException): + '''Midi文件损坏''' + pass + +class ChannelOverFlowError(MSCTBaseException): + '''一个midi中含有过多的通道(应≤16)''' + pass + + + diff --git a/msctPkgver/magicmain.py b/msctPkgver/magicmain.py index 665d445..c2d758a 100644 --- a/msctPkgver/magicmain.py +++ b/msctPkgver/magicmain.py @@ -99,41 +99,12 @@ def _toCmdList_m1( + import mido -def delete_extra_zero(n: float) -> int or float: - """ - 删除多余的0 - ———————————————— - 版权声明:本文为CSDN博主「XerCis」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 - 原文链接:https://blog.csdn.net/lly1122334/article/details/108770141 - 删除小数点后多余的0 - :param n: input - :return: output - """ - n = '{:g}'.format(n) - n = float(n) if '.' in n else int(n) # 含小数点转float否则int - return n -def bpm_by_MetaMessage_Set_tempo(tmp: int) -> int or float: - """ - midi文件tempo事件bpm算法。 - A function that's used to compute the bpm of a midiFile, - which algorithm is made up of midiFile's tempo meta message. - :param tmp:输入mid的metaMessage中速度tempo值 - input the tempo value which is in the tempo meta message. - :return:bpm - - This algorithm is made by ©bgArray. - 算法版权归©诸葛亮与八卦阵所有。 - """ - second = tmp / 1000000 - bpm = delete_extra_zero(60 / second) - # debug.dp(bpm) - return bpm - class NoteMessage: def __init__(self, channel, pitch, velocity, startT, lastT, midi, now_bpm, change_bpm=None): @@ -202,14 +173,9 @@ def load(mid: mido.MidiFile): print(ticks) if msg.is_meta is True and msg.type == "set_tempo": recent_change_bpm = bpm - bpm = bpm_by_MetaMessage_Set_tempo(msg.tempo) + bpm = 60000000 / msg.tempo is_change_bpm = True - # print((ticks * 92) / (mid.ticks_per_beat * 50000)) - # MC_tick = delete_extra_zero(round_up( - # (ticks * 92) / (mid.ticks_per_beat * 50000) - # )) - # print(MC_tick) - # print(ticks / mid.ticks_per_beat / 92 * 60) + if msg.type == 'note_on' and msg.velocity != 0: noteOn.append([msg, msg.note, ticks]) if type_[1] is True: diff --git a/msctPkgver/main.py b/msctPkgver/main.py index 3738f4c..63047f9 100644 --- a/msctPkgver/main.py +++ b/msctPkgver/main.py @@ -38,6 +38,8 @@ import uuid import shutil import math +from .exceptions import * + def makeZip(sourceDir, outFilename, compression=8, exceptFile=None): """使用compression指定的算法打包目录为zip文件\n @@ -62,9 +64,9 @@ def makeZip(sourceDir, outFilename, compression=8, exceptFile=None): class midiConvert: - def __init__(self): + def __init__(self, debug: bool = False): """简单的midi转换类,将midi文件转换为我的世界结构或者包""" - pass + self.debugMode = debug def convert(self, midiFile: str, outputPath: str): """转换前需要先运行此函数来获取基本信息""" @@ -228,17 +230,16 @@ class midiConvert: return a def __score2time(self, score: int): - 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 __formProgressBar( - self, - maxscore: int, - scoreboardname: str, - progressbar: tuple = ( - r"▶ %%N [ %%s/%^s %%% __________ %%t|%^t ]", - ("§e=§r", "§7=§r"), - ), + self, + maxscore: int, + scoreboardname: str, + progressbar: tuple = ( + r"▶ %%N [ %%s/%^s %%% __________ %%t|%^t ]", + ("§e=§r", "§7=§r"), + ), ) -> list: pgsstyle = progressbar[0] @@ -257,11 +258,8 @@ class midiConvert: """ def __replace( - s: str, - tobeReplaced: str, - replaceWith: str, - times: int, - other: str): + s: str, tobeReplaced: str, replaceWith: str, times: int, other: str + ): if times == 0: return s.replace(tobeReplaced, other) if times == s.count(tobeReplaced): @@ -322,33 +320,29 @@ class midiConvert: countof_s = int((i + 1) / maxscore * pgblength) finalprgsbar.append( - "title @a[scores={" + - scoreboardname + - "=" + - str( - i + - 1) + - "}] actionbar " + - __replace( - nowstr, - "_", - progressbar[1][0], - countof_s, - progressbar[1][1])) + "title @a[scores={" + + scoreboardname + + "=" + + str(i + 1) + + "}] actionbar " + + __replace( + nowstr, "_", progressbar[1][0], countof_s, progressbar[1][1] + ) + ) return finalprgsbar def __formCMDblk( - self, - command: str, - particularValue: int, - impluse: int = 0, - condition: bool = False, - needRedstone: bool = True, - tickDelay: int = 0, - customName: str = "", - executeOnFirstTick: bool = False, - trackOutput: bool = True, + self, + command: str, + particularValue: int, + impluse: int = 0, + condition: bool = False, + needRedstone: bool = True, + tickDelay: int = 0, + customName: str = "", + executeOnFirstTick: bool = False, + trackOutput: bool = True, ): """ 使用指定项目返回指定的指令方块放置指令项 @@ -394,8 +388,7 @@ class midiConvert: :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), @@ -412,10 +405,8 @@ class midiConvert: return block def _toCmdList_m1( - self, - scoreboardname: str = "mscplay", - volume: float = 1.0, - speed: float = 1.0) -> list: + self, scoreboardname: str = "mscplay", volume: float = 1.0, speed: float = 1.0 + ) -> list: """ 使用Dislink Sforza的转换思路,将midi转换为我的世界命令列表 :param scoreboardname: 我的世界的计分板名称 @@ -449,31 +440,33 @@ class midiConvert: # print("TT") instrumentID = msg.program if msg.type == "note_on" and msg.velocity != 0: - nowscore = round( - (ticks * tempo) - / ((self.midi.ticks_per_beat * float(speed)) * 50000) - ) + try: + nowscore = round( + (ticks * tempo) + / ((self.midi.ticks_per_beat * float(speed)) * 50000) + ) + except NameError: + raise NotDefineTempoError('计算当前分数时出错 未定义参量') maxscore = max(maxscore, nowscore) soundID, _X = self.__Inst2soundIDwithX(instrumentID) singleTrack.append( - "execute @a[scores={" + - str(scoreboardname) + - "=" + - str(nowscore) + - "}" + - f"] ~ ~ ~ playsound {soundID} @s ~ ~{1 / volume - 1} ~ {msg.velocity * (0.7 if msg.channel == 0 else 0.9)} {2 ** ((msg.note - 60 - _X) / 12)}") + "execute @a[scores={" + + str(scoreboardname) + + "=" + + str(nowscore) + + "}" + + f"] ~ ~ ~ playsound {soundID} @s ~ ~{1 / volume - 1} ~ {msg.velocity * (0.7 if msg.channel == 0 else 0.9)} {2 ** ((msg.note - 60 - _X) / 12)}" + ) commands += 1 if len(singleTrack) != 0: tracks.append(singleTrack) return [tracks, commands, maxscore] - # 值得注意的是,我这里没有修改 + # 值得注意的是,我这里没有修改多少 def _toCmdList_m2( - self, - scoreboardname: str = "mscplay", - volume: float = 1.0, - speed: float = 1.0) -> list: + self, scoreboardname: str = "mscplay", MaxVolume: float = 1.0, speed: float = 1.0 + ) -> list: """ 使用金羿的转换思路,将midi转换为我的世界命令列表,使用线性方法调整音量 :param scoreboardname: 我的世界的计分板名称 @@ -482,14 +475,18 @@ class midiConvert: :return: tuple(命令列表, 命令个数, 计分板最大值) """ tracks = [] - if volume > 1: - volume = 1 - if volume <= 0: - volume = 0.001 + if MaxVolume > 1: + MaxVolume = 1 + if MaxVolume <= 0: + MaxVolume = 0.001 commands = 0 maxscore = 0 + # 一个midi中仅有16通道 我们通过通道来识别而不是音轨 + channels = [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []] + + for i, track in enumerate(self.midi.tracks): ticks = 0 @@ -508,33 +505,7 @@ class midiConvert: # print("TT") instrumentID = msg.program if msg.type == 'note_on' and msg.velocity != 0: - noteOn.append([msg, msg.note, ticks]) - elif type_[1] is True: - if msg.type == 'note_on' and msg.velocity == 0: - for u in noteOn: - index = 0 - if u[1] == msg.note: - lastMessage = u[0] - lastTick = u[2] - break - index += 1 - trackS.append( - NoteMessage( - msg.channel, - msg.note, - lastMessage.velocity, - lastTick, - ticks - lastTick, - mid, - ) - ) - # print(noteOn) - # print(index) - try: - noteOn.pop(index) - except IndexError: - noteOn.pop(index - 1) - if msg.type == "note_on" and msg.velocity != 0: + nowscore = round( (ticks * tempo) / ((self.midi.ticks_per_beat * float(speed)) * 50000) @@ -542,12 +513,13 @@ class midiConvert: maxscore = max(maxscore, nowscore) soundID, _X = self.__Inst2soundIDwithX(instrumentID) singleTrack.append( - "execute @a[scores={" + - str(scoreboardname) + - "=" + - str(nowscore) + - "}" + - f"] ~ ~ ~ playsound {soundID} @s ~ ~{1 / volume - 1} ~ {msg.velocity * (0.7 if msg.channel == 0 else 0.9)} {2 ** ((msg.note - 60 - _X) / 12)}") + "execute @a[scores={" + + str(scoreboardname) + + "=" + + str(nowscore) + + "}" + + f"] ~ ~ ~ playsound {soundID} @s ~ ~{1 / MaxVolume - 1} ~ {msg.velocity * (0.7 if msg.channel == 0 else 0.9)} {2 ** ((msg.note - 60 - _X) / 12)}" + ) commands += 1 if len(singleTrack) != 0: tracks.append(singleTrack) @@ -555,11 +527,11 @@ class midiConvert: return [tracks, commands, maxscore] def _toCmdList_withDelay_m1( - self, - volume: float = 1.0, - speed: float = 1.0, - player: str = "@a", - isMixedWithPrograssBar=False, + self, + volume: float = 1.0, + speed: float = 1.0, + player: str = "@a", + isMixedWithPrograssBar=False, ) -> list: """ 使用Dislink Sforza的转换思路,将midi转换为我的世界命令列表,并输出每个音符之后的延迟 @@ -576,7 +548,8 @@ class midiConvert: if volume <= 0: volume = 0.001 - if isMixedWithPrograssBar: + # 此处是对于仅有 True 的参数和自定义参数的判断 + if isMixedWithPrograssBar == True: isMixedWithPrograssBar = ( r"▶ %%N [ %%s/%^s %%% __________ %%t|%^t ]", ("§e=§r", "§7=§r"), @@ -607,7 +580,8 @@ class midiConvert: ) except BaseException: tracks[nowtick] = [ - f"execute {player} ~ ~ ~ playsound {soundID} @s ~ ~{1 / volume - 1} ~ {msg.velocity * (0.7 if msg.channel == 0 else 0.9)} {2 ** ((msg.note - 60 - _X) / 12)}", ] + f"execute {player} ~ ~ ~ playsound {soundID} @s ~ ~{1 / volume - 1} ~ {msg.velocity * (0.7 if msg.channel == 0 else 0.9)} {2 ** ((msg.note - 60 - _X) / 12)}", + ] allticks = list(tracks.keys()) @@ -629,11 +603,8 @@ class midiConvert: """ def __replace( - s: str, - tobeReplaced: str, - replaceWith: str, - times: int, - other: str): + s: str, tobeReplaced: str, replaceWith: str, times: int, other: str + ): if times == 0: return s.replace(tobeReplaced, other) if times == s.count(tobeReplaced): @@ -699,12 +670,12 @@ class midiConvert: if ids[r"%%s"]: nowstr = nowstr.replace(r"%%s", str(allticks[i] + 1)) if ids[r"%%t"]: - nowstr = nowstr.replace( - r"%%t", self.__score2time( - allticks[i] + 1)) + nowstr = nowstr.replace(r"%%t", self.__score2time(allticks[i] + 1)) if ids[r"%%%"]: - nowstr = nowstr.replace(r"%%%", str( - int((allticks[i] + 1) / allticks[-1] * 10000) / 100) + "%", ) + nowstr = nowstr.replace( + r"%%%", + str(int((allticks[i] + 1) / allticks[-1] * 10000) / 100) + "%", + ) countof_s = int((allticks[i] + 1) / allticks[-1] * pgblength) @@ -733,13 +704,13 @@ class midiConvert: return math.ceil(math.sqrt(math.ceil(total / maxHeight))) def tomcpack( - self, - method: int = 1, - isAutoReset: bool = False, - progressbar=None, - scoreboardname: str = "mscplay", - volume: float = 1.0, - speed: float = 1.0, + self, + method: int = 1, + isAutoReset: bool = False, + progressbar=None, + scoreboardname: str = "mscplay", + volume: float = 1.0, + speed: float = 1.0, ) -> bool or tuple: """ 使用method指定的转换算法,将midi转换为我的世界mcpack格式的包 @@ -752,8 +723,7 @@ class midiConvert: :return 成功与否,成功返回(True,True),失败返回(False,str失败原因) """ if method == 1: - cmdlist, _a, maxscore = self._toCmdList_m1( - scoreboardname, volume, speed) + cmdlist, _a, maxscore = self._toCmdList_m1(scoreboardname, volume, speed) else: return (False, f"无法找到算法ID{method}对应的转换算法") del _a @@ -766,22 +736,24 @@ class midiConvert: # 写入manifest.json if not os.path.exists(f"{self.outputPath}/temp/manifest.json"): with open( - f"{self.outputPath}/temp/manifest.json", "w", encoding="utf-8" + f"{self.outputPath}/temp/manifest.json", "w", encoding="utf-8" ) as f: - f.write('{\n "format_version": 1,\n "header": {\n "description": "' + - self.midFileName + - ' Pack : behavior pack",\n "version": [ 0, 0, 1 ],\n "name": "' + - self.midFileName + - 'Pack",\n "uuid": "' + - str(uuid.uuid4()) + - '"\n },\n "modules": [\n {\n "description": "' + - f"the Player of the Music {self.midFileName}" + - '",\n "type": "data",\n "version": [ 0, 0, 1 ],\n "uuid": "' + - str(uuid.uuid4()) + - '"\n }\n ]\n}') + f.write( + '{\n "format_version": 1,\n "header": {\n "description": "' + + self.midFileName + + ' Pack : behavior pack",\n "version": [ 0, 0, 1 ],\n "name": "' + + self.midFileName + + 'Pack",\n "uuid": "' + + str(uuid.uuid4()) + + '"\n },\n "modules": [\n {\n "description": "' + + f"the Player of the Music {self.midFileName}" + + '",\n "type": "data",\n "version": [ 0, 0, 1 ],\n "uuid": "' + + str(uuid.uuid4()) + + '"\n }\n ]\n}' + ) else: with open( - f"{self.outputPath}/temp/manifest.json", "r", encoding="utf-8" + f"{self.outputPath}/temp/manifest.json", "r", encoding="utf-8" ) as manifest: data = json.loads(manifest.read()) data["header"][ @@ -792,22 +764,22 @@ class midiConvert: data["modules"][0]["description"] = "None" data["modules"][0]["uuid"] = str(uuid.uuid4()) manifest.close() - open(f"{self.outputPath}/temp/manifest.json", "w", - encoding="utf-8").write(json.dumps(data)) + open(f"{self.outputPath}/temp/manifest.json", "w", encoding="utf-8").write( + json.dumps(data) + ) # 将命令列表写入文件 indexfile = open( - f"{self.outputPath}/temp/functions/index.mcfunction", - "w", - encoding="utf-8") + f"{self.outputPath}/temp/functions/index.mcfunction", "w", encoding="utf-8" + ) for track in cmdlist: indexfile.write( "function mscplay/track" + str(cmdlist.index(track) + 1) + "\n" ) with open( - f"{self.outputPath}/temp/functions/mscplay/track{cmdlist.index(track) + 1}.mcfunction", - "w", - encoding="utf-8", + f"{self.outputPath}/temp/functions/mscplay/track{cmdlist.index(track) + 1}.mcfunction", + "w", + encoding="utf-8", ) as f: f.write("\n".join(track)) indexfile.writelines( @@ -834,20 +806,18 @@ class midiConvert: if progressbar: if progressbar: with open( - f"{self.outputPath}/temp/functions/mscplay/progressShow.mcfunction", - "w", - encoding="utf-8", + f"{self.outputPath}/temp/functions/mscplay/progressShow.mcfunction", + "w", + encoding="utf-8", ) as f: f.writelines( - "\n".join( - self.__formProgressBar( - maxscore, - scoreboardname))) + "\n".join(self.__formProgressBar(maxscore, scoreboardname)) + ) else: with open( - f"{self.outputPath}/temp/functions/mscplay/progressShow.mcfunction", - "w", - encoding="utf-8", + f"{self.outputPath}/temp/functions/mscplay/progressShow.mcfunction", + "w", + encoding="utf-8", ) as f: f.writelines( "\n".join( @@ -860,22 +830,21 @@ class midiConvert: indexfile.close() makeZip( - f"{self.outputPath}/temp/", - self.outputPath + - f"/{self.midFileName}.mcpack") + f"{self.outputPath}/temp/", self.outputPath + f"/{self.midFileName}.mcpack" + ) shutil.rmtree(f"{self.outputPath}/temp/") def toBDXfile( - self, - method: int = 1, - author: str = "Eilles", - progressbar=False, - maxheight: int = 64, - scoreboardname: str = "mscplay", - volume: float = 1.0, - speed: float = 1.0, - isAutoReset: bool = False, + self, + method: int = 1, + author: str = "Eilles", + progressbar=False, + maxheight: int = 64, + scoreboardname: str = "mscplay", + volume: float = 1.0, + speed: float = 1.0, + isAutoReset: bool = False, ): """ 使用method指定的转换算法,将midi转换为BDX结构文件 @@ -943,8 +912,9 @@ class midiConvert: + scoreboardname ) + # 此处是对于仅有 True 的参数和自定义参数的判断 if progressbar: - if progressbar: + if progressbar == True: commands += self.__formProgressBar(maxScore, scoreboardname) else: commands += self.__formProgressBar( @@ -976,8 +946,7 @@ class midiConvert: nowy += 1 if yforward else -1 - if ((nowy > maxheight) and (yforward)) or ( - (nowy < 0) and (not yforward)): + if ((nowy > maxheight) and (yforward)) or ((nowy < 0) and (not yforward)): nowy -= 1 if yforward else -1 yforward = not yforward @@ -985,7 +954,7 @@ class midiConvert: nowz += 1 if zforward else -1 if ((nowz > _sideLength) and (zforward)) or ( - (nowz < 0) and (not zforward) + (nowz < 0) and (not zforward) ): nowz -= 1 if zforward else -1 zforward = not zforward @@ -1005,14 +974,14 @@ class midiConvert: return (True, _bytes, (nowx, maxheight, _sideLength)) def toBDXfile_withDelay( - self, - method: int = 1, - author: str = "Eilles", - progressbar=False, - maxheight: int = 64, - volume: float = 1.0, - speed: float = 1.0, - player: str = "@a", + self, + method: int = 1, + author: str = "Eilles", + progressbar=False, + maxheight: int = 64, + volume: float = 1.0, + speed: float = 1.0, + player: str = "@a", ): """ 使用method指定的转换算法,将midi转换为BDX结构文件 @@ -1027,8 +996,7 @@ class midiConvert: """ if method == 1: - cmdlist = self._toCmdList_withDelay_m1( - volume, speed, player, progressbar) + cmdlist = self._toCmdList_withDelay_m1(volume, speed, player, progressbar) else: return (False, f"无法找到算法ID {method} 对应的转换算法") @@ -1088,8 +1056,7 @@ class midiConvert: nowy += 1 if yforward else -1 - if ((nowy > maxheight) and (yforward)) or ( - (nowy < 0) and (not yforward)): + if ((nowy > maxheight) and (yforward)) or ((nowy < 0) and (not yforward)): nowy -= 1 if yforward else -1 yforward = not yforward @@ -1097,7 +1064,7 @@ class midiConvert: nowz += 1 if zforward else -1 if ((nowz > _sideLength) and (zforward)) or ( - (nowz < 0) and (not zforward) + (nowz < 0) and (not zforward) ): nowz -= 1 if zforward else -1 zforward = not zforward