进一步优化结构,提高插件兼容

This commit is contained in:
EillesWan 2024-03-10 02:22:12 +08:00
parent 95c0ff1b47
commit d4925e4d75
16 changed files with 732 additions and 329 deletions

View File

@ -17,7 +17,7 @@ Terms & Conditions: License.md in the root directory
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
__version__ = "2.0.0-alpha"
__version__ = "2.0.0-beta"
__vername__ = "全新组织架构"
__author__ = (
("金羿", "Eilles Wan"),
@ -34,6 +34,7 @@ __all__ = [
"MineNote",
"MineCommand",
"SingleNoteBox",
"ProgressBarStyle",
# "TimeStamp", 未来功能
# 默认值
"DEFAULT_PROGRESSBAR_STYLE",

View File

@ -385,6 +385,23 @@ MC_PERCUSSION_INSTRUMENT_LIST: List[str] = [
]
"""打击乐器列表"""
MC_PITCHED_INSTRUMENT_LIST: List[str] = [
"note.harp",
"note.pling",
"note.guitar",
"note.iron_xylophone",
"note.bell",
"note.xylophone",
"note.chime",
"note.banjo",
"note.flute",
"note.bass",
"note.didgeridoo",
"note.bit",
"note.cow_bell",
]
"""乐音乐器列表"""
MC_INSTRUMENT_BLOCKS_TABLE: Dict[str, Tuple[str, ...]] = {
"note.bass": ("planks",),
"note.snare": ("sand",),
@ -439,6 +456,30 @@ MM_INSTRUMENT_RANGE_TABLE: Dict[str, Tuple[Tuple[int, int], int]] = {
}
"""不同乐器的音域偏离对照表"""
MM_INSTRUMENT_DEVIATION_TABLE: Dict[str, int] = {
"note.harp": 6,
"note.pling": 6,
"note.guitar": 7,
"note.iron_xylophone": 6,
"note.bell": 4,
"note.xylophone": 4,
"note.chime": 4,
"note.banjo": 6,
"note.flute": 5,
"note.bass": 8,
"note.snare": -1,
"note.didgeridoo": 8,
"mob.zombie.wood": -1,
"note.bit": 6,
"note.hat": -1,
"note.bd": -1,
"firework.blast": -1,
"firework.twinkle": -1,
"fire.ignite": -1,
"note.cow_bell": 5,
}
"""不同乐器的音调偏离对照表"""
# Midi乐器对MC乐器对照表
MM_CLASSIC_PITCHED_INSTRUMENT_TABLE: Dict[int, str] = {

View File

@ -47,12 +47,12 @@ class FutureMidiConvertM4(MidiConvert):
# 临时用的插值计算函数
@staticmethod
def _linear_note(
_note: SingleNote,
_apply_time_division: float = 100,
) -> List[SingleNote]:
"""传入音符数据,返回以半秒为分割的插值列表
_note: MineNote,
_apply_time_division: float = 10,
) -> List[MineNote]:
"""传入音符数据,返回分割的插值列表
:param _note: SingleNote 音符
:param _apply_time_division: int 间隔毫秒
:param _apply_time_division: int 间隔
:return list[tuple(int开始时间毫秒, int乐器, int音符, int力度内置, float音量播放),]"""
if _note.percussive:
@ -63,21 +63,24 @@ class FutureMidiConvertM4(MidiConvert):
totalCount = int(_note.duration / _apply_time_division)
if totalCount == 0:
print(_note.extra_info)
return [
_note,
]
# print(totalCount)
result: List[SingleNote] = []
result: List[MineNote] = []
for _i in range(totalCount):
result.append(
SingleNote(
instrument=_note.inst,
pitch=_note.pitch,
velocity=_note.velocity,
startime=int(_note.start_time + _i * (_note.duration / totalCount)),
lastime=int(_note.duration / totalCount),
MineNote(
mc_sound_name=_note.sound_name,
midi_pitch=_note.note_pitch,
midi_velocity=_note.velocity,
start_time=int(
_note.start_tick + _i * (_note.duration / totalCount)
),
last_time=int(_note.duration / totalCount),
track_number=_note.track_no,
is_percussion=_note.percussive,
extra_information=_note.extra_info,
@ -116,54 +119,68 @@ class FutureMidiConvertM4(MidiConvert):
for channel in self.channels.values():
for note in channel:
note.set_info(
single_note_to_note_parameters(
minenote_to_command_paramaters(
note,
(
self.percussion_note_referrence_table
if note.percussive
else self.pitched_note_reference_table
),
deviation=0,
volume_percentage=(
(max_volume) if note.track_no == 0 else (max_volume * 0.9)
),
volume_processing_method=self.volume_processing_function,
pitch_deviation=self.music_deviation,
)
)
if not note.percussive:
notes_list.extend(self._linear_note(note, note.extra_info[3] * 500))
notes_list.extend(self._linear_note(note,1 * note.extra_info[3]))
else:
notes_list.append(note)
notes_list.sort(key=lambda a: a.start_time)
notes_list.sort(key=lambda a: a.start_tick)
self.music_command_list = []
multi = max_multi = 0
delaytime_previous = 0
for note in notes_list:
delaytime_now = round(note.start_time / speed / 50)
if (tickdelay := (delaytime_now - delaytime_previous)) == 0:
if (tickdelay := (note.start_tick - delaytime_previous)) == 0:
multi += 1
else:
max_multi = max(max_multi, multi)
multi = 0
(
mc_sound_ID,
relative_coordinates,
volume_percentage,
mc_pitch,
) = note.extra_info
self.music_command_list.append(
MineCommand(
command=(
self.execute_cmd_head.format(player_selector)
+ r"playsound {} @s ^ ^ ^{} {} {}".format(*note.extra_info),
+ r"playsound {} @s ^{} ^{} ^{} {} {} {}".format(
mc_sound_ID,
*relative_coordinates,
volume_percentage,
1.0 if note.percussive else mc_pitch,
self.minium_volume,
)
),
annotation=(
"{}播放噪音{}".format(
mctick2timestr(note.start_tick),
mc_sound_ID,
)
if note.percussive
else "{}播放乐音{}".format(
mctick2timestr(note.start_tick),
"{}:{:.2f}".format(mc_sound_ID, mc_pitch),
)
),
tick_delay=tickdelay,
annotation="{}播放{}%{}".format(
mctick2timestr(delaytime_now),
max_volume * 100,
"{}:{}".format(note.extra_info[0], note.extra_info[3]),
),
)
)
delaytime_previous = delaytime_now
delaytime_previous = note.start_tick
return self.music_command_list, round(notes_list[-1].start_time / speed / 50), max_multi + 1
return (
self.music_command_list,
notes_list[-1].start_tick + notes_list[-1].duration,
max_multi + 1,
)
class FutureMidiConvertM5(MidiConvert):

View File

@ -70,13 +70,6 @@ tick * tempo / 1000000.0 / ticks_per_beat * 一秒多少游戏刻
"""
# VoidMido = Union[mido.MidiFile, None] # void mido
# """
# 空Midi类类型
# """
# 已经成为历史了
@dataclass(init=False)
class MusicSequence:
"""
@ -92,23 +85,23 @@ class MusicSequence:
total_note_count: int
"""音符总数"""
used_instrument: List[str]
note_count_per_instrument: Dict[str, int]
"""所使用的乐器"""
minium_volume: float
"""乐曲最小音量"""
music_deviation: float
"""曲音调偏移"""
"""曲音调偏移"""
def __init__(
self,
name_of_music: str,
channels_of_notes: MineNoteChannelType,
music_note_count: Optional[int] = None,
used_instrument_of_music: Optional[List[str]] = None,
note_used_per_instrument: Optional[Dict[str, int]] = None,
minium_volume_of_music: float = 0.1,
deviation: Optional[float] = None,
deviation_value: Optional[float] = None,
) -> None:
"""
我的世界音符序列类
@ -135,26 +128,21 @@ class MusicSequence:
self.channels = channels_of_notes
self.minium_volume = minium_volume_of_music
if used_instrument_of_music is None or music_note_count is None:
if (note_used_per_instrument is None) or (music_note_count is None):
kp = [i.sound_name for j in self.channels.values() for i in j]
self.total_note_count = (
len(kp) if music_note_count is None else music_note_count
)
self.used_instrument = (
list(set(kp))
if used_instrument_of_music is None
else used_instrument_of_music
self.note_count_per_instrument = (
dict([(it, kp.count(it)) for it in set(kp)])
if note_used_per_instrument is None
else note_used_per_instrument
)
else:
self.total_note_count = music_note_count
self.note_count_per_instrument = note_used_per_instrument
self.music_deviation = (
self.guess_deviation(
self.total_note_count,
len(self.used_instrument),
music_channels=self.channels,
)
if deviation is None
else deviation
)
self.music_deviation = 0 if deviation_value is None else deviation_value
@classmethod
def from_mido(
@ -168,10 +156,13 @@ class MusicSequence:
minium_vol: float = 0.1,
volume_processing_function: FittingFunctionType = natural_curve,
default_tempo: int = mido.midifiles.midifiles.DEFAULT_TEMPO,
devation_guess_enabled: bool = True,
deviation: float = 0,
):
note_channels, note_count_total, inst_note_count, qualified_inst_note_count = (
cls.to_music_note_channels(
(
note_channels,
note_count_total,
inst_note_count, # qualified_inst_note_count,
) = cls.to_music_note_channels(
midi=mido_file,
speed=speed_multiplier,
pitched_note_rtable=pitched_note_referance_table,
@ -180,23 +171,13 @@ class MusicSequence:
vol_processing_function=volume_processing_function,
ignore_mismatch_error=mismatch_error_ignorance,
)
)
return cls(
name_of_music=midi_music_name,
channels_of_notes=note_channels,
music_note_count=note_count_total,
used_instrument_of_music=list(inst_note_count.keys()),
note_used_per_instrument=inst_note_count,
minium_volume_of_music=minium_vol,
deviation=(
cls.guess_deviation(
note_count_total,
len(inst_note_count),
inst_note_count,
qualified_inst_note_count,
)
if devation_guess_enabled
else 0
),
deviation_value=deviation,
)
def set_min_volume(self, volume_value: int):
@ -215,30 +196,31 @@ class MusicSequence:
self.channels[channel_no].sort(key=lambda note: note.start_tick)
@staticmethod
def guess_deviation(
def guess_deviation_wasted(
total_note_count: int,
total_instrument_count: int,
note_count_per_instruments: Optional[Dict[str, int]] = None,
qualified_note_count_per_instruments: Optional[Dict[str, int]] = None,
note_count_per_instrument: Optional[Dict[str, int]] = None,
qualified_note_count_per_instrument: Optional[Dict[str, int]] = None,
music_channels: Optional[MineNoteChannelType] = None,
) -> float:
"""已废弃"""
if (
note_count_per_instruments is None
or qualified_note_count_per_instruments is None
note_count_per_instrument is None
or qualified_note_count_per_instrument is None
):
if music_channels is None:
raise ValueError("参数不足,算逑!")
note_count_per_instruments = {}
qualified_note_count_per_instruments = {}
note_count_per_instrument = {}
qualified_note_count_per_instrument = {}
for this_note in [k for j in music_channels.values() for k in j]:
if this_note.sound_name in note_count_per_instruments.keys():
note_count_per_instruments[this_note.sound_name] += 1
qualified_note_count_per_instruments[
if this_note.sound_name in note_count_per_instrument.keys():
note_count_per_instrument[this_note.sound_name] += 1
qualified_note_count_per_instrument[
this_note.sound_name
] += is_note_in_diapason(this_note)
else:
note_count_per_instruments[this_note.sound_name] = 1
qualified_note_count_per_instruments[this_note.sound_name] = int(
note_count_per_instrument[this_note.sound_name] = 1
qualified_note_count_per_instrument[this_note.sound_name] = int(
is_note_in_diapason(this_note)
)
return (
@ -251,9 +233,9 @@ class MusicSequence:
/ total_note_count
- MM_INSTRUMENT_RANGE_TABLE[inst][-1]
)
* (note_count - qualified_note_count_per_instruments[inst])
* (note_count - qualified_note_count_per_instrument[inst])
)
for inst, note_count in note_count_per_instruments.items()
for inst, note_count in note_count_per_instrument.items()
]
)
/ total_instrument_count
@ -269,7 +251,7 @@ class MusicSequence:
percussion_note_rtable: MidiInstrumentTableType = MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE,
default_tempo_value: int = mido.midifiles.midifiles.DEFAULT_TEMPO,
vol_processing_function: FittingFunctionType = natural_curve,
) -> Tuple[MineNoteChannelType, int, Dict[str, int], Dict[str, int]]:
) -> Tuple[MineNoteChannelType, int, Dict[str, int]]: # , Dict[str, int]]:
"""
将midi解析并转换为频道音符字典
@ -291,8 +273,8 @@ class MusicSequence:
midi_channels: MineNoteChannelType = empty_midi_channels(staff=[])
tempo = default_tempo_value
note_count = 0
note_count_per_instruments: Dict[str, int] = {}
qualified_note_count_per_instruments: Dict[str, int] = {}
note_count_per_instrument: Dict[str, int] = {}
# qualified_note_count_per_instruments: Dict[str, int] = {}
# 我们来用通道统计音乐信息
# 但是是用分轨的思路的
@ -382,19 +364,16 @@ class MusicSequence:
)
)
note_count += 1
if (
that_note.sound_name
in note_count_per_instruments.keys()
):
note_count_per_instruments[that_note.sound_name] += 1
qualified_note_count_per_instruments[
that_note.sound_name
] += is_note_in_diapason(that_note)
if that_note.sound_name in note_count_per_instrument.keys():
note_count_per_instrument[that_note.sound_name] += 1
# qualified_note_count_per_instruments[
# that_note.sound_name
# ] += is_note_in_diapason(that_note)
else:
note_count_per_instruments[that_note.sound_name] = 1
qualified_note_count_per_instruments[
that_note.sound_name
] = int(is_note_in_diapason(that_note))
note_count_per_instrument[that_note.sound_name] = 1
# qualified_note_count_per_instruments[
# that_note.sound_name
# ] = int(is_note_in_diapason(that_note))
else:
if ignore_mismatch_error:
print(
@ -431,8 +410,8 @@ class MusicSequence:
return (
channels,
note_count,
note_count_per_instruments,
qualified_note_count_per_instruments,
note_count_per_instrument,
# qualified_note_count_per_instruments,
)
@ -463,7 +442,7 @@ class MidiConvert(MusicSequence):
default_tempo_value: int = mido.midifiles.midifiles.DEFAULT_TEMPO,
pitched_note_rtable: MidiInstrumentTableType = MM_TOUCH_PITCHED_INSTRUMENT_TABLE,
percussion_note_rtable: MidiInstrumentTableType = MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE,
enable_devation_guess: bool = True,
# enable_devation_guess: bool = True,
enable_old_exe_format: bool = False,
minium_volume: float = 0.1,
vol_processing_function: FittingFunctionType = natural_curve,
@ -505,7 +484,7 @@ class MidiConvert(MusicSequence):
minium_vol=minium_volume,
volume_processing_function=vol_processing_function,
default_tempo=default_tempo_value,
devation_guess_enabled=enable_devation_guess,
# devation_guess_enabled=enable_devation_guess,
mismatch_error_ignorance=ignore_mismatch_error,
)
@ -518,7 +497,7 @@ class MidiConvert(MusicSequence):
default_tempo: int = mido.midifiles.midifiles.DEFAULT_TEMPO,
pitched_note_table: MidiInstrumentTableType = MM_TOUCH_PITCHED_INSTRUMENT_TABLE,
percussion_note_table: MidiInstrumentTableType = MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE,
devation_guess_enabled: bool = True,
# devation_guess_enabled: bool = True,
old_exe_format: bool = False,
min_volume: float = 0.1,
vol_processing_func: FittingFunctionType = natural_curve,
@ -560,13 +539,13 @@ class MidiConvert(MusicSequence):
default_tempo_value=default_tempo,
pitched_note_rtable=pitched_note_table,
percussion_note_rtable=percussion_note_table,
enable_devation_guess=devation_guess_enabled,
# enable_devation_guess=devation_guess_enabled,
enable_old_exe_format=old_exe_format,
minium_volume=min_volume,
vol_processing_function=vol_processing_func,
)
except (ValueError, TypeError) as E:
raise MidiDestroyedError(f"文件{midi_file_path}损坏:{E}")
raise MidiDestroyedError(f"文件{midi_file_path}可能损坏:{E}")
except FileNotFoundError as E:
raise FileNotFoundError(f"文件{midi_file_path}不存在:{E}")
@ -584,13 +563,13 @@ class MidiConvert(MusicSequence):
Parameters
----------
maxscore: int
max_score: int
midi的乐器ID
scoreboard_name: str
所使用的计分板名称
progressbar_style: tuple
progressbar_style: ProgressBarStyle
此参数详见 ../docs/库的生成与功能文档.md#进度条自定义
Returns
@ -1004,6 +983,93 @@ class MidiConvert(MusicSequence):
return self.music_command_list, notes_list[-1].start_tick, max_multi + 1
def to_command_list_in_delay_devided_by_instrument(
self,
player_selector: str = "@a",
) -> Tuple[Dict[str, List[MineCommand]], int, Dict[str, int]]:
"""
将midi转换为我的世界命令列表并输出每个音符之后的延迟
Parameters
----------
player_selector: str
玩家选择器默认为`@a`
Returns
-------
Tuple[Dict[str, List[MineCommand]], int音乐时长游戏刻, int最大同时播放的指令数量 )
"""
notes_list: List[MineNote] = sorted(
[i for j in self.channels.values() for i in j],
key=lambda note: note.start_tick,
)
command_dict: Dict[str, List[MineCommand]] = dict(
[(inst, []) for inst in self.note_count_per_instrument.keys()]
)
multi: Dict[str, int] = dict(
[(inst, 0) for inst in self.note_count_per_instrument.keys()]
)
max_multi: Dict[str, int] = dict(
[(inst, 0) for inst in self.note_count_per_instrument.keys()]
)
delaytime_previous: Dict[str, int] = dict(
[(inst, 0) for inst in self.note_count_per_instrument.keys()]
)
for note in notes_list:
if (
tickdelay := (note.start_tick - delaytime_previous[note.sound_name])
) == 0:
multi[note.sound_name] += 1
else:
max_multi[note.sound_name] = max(
max_multi[note.sound_name], multi[note.sound_name]
)
multi[note.sound_name] = 0
(
mc_sound_ID,
relative_coordinates,
volume_percentage,
mc_pitch,
) = minenote_to_command_paramaters(
note,
pitch_deviation=self.music_deviation,
)
command_dict[note.sound_name].append(
MineCommand(
command=(
self.execute_cmd_head.format(player_selector)
+ r"playsound {} @s ^{} ^{} ^{} {} {} {}".format(
mc_sound_ID,
*relative_coordinates,
volume_percentage,
1.0 if note.percussive else mc_pitch,
self.minium_volume,
)
),
annotation=(
"{}播放噪音{}".format(
mctick2timestr(note.start_tick),
mc_sound_ID,
)
if note.percussive
else "{}播放乐音{}".format(
mctick2timestr(note.start_tick),
"{}:{:.2f}".format(mc_sound_ID, mc_pitch),
)
),
tick_delay=tickdelay,
),
)
delaytime_previous[note.sound_name] = note.start_tick
self.music_command_list = [j for i in command_dict.values() for j in i]
return command_dict, notes_list[-1].start_tick, max_multi
def copy_important(self):
dst = MidiConvert.from_mido_obj(
midi_obj=mido.MidiFile(),

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""
存放非音·创本体的附加内容插件
存放非音·创本体的附加功能件
版权所有 © 2024 · 开发者
Copyright © 2024 all the developers of Musicreater
@ -16,7 +16,7 @@ Terms & Conditions: License.md in the root directory
__all__ = [
# 通用
"ConvertConfig",
# "ConvertConfig",
"bottem_side_length_of_smallest_square_bottom_box",
# 打包
"compress_zipfile",
@ -43,7 +43,7 @@ __all__ = [
]
__author__ = (("金羿", "Eilles Wan"), ("诸葛亮与八卦阵", "bgArray"))
from .main import ConvertConfig
# from .main import ConvertConfig
from .archive import compress_zipfile, behavior_mcpack_manifest

View File

@ -18,6 +18,7 @@ __all__ = [
"to_addon_pack_in_delay",
"to_addon_pack_in_score",
"to_addon_pack_in_repeater",
"to_addon_pack_in_repeater_divided_by_instrument",
]
__author__ = (("金羿", "Eilles Wan"),)
@ -25,4 +26,5 @@ from .main import (
to_addon_pack_in_delay,
to_addon_pack_in_repeater,
to_addon_pack_in_score,
to_addon_pack_in_repeater_divided_by_instrument,
)

View File

@ -16,12 +16,12 @@ import os
import shutil
from typing import Tuple
from TrimMCStruct import Structure
from ...main import MidiConvert
from ..archive import behavior_mcpack_manifest, compress_zipfile
from ..main import ConvertConfig
from ...subclass import ProgressBarStyle
from ...types import Optional, Literal
from ..mcstructure import (
Structure,
COMPABILITY_VERSION_117,
COMPABILITY_VERSION_119,
commands_to_redstone_delay_structure,
@ -32,7 +32,8 @@ from ..mcstructure import (
def to_addon_pack_in_score(
midi_cvt: MidiConvert,
data_cfg: ConvertConfig,
dist_path: str,
progressbar_style: Optional[ProgressBarStyle],
scoreboard_name: str = "mscplay",
auto_reset: bool = False,
) -> Tuple[int, int]:
@ -43,8 +44,10 @@ def to_addon_pack_in_score(
----------
midi_cvt: MidiConvert 对象
用于转换的MidiConvert对象
data_cfg: ConvertConfig 对象
部分转换通用参数
dist_path: str
转换结果输出的目标路径
progressbar_style: ProgressBarStyle 对象
进度条对象
scoreboard_name: str
我的世界的计分板名称
auto_reset: bool
@ -60,12 +63,12 @@ def to_addon_pack_in_score(
)
# 当文件f夹{self.outputPath}/temp/functions存在时清空其下所有项目然后创建
if os.path.exists(f"{data_cfg.dist_path}/temp/functions/"):
shutil.rmtree(f"{data_cfg.dist_path}/temp/functions/")
os.makedirs(f"{data_cfg.dist_path}/temp/functions/mscplay")
if os.path.exists(f"{dist_path}/temp/functions/"):
shutil.rmtree(f"{dist_path}/temp/functions/")
os.makedirs(f"{dist_path}/temp/functions/mscplay")
# 写入manifest.json
with open(f"{data_cfg.dist_path}/temp/manifest.json", "w", encoding="utf-8") as f:
with open(f"{dist_path}/temp/manifest.json", "w", encoding="utf-8") as f:
json.dump(
behavior_mcpack_manifest(
pack_description=f"{midi_cvt.music_name} 音乐播放包MCFUNCTION(MCPACK) 计分播放器 - 由 音·创 生成",
@ -78,18 +81,18 @@ def to_addon_pack_in_score(
# 写入stop.mcfunction
with open(
f"{data_cfg.dist_path}/temp/functions/stop.mcfunction", "w", encoding="utf-8"
f"{dist_path}/temp/functions/stop.mcfunction", "w", encoding="utf-8"
) as f:
f.write("scoreboard players reset @a {}".format(scoreboard_name))
# 将命令列表写入文件
index_file = open(
f"{data_cfg.dist_path}/temp/functions/index.mcfunction", "w", encoding="utf-8"
f"{dist_path}/temp/functions/index.mcfunction", "w", encoding="utf-8"
)
for i in range(len(cmdlist)):
index_file.write(f"function mscplay/track{i + 1}\n")
with open(
f"{data_cfg.dist_path}/temp/functions/mscplay/track{i + 1}.mcfunction",
f"{dist_path}/temp/functions/mscplay/track{i + 1}.mcfunction",
"w",
encoding="utf-8",
) as f:
@ -113,13 +116,13 @@ def to_addon_pack_in_score(
if auto_reset
else ""
),
f"function mscplay/progressShow\n" if data_cfg.progressbar_style else "",
f"function mscplay/progressShow\n" if progressbar_style else "",
)
)
if data_cfg.progressbar_style:
if progressbar_style:
with open(
f"{data_cfg.dist_path}/temp/functions/mscplay/progressShow.mcfunction",
f"{dist_path}/temp/functions/mscplay/progressShow.mcfunction",
"w",
encoding="utf-8",
) as f:
@ -128,7 +131,7 @@ def to_addon_pack_in_score(
[
single_cmd.cmd
for single_cmd in midi_cvt.form_progress_bar(
maxscore, scoreboard_name, data_cfg.progressbar_style
maxscore, scoreboard_name, progressbar_style
)
]
)
@ -136,21 +139,22 @@ def to_addon_pack_in_score(
index_file.close()
if os.path.exists(f"{data_cfg.dist_path}/{midi_cvt.music_name}.mcpack"):
os.remove(f"{data_cfg.dist_path}/{midi_cvt.music_name}.mcpack")
if os.path.exists(f"{dist_path}/{midi_cvt.music_name}.mcpack"):
os.remove(f"{dist_path}/{midi_cvt.music_name}.mcpack")
compress_zipfile(
f"{data_cfg.dist_path}/temp/",
f"{data_cfg.dist_path}/{midi_cvt.music_name}.mcpack",
f"{dist_path}/temp/",
f"{dist_path}/{midi_cvt.music_name}.mcpack",
)
shutil.rmtree(f"{data_cfg.dist_path}/temp/")
shutil.rmtree(f"{dist_path}/temp/")
return maxlen, maxscore
def to_addon_pack_in_delay(
midi_cvt: MidiConvert,
data_cfg: ConvertConfig,
dist_path: str,
progressbar_style: Optional[ProgressBarStyle],
player: str = "@a",
max_height: int = 64,
) -> Tuple[int, int]:
@ -161,8 +165,10 @@ def to_addon_pack_in_delay(
----------
midi_cvt: MidiConvert 对象
用于转换的MidiConvert对象
data_cfg: ConvertConfig 对象
部分转换通用参数
dist_path: str
转换结果输出的目标路径
progressbar_style: ProgressBarStyle 对象
进度条对象
player: str
玩家选择器默认为`@a`
max_height: int
@ -183,17 +189,17 @@ def to_addon_pack_in_delay(
player_selector=player,
)[:2]
if not os.path.exists(data_cfg.dist_path):
os.makedirs(data_cfg.dist_path)
if not os.path.exists(dist_path):
os.makedirs(dist_path)
# 当文件f夹{self.outputPath}/temp/存在时清空其下所有项目,然后创建
if os.path.exists(f"{data_cfg.dist_path}/temp/"):
shutil.rmtree(f"{data_cfg.dist_path}/temp/")
os.makedirs(f"{data_cfg.dist_path}/temp/functions/")
os.makedirs(f"{data_cfg.dist_path}/temp/structures/")
if os.path.exists(f"{dist_path}/temp/"):
shutil.rmtree(f"{dist_path}/temp/")
os.makedirs(f"{dist_path}/temp/functions/")
os.makedirs(f"{dist_path}/temp/structures/")
# 写入manifest.json
with open(f"{data_cfg.dist_path}/temp/manifest.json", "w", encoding="utf-8") as f:
with open(f"{dist_path}/temp/manifest.json", "w", encoding="utf-8") as f:
json.dump(
behavior_mcpack_manifest(
pack_description=f"{midi_cvt.music_name} 音乐播放包MCSTRUCTURE(MCPACK) 延迟播放器 - 由 音·创 生成",
@ -206,7 +212,7 @@ def to_addon_pack_in_delay(
# 写入stop.mcfunction
with open(
f"{data_cfg.dist_path}/temp/functions/stop.mcfunction", "w", encoding="utf-8"
f"{dist_path}/temp/functions/stop.mcfunction", "w", encoding="utf-8"
) as f:
f.write(
"gamerule commandblocksenabled false\ngamerule commandblocksenabled true"
@ -214,7 +220,7 @@ def to_addon_pack_in_delay(
# 将命令列表写入文件
index_file = open(
f"{data_cfg.dist_path}/temp/functions/index.mcfunction", "w", encoding="utf-8"
f"{dist_path}/temp/functions/index.mcfunction", "w", encoding="utf-8"
)
struct, size, end_pos = commands_to_structure(
@ -225,7 +231,7 @@ def to_addon_pack_in_delay(
with open(
os.path.abspath(
os.path.join(
data_cfg.dist_path,
dist_path,
"temp/structures/",
f"{midi_cvt.music_name}_main.mcstructure",
)
@ -236,7 +242,7 @@ def to_addon_pack_in_delay(
del struct
if data_cfg.progressbar_style:
if progressbar_style:
scb_name = midi_cvt.music_name[:3] + "Pgb"
index_file.write("scoreboard objectives add {0} dummy {0}\n".format(scb_name))
@ -257,7 +263,7 @@ def to_addon_pack_in_delay(
with open(
os.path.abspath(
os.path.join(
data_cfg.dist_path,
dist_path,
"temp/structures/",
f"{midi_cvt.music_name}_start.mcstructure",
)
@ -269,7 +275,7 @@ def to_addon_pack_in_delay(
index_file.write(f"structure load {midi_cvt.music_name}_start ~ ~ ~1\n")
pgb_struct, pgbSize, pgbNowPos = commands_to_structure(
midi_cvt.form_progress_bar(max_delay, scb_name, data_cfg.progressbar_style),
midi_cvt.form_progress_bar(max_delay, scb_name, progressbar_style),
max_height - 1,
compability_version_=compability_ver,
)
@ -277,7 +283,7 @@ def to_addon_pack_in_delay(
with open(
os.path.abspath(
os.path.join(
data_cfg.dist_path,
dist_path,
"temp/structures/",
f"{midi_cvt.music_name}_pgb.mcstructure",
)
@ -307,7 +313,7 @@ def to_addon_pack_in_delay(
with open(
os.path.abspath(
os.path.join(
data_cfg.dist_path,
dist_path,
"temp/structures/",
f"{midi_cvt.music_name}_reset.mcstructure",
)
@ -331,21 +337,22 @@ def to_addon_pack_in_delay(
index_file.close()
if os.path.exists(f"{data_cfg.dist_path}/{midi_cvt.music_name}.mcpack"):
os.remove(f"{data_cfg.dist_path}/{midi_cvt.music_name}.mcpack")
if os.path.exists(f"{dist_path}/{midi_cvt.music_name}.mcpack"):
os.remove(f"{dist_path}/{midi_cvt.music_name}.mcpack")
compress_zipfile(
f"{data_cfg.dist_path}/temp/",
f"{data_cfg.dist_path}/{midi_cvt.music_name}.mcpack",
f"{dist_path}/temp/",
f"{dist_path}/{midi_cvt.music_name}.mcpack",
)
shutil.rmtree(f"{data_cfg.dist_path}/temp/")
shutil.rmtree(f"{dist_path}/temp/")
return len(command_list), max_delay
def to_addon_pack_in_repeater(
midi_cvt: MidiConvert,
data_cfg: ConvertConfig,
dist_path: str,
progressbar_style: Optional[ProgressBarStyle],
player: str = "@a",
max_height: int = 65,
) -> Tuple[int, int]:
@ -356,8 +363,10 @@ def to_addon_pack_in_repeater(
----------
midi_cvt: MidiConvert 对象
用于转换的MidiConvert对象
data_cfg: ConvertConfig 对象
部分转换通用参数
dist_path: str
转换结果输出的目标路径
progressbar_style: ProgressBarStyle 对象
进度条对象
player: str
玩家选择器默认为`@a`
max_height: int
@ -378,17 +387,17 @@ def to_addon_pack_in_repeater(
player_selector=player,
)
if not os.path.exists(data_cfg.dist_path):
os.makedirs(data_cfg.dist_path)
if not os.path.exists(dist_path):
os.makedirs(dist_path)
# 当文件f夹{self.outputPath}/temp/存在时清空其下所有项目,然后创建
if os.path.exists(f"{data_cfg.dist_path}/temp/"):
shutil.rmtree(f"{data_cfg.dist_path}/temp/")
os.makedirs(f"{data_cfg.dist_path}/temp/functions/")
os.makedirs(f"{data_cfg.dist_path}/temp/structures/")
if os.path.exists(f"{dist_path}/temp/"):
shutil.rmtree(f"{dist_path}/temp/")
os.makedirs(f"{dist_path}/temp/functions/")
os.makedirs(f"{dist_path}/temp/structures/")
# 写入manifest.json
with open(f"{data_cfg.dist_path}/temp/manifest.json", "w", encoding="utf-8") as f:
with open(f"{dist_path}/temp/manifest.json", "w", encoding="utf-8") as f:
json.dump(
behavior_mcpack_manifest(
pack_description=f"{midi_cvt.music_name} 音乐播放包MCSTRUCTURE(MCPACK) 中继器播放器 - 由 音·创 生成",
@ -401,7 +410,7 @@ def to_addon_pack_in_repeater(
# 写入stop.mcfunction
with open(
f"{data_cfg.dist_path}/temp/functions/stop.mcfunction", "w", encoding="utf-8"
f"{dist_path}/temp/functions/stop.mcfunction", "w", encoding="utf-8"
) as f:
f.write(
"gamerule commandblocksenabled false\ngamerule commandblocksenabled true"
@ -409,7 +418,7 @@ def to_addon_pack_in_repeater(
# 将命令列表写入文件
index_file = open(
f"{data_cfg.dist_path}/temp/functions/index.mcfunction", "w", encoding="utf-8"
f"{dist_path}/temp/functions/index.mcfunction", "w", encoding="utf-8"
)
struct, size, end_pos = commands_to_redstone_delay_structure(
@ -421,7 +430,7 @@ def to_addon_pack_in_repeater(
with open(
os.path.abspath(
os.path.join(
data_cfg.dist_path,
dist_path,
"temp/structures/",
f"{midi_cvt.music_name}_main.mcstructure",
)
@ -432,7 +441,7 @@ def to_addon_pack_in_repeater(
del struct
if data_cfg.progressbar_style:
if progressbar_style:
scb_name = midi_cvt.music_name[:3] + "Pgb"
index_file.write("scoreboard objectives add {0} dummy {0}\n".format(scb_name))
@ -453,7 +462,7 @@ def to_addon_pack_in_repeater(
with open(
os.path.abspath(
os.path.join(
data_cfg.dist_path,
dist_path,
"temp/structures/",
f"{midi_cvt.music_name}_start.mcstructure",
)
@ -465,7 +474,7 @@ def to_addon_pack_in_repeater(
index_file.write(f"structure load {midi_cvt.music_name}_start ~ ~ ~1\n")
pgb_struct, pgbSize, pgbNowPos = commands_to_structure(
midi_cvt.form_progress_bar(max_delay, scb_name, data_cfg.progressbar_style),
midi_cvt.form_progress_bar(max_delay, scb_name, progressbar_style),
max_height - 1,
compability_version_=compability_ver,
)
@ -473,7 +482,7 @@ def to_addon_pack_in_repeater(
with open(
os.path.abspath(
os.path.join(
data_cfg.dist_path,
dist_path,
"temp/structures/",
f"{midi_cvt.music_name}_pgb.mcstructure",
)
@ -503,7 +512,7 @@ def to_addon_pack_in_repeater(
with open(
os.path.abspath(
os.path.join(
data_cfg.dist_path,
dist_path,
"temp/structures/",
f"{midi_cvt.music_name}_reset.mcstructure",
)
@ -527,13 +536,128 @@ def to_addon_pack_in_repeater(
index_file.close()
if os.path.exists(f"{data_cfg.dist_path}/{midi_cvt.music_name}.mcpack"):
os.remove(f"{data_cfg.dist_path}/{midi_cvt.music_name}.mcpack")
if os.path.exists(f"{dist_path}/{midi_cvt.music_name}.mcpack"):
os.remove(f"{dist_path}/{midi_cvt.music_name}.mcpack")
compress_zipfile(
f"{data_cfg.dist_path}/temp/",
f"{data_cfg.dist_path}/{midi_cvt.music_name}.mcpack",
f"{dist_path}/temp/",
f"{dist_path}/{midi_cvt.music_name}.mcpack",
)
shutil.rmtree(f"{data_cfg.dist_path}/temp/")
shutil.rmtree(f"{dist_path}/temp/")
return len(command_list), max_delay
def to_addon_pack_in_repeater_divided_by_instrument(
midi_cvt: MidiConvert,
dist_path: str,
player: str = "@a",
max_height: int = 65,
base_block: str = "concrete",
) -> Tuple[int, int]:
"""
将midi以中继器播放器形式转换为mcstructure结构文件后打包成附加包并在附加包中生成相应地导入函数
Parameters
----------
midi_cvt: MidiConvert 对象
用于转换的MidiConvert对象
dist_path: str
转换结果输出的目标路径
player: str
玩家选择器默认为`@a`
max_height: int
生成结构最大高度
Returns
-------
tuple[int指令数量, int音乐总延迟]
"""
compability_ver = (
COMPABILITY_VERSION_117
if midi_cvt.enable_old_exe_format
else COMPABILITY_VERSION_119
)
if not os.path.exists(dist_path):
os.makedirs(dist_path)
# 当文件f夹{self.outputPath}/temp/存在时清空其下所有项目,然后创建
if os.path.exists(f"{dist_path}/temp/"):
shutil.rmtree(f"{dist_path}/temp/")
os.makedirs(f"{dist_path}/temp/functions/")
os.makedirs(f"{dist_path}/temp/structures/")
# 写入manifest.json
with open(f"{dist_path}/temp/manifest.json", "w", encoding="utf-8") as f:
json.dump(
behavior_mcpack_manifest(
pack_description=f"{midi_cvt.music_name} 音乐播放包MCSTRUCTURE(MCPACK) 中继器播放器 - 由 音·创 生成",
pack_name=midi_cvt.music_name + "播放",
modules_description=f"无 - 由 音·创 生成",
),
fp=f,
indent=4,
)
# 写入stop.mcfunction
with open(
f"{dist_path}/temp/functions/stop.mcfunction", "w", encoding="utf-8"
) as f:
f.write(
"gamerule commandblocksenabled false\ngamerule commandblocksenabled true"
)
# 将命令列表写入文件
index_file = open(
f"{dist_path}/temp/functions/index.mcfunction", "w", encoding="utf-8"
)
cmd_dict, max_delay, max_multiple_cmd_count = (
midi_cvt.to_command_list_in_delay_devided_by_instrument(
player_selector=player,
)
)
base_height = 0
for inst, cmd_list in cmd_dict.items():
struct, size, end_pos = commands_to_redstone_delay_structure(
cmd_list,
max_delay,
max_multiple_cmd_count[inst],
base_block,
"z+",
compability_version_=compability_ver,
)
bkn = "{}_{}".format(midi_cvt.music_name, inst.replace(".", "-"))
with open(
os.path.abspath(
os.path.join(
dist_path,
"temp/structures/",
"{}_main.mcstructure".format(bkn),
)
),
"wb+",
) as f:
struct.dump(f)
index_file.write("structure load {}_main ~ ~{} ~3\n".format(bkn, base_height))
base_height += 2 + size[1]
index_file.close()
if os.path.exists(f"{dist_path}/{midi_cvt.music_name}.mcpack"):
os.remove(f"{dist_path}/{midi_cvt.music_name}.mcpack")
compress_zipfile(
f"{dist_path}/temp/",
f"{dist_path}/{midi_cvt.music_name}.mcpack",
)
shutil.rmtree(f"{dist_path}/temp/")
return midi_cvt.total_note_count, max_delay

View File

@ -17,7 +17,8 @@ import os
import brotli
from ...main import MidiConvert
from ...subclass import MineCommand
from ...subclass import MineCommand, ProgressBarStyle
from ...types import Optional
from ..bdx import (
bdx_move,
commands_to_BDX_bytes,
@ -26,12 +27,12 @@ from ..bdx import (
y,
z,
)
from ..main import ConvertConfig
def to_BDX_file_in_score(
midi_cvt: MidiConvert,
data_cfg: ConvertConfig,
dist_path: str,
progressbar_style: Optional[ProgressBarStyle],
scoreboard_name: str = "mscplay",
auto_reset: bool = False,
author: str = "Eilles",
@ -44,8 +45,10 @@ def to_BDX_file_in_score(
----------
midi_cvt: MidiConvert 对象
用于转换的MidiConvert对象
data_cfg: ConvertConfig 对象
部分转换通用参数
dist_path: str
转换结果输出的目标路径
progressbar_style: ProgressBarStyle 对象
进度条对象
scoreboard_name: str
我的世界的计分板名称
auto_reset: bool
@ -64,11 +67,11 @@ def to_BDX_file_in_score(
scoreboard_name=scoreboard_name,
)
if not os.path.exists(data_cfg.dist_path):
os.makedirs(data_cfg.dist_path)
if not os.path.exists(dist_path):
os.makedirs(dist_path)
with open(
os.path.abspath(os.path.join(data_cfg.dist_path, f"{midi_cvt.music_name}.bdx")),
os.path.abspath(os.path.join(dist_path, f"{midi_cvt.music_name}.bdx")),
"w+",
) as f:
f.write("BD@")
@ -97,11 +100,9 @@ def to_BDX_file_in_score(
max_height - 1,
)
if data_cfg.progressbar_style:
if progressbar_style:
pgbBytes, pgbSize, pgbNowPos = commands_to_BDX_bytes(
midi_cvt.form_progress_bar(
max_score, scoreboard_name, data_cfg.progressbar_style
),
midi_cvt.form_progress_bar(max_score, scoreboard_name, progressbar_style),
max_height - 1,
)
_bytes += pgbBytes
@ -116,7 +117,7 @@ def to_BDX_file_in_score(
_bytes += cmdBytes
with open(
os.path.abspath(os.path.join(data_cfg.dist_path, f"{midi_cvt.music_name}.bdx")),
os.path.abspath(os.path.join(dist_path, f"{midi_cvt.music_name}.bdx")),
"ab+",
) as f:
f.write(brotli.compress(_bytes + b"XE"))
@ -126,7 +127,8 @@ def to_BDX_file_in_score(
def to_BDX_file_in_delay(
midi_cvt: MidiConvert,
data_cfg: ConvertConfig,
dist_path: str,
progressbar_style: Optional[ProgressBarStyle],
player: str = "@a",
author: str = "Eilles",
max_height: int = 64,
@ -138,8 +140,10 @@ def to_BDX_file_in_delay(
----------
midi_cvt: MidiConvert 对象
用于转换的MidiConvert对象
data_cfg: ConvertConfig 对象
部分转换通用参数
dist_path: str
转换结果输出的目标路径
progressbar_style: ProgressBarStyle 对象
进度条对象
player: str
玩家选择器默认为`@a`
author: str
@ -156,11 +160,11 @@ def to_BDX_file_in_delay(
player_selector=player,
)[:2]
if not os.path.exists(data_cfg.dist_path):
os.makedirs(data_cfg.dist_path)
if not os.path.exists(dist_path):
os.makedirs(dist_path)
with open(
os.path.abspath(os.path.join(data_cfg.dist_path, f"{midi_cvt.music_name}.bdx")),
os.path.abspath(os.path.join(dist_path, f"{midi_cvt.music_name}.bdx")),
"w+",
) as f:
f.write("BD@")
@ -171,7 +175,7 @@ def to_BDX_file_in_delay(
cmdBytes, size, finalPos = commands_to_BDX_bytes(cmdlist, max_height - 1)
if data_cfg.progressbar_style:
if progressbar_style:
scb_name = midi_cvt.music_name[:3] + "Pgb"
_bytes += form_command_block_in_BDX_bytes(
r"scoreboard objectives add {} dummy {}".replace(r"{}", scb_name),
@ -187,7 +191,7 @@ def to_BDX_file_in_delay(
)
_bytes += bdx_move(y, 1)
pgbBytes, pgbSize, pgbNowPos = commands_to_BDX_bytes(
midi_cvt.form_progress_bar(max_delay, scb_name, data_cfg.progressbar_style),
midi_cvt.form_progress_bar(max_delay, scb_name, progressbar_style),
max_height - 1,
)
_bytes += pgbBytes
@ -208,7 +212,7 @@ def to_BDX_file_in_delay(
_bytes += cmdBytes
with open(
os.path.abspath(os.path.join(data_cfg.dist_path, f"{midi_cvt.music_name}.bdx")),
os.path.abspath(os.path.join(dist_path, f"{midi_cvt.music_name}.bdx")),
"ab+",
) as f:
f.write(brotli.compress(_bytes + b"XE"))

View File

@ -16,77 +16,77 @@ Terms & Conditions: License.md in the root directory
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
from dataclasses import dataclass
from typing import Literal, Tuple, Union
# from dataclasses import dataclass
# from typing import Literal, Tuple, Union
from ..subclass import DEFAULT_PROGRESSBAR_STYLE, ProgressBarStyle
# from ..subclass import DEFAULT_PROGRESSBAR_STYLE, ProgressBarStyle
@dataclass(init=False)
class ConvertConfig: # 必定要改
"""
转换通用设置存储类
"""
# @dataclass(init=False)
# class ConvertConfig: # 必定要改
# """
# 转换通用设置存储类
# """
progressbar_style: Union[ProgressBarStyle, None]
"""进度条样式"""
# progressbar_style: Union[ProgressBarStyle, None]
# """进度条样式"""
dist_path: str
"""输出目录"""
# dist_path: str
# """输出目录"""
def __init__(
self,
output_path: str,
progressbar: Union[bool, Tuple[str, Tuple[str, str]], ProgressBarStyle] = True,
ignore_progressbar_param_error: bool = False,
):
"""
将已经转换好的数据内容指令载入MC可读格式
# def __init__(
# self,
# output_path: str,
# progressbar: Union[bool, Tuple[str, Tuple[str, str]], ProgressBarStyle] = True,
# ignore_progressbar_param_error: bool = False,
# ):
# """
# 将已经转换好的数据内容指令载入MC可读格式
Parameters
----------
output_path: str
生成内容的输出目录
volume: float
音量比率范围为(0,1]其原理为在距离玩家 (1 / volume -1) 的地方播放音频
speed: float
速度倍率注意这里的速度指的是播放速度倍率其原理为在播放音频的时候每个音符的播放时间除以 speed
progressbar: bool|tuple[str, Tuple[str,]]
进度条当此参数为 `True` 时使用默认进度条为其他的**值为真**的参数时识别为进度条自定义参数为其他**值为假**的时候不生成进度条
# Parameters
# ----------
# output_path: str
# 生成内容的输出目录
# volume: float
# 音量比率,范围为(0,1],其原理为在距离玩家 (1 / volume -1) 的地方播放音频
# speed: float
# 速度倍率,注意:这里的速度指的是播放速度倍率,其原理为在播放音频的时候,每个音符的播放时间除以 speed
# progressbar: bool|tuple[str, Tuple[str,]]
# 进度条,当此参数为 `True` 时使用默认进度条,为其他的**值为真**的参数时识别为进度条自定义参数,为其他**值为假**的时候不生成进度条
"""
# """
self.dist_path = output_path
"""输出目录"""
# self.dist_path = output_path
# """输出目录"""
if progressbar:
# 此处是对于仅有 True 的参数和自定义参数的判断
# 改这一段没🐎
if progressbar is True:
self.progressbar_style = DEFAULT_PROGRESSBAR_STYLE
"""进度条样式"""
return
elif isinstance(progressbar, ProgressBarStyle):
self.progressbar_style = progressbar
"""进度条样式"""
return
elif isinstance(progressbar, tuple):
if isinstance(progressbar[0], str) and isinstance(
progressbar[1], tuple
):
if isinstance(progressbar[1][0], str) and isinstance(
progressbar[1][1], str
):
self.progressbar_style = ProgressBarStyle(
progressbar[0], progressbar[1][0], progressbar[1][1]
)
return
if not ignore_progressbar_param_error:
raise TypeError(
"参数 {} 的类型 {} 与所需类型 Union[bool, Tuple[str, Tuple[str, str]], ProgressBarStyle] 不符。".format(
progressbar, type(progressbar)
)
)
# if progressbar:
# # 此处是对于仅有 True 的参数和自定义参数的判断
# # 改这一段没🐎
# if progressbar is True:
# self.progressbar_style = DEFAULT_PROGRESSBAR_STYLE
# """进度条样式"""
# return
# elif isinstance(progressbar, ProgressBarStyle):
# self.progressbar_style = progressbar
# """进度条样式"""
# return
# elif isinstance(progressbar, tuple):
# if isinstance(progressbar[0], str) and isinstance(
# progressbar[1], tuple
# ):
# if isinstance(progressbar[1][0], str) and isinstance(
# progressbar[1][1], str
# ):
# self.progressbar_style = ProgressBarStyle(
# progressbar[0], progressbar[1][0], progressbar[1][1]
# )
# return
# if not ignore_progressbar_param_error:
# raise TypeError(
# "参数 {} 的类型 {} 与所需类型 Union[bool, Tuple[str, Tuple[str, str]], ProgressBarStyle] 不符。".format(
# progressbar, type(progressbar)
# )
# )
self.progressbar_style = None
"""进度条样式组"""
# self.progressbar_style = None
# """进度条样式组"""

View File

@ -18,6 +18,7 @@ __all__ = [
"to_mcstructure_file_in_delay",
"to_mcstructure_file_in_repeater",
"to_mcstructure_file_in_score",
"to_mcstructure_files_in_repeater_divided_by_instruments",
]
__author__ = (("金羿", "Eilles Wan"),)
@ -25,4 +26,5 @@ from .main import (
to_mcstructure_file_in_delay,
to_mcstructure_file_in_repeater,
to_mcstructure_file_in_score,
to_mcstructure_files_in_repeater_divided_by_instruments,
)

View File

@ -14,9 +14,7 @@ Terms & Conditions: License.md in the root directory
import os
from typing import Literal
# from ...exceptions import CommandFormatError
from ...main import MidiConvert
from ..main import ConvertConfig
from ...subclass import MineCommand
from ..mcstructure import (
COMPABILITY_VERSION_117,
@ -28,7 +26,7 @@ from ..mcstructure import (
def to_mcstructure_file_in_delay(
midi_cvt: MidiConvert,
data_cfg: ConvertConfig,
dist_path: str,
player: str = "@a",
max_height: int = 64,
):
@ -39,8 +37,8 @@ def to_mcstructure_file_in_delay(
----------
midi_cvt: MidiConvert 对象
用于转换的MidiConvert对象
data_cfg: ConvertConfig 对象
部分转换通用参数
dist_path: str
转换结果输出的目标路径
player: str
玩家选择器默认为`@a`
max_height: int
@ -61,17 +59,15 @@ def to_mcstructure_file_in_delay(
player_selector=player,
)[:2]
if not os.path.exists(data_cfg.dist_path):
os.makedirs(data_cfg.dist_path)
if not os.path.exists(dist_path):
os.makedirs(dist_path)
struct, size, end_pos = commands_to_structure(
cmd_list, max_height - 1, compability_version_=compability_ver
)
with open(
os.path.abspath(
os.path.join(data_cfg.dist_path, f"{midi_cvt.music_name}.mcstructure")
),
os.path.abspath(os.path.join(dist_path, f"{midi_cvt.music_name}.mcstructure")),
"wb+",
) as f:
struct.dump(f)
@ -81,7 +77,7 @@ def to_mcstructure_file_in_delay(
def to_mcstructure_file_in_score(
midi_cvt: MidiConvert,
data_cfg: ConvertConfig,
dist_path: str,
scoreboard_name: str = "mscplay",
auto_reset: bool = False,
max_height: int = 64,
@ -93,8 +89,8 @@ def to_mcstructure_file_in_score(
----------
midi_cvt: MidiConvert 对象
用于转换的MidiConvert对象
data_cfg: ConvertConfig 对象
部分转换通用参数
dist_path: str
转换结果输出的目标路径
scoreboard_name: str
我的世界的计分板名称
auto_reset: bool
@ -117,8 +113,8 @@ def to_mcstructure_file_in_score(
scoreboard_name=scoreboard_name,
)
if not os.path.exists(data_cfg.dist_path):
os.makedirs(data_cfg.dist_path)
if not os.path.exists(dist_path):
os.makedirs(dist_path)
struct, size, end_pos = commands_to_structure(
midi_cvt.music_command_list
@ -142,9 +138,7 @@ def to_mcstructure_file_in_score(
)
with open(
os.path.abspath(
os.path.join(data_cfg.dist_path, f"{midi_cvt.music_name}.mcstructure")
),
os.path.abspath(os.path.join(dist_path, f"{midi_cvt.music_name}.mcstructure")),
"wb+",
) as f:
struct.dump(f)
@ -154,7 +148,7 @@ def to_mcstructure_file_in_score(
def to_mcstructure_file_in_repeater(
midi_cvt: MidiConvert,
data_cfg: ConvertConfig,
dist_path: str,
player: str = "@a",
axis_side: Literal["z+", "z-", "Z+", "Z-", "x+", "x-", "X+", "X-"] = "z+",
basement_block: str = "concrete",
@ -166,8 +160,8 @@ def to_mcstructure_file_in_repeater(
----------
midi_cvt: MidiConvert 对象
用于转换的MidiConvert对象
data_cfg: ConvertConfig 对象
部分转换通用参数
dist_path: str
转换结果输出的目标路径
player: str
玩家选择器默认为`@a`
axis_side: Literal["z+","z-","Z+","Z-","x+","x-","X+","X-"]
@ -190,8 +184,8 @@ def to_mcstructure_file_in_repeater(
player_selector=player,
)
if not os.path.exists(data_cfg.dist_path):
os.makedirs(data_cfg.dist_path)
if not os.path.exists(dist_path):
os.makedirs(dist_path)
struct, size, end_pos = commands_to_redstone_delay_structure(
cmd_list,
@ -203,11 +197,78 @@ def to_mcstructure_file_in_repeater(
)
with open(
os.path.abspath(
os.path.join(data_cfg.dist_path, f"{midi_cvt.music_name}.mcstructure")
),
os.path.abspath(os.path.join(dist_path, f"{midi_cvt.music_name}.mcstructure")),
"wb+",
) as f:
struct.dump(f)
return size, max_delay
def to_mcstructure_files_in_repeater_divided_by_instruments(
midi_cvt: MidiConvert,
dist_path: str,
player: str = "@a",
axis_side: Literal["z+", "z-", "Z+", "Z-", "x+", "x-", "X+", "X-"] = "z+",
basement_block: str = "concrete",
):
"""
将midi以延迟播放器形式转换为mcstructure结构文件
Parameters
----------
midi_cvt: MidiConvert 对象
用于转换的MidiConvert对象
dist_path: str
转换结果输出的目标路径
player: str
玩家选择器默认为`@a`
axis_side: Literal["z+","z-","Z+","Z-","x+","x-","X+","X-"]
生成结构的延展方向
basement_block: str
结构的基底方块
Returns
-------
int音乐总延迟
"""
compability_ver = (
COMPABILITY_VERSION_117
if midi_cvt.enable_old_exe_format
else COMPABILITY_VERSION_119
)
cmd_dict, max_delay, max_multiple_cmd_count = (
midi_cvt.to_command_list_in_delay_devided_by_instrument(
player_selector=player,
)
)
if not os.path.exists(dist_path):
os.makedirs(dist_path)
for inst, cmd_list in cmd_dict.items():
struct, size, end_pos = commands_to_redstone_delay_structure(
cmd_list,
max_delay,
max_multiple_cmd_count[inst],
basement_block,
axis_side,
compability_version_=compability_ver,
)
with open(
os.path.abspath(
os.path.join(
dist_path,
"{}_{}.mcstructure".format(
midi_cvt.music_name, inst.replace(".", "-")
),
)
),
"wb+",
) as f:
struct.dump(f)
return max_delay

View File

@ -118,6 +118,7 @@ class MineNote:
"Percussive" if self.percussive else "",
self.sound_name,
"" if self.percussive else "NotePitch = {}, ".format(self.note_pitch),
self.velocity,
self.start_tick,
self.duration,
", Track = {}".format(self.track_no) if is_track else "",
@ -554,6 +555,25 @@ class ProgressBarStyle:
self.to_play_style = to_play_s
self.played_style = played_s
@classmethod
def from_tuple(cls, tuplized_style: Tuple[str, Tuple[str, str]]):
"""自旧版进度条元组表示法读入数据(已不建议使用)"""
if isinstance(tuplized_style, tuple):
if isinstance(tuplized_style[0], str) and isinstance(
tuplized_style[1], tuple
):
if isinstance(tuplized_style[1][0], str) and isinstance(
tuplized_style[1][1], str
):
return cls(
tuplized_style[0], tuplized_style[1][0], tuplized_style[1][1]
)
raise ValueError(
"元组表示的进度条样式组 {} 格式错误,已不建议使用此功能,请尽快更换。".format(
tuplized_style
)
)
def set_base_style(self, value: str):
"""设置基础样式"""
self.base_style = value

View File

@ -18,7 +18,12 @@ Terms & Conditions: License.md in the root directory
import math
import random
from .constants import MC_INSTRUMENT_BLOCKS_TABLE, MM_INSTRUMENT_RANGE_TABLE
from .constants import (
MC_INSTRUMENT_BLOCKS_TABLE,
MM_INSTRUMENT_DEVIATION_TABLE,
MC_PITCHED_INSTRUMENT_LIST,
MM_INSTRUMENT_RANGE_TABLE,
)
from .subclass import SingleNote, MineNote
from .types import (
@ -61,7 +66,7 @@ def inst_to_sould_with_deviation(
) -> Tuple[str, int]:
"""
返回midi的乐器ID对应的我的世界乐器名对于音域转换算法如下
2**( ( msg.note - 66 ) / 12 ) 即为MC的音高
2**( ( msg.note - 60 - X ) / 12 ) 即为MC的音高
Parameters
----------
@ -74,16 +79,17 @@ def inst_to_sould_with_deviation(
-------
tuple(str我的世界乐器名, int转换算法中的X)
"""
return (
reference_table.get(
instrumentID,
default_instrument,
),
6,
sound_id = midi_inst_to_mc_sound(
instrumentID=instrumentID,
reference_table=reference_table,
default_instrument=default_instrument,
)
return sound_id, MM_INSTRUMENT_DEVIATION_TABLE.get(
sound_id,
MM_INSTRUMENT_DEVIATION_TABLE.get(
default_instrument, 6 if sound_id in MC_PITCHED_INSTRUMENT_LIST else -1
),
)
# 明明已经走了
# 凭什么还要在我心里留下缠绵缱绻
def midi_inst_to_mc_sound(
@ -179,7 +185,18 @@ def minenote_to_command_paramaters(
(
None
if note_.percussive
else 2 ** ((note_.note_pitch - 66 + pitch_deviation) / 12)
else (
2
** (
(
note_.note_pitch
- 60
- MM_INSTRUMENT_DEVIATION_TABLE.get(note_.sound_name, 6)
+ pitch_deviation
)
/ 12
)
)
),
)
@ -205,7 +222,7 @@ def single_note_to_command_parameters(
:return str[我的世界音符ID], Tuple[float,float,float]播放视角坐标, float[指令音量参数], float[指令音调参数]
"""
mc_sound_ID = midi_inst_to_mc_sound(
mc_sound_ID, _X = inst_to_sould_with_deviation(
note_.inst,
reference_table,
"note.bd" if note_.percussive else "note.flute",
@ -217,7 +234,7 @@ def single_note_to_command_parameters(
mc_sound_ID,
(0, mc_distance_volume, 0),
note_.velocity / 127,
None if note_.percussive else 2 ** ((note_.pitch - 66 + deviation) / 12),
None if note_.percussive else 2 ** ((note_.pitch - 60 - _X + deviation) / 12),
)

View File

@ -19,7 +19,6 @@ Terms & Conditions: ./License.md
import os
import Musicreater
from Musicreater.plugin import ConvertConfig
from Musicreater.plugin.addonpack import (
to_addon_pack_in_delay,
to_addon_pack_in_repeater,
@ -160,7 +159,7 @@ print(f"正在处理 {midi_path} ")
cvt_mid = Musicreater.MidiConvert.from_midi_file(
midi_path, old_exe_format=False, min_volume=prompts[0], play_speed=prompts[1]
)
cvt_cfg = ConvertConfig(out_path, prompts[2])
if fileFormat == 0:
if playerFormat == 1:
@ -177,28 +176,62 @@ elif fileFormat == 2:
elif playerFormat == 2:
cvt_method = to_mcstructure_file_in_repeater
# 测试
# print(cvt_mid)
print(
" 指令总长:{},最高延迟:{}".format(
*(cvt_method(cvt_mid, cvt_cfg, *prompts[3:])) # type: ignore
*(
cvt_method(
cvt_mid,
out_path,
Musicreater.DEFAULT_PROGRESSBAR_STYLE if prompts[2] else None, # type: ignore
*prompts[3:],
)
)
)
if fileFormat == 0
else (
" 指令总长:{},最高延迟:{},结构大小{},终点坐标{}".format(
*(
to_BDX_file_in_score(cvt_mid, cvt_cfg, *prompts[3:])
to_BDX_file_in_score(
cvt_mid,
out_path,
Musicreater.DEFAULT_PROGRESSBAR_STYLE if prompts[2] else None,
*prompts[3:],
)
if playerFormat == 1
else to_BDX_file_in_delay(cvt_mid, cvt_cfg, *prompts[3:])
else to_BDX_file_in_delay(
cvt_mid,
out_path,
Musicreater.DEFAULT_PROGRESSBAR_STYLE if prompts[2] else None,
*prompts[3:],
)
)
)
if fileFormat == 1
else (
" 结构大小:{},延迟总数:{},指令数量:{}".format(
*(cvt_method(cvt_mid, cvt_cfg, *prompts[3:])) # type: ignore
*(
cvt_method(
cvt_mid,
out_path,
*prompts[3:],
)
if playerFormat == 2
)
)
if playerFormat == 1
else " 结构大小:{},延迟总数:{}".format(
*(cvt_method(cvt_mid, cvt_cfg, *prompts[3:])) # type: ignore
*(
cvt_method(
cvt_mid,
out_path,
# Musicreater.DEFAULT_PROGRESSBAR_STYLE if prompts[2] else None, # type: ignore
*prompts[3:],
)
)
)
)
)

View File

@ -7,7 +7,8 @@ print(
Musicreater.experiment.FutureMidiConvertM4.from_midi_file(
input("midi路径:"), old_exe_format=False
),
Musicreater.plugin.ConvertConfig(input("输出路径:"),),
input("输出路径:"),
# Musicreater.plugin.ConvertConfig(input("输出路径:"),),
max_height=32,
)
)

14
example_singleConvert.py Normal file
View File

@ -0,0 +1,14 @@
import Musicreater
import Musicreater.plugin
import Musicreater.plugin.addonpack
print(
Musicreater.plugin.addonpack.to_addon_pack_in_repeater_divided_by_instrument(
Musicreater.MidiConvert.from_midi_file(
input("midi路径:"), old_exe_format=False
),
input("输出路径:"),
# Musicreater.plugin.ConvertConfig(input("输出路径:"),),
# max_height=32,
)
)