mirror of
https://github.com/TriM-Organization/Musicreater.git
synced 2024-11-11 01:27:35 +08:00
进一步优化结构,提高插件兼容
This commit is contained in:
parent
95c0ff1b47
commit
d4925e4d75
@ -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",
|
||||
|
@ -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",),
|
||||
@ -425,7 +442,7 @@ MM_INSTRUMENT_RANGE_TABLE: Dict[str, Tuple[Tuple[int, int], int]] = {
|
||||
"note.banjo": ((42, 66), 54),
|
||||
"note.flute": ((54, 78), 66),
|
||||
"note.bass": ((18, 42), 30),
|
||||
"note.snare": ((-1, 128), 0), # 实际上是 0~127
|
||||
"note.snare": ((-1, 128), 0), # 实际上是 0~127
|
||||
"note.didgeridoo": ((18, 42), 30),
|
||||
"mob.zombie.wood": ((-1, 128), 0),
|
||||
"note.bit": ((42, 66), 54),
|
||||
@ -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] = {
|
||||
|
@ -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(
|
||||
self.execute_cmd_head.format(player_selector)
|
||||
+ r"playsound {} @s ^ ^ ^{} {} {}".format(*note.extra_info),
|
||||
tick_delay=tickdelay,
|
||||
annotation="在{}播放{}%的{}音".format(
|
||||
mctick2timestr(delaytime_now),
|
||||
max_volume * 100,
|
||||
"{}:{}".format(note.extra_info[0], note.extra_info[3]),
|
||||
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 = 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):
|
||||
|
@ -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,35 +156,28 @@ 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(
|
||||
midi=mido_file,
|
||||
speed=speed_multiplier,
|
||||
pitched_note_rtable=pitched_note_referance_table,
|
||||
percussion_note_rtable=percussion_note_referance_table,
|
||||
default_tempo_value=default_tempo,
|
||||
vol_processing_function=volume_processing_function,
|
||||
ignore_mismatch_error=mismatch_error_ignorance,
|
||||
)
|
||||
(
|
||||
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,
|
||||
percussion_note_rtable=percussion_note_referance_table,
|
||||
default_tempo_value=default_tempo,
|
||||
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(),
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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
|
||||
|
@ -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"))
|
||||
|
@ -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
|
||||
# """进度条样式组"""
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
)
|
||||
|
||||
|
||||
|
49
example.py
49
example.py
@ -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:],
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -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
14
example_singleConvert.py
Normal 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,
|
||||
)
|
||||
)
|
Loading…
Reference in New Issue
Block a user