From bbc67921d679189878e3023479d5033e8df63397 Mon Sep 17 00:00:00 2001 From: EillesWan Date: Fri, 13 Feb 2026 19:19:08 +0800 Subject: [PATCH] =?UTF-8?q?=E6=88=91=E7=9A=84=E9=80=9A=E4=B9=89=E7=81=B5?= =?UTF-8?q?=E7=A0=81=E7=BD=A2=E5=B7=A5=E4=BA=86=EF=BC=8C=E6=B2=A1=E6=9C=89?= =?UTF-8?q?=E5=86=85=E8=81=94=E5=BB=BA=E8=AE=AE=EF=BC=8C=E6=88=91=E4=B9=9F?= =?UTF-8?q?=E8=A6=81=E7=BD=A2=E5=B7=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../builtin_plugins/midi_read/__init__.py | 7 ++- Musicreater/builtin_plugins/midi_read/main.py | 1 - .../builtin_plugins/to_commands/__init__.py | 24 +++++++++ .../builtin_plugins/to_commands/main.py | 50 +++++++++++++++++++ Musicreater/exceptions.py | 9 +++- Musicreater/plugins.py | 21 +++++--- old-things/Musicreater/old_main.py | 47 +++++++++-------- 7 files changed, 128 insertions(+), 31 deletions(-) create mode 100644 Musicreater/builtin_plugins/to_commands/__init__.py create mode 100644 Musicreater/builtin_plugins/to_commands/main.py diff --git a/Musicreater/builtin_plugins/midi_read/__init__.py b/Musicreater/builtin_plugins/midi_read/__init__.py index 931bc77..eaf993b 100644 --- a/Musicreater/builtin_plugins/midi_read/__init__.py +++ b/Musicreater/builtin_plugins/midi_read/__init__.py @@ -17,4 +17,9 @@ Terms & Conditions: License.md in the root directory # 若需转载或借鉴 许可声明请查看仓库目录下的 License.md -from .main import MidiImportConfig, MidiImport2MusicPlugin \ No newline at end of file +from .main import MidiImportConfig, MidiImport2MusicPlugin + +__all__ = [ + "MidiImportConfig", + "MidiImport2MusicPlugin", +] \ No newline at end of file diff --git a/Musicreater/builtin_plugins/midi_read/main.py b/Musicreater/builtin_plugins/midi_read/main.py index cb7558e..063f3a3 100644 --- a/Musicreater/builtin_plugins/midi_read/main.py +++ b/Musicreater/builtin_plugins/midi_read/main.py @@ -41,7 +41,6 @@ from .constants import ( MM_TOUCH_PITCHED_INSTRUMENT_TABLE, ) from .exceptions import ( - MidiFormatError, NoteOnOffMismatchError, ChannelOverFlowError, LyricMismatchError, diff --git a/Musicreater/builtin_plugins/to_commands/__init__.py b/Musicreater/builtin_plugins/to_commands/__init__.py new file mode 100644 index 0000000..b98dc40 --- /dev/null +++ b/Musicreater/builtin_plugins/to_commands/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- + +""" +音·创 v3 内置的 指令生成插件 +""" + +""" +版权所有 © 2026 金羿、玉衡Alioth +Copyright © 2026 Eilles, YuhengAlioth + +开源相关声明请见 仓库根目录下的 License.md +Terms & Conditions: License.md in the root directory +""" + +# 睿乐组织 开发交流群 861684859 +# Email TriM-Organization@hotmail.com +# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md + +from .main import CommandConvertionConfig, NoteDataConvert2CommandPlugin + +__all__ = [ + "CommandConvertionConfig", + "NoteDataConvert2CommandPlugin", +] diff --git a/Musicreater/builtin_plugins/to_commands/main.py b/Musicreater/builtin_plugins/to_commands/main.py new file mode 100644 index 0000000..6583f1b --- /dev/null +++ b/Musicreater/builtin_plugins/to_commands/main.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- + +""" +音·创 v3 内置的 指令生成插件 +""" + +""" +版权所有 © 2026 金羿、玉衡Alioth +Copyright © 2026 Eilles, YuhengAlioth + +开源相关声明请见 仓库根目录下的 License.md +Terms & Conditions: License.md in the root directory +""" + +# 睿乐组织 开发交流群 861684859 +# Email TriM-Organization@hotmail.com +# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md + + +from dataclasses import dataclass +from enum import Enum +from pathlib import Path +from typing import BinaryIO, Optional, Dict, List, Callable, Tuple, Mapping + +from Musicreater import SingleMusic, SingleTrack, SingleNote, SoundAtmos +from Musicreater.plugins import ( + library_plugin, + PluginConfig, + PluginMetaInformation, + PluginTypes, + LibraryPluginBase, +) +from Musicreater.exceptions import ZeroSpeedError, IllegalMinimumVolumeError +from Musicreater._utils import enumerated_stuffcopy_dictionary + + +@dataclass +class CommandConvertionConfig(PluginConfig): ... + + +@library_plugin("notedata_2_command_plugin") +class NoteDataConvert2CommandPlugin(LibraryPluginBase): + metainfo = PluginMetaInformation( + name="音符数据指令支持插件", + author="金羿、玉衡Alioth", + description="从音符数据转换为我的世界指令相关格式", + version=(0, 0, 1), + type=PluginTypes.LIBRARY, + license="Same as Musicreater", + ) diff --git a/Musicreater/exceptions.py b/Musicreater/exceptions.py index 4eaa347..0402abb 100644 --- a/Musicreater/exceptions.py +++ b/Musicreater/exceptions.py @@ -225,12 +225,19 @@ class PluginLoadError(MusicreaterOuterlyError): super().__init__("插件加载错误 - ", *args) +class PluginDependencyNotFound(PluginLoadError): + """插件依赖未找到""" + + def __init__(self, *args): + super().__init__("未找到所需的插件依赖:", *args) + + class PluginNotFoundError(PluginLoadError): """插件未找到""" def __init__(self, *args): """插件未找到""" - super().__init__("插件未找到:", *args) + super().__init__("无法找到插件:", *args) class PluginRegisteredError(PluginLoadError): diff --git a/Musicreater/plugins.py b/Musicreater/plugins.py index c4fe912..3bd7cb3 100644 --- a/Musicreater/plugins.py +++ b/Musicreater/plugins.py @@ -33,6 +33,7 @@ from typing import ( TypeVar, Mapping, Callable, + Type, ) from itertools import chain @@ -61,6 +62,7 @@ from .exceptions import ( PluginInstanceNotFoundError, PluginRegisteredError, PluginNotFoundError, + PluginDependencyNotFound, ) @@ -147,6 +149,7 @@ class PluginRegistry: self._track_output_plugins: Dict[str, TrackOutputPluginBase] = {} self._service_plugins: Dict[str, ServicePluginBase] = {} self._library_plugins: Dict[str, LibraryPluginBase] = {} + self._all_plugin_id: List = [] def __iter__(self) -> Iterator[Tuple[PluginTypes, Mapping[str, TopPluginBase]]]: """迭代器,返回所有插件""" @@ -163,23 +166,25 @@ class PluginRegistry: ) ) - @staticmethod - def _register_plugin(cls_dict: dict, plg_class: type, plg_id: str) -> None: + def _register_plugin( + self, cls_dict: dict, plg_class: Type[TopPluginBase], plg_id: str + ) -> None: """注册插件""" if plg_id in cls_dict: if cls_dict[plg_id].metainfo.version >= plg_class.metainfo.version: raise PluginRegisteredError( - "插件惟一识别码`{}`所对应的插件已存在更高版本`{}`,请勿重复注册同一插件!".format( + "插件惟一识别码`{}`所对应的插件已存在更高版本`{}`,请勿重复注册同一插件。".format( plg_id, plg_class.metainfo ) ) + if (i for i in plg_class.metainfo.dependencies if i not in self._all_plugin_id): + raise PluginDependencyNotFound( + "插件 `{}` 依赖于这些插件:`{}`。载入此插件时,请务必将后者提前载入。" + ) cls_dict[plg_id] = plg_class() + self._all_plugin_id.append(plg_id) - def register_music_input_plugin( - self, - plugin_class: type, - plugin_id: str, - ) -> None: + def register_music_input_plugin(self, plugin_class: type, plugin_id: str) -> None: """注册输入插件-整首曲目""" self._register_plugin(self._music_input_plugins, plugin_class, plugin_id) diff --git a/old-things/Musicreater/old_main.py b/old-things/Musicreater/old_main.py index 51e985b..f8b7aea 100644 --- a/old-things/Musicreater/old_main.py +++ b/old-things/Musicreater/old_main.py @@ -37,14 +37,17 @@ from itertools import chain import mido from Musicreater.constants import * +from Musicreater.exceptions import IllegalMinimumVolumeError, NoteBinaryFileVerificationFailed as MusicSequenceVerificationFailed, SingleNoteDecodeError, NoteBinaryFileTypeError as MusicSequenceTypeError, ZeroSpeedError + +from Musicreater.builtin_plugins.midi_read.constants import MIDI_DEFAULT_PROGRAM_VALUE, MIDI_DEFAULT_VOLUME_VALUE, MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE, MM_TOUCH_PITCHED_INSTRUMENT_TABLE +from Musicreater.builtin_plugins.midi_read.exceptions import NoteOnOffMismatchError, LyricMismatchError +from Musicreater.builtin_plugins.midi_read.utils import volume_2_distance_natural, panning_2_rotation_trigonometric, panning_2_rotation_linear + + from .old_exceptions import * from .subclass import * from .old_types import * -from .utils import * - -from Musicreater.builtin_plugins.midi_read.constants import * -from Musicreater.builtin_plugins.midi_read.utils import * - +from .old_utils import * """ 学习笔记: tempo: microseconds per quarter note 毫秒每四分音符,换句话说就是一拍占多少微秒 @@ -78,6 +81,10 @@ tick * tempo / 1000000.0 / ticks_per_beat * 一秒多少游戏刻 """ +MIDI_PAN = "midi-pan" +MIDI_PROGRAM = "midi-program" +MIDI_VOLUME = "midi-volume" + @dataclass(init=False) class MusicSequence: @@ -273,7 +280,7 @@ class MusicSequence: 8 : (stt_index := 8 + (group_1 >> 10)) ].decode("GB18030") - channels_: MineNoteChannelType = enumerated_stuff_copy(staff=[]) + channels_: MineNoteChannelType = enumerated_stuffcopy_dictionary(staff=[]) total_note_count = 0 if verify: _header_index = stt_index @@ -310,9 +317,9 @@ class MusicSequence: stt_index = end_index except Exception as _err: # print(channels_) - raise MusicSequenceDecodeError( - _err, "当前全部通道数据:", channels_ - ) + raise SingleNoteDecodeError( + "当前全部通道数据:", channels_ + ) from _err if verify: if ( _count_verify := xxh3_64( @@ -415,7 +422,7 @@ class MusicSequence: _t6_buffer = _t2_buffer = 0 _channel_inst_chart: Dict[str, Dict[str, int]] = {} - channels_: MineNoteChannelType = enumerated_stuff_copy(staff=[]) + channels_: MineNoteChannelType = enumerated_stuffcopy_dictionary(staff=[]) for i in range(total_note_count): if verify: @@ -468,9 +475,9 @@ class MusicSequence: stt_index = end_index except Exception as _err: # print(bytes_buffer_in[stt_index:end_index]) - raise MusicSequenceDecodeError( - _err, "所截取的音符码:", bytes_buffer_in[stt_index:end_index] - ) + raise SingleNoteDecodeError( + "所截取的音符码:", bytes_buffer_in[stt_index:end_index] + ) from _err if _read_note.sound_name in _channel_inst_chart: _channel_inst_chart[_read_note.sound_name]["CNT"] += 1 @@ -525,7 +532,7 @@ class MusicSequence: music_name_ = bytes_buffer_in[ 8 : (stt_index := 8 + (group_1 >> 10)) ].decode("GB18030") - channels_: MineNoteChannelType = enumerated_stuff_copy(staff=[]) + channels_: MineNoteChannelType = enumerated_stuffcopy_dictionary(staff=[]) for channel_index in channels_.keys(): for i in range( int.from_bytes( @@ -568,7 +575,7 @@ class MusicSequence: music_name_ = bytes_buffer_in[ 8 : (stt_index := 8 + (group_1 >> 10)) ].decode("utf-8") - channels_: MineNoteChannelType = enumerated_stuff_copy(staff=[]) + channels_: MineNoteChannelType = enumerated_stuffcopy_dictionary(staff=[]) for channel_index in channels_.keys(): for i in range( int.from_bytes( @@ -860,9 +867,9 @@ class MusicSequence: raise ZeroSpeedError("播放速度不得为零,应为 (0,1] 范围内的实数。") # 一个midi中仅有16个通道 我们通过通道来识别而不是音轨 - midi_channels: MineNoteChannelType = enumerated_stuff_copy(staff=[]) + midi_channels: MineNoteChannelType = enumerated_stuffcopy_dictionary(staff=[]) - channel_controler: Dict[int, Dict[str, int]] = enumerated_stuff_copy( + channel_controler: Dict[int, Dict[str, int]] = enumerated_stuffcopy_dictionary( staff={ MIDI_PROGRAM: default_program_value, MIDI_VOLUME: default_volume_value, @@ -883,7 +890,7 @@ class MusicSequence: int, ] ], - ] = enumerated_stuff_copy(staff=[]) + ] = enumerated_stuffcopy_dictionary(staff=[]) note_queue_B: Dict[ int, List[ @@ -892,7 +899,7 @@ class MusicSequence: int, ] ], - ] = enumerated_stuff_copy(staff=[]) + ] = enumerated_stuffcopy_dictionary(staff=[]) lyric_cache: List[Tuple[int, str]] = [] @@ -973,7 +980,7 @@ class MusicSequence: # 更新结果信息 midi_channels[msg.channel].append( - that_note := midi_msgs_to_minenote( + that_note := midi_msgs_to_minenote( # 无法强行兼容了,pass inst_=( msg.note if (_is_percussion := (msg.channel == 9))