mirror of
https://github.com/TriM-Organization/Musicreater.git
synced 2026-04-26 19:25:38 +00:00
完美,同志,完美!!!!!!!
This commit is contained in:
1254
old-things/Musicreater/experiment.py
Normal file
1254
old-things/Musicreater/experiment.py
Normal file
File diff suppressed because it is too large
Load Diff
265
old-things/Musicreater/magicmain.py
Normal file
265
old-things/Musicreater/magicmain.py
Normal file
@@ -0,0 +1,265 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
功能测试 若非已知 请勿更改
|
||||
此文件仅供功能测试,并非实际调用的文件
|
||||
请注意,此处的文件均为测试使用
|
||||
不要更改 不要更改 不要更改
|
||||
请注意这里的一切均需要其原作者更改
|
||||
这里用于放置一些新奇的点子
|
||||
用于测试
|
||||
不要更改 不要更改 不要更改!
|
||||
"""
|
||||
|
||||
# 音·创 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 版权所有 金羿("Eilles") & 诸葛亮与八卦阵("bgArray") & 鸣凤鸽子("MingFengPigeon")
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
|
||||
"""
|
||||
音·创 (Musicreater)
|
||||
是一款免费开源的针对《我的世界》的midi音乐转换库
|
||||
Musicreater (音·创)
|
||||
A free open source library used for convert midi file into formats that is suitable for **Minecraft**.
|
||||
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 ../License.md
|
||||
Terms & Conditions: ../License.md
|
||||
"""
|
||||
|
||||
|
||||
# ============================
|
||||
|
||||
|
||||
import mido
|
||||
|
||||
|
||||
class NoteMessage:
|
||||
def __init__(
|
||||
self, channel, pitch, velocity, startT, lastT, midi, now_bpm, change_bpm=None
|
||||
):
|
||||
self.channel = channel
|
||||
self.note = pitch
|
||||
self.velocity = velocity
|
||||
self.startTime = startT
|
||||
self.lastTime = lastT
|
||||
self.tempo = now_bpm # 这里要程序实现获取bpm可以参考我的程序
|
||||
|
||||
def mt2gt(mt, tpb_a, bpm_a):
|
||||
return mt / tpb_a / bpm_a * 60
|
||||
|
||||
self.startTrueTime = mt2gt(
|
||||
self.startTime, midi.ticks_per_beat, self.tempo
|
||||
) # / 20
|
||||
# delete_extra_zero(round_up())
|
||||
if change_bpm is not None:
|
||||
self.lastTrueTime = mt2gt(
|
||||
self.lastTime, midi.ticks_per_beat, change_bpm
|
||||
) # / 20
|
||||
else:
|
||||
self.lastTrueTime = mt2gt(
|
||||
self.lastTime, midi.ticks_per_beat, self.tempo
|
||||
) # / 20
|
||||
# delete_extra_zero(round_up())
|
||||
print((self.startTime * self.tempo) / (midi.ticks_per_beat * 50000))
|
||||
|
||||
def __str__(self):
|
||||
return (
|
||||
"noteMessage channel="
|
||||
+ str(self.channel)
|
||||
+ " note="
|
||||
+ str(self.note)
|
||||
+ " velocity="
|
||||
+ str(self.velocity)
|
||||
+ " startTime="
|
||||
+ str(self.startTime)
|
||||
+ " lastTime="
|
||||
+ str(self.lastTime)
|
||||
+ " startTrueTime="
|
||||
+ str(self.startTrueTime)
|
||||
+ " lastTrueTime="
|
||||
+ str(self.lastTrueTime)
|
||||
)
|
||||
|
||||
|
||||
def load(mid: mido.MidiFile):
|
||||
|
||||
type_ = [False, False, False] # note_off / note_on+0 / mixed
|
||||
|
||||
is_tempo = False
|
||||
|
||||
# 预检
|
||||
for i, track in enumerate(mid.tracks):
|
||||
for msg in track:
|
||||
# print(msg)
|
||||
if msg.is_meta is not True:
|
||||
if msg.type == "note_on" and msg.velocity == 0:
|
||||
type_[1] = True
|
||||
elif msg.type == "note_off":
|
||||
type_[0] = True
|
||||
if msg.is_meta is True and msg.type == "set_tempo":
|
||||
is_tempo = True
|
||||
|
||||
if is_tempo is not True:
|
||||
raise Exception("这个mid没有可供计算时间的tempo事件")
|
||||
|
||||
if type_[0] is True and type_[1] is True:
|
||||
type_[2] = True
|
||||
type_[1] = False
|
||||
type_[0] = False
|
||||
print(type_)
|
||||
|
||||
bpm = 0
|
||||
recent_change_bpm = 0
|
||||
is_change_bpm = False
|
||||
# 实检
|
||||
for i, track in enumerate(mid.tracks):
|
||||
noteOn = []
|
||||
trackS = []
|
||||
ticks = 0
|
||||
for msg in track:
|
||||
print(msg)
|
||||
ticks += msg.time
|
||||
print(ticks)
|
||||
if msg.is_meta is True and msg.type == "set_tempo":
|
||||
recent_change_bpm = bpm
|
||||
bpm = 60000000 / msg.tempo
|
||||
is_change_bpm = True
|
||||
|
||||
if msg.type == "note_on" and msg.velocity != 0:
|
||||
noteOn.append([msg, msg.note, ticks])
|
||||
if type_[1] is True:
|
||||
if msg.type == "note_on" and msg.velocity == 0:
|
||||
for u in noteOn:
|
||||
index = 0
|
||||
if u[1] == msg.note:
|
||||
lastMessage = u[0]
|
||||
lastTick = u[2]
|
||||
break
|
||||
index += 1
|
||||
print(lastTick)
|
||||
if is_change_bpm and recent_change_bpm != 0:
|
||||
trackS.append(
|
||||
NoteMessage(
|
||||
msg.channel,
|
||||
msg.note,
|
||||
lastMessage.velocity,
|
||||
lastTick,
|
||||
ticks - lastTick,
|
||||
mid,
|
||||
recent_change_bpm,
|
||||
bpm,
|
||||
)
|
||||
)
|
||||
is_change_bpm = False
|
||||
else:
|
||||
trackS.append(
|
||||
NoteMessage(
|
||||
msg.channel,
|
||||
msg.note,
|
||||
lastMessage.velocity,
|
||||
lastTick,
|
||||
ticks - lastTick,
|
||||
mid,
|
||||
bpm,
|
||||
)
|
||||
)
|
||||
# print(noteOn)
|
||||
# print(index)
|
||||
try:
|
||||
noteOn.pop(index)
|
||||
except IndexError:
|
||||
noteOn.pop(index - 1)
|
||||
print(trackS)
|
||||
for j in trackS:
|
||||
print(j)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
load(mido.MidiFile("test.mid"))
|
||||
|
||||
|
||||
# ============================
|
||||
from typing import Literal
|
||||
|
||||
from ..constants import x, y, z
|
||||
|
||||
|
||||
# 不要用 没写完
|
||||
def delay_to_note_blocks(
|
||||
baseblock: str = "stone",
|
||||
position_forward: Literal["x", "y", "z"] = z,
|
||||
):
|
||||
"""传入音符,生成以音符盒存储的红石音乐
|
||||
:param:
|
||||
baseblock: 中继器的下垫方块
|
||||
position_forward: 结构延长方向
|
||||
:return 是否生成成功
|
||||
"""
|
||||
|
||||
from TrimMCStruct import Block, Structure
|
||||
|
||||
struct = Structure(
|
||||
(_sideLength, max_height, _sideLength), # 声明结构大小
|
||||
)
|
||||
|
||||
log = print
|
||||
|
||||
startpos = [0, 0, 0]
|
||||
|
||||
# 1拍 x 2.5 rt
|
||||
for i in notes:
|
||||
error = True
|
||||
try:
|
||||
struct.set_block(
|
||||
[startpos[0], startpos[1] + 1, startpos[2]],
|
||||
form_note_block_in_NBT_struct(height2note[i[0]], instrument),
|
||||
)
|
||||
struct.set_block(
|
||||
startpos,
|
||||
Block("universal_minecraft", instuments[i[0]][1]),
|
||||
)
|
||||
error = False
|
||||
except ValueError:
|
||||
log("无法放置音符:" + str(i) + "于" + str(startpos))
|
||||
struct.set_block(Block("universal_minecraft", baseblock), startpos)
|
||||
struct.set_block(
|
||||
Block("universal_minecraft", baseblock),
|
||||
[startpos[0], startpos[1] + 1, startpos[2]],
|
||||
)
|
||||
finally:
|
||||
if error is True:
|
||||
log("无法放置音符:" + str(i) + "于" + str(startpos))
|
||||
struct.set_block(Block("universal_minecraft", baseblock), startpos)
|
||||
struct.set_block(
|
||||
Block("universal_minecraft", baseblock),
|
||||
[startpos[0], startpos[1] + 1, startpos[2]],
|
||||
)
|
||||
delay = int(i[1] * speed + 0.5)
|
||||
if delay <= 4:
|
||||
startpos[0] += 1
|
||||
struct.set_block(
|
||||
form_repeater_in_NBT_struct(delay, "west"),
|
||||
[startpos[0], startpos[1] + 1, startpos[2]],
|
||||
)
|
||||
struct.set_block(Block("universal_minecraft", baseblock), startpos)
|
||||
else:
|
||||
for j in range(int(delay / 4)):
|
||||
startpos[0] += 1
|
||||
struct.set_block(
|
||||
form_repeater_in_NBT_struct(4, "west"),
|
||||
[startpos[0], startpos[1] + 1, startpos[2]],
|
||||
)
|
||||
struct.set_block(Block("universal_minecraft", baseblock), startpos)
|
||||
if delay % 4 != 0:
|
||||
startpos[0] += 1
|
||||
struct.set_block(
|
||||
form_repeater_in_NBT_struct(delay % 4, "west"),
|
||||
[startpos[0], startpos[1] + 1, startpos[2]],
|
||||
)
|
||||
struct.set_block(Block("universal_minecraft", baseblock), startpos)
|
||||
startpos[0] += posadder[0]
|
||||
startpos[1] += posadder[1]
|
||||
startpos[2] += posadder[2]
|
||||
165
old-things/Musicreater/old_exceptions.py
Normal file
165
old-things/Musicreater/old_exceptions.py
Normal file
@@ -0,0 +1,165 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
存放一些报错类型
|
||||
"""
|
||||
|
||||
"""
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 仓库根目录下的 License.md
|
||||
Terms & Conditions: License.md in the root directory
|
||||
"""
|
||||
|
||||
# 睿乐组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
|
||||
class MSCTBaseException(Exception):
|
||||
"""音·创 的所有错误均继承于此"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""音·创 的所有错误均继承于此"""
|
||||
super().__init__("音·创", *args)
|
||||
|
||||
def meow(
|
||||
self,
|
||||
):
|
||||
for i in self.args:
|
||||
print(i + "喵!")
|
||||
|
||||
def crash_it(self):
|
||||
raise self
|
||||
|
||||
|
||||
class MidiFormatException(MSCTBaseException):
|
||||
"""音·创 的所有MIDI格式错误均继承于此"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""音·创 的所有MIDI格式错误均继承于此"""
|
||||
super().__init__("MIDI 格式错误", *args)
|
||||
|
||||
|
||||
class MidiDestroyedError(MSCTBaseException):
|
||||
"""Midi文件损坏"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""Midi文件损坏"""
|
||||
super().__init__("MIDI文件损坏:无法读取 MIDI 文件", *args)
|
||||
|
||||
|
||||
# class MidiUnboundError(MSCTBaseException):
|
||||
# """未定义Midi对象(无用)"""
|
||||
|
||||
# def __init__(self, *args):
|
||||
# """未绑定Midi对象"""
|
||||
# super().__init__("未定义MidiFile对象:你甚至没有对象就想要生孩子?", *args)
|
||||
# 此错误在本版本内已经不再使用
|
||||
|
||||
|
||||
class CommandFormatError(MSCTBaseException, RuntimeError):
|
||||
"""指令格式与目标格式不匹配而引起的错误"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""指令格式与目标格式不匹配而引起的错误"""
|
||||
super().__init__("指令格式不匹配", *args)
|
||||
|
||||
|
||||
# class CrossNoteError(MidiFormatException):
|
||||
# """同通道下同音符交叉出现所产生的错误"""
|
||||
|
||||
# def __init__(self, *args):
|
||||
# """同通道下同音符交叉出现所产生的错误"""
|
||||
# super().__init__("同通道下同音符交叉", *args)
|
||||
# 这TM是什么错误?
|
||||
# 我什么时候写的这玩意?
|
||||
# 我哪知道这说的是啥?
|
||||
# !!!
|
||||
# 我知道这是什么了 —— 金羿 2025 0401
|
||||
# 两个其他属性相同的音符在同一个通道,出现连续两个开音信息和连续两个停止信息
|
||||
# 那么这两个音符的音长无法判断。这是个好问题,但是不是我现在能解决的,也不是我们现在想解决的问题
|
||||
|
||||
|
||||
class NotDefineTempoError(MidiFormatException):
|
||||
"""没有Tempo设定导致时间无法计算的错误"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""没有Tempo设定导致时间无法计算的错误"""
|
||||
super().__init__("在曲目开始时没有声明 Tempo(未指定拍长)", *args)
|
||||
|
||||
|
||||
class ChannelOverFlowError(MidiFormatException):
|
||||
"""一个midi中含有过多的通道"""
|
||||
|
||||
def __init__(self, max_channel=16, *args):
|
||||
"""一个midi中含有过多的通道"""
|
||||
super().__init__("含有过多的通道(数量应≤{})".format(max_channel), *args)
|
||||
|
||||
|
||||
class NotDefineProgramError(MidiFormatException):
|
||||
"""没有Program设定导致没有乐器可以选择的错误"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""没有Program设定导致没有乐器可以选择的错误"""
|
||||
super().__init__("未指定演奏乐器", *args)
|
||||
|
||||
|
||||
class NoteOnOffMismatchError(MidiFormatException):
|
||||
"""音符开音和停止不匹配的错误"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""音符开音和停止不匹配的错误"""
|
||||
super().__init__("音符不匹配", *args)
|
||||
|
||||
|
||||
class LyricMismatchError(MSCTBaseException):
|
||||
"""歌词匹配解析错误"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""有可能产生了错误的歌词解析"""
|
||||
super().__init__("歌词解析错误", *args)
|
||||
|
||||
# 已重构
|
||||
class ZeroSpeedError(MSCTBaseException, ZeroDivisionError):
|
||||
"""以0作为播放速度的错误"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""以0作为播放速度的错误"""
|
||||
super().__init__("播放速度为零", *args)
|
||||
|
||||
# 已重构
|
||||
class IllegalMinimumVolumeError(MSCTBaseException, ValueError):
|
||||
"""最小播放音量有误的错误"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""最小播放音量错误"""
|
||||
super().__init__("最小播放音量超出范围", *args)
|
||||
|
||||
|
||||
# 已重构
|
||||
class MusicSequenceDecodeError(MSCTBaseException):
|
||||
"""音乐序列解码错误"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""音乐序列无法正确解码的错误"""
|
||||
super().__init__("解码音符序列文件时出现问题", *args)
|
||||
|
||||
|
||||
# 已重构
|
||||
class MusicSequenceTypeError(MSCTBaseException):
|
||||
"""音乐序列类型错误"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""无法识别音符序列字节码的类型"""
|
||||
super().__init__("错误的音符序列字节类型", *args)
|
||||
|
||||
|
||||
# 已重构
|
||||
class MusicSequenceVerificationFailed(MusicSequenceDecodeError):
|
||||
"""音乐序列校验失败"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""音符序列文件与其校验值不一致"""
|
||||
super().__init__("音符序列文件校验失败", *args)
|
||||
144
old-things/Musicreater/old_init.py
Normal file
144
old-things/Musicreater/old_init.py
Normal file
@@ -0,0 +1,144 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""一个简单的我的世界音频转换库
|
||||
音·创 (Musicreater)
|
||||
是一款免费开源的《我的世界》数字音频支持库。
|
||||
Musicreater(音·创)
|
||||
A free open source library used for dealing with **Minecraft** digital musics.
|
||||
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
音·创(“本项目”)的协议颁发者为 金羿、诸葛亮与八卦阵
|
||||
The Licensor of Musicreater("this project") is Eilles, bgArray.
|
||||
|
||||
本项目根据 第一版 汉钰律许可协议(“本协议”)授权。
|
||||
任何人皆可从以下地址获得本协议副本:https://gitee.com/EillesWan/YulvLicenses。
|
||||
若非因法律要求或经过了特殊准许,此作品在根据本协议“原样”提供的基础上,不予提供任何形式的担保、任何明示、任何暗示或类似承诺。也就是说,用户将自行承担因此作品的质量或性能问题而产生的全部风险。
|
||||
详细的准许和限制条款请见原协议文本。
|
||||
"""
|
||||
|
||||
# 睿乐组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
|
||||
__version__ = "2.4.2.3"
|
||||
__vername__ = "音符附加信息升级"
|
||||
__author__ = (
|
||||
("金羿", "Eilles"),
|
||||
("诸葛亮与八卦阵", "bgArray"),
|
||||
("鱼旧梦", "ElapsingDreams"),
|
||||
("偷吃不是Touch", "Touch"),
|
||||
)
|
||||
__all__ = [
|
||||
# 主要类
|
||||
"MusicSequence",
|
||||
"MidiConvert",
|
||||
# 附加类
|
||||
# "SingleNote",
|
||||
"MineNote",
|
||||
"MineCommand",
|
||||
"SingleNoteBox",
|
||||
"ProgressBarStyle",
|
||||
# "TimeStamp", 未来功能
|
||||
# 字典键
|
||||
"MIDI_PROGRAM",
|
||||
"MIDI_VOLUME",
|
||||
"MIDI_PAN",
|
||||
# 默认值
|
||||
"MIDI_DEFAULT_PROGRAM_VALUE",
|
||||
"MIDI_DEFAULT_VOLUME_VALUE",
|
||||
"DEFAULT_PROGRESSBAR_STYLE",
|
||||
# Midi 自己的对照表
|
||||
"MIDI_PITCH_NAME_TABLE",
|
||||
"MIDI_PITCHED_NOTE_NAME_GROUP",
|
||||
"MIDI_PITCHED_NOTE_NAME_TABLE",
|
||||
"MIDI_PERCUSSION_NOTE_NAME_TABLE",
|
||||
# Minecraft 自己的对照表
|
||||
"MC_PERCUSSION_INSTRUMENT_LIST",
|
||||
"MC_PITCHED_INSTRUMENT_LIST",
|
||||
"MC_INSTRUMENT_BLOCKS_TABLE",
|
||||
"MC_EILLES_RTJE12_INSTRUMENT_REPLACE_TABLE",
|
||||
"MC_EILLES_RTBETA_INSTRUMENT_REPLACE_TABLE",
|
||||
# Midi 与 游戏 的对照表
|
||||
"MM_INSTRUMENT_RANGE_TABLE",
|
||||
"MM_INSTRUMENT_DEVIATION_TABLE",
|
||||
"MM_CLASSIC_PITCHED_INSTRUMENT_TABLE",
|
||||
"MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE",
|
||||
"MM_TOUCH_PITCHED_INSTRUMENT_TABLE",
|
||||
"MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE",
|
||||
"MM_DISLINK_PITCHED_INSTRUMENT_TABLE",
|
||||
"MM_DISLINK_PERCUSSION_INSTRUMENT_TABLE",
|
||||
"MM_NBS_PITCHED_INSTRUMENT_TABLE",
|
||||
"MM_NBS_PERCUSSION_INSTRUMENT_TABLE",
|
||||
# 操作性函数
|
||||
"velocity_2_distance_natural",
|
||||
"velocity_2_distance_straight",
|
||||
"panning_2_rotation_linear",
|
||||
"panning_2_rotation_trigonometric",
|
||||
# 工具函数
|
||||
"load_decode_musicsequence_metainfo",
|
||||
"load_decode_msq_flush_release",
|
||||
"load_decode_fsq_flush_release",
|
||||
"guess_deviation",
|
||||
"mctick2timestr",
|
||||
"midi_inst_to_mc_sound",
|
||||
]
|
||||
|
||||
from .old_main import MusicSequence, MidiConvert
|
||||
|
||||
from .subclass import (
|
||||
MineNote,
|
||||
MineCommand,
|
||||
SingleNoteBox,
|
||||
ProgressBarStyle,
|
||||
mctick2timestr,
|
||||
DEFAULT_PROGRESSBAR_STYLE,
|
||||
)
|
||||
|
||||
from .utils import (
|
||||
# 兼容性函数
|
||||
load_decode_musicsequence_metainfo,
|
||||
load_decode_msq_flush_release,
|
||||
load_decode_fsq_flush_release,
|
||||
# 工具函数
|
||||
guess_deviation,
|
||||
midi_inst_to_mc_sound,
|
||||
# 处理用函数
|
||||
velocity_2_distance_natural,
|
||||
velocity_2_distance_straight,
|
||||
panning_2_rotation_linear,
|
||||
panning_2_rotation_trigonometric,
|
||||
)
|
||||
|
||||
from .constants import (
|
||||
# 字典键
|
||||
MIDI_PROGRAM,
|
||||
MIDI_PAN,
|
||||
MIDI_VOLUME,
|
||||
# 默认值
|
||||
MIDI_DEFAULT_PROGRAM_VALUE,
|
||||
MIDI_DEFAULT_VOLUME_VALUE,
|
||||
# MIDI 表
|
||||
MIDI_PITCH_NAME_TABLE,
|
||||
MIDI_PITCHED_NOTE_NAME_GROUP,
|
||||
MIDI_PITCHED_NOTE_NAME_TABLE,
|
||||
MIDI_PERCUSSION_NOTE_NAME_TABLE,
|
||||
# 我的世界 表
|
||||
MC_EILLES_RTBETA_INSTRUMENT_REPLACE_TABLE,
|
||||
MC_EILLES_RTJE12_INSTRUMENT_REPLACE_TABLE,
|
||||
MC_INSTRUMENT_BLOCKS_TABLE,
|
||||
MC_PERCUSSION_INSTRUMENT_LIST,
|
||||
MC_PITCHED_INSTRUMENT_LIST,
|
||||
# MIDI 到 我的世界 表
|
||||
MM_INSTRUMENT_RANGE_TABLE,
|
||||
MM_INSTRUMENT_DEVIATION_TABLE,
|
||||
MM_CLASSIC_PITCHED_INSTRUMENT_TABLE,
|
||||
MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE,
|
||||
MM_TOUCH_PITCHED_INSTRUMENT_TABLE,
|
||||
MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE,
|
||||
MM_DISLINK_PITCHED_INSTRUMENT_TABLE,
|
||||
MM_DISLINK_PERCUSSION_INSTRUMENT_TABLE,
|
||||
MM_NBS_PITCHED_INSTRUMENT_TABLE,
|
||||
MM_NBS_PERCUSSION_INSTRUMENT_TABLE,
|
||||
)
|
||||
1816
old-things/Musicreater/old_main.py
Normal file
1816
old-things/Musicreater/old_main.py
Normal file
File diff suppressed because it is too large
Load Diff
73
old-things/Musicreater/old_plugin/__init__.py
Normal file
73
old-things/Musicreater/old_plugin/__init__.py
Normal file
@@ -0,0 +1,73 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
存放非音·创本体的附加功能件
|
||||
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 仓库根目录下的 License.md
|
||||
Terms & Conditions: License.md in the root directory
|
||||
"""
|
||||
|
||||
# 睿乐组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
|
||||
__all__ = [
|
||||
# 通用
|
||||
# "ConvertConfig",
|
||||
"bottem_side_length_of_smallest_square_bottom_box",
|
||||
# 打包
|
||||
"compress_zipfile",
|
||||
"behavior_mcpack_manifest",
|
||||
# MCSTRUCTURE 函数
|
||||
"antiaxis",
|
||||
"forward_IER",
|
||||
"command_statevalue",
|
||||
"form_note_block_in_NBT_struct",
|
||||
"form_repeater_in_NBT_struct",
|
||||
"form_command_block_in_NBT_struct",
|
||||
"commands_to_structure",
|
||||
"commands_to_redstone_delay_structure",
|
||||
# MCSTRUCTURE 常量
|
||||
"AXIS_PARTICULAR_VALUE",
|
||||
"COMPABILITY_VERSION_117",
|
||||
"COMPABILITY_VERSION_119",
|
||||
"COMPABILITY_VERSION_121",
|
||||
# BDX 函数
|
||||
"bdx_move",
|
||||
"form_command_block_in_BDX_bytes",
|
||||
"commands_to_BDX_bytes",
|
||||
# BDX 常量
|
||||
"BDX_MOVE_KEY",
|
||||
]
|
||||
__author__ = (("金羿", "Eilles"), ("诸葛亮与八卦阵", "bgArray"))
|
||||
|
||||
# from .main import ConvertConfig
|
||||
|
||||
from .archive import compress_zipfile, behavior_mcpack_manifest
|
||||
|
||||
from .bdx import (
|
||||
BDX_MOVE_KEY,
|
||||
bdx_move,
|
||||
form_command_block_in_BDX_bytes,
|
||||
commands_to_BDX_bytes,
|
||||
)
|
||||
|
||||
from .common import bottem_side_length_of_smallest_square_bottom_box
|
||||
|
||||
from .mcstructure import (
|
||||
antiaxis,
|
||||
forward_IER,
|
||||
AXIS_PARTICULAR_VALUE,
|
||||
COMPABILITY_VERSION_119,
|
||||
COMPABILITY_VERSION_117,
|
||||
COMPABILITY_VERSION_121,
|
||||
command_statevalue,
|
||||
form_note_block_in_NBT_struct,
|
||||
form_repeater_in_NBT_struct,
|
||||
form_command_block_in_NBT_struct,
|
||||
commands_to_structure,
|
||||
commands_to_redstone_delay_structure,
|
||||
)
|
||||
30
old-things/Musicreater/old_plugin/addonpack/__init__.py
Normal file
30
old-things/Musicreater/old_plugin/addonpack/__init__.py
Normal file
@@ -0,0 +1,30 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
用以生成附加包的附加功能
|
||||
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 仓库根目录下的 License.md
|
||||
Terms & Conditions: License.md in the root directory
|
||||
"""
|
||||
|
||||
# 睿乐组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
|
||||
__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"),)
|
||||
|
||||
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,
|
||||
)
|
||||
684
old-things/Musicreater/old_plugin/addonpack/main.py
Normal file
684
old-things/Musicreater/old_plugin/addonpack/main.py
Normal file
@@ -0,0 +1,684 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 仓库根目录下的 License.md
|
||||
Terms & Conditions: License.md in the root directory
|
||||
"""
|
||||
|
||||
# 睿乐组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
from typing import Literal, Optional, Tuple
|
||||
|
||||
from ...old_main import MidiConvert
|
||||
from ...subclass import ProgressBarStyle
|
||||
from ..archive import behavior_mcpack_manifest, compress_zipfile
|
||||
from ..mcstructure import (
|
||||
COMPABILITY_VERSION_117,
|
||||
COMPABILITY_VERSION_119,
|
||||
Structure,
|
||||
commands_to_redstone_delay_structure,
|
||||
commands_to_structure,
|
||||
form_command_block_in_NBT_struct,
|
||||
)
|
||||
|
||||
|
||||
def to_addon_pack_in_score(
|
||||
midi_cvt: MidiConvert,
|
||||
dist_path: str,
|
||||
progressbar_style: Optional[ProgressBarStyle],
|
||||
scoreboard_name: str = "mscplay",
|
||||
auto_reset: bool = False,
|
||||
) -> Tuple[int, int]:
|
||||
"""
|
||||
将midi以计分播放器形式转换为我的世界函数附加包
|
||||
|
||||
Parameters
|
||||
----------
|
||||
midi_cvt: MidiConvert 对象
|
||||
用于转换的MidiConvert对象
|
||||
dist_path: str
|
||||
转换结果输出的目标路径
|
||||
progressbar_style: ProgressBarStyle 对象
|
||||
进度条对象
|
||||
scoreboard_name: str
|
||||
我的世界的计分板名称
|
||||
auto_reset: bool
|
||||
是否自动重置计分板
|
||||
|
||||
Returns
|
||||
-------
|
||||
tuple[int指令数量, int音乐总延迟]
|
||||
"""
|
||||
|
||||
cmdlist, maxlen, maxscore = midi_cvt.to_command_list_in_score(
|
||||
scoreboard_name=scoreboard_name,
|
||||
)
|
||||
|
||||
# 当文件f夹{self.outputPath}/temp/functions存在时清空其下所有项目,然后创建
|
||||
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"{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) 计分播放器 - 由 音·创 生成",
|
||||
pack_name=midi_cvt.music_name + "播放",
|
||||
modules_description=f"无 - 由 音·创 生成",
|
||||
format_version=1 if midi_cvt.enable_old_exe_format else 2,
|
||||
pack_engine_version=(
|
||||
None if midi_cvt.enable_old_exe_format else [1, 19, 50]
|
||||
),
|
||||
),
|
||||
fp=f,
|
||||
indent=4,
|
||||
)
|
||||
|
||||
# 写入stop.mcfunction
|
||||
with open(
|
||||
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"{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"{dist_path}/temp/functions/mscplay/track{i + 1}.mcfunction",
|
||||
"w",
|
||||
encoding="utf-8",
|
||||
) as f:
|
||||
f.write("\n".join([single_cmd.cmd for single_cmd in cmdlist[i]]))
|
||||
index_file.writelines(
|
||||
(
|
||||
"scoreboard players add @a[scores={"
|
||||
+ scoreboard_name
|
||||
+ "=1..}] "
|
||||
+ scoreboard_name
|
||||
+ " 1\n",
|
||||
(
|
||||
(
|
||||
"scoreboard players reset @a[scores={"
|
||||
+ scoreboard_name
|
||||
+ "="
|
||||
+ str(maxscore + 20)
|
||||
+ "..}]"
|
||||
+ f" {scoreboard_name}\n"
|
||||
)
|
||||
if auto_reset
|
||||
else ""
|
||||
),
|
||||
f"function mscplay/progressShow\n" if progressbar_style else "",
|
||||
)
|
||||
)
|
||||
|
||||
if progressbar_style:
|
||||
with open(
|
||||
f"{dist_path}/temp/functions/mscplay/progressShow.mcfunction",
|
||||
"w",
|
||||
encoding="utf-8",
|
||||
) as f:
|
||||
f.writelines(
|
||||
"\n".join(
|
||||
[
|
||||
single_cmd.cmd
|
||||
for single_cmd in midi_cvt.form_progress_bar(
|
||||
maxscore, scoreboard_name, progressbar_style
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
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}[score].mcpack",
|
||||
)
|
||||
|
||||
shutil.rmtree(f"{dist_path}/temp/")
|
||||
|
||||
return maxlen, maxscore
|
||||
|
||||
|
||||
def to_addon_pack_in_delay(
|
||||
midi_cvt: MidiConvert,
|
||||
dist_path: str,
|
||||
progressbar_style: Optional[ProgressBarStyle],
|
||||
player: str = "@a",
|
||||
max_height: int = 64,
|
||||
) -> Tuple[int, int]:
|
||||
"""
|
||||
将midi以延迟播放器形式转换为mcstructure结构文件后打包成附加包,并在附加包中生成相应地导入函数
|
||||
|
||||
Parameters
|
||||
----------
|
||||
midi_cvt: MidiConvert 对象
|
||||
用于转换的MidiConvert对象
|
||||
dist_path: str
|
||||
转换结果输出的目标路径
|
||||
progressbar_style: ProgressBarStyle 对象
|
||||
进度条对象
|
||||
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
|
||||
)
|
||||
|
||||
command_list, max_delay = midi_cvt.to_command_list_in_delay(
|
||||
player_selector=player,
|
||||
)[:2]
|
||||
|
||||
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"无 - 由 音·创 生成",
|
||||
format_version=1 if midi_cvt.enable_old_exe_format else 2,
|
||||
pack_engine_version=(
|
||||
None if midi_cvt.enable_old_exe_format else [1, 19, 50]
|
||||
),
|
||||
),
|
||||
fp=f,
|
||||
indent=4,
|
||||
ensure_ascii=False,
|
||||
)
|
||||
|
||||
# 写入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"
|
||||
)
|
||||
|
||||
struct, size, end_pos = commands_to_structure(
|
||||
command_list,
|
||||
max_height - 1,
|
||||
compability_version_=compability_ver,
|
||||
)
|
||||
with open(
|
||||
os.path.abspath(
|
||||
os.path.join(
|
||||
dist_path,
|
||||
"temp/structures/",
|
||||
f"{midi_cvt.music_name}_main.mcstructure",
|
||||
)
|
||||
),
|
||||
"wb+",
|
||||
) as f:
|
||||
struct.dump(f)
|
||||
|
||||
del struct
|
||||
|
||||
if progressbar_style:
|
||||
scb_name = midi_cvt.music_name[:3] + "Pgb"
|
||||
index_file.write("scoreboard objectives add {0} dummy {0}计\n".format(scb_name))
|
||||
|
||||
struct_a = Structure((1, 1, 1), compability_version=compability_ver)
|
||||
struct_a.set_block(
|
||||
(0, 0, 0),
|
||||
form_command_block_in_NBT_struct(
|
||||
r"scoreboard players add {} {} 1".format(player, scb_name),
|
||||
(0, 0, 0),
|
||||
1,
|
||||
1,
|
||||
alwaysRun=False,
|
||||
customName="显示进度条并加分",
|
||||
compability_version_number=compability_ver,
|
||||
),
|
||||
)
|
||||
|
||||
with open(
|
||||
os.path.abspath(
|
||||
os.path.join(
|
||||
dist_path,
|
||||
"temp/structures/",
|
||||
f"{midi_cvt.music_name}_start.mcstructure",
|
||||
)
|
||||
),
|
||||
"wb+",
|
||||
) as f:
|
||||
struct_a.dump(f)
|
||||
|
||||
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, progressbar_style),
|
||||
max_height - 1,
|
||||
compability_version_=compability_ver,
|
||||
)
|
||||
|
||||
with open(
|
||||
os.path.abspath(
|
||||
os.path.join(
|
||||
dist_path,
|
||||
"temp/structures/",
|
||||
f"{midi_cvt.music_name}_pgb.mcstructure",
|
||||
)
|
||||
),
|
||||
"wb+",
|
||||
) as f:
|
||||
pgb_struct.dump(f)
|
||||
|
||||
index_file.write(f"structure load {midi_cvt.music_name}_pgb ~ ~1 ~1\n")
|
||||
|
||||
struct_a = Structure(
|
||||
(1, 1, 1),
|
||||
)
|
||||
struct_a.set_block(
|
||||
(0, 0, 0),
|
||||
form_command_block_in_NBT_struct(
|
||||
r"scoreboard players reset {} {}".format(player, scb_name),
|
||||
(0, 0, 0),
|
||||
1,
|
||||
0,
|
||||
alwaysRun=False,
|
||||
customName="重置进度条计分板",
|
||||
compability_version_number=compability_ver,
|
||||
),
|
||||
)
|
||||
|
||||
with open(
|
||||
os.path.abspath(
|
||||
os.path.join(
|
||||
dist_path,
|
||||
"temp/structures/",
|
||||
f"{midi_cvt.music_name}_reset.mcstructure",
|
||||
)
|
||||
),
|
||||
"wb+",
|
||||
) as f:
|
||||
struct_a.dump(f)
|
||||
|
||||
del struct_a, pgb_struct
|
||||
|
||||
index_file.write(
|
||||
f"structure load {midi_cvt.music_name}_reset ~{pgbSize[0] + 2} ~ ~1\n"
|
||||
)
|
||||
|
||||
index_file.write(
|
||||
f"structure load {midi_cvt.music_name}_main ~{pgbSize[0] + 2} ~1 ~1\n"
|
||||
)
|
||||
|
||||
else:
|
||||
index_file.write(f"structure load {midi_cvt.music_name}_main ~ ~ ~1\n")
|
||||
|
||||
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}[delay].mcpack",
|
||||
)
|
||||
|
||||
shutil.rmtree(f"{dist_path}/temp/")
|
||||
|
||||
return len(command_list), max_delay
|
||||
|
||||
|
||||
def to_addon_pack_in_repeater(
|
||||
midi_cvt: MidiConvert,
|
||||
dist_path: str,
|
||||
progressbar_style: Optional[ProgressBarStyle],
|
||||
player: str = "@a",
|
||||
axis_side: Literal["z+", "z-", "Z+", "Z-", "x+", "x-", "X+", "X-"] = "z+",
|
||||
basement_block: str = "concrete",
|
||||
max_height: int = 65,
|
||||
) -> Tuple[int, int]:
|
||||
"""
|
||||
将midi以中继器播放器形式转换为mcstructure结构文件后打包成附加包,并在附加包中生成相应地导入函数
|
||||
|
||||
Parameters
|
||||
----------
|
||||
midi_cvt: MidiConvert 对象
|
||||
用于转换的MidiConvert对象
|
||||
dist_path: str
|
||||
转换结果输出的目标路径
|
||||
progressbar_style: ProgressBarStyle 对象
|
||||
进度条对象
|
||||
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
|
||||
)
|
||||
|
||||
command_list, max_delay, max_together = midi_cvt.to_command_list_in_delay(
|
||||
player_selector=player,
|
||||
)
|
||||
|
||||
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"无 - 由 音·创 生成",
|
||||
format_version=1 if midi_cvt.enable_old_exe_format else 2,
|
||||
pack_engine_version=(
|
||||
None if midi_cvt.enable_old_exe_format else [1, 19, 50]
|
||||
),
|
||||
),
|
||||
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"
|
||||
)
|
||||
|
||||
struct, size, end_pos = commands_to_redstone_delay_structure(
|
||||
commands=command_list,
|
||||
delay_length=max_delay,
|
||||
max_multicmd_length=max_together,
|
||||
base_block=basement_block,
|
||||
axis_=axis_side,
|
||||
compability_version_=compability_ver,
|
||||
)
|
||||
with open(
|
||||
os.path.abspath(
|
||||
os.path.join(
|
||||
dist_path,
|
||||
"temp/structures/",
|
||||
f"{midi_cvt.music_name}_main.mcstructure",
|
||||
)
|
||||
),
|
||||
"wb+",
|
||||
) as f:
|
||||
struct.dump(f)
|
||||
|
||||
del struct
|
||||
|
||||
if progressbar_style:
|
||||
scb_name = midi_cvt.music_name[:3] + "Pgb"
|
||||
index_file.write("scoreboard objectives add {0} dummy {0}计\n".format(scb_name))
|
||||
|
||||
struct_a = Structure((1, 1, 1), compability_version=compability_ver)
|
||||
struct_a.set_block(
|
||||
(0, 0, 0),
|
||||
form_command_block_in_NBT_struct(
|
||||
r"scoreboard players add {} {} 1".format(player, scb_name),
|
||||
(0, 0, 0),
|
||||
1,
|
||||
1,
|
||||
alwaysRun=False,
|
||||
customName="显示进度条并加分",
|
||||
compability_version_number=compability_ver,
|
||||
),
|
||||
)
|
||||
|
||||
with open(
|
||||
os.path.abspath(
|
||||
os.path.join(
|
||||
dist_path,
|
||||
"temp/structures/",
|
||||
f"{midi_cvt.music_name}_start.mcstructure",
|
||||
)
|
||||
),
|
||||
"wb+",
|
||||
) as f:
|
||||
struct_a.dump(f)
|
||||
|
||||
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, progressbar_style),
|
||||
max_height - 1,
|
||||
compability_version_=compability_ver,
|
||||
)
|
||||
|
||||
with open(
|
||||
os.path.abspath(
|
||||
os.path.join(
|
||||
dist_path,
|
||||
"temp/structures/",
|
||||
f"{midi_cvt.music_name}_pgb.mcstructure",
|
||||
)
|
||||
),
|
||||
"wb+",
|
||||
) as f:
|
||||
pgb_struct.dump(f)
|
||||
|
||||
index_file.write(f"structure load {midi_cvt.music_name}_pgb ~ ~1 ~1\n")
|
||||
|
||||
struct_a = Structure(
|
||||
(1, 1, 1),
|
||||
)
|
||||
struct_a.set_block(
|
||||
(0, 0, 0),
|
||||
form_command_block_in_NBT_struct(
|
||||
r"scoreboard players reset {} {}".format(player, scb_name),
|
||||
(0, 0, 0),
|
||||
1,
|
||||
0,
|
||||
alwaysRun=False,
|
||||
customName="重置进度条计分板",
|
||||
compability_version_number=compability_ver,
|
||||
),
|
||||
)
|
||||
|
||||
with open(
|
||||
os.path.abspath(
|
||||
os.path.join(
|
||||
dist_path,
|
||||
"temp/structures/",
|
||||
f"{midi_cvt.music_name}_reset.mcstructure",
|
||||
)
|
||||
),
|
||||
"wb+",
|
||||
) as f:
|
||||
struct_a.dump(f)
|
||||
|
||||
del struct_a, pgb_struct
|
||||
|
||||
index_file.write(
|
||||
f"structure load {midi_cvt.music_name}_reset ~{pgbSize[0] + 2} ~ ~1\n"
|
||||
)
|
||||
|
||||
index_file.write(
|
||||
f"structure load {midi_cvt.music_name}_main ~{pgbSize[0] + 2} ~1 ~1\n"
|
||||
)
|
||||
|
||||
else:
|
||||
index_file.write(f"structure load {midi_cvt.music_name}_main ~ ~ ~1\n")
|
||||
|
||||
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}[repeater].mcpack",
|
||||
)
|
||||
|
||||
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",
|
||||
axis_side: Literal["z+", "z-", "Z+", "Z-", "x+", "x-", "X+", "X-"] = "z+",
|
||||
) -> 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"无 - 由 音·创 生成",
|
||||
format_version=1 if midi_cvt.enable_old_exe_format else 2,
|
||||
pack_engine_version=(
|
||||
None if midi_cvt.enable_old_exe_format else [1, 19, 50]
|
||||
),
|
||||
),
|
||||
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,
|
||||
axis_=axis_side,
|
||||
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}[repeater-div].mcpack",
|
||||
)
|
||||
|
||||
shutil.rmtree(f"{dist_path}/temp/")
|
||||
|
||||
return midi_cvt.total_note_count, max_delay
|
||||
104
old-things/Musicreater/old_plugin/archive.py
Normal file
104
old-things/Musicreater/old_plugin/archive.py
Normal file
@@ -0,0 +1,104 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
存放关于文件打包的内容
|
||||
"""
|
||||
|
||||
|
||||
"""
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 仓库根目录下的 License.md
|
||||
Terms & Conditions: License.md in the root directory
|
||||
"""
|
||||
|
||||
# 睿乐组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
|
||||
import datetime
|
||||
import os
|
||||
import uuid
|
||||
import zipfile
|
||||
from typing import List, Literal, Union
|
||||
|
||||
|
||||
def compress_zipfile(sourceDir, outFilename, compression=8, exceptFile=None):
|
||||
"""
|
||||
使用指定的压缩算法将目录打包为zip文件
|
||||
|
||||
Parameters
|
||||
------------
|
||||
sourceDir: str
|
||||
要压缩的源目录路径
|
||||
outFilename: str
|
||||
输出的zip文件路径
|
||||
compression: int, 可选
|
||||
压缩算法,默认为8 (DEFLATED)
|
||||
可用算法:
|
||||
STORED = 0
|
||||
DEFLATED = 8 (默认)
|
||||
BZIP2 = 12
|
||||
LZMA = 14
|
||||
exceptFile: list[str], 可选
|
||||
需要排除在压缩包外的文件名称列表(可选)
|
||||
|
||||
Returns
|
||||
---------
|
||||
None
|
||||
"""
|
||||
|
||||
zipf = zipfile.ZipFile(outFilename, "w", compression)
|
||||
pre_len = len(os.path.dirname(sourceDir))
|
||||
for parent, dirnames, filenames in os.walk(sourceDir):
|
||||
for filename in filenames:
|
||||
if filename == exceptFile:
|
||||
continue
|
||||
pathfile = os.path.join(parent, filename)
|
||||
arc_name = pathfile[pre_len:].strip(os.path.sep) # 相对路径
|
||||
zipf.write(pathfile, arc_name)
|
||||
zipf.close()
|
||||
|
||||
|
||||
def behavior_mcpack_manifest(
|
||||
format_version: Union[Literal[1], Literal[2]] = 1,
|
||||
pack_description: str = "",
|
||||
pack_version: Union[List[int], Literal[None]] = None,
|
||||
pack_name: str = "",
|
||||
pack_uuid: Union[str, Literal[None]] = None,
|
||||
pack_engine_version: Union[List[int], None] = None,
|
||||
modules_description: str = "",
|
||||
modules_version: List[int] = [0, 0, 1],
|
||||
modules_uuid: Union[str, Literal[None]] = None,
|
||||
):
|
||||
"""
|
||||
生成一个我的世界行为包组件的定义清单文件
|
||||
"""
|
||||
if not pack_version:
|
||||
now_date = datetime.datetime.now()
|
||||
pack_version = [
|
||||
now_date.year,
|
||||
now_date.month * 100 + now_date.day,
|
||||
now_date.hour * 100 + now_date.minute,
|
||||
]
|
||||
result = {
|
||||
"format_version": format_version,
|
||||
"header": {
|
||||
"description": pack_description,
|
||||
"version": pack_version,
|
||||
"name": pack_name,
|
||||
"uuid": str(uuid.uuid4()) if not pack_uuid else pack_uuid,
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"description": modules_description,
|
||||
"type": "data",
|
||||
"version": modules_version,
|
||||
"uuid": str(uuid.uuid4()) if not modules_uuid else modules_uuid,
|
||||
}
|
||||
],
|
||||
}
|
||||
if pack_engine_version:
|
||||
result["header"]["min_engine_version"] = pack_engine_version
|
||||
return result
|
||||
229
old-things/Musicreater/old_plugin/bdx.py
Normal file
229
old-things/Musicreater/old_plugin/bdx.py
Normal file
@@ -0,0 +1,229 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
存放有关BDX结构操作的内容
|
||||
"""
|
||||
|
||||
"""
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 仓库根目录下的 License.md
|
||||
Terms & Conditions: License.md in the root directory
|
||||
"""
|
||||
|
||||
# 睿乐组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
from typing import List
|
||||
|
||||
from ..constants import x, y, z
|
||||
from ..subclass import MineCommand
|
||||
from .common import bottem_side_length_of_smallest_square_bottom_box
|
||||
|
||||
BDX_MOVE_KEY = {
|
||||
"x": [b"\x0f", b"\x0e", b"\x1c", b"\x14", b"\x15"],
|
||||
"y": [b"\x11", b"\x10", b"\x1d", b"\x16", b"\x17"],
|
||||
"z": [b"\x13", b"\x12", b"\x1e", b"\x18", b"\x19"],
|
||||
}
|
||||
"""key存储了方块移动指令的数据,其中可以用key[x|y|z][0|1]来表示xyz的减或增
|
||||
而key[][2+]是用来增加指定数目的"""
|
||||
|
||||
|
||||
def bdx_move(axis: str, value: int):
|
||||
if value == 0:
|
||||
return b""
|
||||
if abs(value) == 1:
|
||||
return BDX_MOVE_KEY[axis][0 if value == -1 else 1]
|
||||
|
||||
pointer = sum(
|
||||
[
|
||||
value != -1,
|
||||
value < -1 or value > 1,
|
||||
value < -128 or value > 127,
|
||||
value < -32768 or value > 32767,
|
||||
]
|
||||
)
|
||||
|
||||
return BDX_MOVE_KEY[axis][pointer] + value.to_bytes(
|
||||
2 ** (pointer - 2), "big", signed=True
|
||||
)
|
||||
|
||||
|
||||
def form_command_block_in_BDX_bytes(
|
||||
command: str,
|
||||
particularValue: int,
|
||||
impluse: int = 0,
|
||||
condition: bool = False,
|
||||
needRedstone: bool = True,
|
||||
tickDelay: int = 0,
|
||||
customName: str = "",
|
||||
executeOnFirstTick: bool = False,
|
||||
trackOutput: bool = True,
|
||||
) -> bytes:
|
||||
"""
|
||||
使用指定参数生成指定的指令方块放置指令项
|
||||
|
||||
Parameters
|
||||
------------
|
||||
command: str
|
||||
指令
|
||||
particularValue: int
|
||||
方块特殊值,即朝向
|
||||
:0 下 无条件
|
||||
:1 上 无条件
|
||||
:2 z轴负方向 无条件
|
||||
:3 z轴正方向 无条件
|
||||
:4 x轴负方向 无条件
|
||||
:5 x轴正方向 无条件
|
||||
:6 下 无条件
|
||||
:7 下 无条件
|
||||
:8 下 有条件
|
||||
:9 上 有条件
|
||||
:10 z轴负方向 有条件
|
||||
:11 z轴正方向 有条件
|
||||
:12 x轴负方向 有条件
|
||||
:13 x轴正方向 有条件
|
||||
:14 下 有条件
|
||||
:14 下 有条件
|
||||
注意!此处特殊值中的条件会被下面condition参数覆写
|
||||
impluse: int (0|1|2)
|
||||
方块类型
|
||||
0脉冲 1循环 2连锁
|
||||
condition: bool
|
||||
是否有条件
|
||||
needRedstone: bool
|
||||
是否需要红石
|
||||
tickDelay: int
|
||||
执行延时
|
||||
customName: str
|
||||
悬浮字
|
||||
lastOutput: str
|
||||
命令方块的上次输出字符串,注意此处需要留空
|
||||
executeOnFirstTick: bool
|
||||
是否启用首刻执行(循环指令方块是否激活后立即执行,若为False,则从激活时起延迟后第一次执行)
|
||||
trackOutput: bool
|
||||
是否启用命令方块输出
|
||||
|
||||
Returns
|
||||
---------
|
||||
bytes
|
||||
用以生成 bdx 结构的字节码
|
||||
"""
|
||||
block = b"\x24" + particularValue.to_bytes(2, byteorder="big", signed=False)
|
||||
|
||||
for i in [
|
||||
impluse.to_bytes(4, byteorder="big", signed=False),
|
||||
bytes(command, encoding="utf-8") + b"\x00",
|
||||
bytes(customName, encoding="utf-8") + b"\x00",
|
||||
bytes("", encoding="utf-8") + b"\x00",
|
||||
tickDelay.to_bytes(4, byteorder="big", signed=True),
|
||||
executeOnFirstTick.to_bytes(1, byteorder="big"),
|
||||
trackOutput.to_bytes(1, byteorder="big"),
|
||||
condition.to_bytes(1, byteorder="big"),
|
||||
needRedstone.to_bytes(1, byteorder="big"),
|
||||
]:
|
||||
block += i
|
||||
return block
|
||||
|
||||
|
||||
def commands_to_BDX_bytes(
|
||||
commands_list: List[MineCommand],
|
||||
max_height: int = 64,
|
||||
):
|
||||
"""
|
||||
指令列表转换为用以生成 bdx 结构的字节码
|
||||
|
||||
Parameters
|
||||
------------
|
||||
commands: list[tuple[str, int]]
|
||||
指令列表,每个元素为 (指令, 延迟)
|
||||
max_height: int
|
||||
生成结构最大高度
|
||||
|
||||
Returns
|
||||
---------
|
||||
tuple[bool, bytes, int] or tuple[bool, str]
|
||||
成功与否,成功返回 (True, 未经过压缩的源, 结构占用大小),失败返回 (False, str失败原因)
|
||||
"""
|
||||
|
||||
_sideLength = bottem_side_length_of_smallest_square_bottom_box(
|
||||
len(commands_list), max_height
|
||||
)
|
||||
_bytes = b""
|
||||
|
||||
y_forward = True
|
||||
z_forward = True
|
||||
|
||||
now_y = 0
|
||||
now_z = 0
|
||||
now_x = 0
|
||||
|
||||
for command in commands_list:
|
||||
_bytes += form_command_block_in_BDX_bytes(
|
||||
command.command_text,
|
||||
(
|
||||
(1 if y_forward else 0)
|
||||
if (
|
||||
((now_y != 0) and (not y_forward))
|
||||
or (y_forward and (now_y != (max_height - 1)))
|
||||
)
|
||||
else (
|
||||
(3 if z_forward else 2)
|
||||
if (
|
||||
((now_z != 0) and (not z_forward))
|
||||
or (z_forward and (now_z != _sideLength - 1))
|
||||
)
|
||||
else 5
|
||||
)
|
||||
),
|
||||
impluse=2,
|
||||
condition=command.conditional,
|
||||
needRedstone=False,
|
||||
tickDelay=command.delay,
|
||||
customName=command.annotation_text,
|
||||
executeOnFirstTick=False,
|
||||
trackOutput=True,
|
||||
)
|
||||
|
||||
# (1 if y_forward else 0) if ( # 如果y+则向上,反之向下
|
||||
# ((now_y != 0) and (not y_forward)) # 如果不是y轴上首个方块
|
||||
# or (y_forward and (now_y != (max_height - 1))) # 如果不是y轴上末端方块
|
||||
# ) else ( # 否则,即是y轴末端或首个方块
|
||||
# (3 if z_forward else 2) if ( # 如果z+则向z轴正方向,反之负方向
|
||||
# ((now_z != 0) and (not z_forward)) # 如果不是z轴上的首个方块
|
||||
# or (z_forward and (now_z != _sideLength - 1)) # 如果不是z轴上的末端方块
|
||||
# ) else 5 # 否则,则要面向x轴正方向
|
||||
# )
|
||||
|
||||
now_y += 1 if y_forward else -1
|
||||
|
||||
if ((now_y >= max_height) and y_forward) or ((now_y < 0) and (not y_forward)):
|
||||
now_y -= 1 if y_forward else -1
|
||||
|
||||
y_forward = not y_forward
|
||||
|
||||
now_z += 1 if z_forward else -1
|
||||
|
||||
if ((now_z >= _sideLength) and z_forward) or (
|
||||
(now_z < 0) and (not z_forward)
|
||||
):
|
||||
now_z -= 1 if z_forward else -1
|
||||
z_forward = not z_forward
|
||||
_bytes += BDX_MOVE_KEY[x][1]
|
||||
now_x += 1
|
||||
else:
|
||||
_bytes += BDX_MOVE_KEY[z][int(z_forward)]
|
||||
|
||||
else:
|
||||
_bytes += BDX_MOVE_KEY[y][int(y_forward)]
|
||||
|
||||
return (
|
||||
_bytes,
|
||||
[
|
||||
now_x + 1,
|
||||
max_height if now_x or now_z else now_y,
|
||||
_sideLength if now_x else now_z,
|
||||
],
|
||||
[now_x, now_y, now_z],
|
||||
)
|
||||
20
old-things/Musicreater/old_plugin/bdxfile/__init__.py
Normal file
20
old-things/Musicreater/old_plugin/bdxfile/__init__.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
用以生成BDX结构文件的附加功能
|
||||
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 仓库根目录下的 License.md
|
||||
Terms & Conditions: License.md in the root directory
|
||||
"""
|
||||
|
||||
# 睿乐组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
|
||||
__all__ = ["to_BDX_file_in_score", "to_BDX_file_in_delay"]
|
||||
__author__ = (("金羿", "Eilles"),)
|
||||
|
||||
from .main import to_BDX_file_in_delay, to_BDX_file_in_score
|
||||
220
old-things/Musicreater/old_plugin/bdxfile/main.py
Normal file
220
old-things/Musicreater/old_plugin/bdxfile/main.py
Normal file
@@ -0,0 +1,220 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 仓库根目录下的 License.md
|
||||
Terms & Conditions: License.md in the root directory
|
||||
"""
|
||||
|
||||
# 睿乐组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
import brotli
|
||||
|
||||
from ...old_main import MidiConvert
|
||||
from ...subclass import MineCommand, ProgressBarStyle
|
||||
from ..bdx import (
|
||||
bdx_move,
|
||||
commands_to_BDX_bytes,
|
||||
form_command_block_in_BDX_bytes,
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
)
|
||||
|
||||
|
||||
def to_BDX_file_in_score(
|
||||
midi_cvt: MidiConvert,
|
||||
dist_path: str,
|
||||
progressbar_style: Optional[ProgressBarStyle],
|
||||
scoreboard_name: str = "mscplay",
|
||||
auto_reset: bool = False,
|
||||
author: str = "Eilles",
|
||||
max_height: int = 64,
|
||||
):
|
||||
"""
|
||||
将midi以计分播放器形式转换为BDX结构文件
|
||||
|
||||
Parameters
|
||||
----------
|
||||
midi_cvt: MidiConvert 对象
|
||||
用于转换的MidiConvert对象
|
||||
dist_path: str
|
||||
转换结果输出的目标路径
|
||||
progressbar_style: ProgressBarStyle 对象
|
||||
进度条对象
|
||||
scoreboard_name: str
|
||||
我的世界的计分板名称
|
||||
auto_reset: bool
|
||||
是否自动重置计分板
|
||||
author: str
|
||||
作者名称
|
||||
max_height: int
|
||||
生成结构最大高度
|
||||
|
||||
Returns
|
||||
-------
|
||||
tuple[int指令数量, int音乐总延迟, tuple[int,]结构大小, tuple[int,]终点坐标]
|
||||
"""
|
||||
|
||||
cmdlist, command_count, max_score = midi_cvt.to_command_list_in_score(
|
||||
scoreboard_name=scoreboard_name,
|
||||
)
|
||||
|
||||
if not os.path.exists(dist_path):
|
||||
os.makedirs(dist_path)
|
||||
|
||||
with open(
|
||||
os.path.abspath(os.path.join(dist_path, f"{midi_cvt.music_name}[score].bdx")),
|
||||
"w+",
|
||||
) as f:
|
||||
f.write("BD@")
|
||||
|
||||
_bytes = (
|
||||
b"BDX\x00" + author.encode("utf-8") + b" & Musicreater\x00\x01command_block\x00"
|
||||
)
|
||||
|
||||
cmdBytes, size, finalPos = commands_to_BDX_bytes(
|
||||
midi_cvt.music_command_list
|
||||
+ (
|
||||
[
|
||||
MineCommand(
|
||||
command="scoreboard players reset @a[scores={"
|
||||
+ scoreboard_name
|
||||
+ "="
|
||||
+ str(max_score + 20)
|
||||
+ "}] "
|
||||
+ scoreboard_name,
|
||||
annotation="自动重置计分板",
|
||||
)
|
||||
]
|
||||
if auto_reset
|
||||
else []
|
||||
),
|
||||
max_height - 1,
|
||||
)
|
||||
|
||||
if progressbar_style:
|
||||
pgbBytes, pgbSize, pgbNowPos = commands_to_BDX_bytes(
|
||||
midi_cvt.form_progress_bar(max_score, scoreboard_name, progressbar_style),
|
||||
max_height - 1,
|
||||
)
|
||||
_bytes += pgbBytes
|
||||
_bytes += bdx_move(y, -pgbNowPos[1])
|
||||
_bytes += bdx_move(z, -pgbNowPos[2])
|
||||
_bytes += bdx_move(x, 2)
|
||||
|
||||
size[0] += 2 + pgbSize[0]
|
||||
size[1] = max(size[1], pgbSize[1])
|
||||
size[2] = max(size[2], pgbSize[2])
|
||||
|
||||
_bytes += cmdBytes
|
||||
|
||||
with open(
|
||||
os.path.abspath(os.path.join(dist_path, f"{midi_cvt.music_name}[score].bdx")),
|
||||
"ab+",
|
||||
) as f:
|
||||
f.write(brotli.compress(_bytes + b"XE"))
|
||||
|
||||
return command_count, max_score, size, finalPos
|
||||
|
||||
|
||||
def to_BDX_file_in_delay(
|
||||
midi_cvt: MidiConvert,
|
||||
dist_path: str,
|
||||
progressbar_style: Optional[ProgressBarStyle],
|
||||
player: str = "@a",
|
||||
author: str = "Eilles",
|
||||
max_height: int = 64,
|
||||
):
|
||||
"""
|
||||
使用method指定的转换算法,将midi转换为BDX结构文件
|
||||
|
||||
Parameters
|
||||
----------
|
||||
midi_cvt: MidiConvert 对象
|
||||
用于转换的MidiConvert对象
|
||||
dist_path: str
|
||||
转换结果输出的目标路径
|
||||
progressbar_style: ProgressBarStyle 对象
|
||||
进度条对象
|
||||
player: str
|
||||
玩家选择器,默认为`@a`
|
||||
author: str
|
||||
作者名称
|
||||
max_height: int
|
||||
生成结构最大高度
|
||||
|
||||
Returns
|
||||
-------
|
||||
tuple[int指令数量, int音乐总延迟, tuple[int,]结构大小, tuple[int,]终点坐标]
|
||||
"""
|
||||
|
||||
cmdlist, max_delay = midi_cvt.to_command_list_in_delay(
|
||||
player_selector=player,
|
||||
)[:2]
|
||||
|
||||
if not os.path.exists(dist_path):
|
||||
os.makedirs(dist_path)
|
||||
|
||||
with open(
|
||||
os.path.abspath(os.path.join(dist_path, f"{midi_cvt.music_name}[delay].bdx")),
|
||||
"w+",
|
||||
) as f:
|
||||
f.write("BD@")
|
||||
|
||||
_bytes = (
|
||||
b"BDX\x00" + author.encode("utf-8") + b" & Musicreater\x00\x01command_block\x00"
|
||||
)
|
||||
|
||||
cmdBytes, size, finalPos = commands_to_BDX_bytes(cmdlist, max_height - 1)
|
||||
|
||||
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),
|
||||
1,
|
||||
customName="初始化进度条",
|
||||
)
|
||||
_bytes += bdx_move(z, 2)
|
||||
_bytes += form_command_block_in_BDX_bytes(
|
||||
r"scoreboard players add {} {} 1".format(player, scb_name),
|
||||
1,
|
||||
1,
|
||||
customName="显示进度条并加分",
|
||||
)
|
||||
_bytes += bdx_move(y, 1)
|
||||
pgbBytes, pgbSize, pgbNowPos = commands_to_BDX_bytes(
|
||||
midi_cvt.form_progress_bar(max_delay, scb_name, progressbar_style),
|
||||
max_height - 1,
|
||||
)
|
||||
_bytes += pgbBytes
|
||||
_bytes += bdx_move(y, -1 - pgbNowPos[1])
|
||||
_bytes += bdx_move(z, -2 - pgbNowPos[2])
|
||||
_bytes += bdx_move(x, 2)
|
||||
_bytes += form_command_block_in_BDX_bytes(
|
||||
r"scoreboard players reset {} {}".format(player, scb_name),
|
||||
1,
|
||||
customName="置零进度条",
|
||||
)
|
||||
_bytes += bdx_move(y, 1)
|
||||
size[0] += 2 + pgbSize[0]
|
||||
size[1] = max(size[1], pgbSize[1])
|
||||
size[2] = max(size[2], pgbSize[2])
|
||||
|
||||
size[1] += 1
|
||||
_bytes += cmdBytes
|
||||
|
||||
with open(
|
||||
os.path.abspath(os.path.join(dist_path, f"{midi_cvt.music_name}[delay].bdx")),
|
||||
"ab+",
|
||||
) as f:
|
||||
f.write(brotli.compress(_bytes + b"XE"))
|
||||
|
||||
return len(cmdlist), max_delay, size, finalPos
|
||||
40
old-things/Musicreater/old_plugin/common.py
Normal file
40
old-things/Musicreater/old_plugin/common.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
存放通用的普遍性的插件内容
|
||||
"""
|
||||
|
||||
"""
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 仓库根目录下的 License.md
|
||||
Terms & Conditions: License.md in the root directory
|
||||
"""
|
||||
|
||||
# 睿乐组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
|
||||
import math
|
||||
|
||||
|
||||
def bottem_side_length_of_smallest_square_bottom_box(
|
||||
_total_block_count: int, _max_height: int
|
||||
):
|
||||
"""
|
||||
给定结构的总方块数量和规定的最大高度,返回该结构应当构成的图形,在底面的外切正方形之边长
|
||||
|
||||
Parameters
|
||||
------------
|
||||
_total_block_count: int
|
||||
总方块数量
|
||||
_max_height: int
|
||||
规定的结构最大高度
|
||||
|
||||
Returns
|
||||
---------
|
||||
int
|
||||
外切正方形的边长
|
||||
"""
|
||||
return math.ceil(math.sqrt(math.ceil(_total_block_count / _max_height)))
|
||||
92
old-things/Musicreater/old_plugin/main.py
Normal file
92
old-things/Musicreater/old_plugin/main.py
Normal file
@@ -0,0 +1,92 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
存放附加内容功能
|
||||
"""
|
||||
|
||||
"""
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 仓库根目录下的 License.md
|
||||
Terms & Conditions: License.md in the root directory
|
||||
"""
|
||||
|
||||
# 睿乐组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
|
||||
# from dataclasses import dataclass
|
||||
# from typing import Literal, Tuple, Union
|
||||
|
||||
# from ..subclass import DEFAULT_PROGRESSBAR_STYLE, ProgressBarStyle
|
||||
|
||||
|
||||
# @dataclass(init=False)
|
||||
# class ConvertConfig: # 必定要改
|
||||
# """
|
||||
# 转换通用设置存储类
|
||||
# """
|
||||
|
||||
# progressbar_style: Union[ProgressBarStyle, None]
|
||||
# """进度条样式"""
|
||||
|
||||
# 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可读格式
|
||||
|
||||
# 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
|
||||
# """输出目录"""
|
||||
|
||||
# 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
|
||||
# """进度条样式组"""
|
||||
30
old-things/Musicreater/old_plugin/mcstructfile/__init__.py
Normal file
30
old-things/Musicreater/old_plugin/mcstructfile/__init__.py
Normal file
@@ -0,0 +1,30 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
用以生成单个mcstructure文件的附加功能
|
||||
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 仓库根目录下的 License.md
|
||||
Terms & Conditions: License.md in the root directory
|
||||
"""
|
||||
|
||||
# 睿乐组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
|
||||
__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"),)
|
||||
|
||||
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,
|
||||
)
|
||||
298
old-things/Musicreater/old_plugin/mcstructfile/main.py
Normal file
298
old-things/Musicreater/old_plugin/mcstructfile/main.py
Normal file
@@ -0,0 +1,298 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 仓库根目录下的 License.md
|
||||
Terms & Conditions: License.md in the root directory
|
||||
"""
|
||||
|
||||
# 睿乐组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
import os
|
||||
from typing import Literal
|
||||
|
||||
from ...old_main import MidiConvert
|
||||
from ...subclass import MineCommand
|
||||
from ..mcstructure import (
|
||||
COMPABILITY_VERSION_117,
|
||||
COMPABILITY_VERSION_119,
|
||||
commands_to_redstone_delay_structure,
|
||||
commands_to_structure,
|
||||
)
|
||||
|
||||
|
||||
def to_mcstructure_file_in_delay(
|
||||
midi_cvt: MidiConvert,
|
||||
dist_path: str,
|
||||
player: str = "@a",
|
||||
max_height: int = 64,
|
||||
):
|
||||
"""
|
||||
将midi以延迟播放器形式转换为mcstructure结构文件
|
||||
|
||||
Parameters
|
||||
----------
|
||||
midi_cvt: MidiConvert 对象
|
||||
用于转换的MidiConvert对象
|
||||
dist_path: str
|
||||
转换结果输出的目标路径
|
||||
player: str
|
||||
玩家选择器,默认为`@a`
|
||||
max_height: int
|
||||
生成结构最大高度
|
||||
|
||||
Returns
|
||||
-------
|
||||
tuple[tuple[int,int,int]结构大小, int音乐总延迟]
|
||||
"""
|
||||
|
||||
compability_ver = (
|
||||
COMPABILITY_VERSION_117
|
||||
if midi_cvt.enable_old_exe_format
|
||||
else COMPABILITY_VERSION_119
|
||||
)
|
||||
|
||||
cmd_list, max_delay = midi_cvt.to_command_list_in_delay(
|
||||
player_selector=player,
|
||||
)[:2]
|
||||
|
||||
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(dist_path, f"{midi_cvt.music_name}[delay].mcstructure")),
|
||||
"wb+",
|
||||
) as f:
|
||||
struct.dump(f)
|
||||
|
||||
return size, max_delay
|
||||
|
||||
|
||||
def to_mcstructure_file_in_score(
|
||||
midi_cvt: MidiConvert,
|
||||
dist_path: str,
|
||||
scoreboard_name: str = "mscplay",
|
||||
auto_reset: bool = False,
|
||||
max_height: int = 64,
|
||||
):
|
||||
"""
|
||||
将midi以延迟播放器形式转换为mcstructure结构文件
|
||||
|
||||
Parameters
|
||||
----------
|
||||
midi_cvt: MidiConvert 对象
|
||||
用于转换的MidiConvert对象
|
||||
dist_path: str
|
||||
转换结果输出的目标路径
|
||||
scoreboard_name: str
|
||||
我的世界的计分板名称
|
||||
auto_reset: bool
|
||||
是否自动重置计分板
|
||||
max_height: int
|
||||
生成结构最大高度
|
||||
|
||||
Returns
|
||||
-------
|
||||
tuple[tuple[int,int,int]结构大小, int音乐总延迟, int指令数量
|
||||
"""
|
||||
|
||||
compability_ver = (
|
||||
COMPABILITY_VERSION_117
|
||||
if midi_cvt.enable_old_exe_format
|
||||
else COMPABILITY_VERSION_119
|
||||
)
|
||||
|
||||
cmd_list, cmd_count, max_delay = midi_cvt.to_command_list_in_score(
|
||||
scoreboard_name=scoreboard_name,
|
||||
)
|
||||
|
||||
if not os.path.exists(dist_path):
|
||||
os.makedirs(dist_path)
|
||||
|
||||
struct, size, end_pos = commands_to_structure(
|
||||
midi_cvt.music_command_list
|
||||
+ (
|
||||
[
|
||||
MineCommand(
|
||||
command="scoreboard players reset @a[scores={"
|
||||
+ scoreboard_name
|
||||
+ "="
|
||||
+ str(max_delay + 20)
|
||||
+ "}] "
|
||||
+ scoreboard_name,
|
||||
annotation="自动重置计分板",
|
||||
)
|
||||
]
|
||||
if auto_reset
|
||||
else []
|
||||
),
|
||||
max_height - 1,
|
||||
compability_version_=compability_ver,
|
||||
)
|
||||
|
||||
with open(
|
||||
os.path.abspath(os.path.join(dist_path, f"{midi_cvt.music_name}[score].mcstructure")),
|
||||
"wb+",
|
||||
) as f:
|
||||
struct.dump(f)
|
||||
|
||||
return size, max_delay, cmd_count
|
||||
|
||||
|
||||
def to_mcstructure_file_in_repeater(
|
||||
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
|
||||
-------
|
||||
tuple[tuple[int,int,int]结构大小, int音乐总延迟]
|
||||
"""
|
||||
|
||||
compability_ver = (
|
||||
COMPABILITY_VERSION_117
|
||||
if midi_cvt.enable_old_exe_format
|
||||
else COMPABILITY_VERSION_119
|
||||
)
|
||||
|
||||
cmd_list, max_delay, max_multiple_cmd = midi_cvt.to_command_list_in_delay(
|
||||
player_selector=player,
|
||||
)
|
||||
|
||||
if not os.path.exists(dist_path):
|
||||
os.makedirs(dist_path)
|
||||
|
||||
struct, size, end_pos = commands_to_redstone_delay_structure(
|
||||
cmd_list,
|
||||
max_delay,
|
||||
max_multiple_cmd,
|
||||
basement_block,
|
||||
axis_side,
|
||||
compability_version_=compability_ver,
|
||||
)
|
||||
|
||||
with open(
|
||||
os.path.abspath(os.path.join(dist_path, f"{midi_cvt.music_name}[repeater].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,
|
||||
"{}[repeater-div]_{}.mcstructure".format(
|
||||
midi_cvt.music_name, inst.replace(".", "-")
|
||||
),
|
||||
)
|
||||
),
|
||||
"wb+",
|
||||
) as f:
|
||||
struct.dump(f)
|
||||
|
||||
return max_delay
|
||||
|
||||
|
||||
def to_mcstructure_file_in_blocks(
|
||||
midi_cvt: MidiConvert,
|
||||
dist_path: str,
|
||||
player: str = "@a",
|
||||
):
|
||||
"""
|
||||
将midi以方块形式转换为mcstructure结构文件
|
||||
|
||||
Parameters
|
||||
----------
|
||||
midi_cvt: MidiConvert 对象
|
||||
用于转换的MidiConvert对象
|
||||
dist_path: str
|
||||
转换结果输出的目标路径
|
||||
player: str
|
||||
玩家选择器,默认为`@a`
|
||||
|
||||
Returns
|
||||
-------
|
||||
int音乐总延迟
|
||||
"""
|
||||
pass
|
||||
543
old-things/Musicreater/old_plugin/mcstructure.py
Normal file
543
old-things/Musicreater/old_plugin/mcstructure.py
Normal file
@@ -0,0 +1,543 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
存放有关MCSTRUCTURE结构操作的内容
|
||||
"""
|
||||
|
||||
"""
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 仓库根目录下的 License.md
|
||||
Terms & Conditions: License.md in the root directory
|
||||
"""
|
||||
|
||||
# 睿乐组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
|
||||
from typing import List, Literal, Tuple
|
||||
|
||||
from TrimMCStruct import Block, Structure, TAG_Byte, TAG_Long
|
||||
|
||||
from ..constants import x, y, z
|
||||
from ..subclass import MineCommand
|
||||
from .common import bottem_side_length_of_smallest_square_bottom_box
|
||||
|
||||
|
||||
def antiaxis(axis: Literal["x", "z", "X", "Z"]):
|
||||
return z if axis == x else x
|
||||
|
||||
|
||||
def forward_IER(forward: bool):
|
||||
return 1 if forward else -1
|
||||
|
||||
|
||||
AXIS_PARTICULAR_VALUE = {
|
||||
x: {
|
||||
True: 5,
|
||||
False: 4,
|
||||
},
|
||||
y: {
|
||||
True: 1,
|
||||
False: 0,
|
||||
},
|
||||
z: {
|
||||
True: 3,
|
||||
False: 2,
|
||||
},
|
||||
}
|
||||
|
||||
# 1.19的结构兼容版本号
|
||||
COMPABILITY_VERSION_119: int = 17959425
|
||||
"""
|
||||
Minecraft 1.19 兼容版本号
|
||||
"""
|
||||
# 1.17的结构兼容版本号
|
||||
COMPABILITY_VERSION_117: int = 17879555
|
||||
"""
|
||||
Minecraft 1.17 兼容版本号
|
||||
"""
|
||||
COMPABILITY_VERSION_121: int = 18168865
|
||||
"""
|
||||
Minecraft 1.21 兼容版本号
|
||||
"""
|
||||
|
||||
|
||||
def command_statevalue(axis_: Literal["x", "y", "z", "X", "Y", "Z"], forward_: bool):
|
||||
return AXIS_PARTICULAR_VALUE[axis_.lower()][forward_]
|
||||
|
||||
|
||||
def form_note_block_in_NBT_struct(
|
||||
note: int,
|
||||
coordinate: Tuple[int, int, int],
|
||||
instrument: str = "note.harp",
|
||||
powered: bool = False,
|
||||
compability_version_number: int = COMPABILITY_VERSION_119,
|
||||
) -> Block:
|
||||
"""
|
||||
生成音符盒方块
|
||||
|
||||
Parameters
|
||||
------------
|
||||
note: int (0~24)
|
||||
音符的音高
|
||||
coordinate: tuple[int, int, int]
|
||||
此方块所在之相对坐标
|
||||
instrument: str
|
||||
音符盒的乐器
|
||||
powered: bool
|
||||
是否已被激活
|
||||
|
||||
Returns
|
||||
-------
|
||||
Block
|
||||
生成的方块对象
|
||||
"""
|
||||
|
||||
return Block(
|
||||
"minecraft",
|
||||
"noteblock",
|
||||
{
|
||||
"instrument": instrument.replace("note.", ""),
|
||||
"note": note,
|
||||
"powered": powered,
|
||||
},
|
||||
{
|
||||
"block_entity_data": {
|
||||
"note": TAG_Byte(note),
|
||||
"id": "noteblock",
|
||||
"x": coordinate[0],
|
||||
"y": coordinate[1],
|
||||
"z": coordinate[2],
|
||||
} # type: ignore
|
||||
},
|
||||
compability_version=compability_version_number,
|
||||
)
|
||||
|
||||
|
||||
def form_repeater_in_NBT_struct(
|
||||
delay: int,
|
||||
facing: int,
|
||||
compability_version_number: int = COMPABILITY_VERSION_119,
|
||||
) -> Block:
|
||||
"""
|
||||
生成中继器方块
|
||||
|
||||
Parameters
|
||||
----------
|
||||
facing: int (0~3)
|
||||
朝向:
|
||||
Z- 北 0
|
||||
X- 东 1
|
||||
Z+ 南 2
|
||||
X+ 西 3
|
||||
delay: int (0~3)
|
||||
信号延迟
|
||||
|
||||
Returns
|
||||
-------
|
||||
Block
|
||||
生成的方块对象
|
||||
"""
|
||||
|
||||
return Block(
|
||||
"minecraft",
|
||||
"unpowered_repeater",
|
||||
{
|
||||
"repeater_delay": delay,
|
||||
"direction": facing,
|
||||
},
|
||||
compability_version=compability_version_number,
|
||||
)
|
||||
|
||||
|
||||
def form_command_block_in_NBT_struct(
|
||||
command: str,
|
||||
coordinate: tuple,
|
||||
particularValue: int,
|
||||
impluse: int = 0,
|
||||
condition: bool = False,
|
||||
alwaysRun: bool = True,
|
||||
tickDelay: int = 0,
|
||||
customName: str = "",
|
||||
executeOnFirstTick: bool = False,
|
||||
trackOutput: bool = True,
|
||||
compability_version_number: int = COMPABILITY_VERSION_119,
|
||||
) -> Block:
|
||||
"""
|
||||
使用指定参数生成指令方块
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
command: str
|
||||
指令
|
||||
coordinate: tuple[int,int,int]
|
||||
此方块所在之相对坐标
|
||||
particularValue: int
|
||||
方块特殊值,即朝向
|
||||
:0 下 无条件
|
||||
:1 上 无条件
|
||||
:2 z轴负方向 无条件
|
||||
:3 z轴正方向 无条件
|
||||
:4 x轴负方向 无条件
|
||||
:5 x轴正方向 无条件
|
||||
:6 下 无条件
|
||||
:7 下 无条件
|
||||
:8 下 有条件
|
||||
:9 上 有条件
|
||||
:10 z轴负方向 有条件
|
||||
:11 z轴正方向 有条件
|
||||
:12 x轴负方向 有条件
|
||||
:13 x轴正方向 有条件
|
||||
:14 下 有条件
|
||||
:14 下 有条件
|
||||
注意!此处特殊值中的条件会被下面condition参数覆写
|
||||
impluse: int (0|1|2)
|
||||
方块类型
|
||||
0脉冲 1循环 2连锁
|
||||
condition: bool
|
||||
是否有条件
|
||||
alwaysRun: bool
|
||||
是否始终执行
|
||||
tickDelay: int
|
||||
执行延时
|
||||
customName: str
|
||||
悬浮字
|
||||
executeOnFirstTick: bool
|
||||
是否启用首刻执行(循环指令方块是否激活后立即执行,若为False,则从激活时起延迟后第一次执行)
|
||||
trackOutput: bool
|
||||
是否启用命令方块输出
|
||||
compability_version_number: int
|
||||
版本兼容代号
|
||||
|
||||
Returns
|
||||
-------
|
||||
Block
|
||||
生成的方块对象
|
||||
"""
|
||||
|
||||
return Block(
|
||||
"minecraft",
|
||||
(
|
||||
"command_block"
|
||||
if impluse == 0
|
||||
else ("repeating_command_block" if impluse == 1 else "chain_command_block")
|
||||
),
|
||||
states={"conditional_bit": condition, "facing_direction": particularValue},
|
||||
extra_data={
|
||||
"block_entity_data": {
|
||||
"Command": command,
|
||||
"CustomName": customName,
|
||||
"ExecuteOnFirstTick": executeOnFirstTick,
|
||||
"LPCommandMode": 0,
|
||||
"LPCondionalMode": False,
|
||||
"LPRedstoneMode": False,
|
||||
"LastExecution": TAG_Long(0),
|
||||
"LastOutput": "",
|
||||
"LastOutputParams": [],
|
||||
"SuccessCount": 0,
|
||||
"TickDelay": tickDelay,
|
||||
"TrackOutput": trackOutput,
|
||||
"Version": (
|
||||
25 if compability_version_number <= COMPABILITY_VERSION_119 else 43
|
||||
),
|
||||
"auto": alwaysRun,
|
||||
"conditionMet": False, # 是否已经满足条件
|
||||
"conditionalMode": condition,
|
||||
"id": "CommandBlock",
|
||||
"isMovable": True,
|
||||
"powered": False, # 是否已激活
|
||||
"x": coordinate[0],
|
||||
"y": coordinate[1],
|
||||
"z": coordinate[2],
|
||||
} # type: ignore
|
||||
},
|
||||
compability_version=compability_version_number,
|
||||
)
|
||||
|
||||
|
||||
def commands_to_structure(
|
||||
commands: List[MineCommand],
|
||||
max_height: int = 64,
|
||||
compability_version_: int = COMPABILITY_VERSION_119,
|
||||
):
|
||||
"""
|
||||
由指令列表生成(纯指令方块)结构
|
||||
|
||||
Parameters
|
||||
------------
|
||||
commands: list
|
||||
指令列表
|
||||
max_height: int
|
||||
生成结构最大高度
|
||||
|
||||
Returns
|
||||
---------
|
||||
Structure, tuple[int, int, int], tuple[int, int, int]
|
||||
结构类, 结构占用大小, 终点坐标
|
||||
"""
|
||||
|
||||
_sideLength = bottem_side_length_of_smallest_square_bottom_box(
|
||||
len(commands), max_height
|
||||
)
|
||||
|
||||
struct = Structure(
|
||||
size=(_sideLength, max_height, _sideLength), # 声明结构大小
|
||||
compability_version=compability_version_,
|
||||
)
|
||||
|
||||
y_forward = True
|
||||
z_forward = True
|
||||
|
||||
now_y = 0
|
||||
now_z = 0
|
||||
now_x = 0
|
||||
|
||||
for command in commands:
|
||||
coordinate = (now_x, now_y, now_z)
|
||||
struct.set_block(
|
||||
coordinate,
|
||||
form_command_block_in_NBT_struct(
|
||||
command=command.command_text,
|
||||
coordinate=coordinate,
|
||||
particularValue=(
|
||||
(1 if y_forward else 0)
|
||||
if (
|
||||
((now_y != 0) and (not y_forward))
|
||||
or (y_forward and (now_y != (max_height - 1)))
|
||||
)
|
||||
else (
|
||||
(3 if z_forward else 2)
|
||||
if (
|
||||
((now_z != 0) and (not z_forward))
|
||||
or (z_forward and (now_z != _sideLength - 1))
|
||||
)
|
||||
else 5
|
||||
)
|
||||
),
|
||||
impluse=2,
|
||||
condition=False,
|
||||
alwaysRun=True,
|
||||
tickDelay=command.delay,
|
||||
customName=command.annotation_text,
|
||||
executeOnFirstTick=False,
|
||||
trackOutput=True,
|
||||
compability_version_number=compability_version_,
|
||||
),
|
||||
)
|
||||
|
||||
now_y += 1 if y_forward else -1
|
||||
|
||||
if ((now_y >= max_height) and y_forward) or ((now_y < 0) and (not y_forward)):
|
||||
now_y -= 1 if y_forward else -1
|
||||
|
||||
y_forward = not y_forward
|
||||
|
||||
now_z += 1 if z_forward else -1
|
||||
|
||||
if ((now_z >= _sideLength) and z_forward) or (
|
||||
(now_z < 0) and (not z_forward)
|
||||
):
|
||||
now_z -= 1 if z_forward else -1
|
||||
z_forward = not z_forward
|
||||
now_x += 1
|
||||
|
||||
return (
|
||||
struct,
|
||||
(
|
||||
now_x + 1,
|
||||
max_height if now_x or now_z else now_y,
|
||||
_sideLength if now_x else now_z,
|
||||
),
|
||||
(now_x, now_y, now_z),
|
||||
)
|
||||
|
||||
|
||||
def commands_to_redstone_delay_structure(
|
||||
commands: List[MineCommand],
|
||||
delay_length: int,
|
||||
max_multicmd_length: int,
|
||||
base_block: str = "concrete",
|
||||
axis_: Literal["z+", "z-", "Z+", "Z-", "x+", "x-", "X+", "X-"] = "z+",
|
||||
compability_version_: int = COMPABILITY_VERSION_119,
|
||||
) -> Tuple[Structure, Tuple[int, int, int], Tuple[int, int, int]]:
|
||||
"""
|
||||
由指令列表生成由红石中继器延迟的结构
|
||||
|
||||
Parameters
|
||||
------------
|
||||
commands: list
|
||||
指令列表
|
||||
delay_length: int
|
||||
延时总长
|
||||
max_multicmd_length: int
|
||||
最大同时播放的音符数量
|
||||
base_block: Block
|
||||
生成结构的基底方块
|
||||
axis_: str
|
||||
生成结构的延展方向
|
||||
|
||||
Returns
|
||||
---------
|
||||
Structure, tuple[int, int, int], tuple[int, int, int]
|
||||
结构类, 结构占用大小, 终点坐标
|
||||
"""
|
||||
if axis_ in ["z+", "Z+"]:
|
||||
extensioon_direction = z
|
||||
aside_direction = x
|
||||
repeater_facing = 2
|
||||
forward = True
|
||||
elif axis_ in ["z-", "Z-"]:
|
||||
extensioon_direction = z
|
||||
aside_direction = x
|
||||
repeater_facing = 0
|
||||
forward = False
|
||||
elif axis_ in ["x+", "X+"]:
|
||||
extensioon_direction = x
|
||||
aside_direction = z
|
||||
repeater_facing = 3
|
||||
forward = True
|
||||
elif axis_ in ["x-", "X-"]:
|
||||
extensioon_direction = x
|
||||
aside_direction = z
|
||||
repeater_facing = 1
|
||||
forward = False
|
||||
else:
|
||||
raise ValueError(f"axis_({axis_}) 参数错误。")
|
||||
|
||||
goahead = forward_IER(forward)
|
||||
|
||||
command_actually_length = sum([int(bool(cmd.delay)) for cmd in commands])
|
||||
|
||||
a = 1
|
||||
a_max = 0
|
||||
total_cmd = 0
|
||||
for cmd in commands:
|
||||
# print("\r 正在进行处理:",end="")
|
||||
if cmd.delay > 2:
|
||||
a_max = max(a, a_max)
|
||||
total_cmd += (a := 1)
|
||||
else:
|
||||
a += 1
|
||||
|
||||
struct = Structure(
|
||||
size=(
|
||||
round(delay_length / 2 + total_cmd) if extensioon_direction == x else a_max,
|
||||
3,
|
||||
round(delay_length / 2 + total_cmd) if extensioon_direction == z else a_max,
|
||||
),
|
||||
fill=Block("minecraft", "air", compability_version=compability_version_),
|
||||
compability_version=compability_version_,
|
||||
)
|
||||
|
||||
pos_now = {
|
||||
x: ((1 if extensioon_direction == x else 0) if forward else struct.size[0]),
|
||||
y: 0,
|
||||
z: ((1 if extensioon_direction == z else 0) if forward else struct.size[2]),
|
||||
}
|
||||
|
||||
chain_list = 0
|
||||
# print("结构元信息设定完毕")
|
||||
|
||||
for cmd in commands:
|
||||
# print("\r 正在进行处理:",end="")
|
||||
if cmd.delay > 1:
|
||||
# print("\rdelay > 0",end='')
|
||||
single_repeater_value = int(cmd.delay / 2) % 4 - 1
|
||||
additional_repeater = int(cmd.delay / 2 // 4)
|
||||
for i in range(additional_repeater):
|
||||
struct.set_block(
|
||||
tuple(pos_now.values()), # type: ignore
|
||||
Block(
|
||||
"minecraft",
|
||||
base_block,
|
||||
compability_version=compability_version_,
|
||||
),
|
||||
)
|
||||
struct.set_block(
|
||||
(pos_now[x], 1, pos_now[z]),
|
||||
form_repeater_in_NBT_struct(
|
||||
delay=3,
|
||||
facing=repeater_facing,
|
||||
compability_version_number=compability_version_,
|
||||
),
|
||||
)
|
||||
pos_now[extensioon_direction] += goahead
|
||||
if single_repeater_value >= 0:
|
||||
struct.set_block(
|
||||
tuple(pos_now.values()), # type: ignore
|
||||
Block(
|
||||
"minecraft",
|
||||
base_block,
|
||||
compability_version=compability_version_,
|
||||
),
|
||||
)
|
||||
struct.set_block(
|
||||
(pos_now[x], 1, pos_now[z]),
|
||||
form_repeater_in_NBT_struct(
|
||||
delay=single_repeater_value,
|
||||
facing=repeater_facing,
|
||||
compability_version_number=compability_version_,
|
||||
),
|
||||
)
|
||||
pos_now[extensioon_direction] += goahead
|
||||
struct.set_block(
|
||||
(pos_now[x], 1, pos_now[z]),
|
||||
form_command_block_in_NBT_struct(
|
||||
command=cmd.command_text,
|
||||
coordinate=(pos_now[x], 1, pos_now[z]),
|
||||
particularValue=command_statevalue(extensioon_direction, forward),
|
||||
# impluse= (0 if first_impluse else 2),
|
||||
impluse=0,
|
||||
condition=False,
|
||||
alwaysRun=False,
|
||||
tickDelay=cmd.delay % 2,
|
||||
customName=cmd.annotation_text,
|
||||
compability_version_number=compability_version_,
|
||||
),
|
||||
)
|
||||
struct.set_block(
|
||||
(pos_now[x], 2, pos_now[z]),
|
||||
Block(
|
||||
"minecraft",
|
||||
"redstone_wire",
|
||||
compability_version=compability_version_,
|
||||
),
|
||||
)
|
||||
pos_now[extensioon_direction] += goahead
|
||||
chain_list = 1
|
||||
|
||||
else:
|
||||
# print(pos_now)
|
||||
now_pos_copy = pos_now.copy()
|
||||
now_pos_copy[extensioon_direction] -= goahead
|
||||
now_pos_copy[aside_direction] += chain_list
|
||||
# print(pos_now,"\n=========")
|
||||
struct.set_block(
|
||||
(now_pos_copy[x], 1, now_pos_copy[z]),
|
||||
form_command_block_in_NBT_struct(
|
||||
command=cmd.command_text,
|
||||
coordinate=(now_pos_copy[x], 1, now_pos_copy[z]),
|
||||
particularValue=command_statevalue(extensioon_direction, forward),
|
||||
# impluse= (0 if first_impluse else 2),
|
||||
impluse=0,
|
||||
condition=False,
|
||||
alwaysRun=False,
|
||||
tickDelay=cmd.delay % 2,
|
||||
customName=cmd.annotation_text,
|
||||
compability_version_number=compability_version_,
|
||||
),
|
||||
)
|
||||
struct.set_block(
|
||||
(now_pos_copy[x], 2, now_pos_copy[z]),
|
||||
Block(
|
||||
"minecraft",
|
||||
"redstone_wire",
|
||||
compability_version=compability_version_,
|
||||
),
|
||||
)
|
||||
chain_list += 1
|
||||
|
||||
return struct, struct.size, tuple(pos_now.values()) # type: ignore
|
||||
117
old-things/Musicreater/old_plugin/noteblock.py
Normal file
117
old-things/Musicreater/old_plugin/noteblock.py
Normal file
@@ -0,0 +1,117 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
存放有关红石音乐生成操作的内容
|
||||
"""
|
||||
|
||||
"""
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 仓库根目录下的 License.md
|
||||
Terms & Conditions: License.md in the root directory
|
||||
"""
|
||||
|
||||
# 睿乐组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
|
||||
from ..old_exceptions import NotDefineProgramError, ZeroSpeedError
|
||||
from ..old_main import MidiConvert
|
||||
from ..subclass import MineCommand
|
||||
from ..utils import inst_to_sould_with_deviation, perc_inst_to_soundID_withX
|
||||
|
||||
# 你以为写完了吗?其实并没有
|
||||
|
||||
|
||||
def to_note_list(
|
||||
midi_cvt: MidiConvert,
|
||||
speed: float = 1.0,
|
||||
) -> list:
|
||||
"""
|
||||
使用金羿的转换思路,将midi转换为我的世界音符盒所用的音高列表,并输出每个音符之后的延迟
|
||||
|
||||
Parameters
|
||||
----------
|
||||
speed: float
|
||||
速度,注意:这里的速度指的是播放倍率,其原理为在播放音频的时候,每个音符的播放时间除以 speed
|
||||
|
||||
Returns
|
||||
-------
|
||||
tuple( list[tuple(str指令, int距离上一个指令的延迟 ),...], int音乐时长游戏刻 )
|
||||
"""
|
||||
|
||||
if speed == 0:
|
||||
raise ZeroSpeedError("播放速度仅可为正实数")
|
||||
|
||||
midi_channels = (
|
||||
midi_cvt.to_music_channels() if not midi_cvt.channels else midi_cvt.channels
|
||||
)
|
||||
|
||||
tracks = {}
|
||||
|
||||
# 此处 我们把通道视为音轨
|
||||
for i in midi_channels.keys():
|
||||
# 如果当前通道为空 则跳过
|
||||
if not midi_channels[i]:
|
||||
continue
|
||||
|
||||
# 第十通道是打击乐通道
|
||||
SpecialBits = True if i == 9 else False
|
||||
|
||||
# nowChannel = []
|
||||
|
||||
for track_no, track in midi_channels[i].items():
|
||||
for msg in track:
|
||||
if msg[0] == "PgmC":
|
||||
InstID = msg[1]
|
||||
|
||||
elif msg[0] == "NoteS":
|
||||
try:
|
||||
soundID, _X = (
|
||||
perc_inst_to_soundID_withX(InstID)
|
||||
if SpecialBits
|
||||
else inst_to_sould_with_deviation(InstID)
|
||||
)
|
||||
except UnboundLocalError as E:
|
||||
soundID, _X = (
|
||||
perc_inst_to_soundID_withX(-1)
|
||||
if SpecialBits
|
||||
else inst_to_sould_with_deviation(-1)
|
||||
)
|
||||
score_now = round(msg[-1] / float(speed) / 50)
|
||||
# print(score_now)
|
||||
|
||||
try:
|
||||
tracks[score_now].append(
|
||||
self.execute_cmd_head.format(player)
|
||||
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} "
|
||||
f"{2 ** ((msg[1] - 60 - _X) / 12)}"
|
||||
)
|
||||
except KeyError:
|
||||
tracks[score_now] = [
|
||||
self.execute_cmd_head.format(player)
|
||||
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} "
|
||||
f"{2 ** ((msg[1] - 60 - _X) / 12)}"
|
||||
]
|
||||
|
||||
all_ticks = list(tracks.keys())
|
||||
all_ticks.sort()
|
||||
results = []
|
||||
|
||||
for i in range(len(all_ticks)):
|
||||
for j in range(len(tracks[all_ticks[i]])):
|
||||
results.append(
|
||||
(
|
||||
tracks[all_ticks[i]][j],
|
||||
(
|
||||
0
|
||||
if j != 0
|
||||
else (
|
||||
all_ticks[i] - all_ticks[i - 1] if i != 0 else all_ticks[i]
|
||||
)
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
return [results, max(all_ticks)]
|
||||
18
old-things/Musicreater/old_plugin/schematic.py
Normal file
18
old-things/Musicreater/old_plugin/schematic.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
存放有关Schematic结构生成的内容
|
||||
"""
|
||||
|
||||
"""
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 仓库根目录下的 License.md
|
||||
Terms & Conditions: License.md in the root directory
|
||||
"""
|
||||
|
||||
# 睿乐组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
# import nbtschematic
|
||||
22
old-things/Musicreater/old_plugin/schematic/__init__.py
Normal file
22
old-things/Musicreater/old_plugin/schematic/__init__.py
Normal file
@@ -0,0 +1,22 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
用以生成Schematic结构的附加功能
|
||||
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 仓库根目录下的 License.md
|
||||
Terms & Conditions: License.md in the root directory
|
||||
"""
|
||||
|
||||
# 睿乐组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
|
||||
__all__ = [
|
||||
]
|
||||
__author__ = (("金羿", "Eilles"),)
|
||||
|
||||
from .main import *
|
||||
|
||||
14
old-things/Musicreater/old_plugin/schematic/main.py
Normal file
14
old-things/Musicreater/old_plugin/schematic/main.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 仓库根目录下的 License.md
|
||||
Terms & Conditions: License.md in the root directory
|
||||
"""
|
||||
|
||||
# 睿乐组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
from ..schematic import *
|
||||
21
old-things/Musicreater/old_plugin/websocket/__init__.py
Normal file
21
old-things/Musicreater/old_plugin/websocket/__init__.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
用以启动WebSocket服务器播放的附加功能
|
||||
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 仓库根目录下的 License.md
|
||||
Terms & Conditions: License.md in the root directory
|
||||
"""
|
||||
|
||||
# 睿乐组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
|
||||
__all__ = []
|
||||
__author__ = (("金羿", "Eilles"),)
|
||||
|
||||
from .main import *
|
||||
|
||||
142
old-things/Musicreater/old_plugin/websocket/main.py
Normal file
142
old-things/Musicreater/old_plugin/websocket/main.py
Normal file
@@ -0,0 +1,142 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 仓库根目录下的 License.md
|
||||
Terms & Conditions: License.md in the root directory
|
||||
"""
|
||||
|
||||
# 睿乐组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
|
||||
import asyncio
|
||||
import time
|
||||
import uuid
|
||||
from typing import List, Literal, Optional, Tuple
|
||||
|
||||
import fcwslib
|
||||
|
||||
from ...old_main import MidiConvert
|
||||
from ...subclass import MineCommand, ProgressBarStyle
|
||||
|
||||
|
||||
def to_websocket_server(
|
||||
midi_cvt_lst: List[MidiConvert],
|
||||
server_dist: str,
|
||||
server_port: int,
|
||||
progressbar_style: Optional[ProgressBarStyle],
|
||||
) -> None:
|
||||
"""
|
||||
将midi以延迟播放器形式转换为mcstructure结构文件后打包成附加包,并在附加包中生成相应地导入函数
|
||||
|
||||
Parameters
|
||||
----------
|
||||
midi_cvt: List[MidiConvert]
|
||||
一组用于转换的MidiConvert对象
|
||||
server_dist: str
|
||||
WebSocket播放服务器开启地址
|
||||
server_port: str
|
||||
WebSocket播放服务器开启端口
|
||||
progressbar_style: ProgressBarStyle 对象
|
||||
进度条对象
|
||||
|
||||
Returns
|
||||
-------
|
||||
None
|
||||
"""
|
||||
|
||||
replacement = str(uuid.uuid4())
|
||||
|
||||
musics = dict(
|
||||
[
|
||||
(k.music_name, k.to_command_list_in_delay(replacement)[:2])
|
||||
for k in midi_cvt_lst
|
||||
]
|
||||
)
|
||||
|
||||
class Plugin(fcwslib.Plugin):
|
||||
async def on_connect(self) -> None:
|
||||
print("已成功获连接")
|
||||
await self.send_command("list", callback=self.cmd_feedback)
|
||||
await self.subscribe("PlayerMessage", callback=self.player_message)
|
||||
|
||||
async def on_disconnect(self) -> None:
|
||||
print("连接已然终止")
|
||||
await self.disconnect()
|
||||
|
||||
async def on_receive(self, response) -> None:
|
||||
print("已收取非已知列回复 {}".format(response))
|
||||
|
||||
async def cmd_feedback(self, response) -> None:
|
||||
print("已收取指令执行回复 {}".format(response))
|
||||
|
||||
async def player_message(self, response) -> None:
|
||||
print("已收取玩家事件回复 {}".format(response))
|
||||
if response["body"]["message"].startswith(("。播放", ".play")):
|
||||
whom_to_play: str = response["body"]["sender"]
|
||||
music_to_play: str = (
|
||||
response["body"]["message"]
|
||||
.replace("。播放", "")
|
||||
.replace(".play", "")
|
||||
.strip()
|
||||
)
|
||||
if music_to_play in musics.keys():
|
||||
self.check_play = True
|
||||
delay_of_now = 0
|
||||
now_played_cmd = 0
|
||||
_time = time.time()
|
||||
for i in range(musics[music_to_play][1]):
|
||||
if not self.check_play:
|
||||
break
|
||||
await asyncio.sleep((0.05 - (time.time() - _time)) % 0.05)
|
||||
_time = time.time()
|
||||
if progressbar_style:
|
||||
await self.send_command(
|
||||
"title {} actionbar {}".format(
|
||||
whom_to_play,
|
||||
progressbar_style.play_output(
|
||||
played_delays=i,
|
||||
total_delays=musics[music_to_play][1],
|
||||
music_name=music_to_play,
|
||||
),
|
||||
),
|
||||
callback=self.cmd_feedback,
|
||||
)
|
||||
delay_of_now += 1
|
||||
if (
|
||||
delay_of_now
|
||||
>= (cmd := musics[music_to_play][0][now_played_cmd]).delay
|
||||
):
|
||||
await self.send_command(
|
||||
cmd.command_text.replace(replacement, whom_to_play),
|
||||
callback=self.cmd_feedback,
|
||||
)
|
||||
now_played_cmd += 1
|
||||
delay_of_now = 0
|
||||
|
||||
else:
|
||||
await self.send_command(
|
||||
"tellraw {} {}{}{}".format(
|
||||
whom_to_play,
|
||||
r'{"rawtext":[{"text":"§c§l所选歌曲',
|
||||
music_to_play,
|
||||
'无法播放:播放列表不存在之"}]}',
|
||||
),
|
||||
callback=self.cmd_feedback,
|
||||
)
|
||||
elif response["body"]["message"].startswith(
|
||||
("。停止播放", ".stopplay", ".stoplay")
|
||||
):
|
||||
self.check_play = False
|
||||
|
||||
elif response["body"]["message"].startswith(
|
||||
("。终止连接", ".terminate", ".endconnection")
|
||||
):
|
||||
await self.disconnect()
|
||||
|
||||
server = fcwslib.Server(server=server_dist, port=server_port, debug_mode=True)
|
||||
server.add_plugin(Plugin)
|
||||
asyncio.run(server.run_forever())
|
||||
73
old-things/Musicreater/old_types.py
Normal file
73
old-things/Musicreater/old_types.py
Normal file
@@ -0,0 +1,73 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
存放数据类型的定义
|
||||
"""
|
||||
|
||||
"""
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 仓库根目录下的 License.md
|
||||
Terms & Conditions: License.md in the root directory
|
||||
"""
|
||||
|
||||
# 睿乐组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
from typing import Callable, Dict, List, Literal, Mapping, Tuple, Union
|
||||
|
||||
from .subclass import MineNote
|
||||
|
||||
MidiNoteNameTableType = Mapping[int, Tuple[str, ...]]
|
||||
"""
|
||||
Midi音符名称对照表类型
|
||||
"""
|
||||
|
||||
MidiInstrumentTableType = Mapping[int, str]
|
||||
"""
|
||||
Midi乐器对照表类型
|
||||
"""
|
||||
|
||||
FittingFunctionType = Callable[[float], float]
|
||||
"""
|
||||
拟合函数类型
|
||||
"""
|
||||
|
||||
ChannelType = Dict[
|
||||
int,
|
||||
Dict[
|
||||
int,
|
||||
List[
|
||||
Union[
|
||||
Tuple[Literal["PgmC"], int, int],
|
||||
Tuple[Literal["NoteS"], int, int, int],
|
||||
Tuple[Literal["NoteE"], int, int],
|
||||
]
|
||||
],
|
||||
],
|
||||
]
|
||||
"""
|
||||
以字典所标记的通道信息类型(已弃用)
|
||||
|
||||
Dict[int,Dict[int,List[Union[Tuple[Literal["PgmC"], int, int],Tuple[Literal["NoteS"], int, int, int],Tuple[Literal["NoteE"], int, int],]],],]
|
||||
"""
|
||||
|
||||
|
||||
MineNoteChannelType = Mapping[
|
||||
int,
|
||||
List[MineNote,],
|
||||
]
|
||||
"""
|
||||
我的世界通道信息类型
|
||||
|
||||
Dict[int,Dict[int,List[MineNote,],],]
|
||||
"""
|
||||
|
||||
MineNoteTrackType = Mapping[
|
||||
int,
|
||||
List[MineNote,],
|
||||
]
|
||||
|
||||
|
||||
861
old-things/Musicreater/subclass.py
Normal file
861
old-things/Musicreater/subclass.py
Normal file
@@ -0,0 +1,861 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
存储音·创附属子类
|
||||
"""
|
||||
|
||||
"""
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 仓库根目录下的 License.md
|
||||
Terms & Conditions: License.md in the root directory
|
||||
"""
|
||||
|
||||
# 睿乐组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
from math import sin, cos, asin, radians, degrees, sqrt, atan
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional, Any, List, Tuple, Union, Dict, Sequence
|
||||
|
||||
from .constants import MC_PITCHED_INSTRUMENT_LIST
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class MineNote:
|
||||
"""存储单个音符的类"""
|
||||
|
||||
sound_name: str
|
||||
"""乐器ID"""
|
||||
|
||||
note_pitch: int
|
||||
"""midi音高"""
|
||||
|
||||
velocity: int
|
||||
"""力度"""
|
||||
|
||||
start_tick: int
|
||||
"""开始之时 命令刻"""
|
||||
|
||||
duration: int
|
||||
"""音符持续时间 命令刻"""
|
||||
|
||||
high_precision_time: int
|
||||
"""高精度开始时间偏量 1/1250 秒"""
|
||||
|
||||
percussive: bool
|
||||
"""是否作为打击乐器启用"""
|
||||
|
||||
sound_distance: float
|
||||
"""声源距离 方块"""
|
||||
|
||||
sound_azimuth: Tuple[float, float]
|
||||
"""声源方位 角度"""
|
||||
|
||||
extra_info: Dict[str, Any]
|
||||
"""你觉得放什么好?"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
mc_sound_name: str,
|
||||
midi_pitch: Optional[int],
|
||||
midi_velocity: int,
|
||||
start_time: int,
|
||||
last_time: int,
|
||||
mass_precision_time: int = 0,
|
||||
is_percussion: Optional[bool] = None,
|
||||
distance: Optional[float] = None,
|
||||
azimuth: Optional[Tuple[float, float]] = None,
|
||||
extra_information: Dict[str, Any] = {},
|
||||
):
|
||||
"""
|
||||
用于存储单个音符的类
|
||||
|
||||
Parameters
|
||||
------------
|
||||
mc_sound_name: str
|
||||
《我的世界》声音ID
|
||||
midi_pitch: int
|
||||
midi音高
|
||||
midi_velocity: int
|
||||
midi响度(力度)
|
||||
start_time: int
|
||||
开始之时(命令刻)
|
||||
注:此处的时间是用从乐曲开始到当前的刻数
|
||||
last_time: int
|
||||
音符延续时间(命令刻)
|
||||
mass_precision_time: int
|
||||
高精度的开始时间偏移量(1/1250秒)
|
||||
is_percussion: bool
|
||||
是否作为打击乐器
|
||||
distance: float
|
||||
发声源距离玩家的距离(半径 `r`)
|
||||
注:距离越近,音量越高,默认为 0。此参数可以与音量成某种函数关系。
|
||||
azimuth: tuple[float, float]
|
||||
声源方位
|
||||
注:此参数为tuple,包含两个元素,分别表示:
|
||||
`rV` 发声源在竖直(上下)轴上,从玩家视角正前方开始,向顺时针旋转的角度
|
||||
`rH` 发声源在水平(左右)轴上,从玩家视角正前方开始,向上(到达玩家正上方顶点后变为向下,以此类推的旋转)旋转的角度
|
||||
extra_information: Dict[str, Any]
|
||||
附加信息,尽量存储为字典
|
||||
|
||||
Returns
|
||||
---------
|
||||
MineNote 类
|
||||
"""
|
||||
self.sound_name: str = mc_sound_name
|
||||
"""乐器ID"""
|
||||
self.note_pitch: int = 66 if midi_pitch is None else midi_pitch
|
||||
"""midi音高"""
|
||||
self.velocity: int = midi_velocity
|
||||
"""响度(力度)"""
|
||||
self.start_tick: int = start_time
|
||||
"""开始之时 命令刻"""
|
||||
self.duration: int = last_time
|
||||
"""音符持续时间 命令刻"""
|
||||
self.high_precision_time: int = mass_precision_time
|
||||
"""高精度开始时间偏量 0.4 毫秒"""
|
||||
|
||||
self.percussive = (
|
||||
(mc_sound_name not in MC_PITCHED_INSTRUMENT_LIST)
|
||||
if (is_percussion is None)
|
||||
else is_percussion
|
||||
)
|
||||
"""是否为打击乐器"""
|
||||
|
||||
self.sound_azimuth = (azimuth[0] % 360, azimuth[1] % 360) if azimuth else (0, 0)
|
||||
"""声源方位"""
|
||||
|
||||
# 如果指定为零,那么为零,但如果不指定或者指定为负数,则为 0.01 的距离
|
||||
self.sound_distance = (
|
||||
(16 if distance > 16 else (distance if distance >= 0 else 0.01))
|
||||
if distance is not None
|
||||
else 0.01
|
||||
)
|
||||
"""声源距离"""
|
||||
|
||||
self.extra_info = extra_information if extra_information else {}
|
||||
|
||||
@classmethod
|
||||
def from_traditional(
|
||||
cls,
|
||||
mc_sound_name: str,
|
||||
midi_pitch: Optional[int],
|
||||
midi_velocity: int,
|
||||
start_time: int,
|
||||
last_time: int,
|
||||
mass_precision_time: int = 0,
|
||||
is_percussion: Optional[bool] = None,
|
||||
displacement: Optional[Tuple[float, float, float]] = None,
|
||||
extra_information: Optional[Any] = None,
|
||||
):
|
||||
"""
|
||||
从传统音像位移格式传参,写入用于存储单个音符的类
|
||||
|
||||
Parameters
|
||||
------------
|
||||
mc_sound_name: str
|
||||
《我的世界》声音ID
|
||||
midi_pitch: int
|
||||
midi音高
|
||||
midi_velocity: int
|
||||
midi响度(力度)
|
||||
start_time: int
|
||||
开始之时(命令刻)
|
||||
注:此处的时间是用从乐曲开始到当前的刻数
|
||||
last_time: int
|
||||
音符延续时间(命令刻)
|
||||
mass_precision_time: int
|
||||
高精度的开始时间偏移量(1/1250秒)
|
||||
is_percussion: bool
|
||||
是否作为打击乐器
|
||||
displacement: tuple[float, float, float]
|
||||
声像位移
|
||||
extra_information: Any
|
||||
附加信息,尽量为字典。
|
||||
|
||||
Returns
|
||||
---------
|
||||
MineNote 类
|
||||
"""
|
||||
|
||||
if displacement is None:
|
||||
displacement = (0, 0, 0)
|
||||
r = 0
|
||||
alpha_v = 0
|
||||
beta_h = 0
|
||||
else:
|
||||
r = sqrt(displacement[0] ** 2 + displacement[1] ** 2 + displacement[2] ** 2)
|
||||
if r == 0:
|
||||
alpha_v = 0
|
||||
beta_h = 0
|
||||
else:
|
||||
beta_h = round(degrees(asin(displacement[1] / r)), 8)
|
||||
if displacement[2] == 0:
|
||||
alpha_v = -90 if displacement[0] > 0 else 90
|
||||
else:
|
||||
alpha_v = round(
|
||||
degrees(atan(-displacement[0] / displacement[2])), 8
|
||||
)
|
||||
|
||||
return cls(
|
||||
mc_sound_name=mc_sound_name,
|
||||
midi_pitch=midi_pitch,
|
||||
midi_velocity=midi_velocity,
|
||||
start_time=start_time,
|
||||
last_time=last_time,
|
||||
mass_precision_time=mass_precision_time,
|
||||
is_percussion=is_percussion,
|
||||
distance=r,
|
||||
azimuth=(alpha_v, beta_h),
|
||||
extra_information=(
|
||||
(
|
||||
extra_information
|
||||
if isinstance(extra_information, dict)
|
||||
else {"EXTRA_INFO": extra_information}
|
||||
)
|
||||
if extra_information
|
||||
else {}
|
||||
),
|
||||
)
|
||||
|
||||
@property
|
||||
def position_displacement(self) -> Tuple[float, float, float]:
|
||||
"""声像位移"""
|
||||
dk1 = self.sound_distance * round(cos(radians(self.sound_azimuth[1])), 8)
|
||||
return (
|
||||
-dk1 * round(sin(radians(self.sound_azimuth[0])), 8),
|
||||
self.sound_distance * round(sin(radians(self.sound_azimuth[1])), 8),
|
||||
dk1 * round(cos(radians(self.sound_azimuth[0])), 8),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def decode(cls, code_buffer: bytes, is_high_time_precision: bool = True):
|
||||
"""自字节码析出 MineNote 类"""
|
||||
group_1 = int.from_bytes(code_buffer[:6], "big")
|
||||
percussive_ = bool(group_1 & 0b1)
|
||||
duration_ = (group_1 := group_1 >> 1) & 0b11111111111111111
|
||||
start_tick_ = (group_1 := group_1 >> 17) & 0b11111111111111111
|
||||
note_pitch_ = (group_1 := group_1 >> 17) & 0b1111111
|
||||
sound_name_length = group_1 >> 7
|
||||
|
||||
if code_buffer[6] & 0b1:
|
||||
distance_ = (
|
||||
code_buffer[8 + sound_name_length]
|
||||
if is_high_time_precision
|
||||
else code_buffer[7 + sound_name_length]
|
||||
) / 15
|
||||
|
||||
group_2 = int.from_bytes(
|
||||
(
|
||||
code_buffer[9 + sound_name_length : 14 + sound_name_length]
|
||||
if is_high_time_precision
|
||||
else code_buffer[8 + sound_name_length : 13 + sound_name_length]
|
||||
),
|
||||
"big",
|
||||
)
|
||||
azimuth_ = ((group_2 >> 20) / 2912, (group_2 & 0xFFFFF) / 2912)
|
||||
|
||||
else:
|
||||
distance_ = 0
|
||||
azimuth_ = (0, 0)
|
||||
|
||||
try:
|
||||
return cls(
|
||||
mc_sound_name=(
|
||||
o := (
|
||||
code_buffer[8 : 8 + sound_name_length]
|
||||
if is_high_time_precision
|
||||
else code_buffer[7 : 7 + sound_name_length]
|
||||
)
|
||||
).decode(encoding="GB18030"),
|
||||
midi_pitch=note_pitch_,
|
||||
midi_velocity=code_buffer[6] >> 1,
|
||||
start_time=start_tick_,
|
||||
last_time=duration_,
|
||||
mass_precision_time=code_buffer[7] if is_high_time_precision else 0,
|
||||
is_percussion=percussive_,
|
||||
distance=distance_,
|
||||
azimuth=azimuth_,
|
||||
)
|
||||
except:
|
||||
print(code_buffer, "\n", o)
|
||||
raise
|
||||
|
||||
def encode(
|
||||
self, is_displacement_included: bool = True, is_high_time_precision: bool = True
|
||||
) -> bytes:
|
||||
"""
|
||||
将数据打包为字节码
|
||||
|
||||
Parameters
|
||||
------------
|
||||
is_displacement_included: bool
|
||||
是否包含声像偏移数据,默认为**是**
|
||||
is_high_time_precision: bool
|
||||
是否启用高精度,默认为**是**
|
||||
|
||||
Returns
|
||||
---------
|
||||
bytes
|
||||
打包好的字节码
|
||||
"""
|
||||
|
||||
# MineNote 的字节码共有三个顺次版本分别如下
|
||||
|
||||
# 字符串长度 6 位 支持到 63
|
||||
# note_pitch 7 位 支持到 127
|
||||
# start_tick 17 位 支持到 131071 即 109.22583 分钟 合 1.8204305 小时
|
||||
# duration 17 位 支持到 131071 即 109.22583 分钟 合 1.8204305 小时
|
||||
# percussive 长度 1 位 支持到 1
|
||||
# 共 48 位 合 6 字节
|
||||
# +++
|
||||
# velocity 长度 7 位 支持到 127
|
||||
# is_displacement_included 长度 1 位 支持到 1
|
||||
# 共 8 位 合 1 字节
|
||||
# +++
|
||||
# (在第二版中已舍弃)
|
||||
# track_no 长度 8 位 支持到 255 合 1 字节
|
||||
# (在第二版中新增)
|
||||
# high_time_precision(可选)长度 8 位 支持到 255 合 1 字节 支持 1/1250 秒
|
||||
# +++
|
||||
# sound_name 长度最多 63 支持到 31 个中文字符 或 63 个西文字符
|
||||
# 第一版编码: UTF-8
|
||||
# 第二版编码: GB18030
|
||||
# +++
|
||||
# (在第三版中已废弃)
|
||||
# position_displacement 每个元素长 16 位 合 2 字节
|
||||
# 共 48 位 合 6 字节 支持存储三位小数和两位整数,其值必须在 [0, 65.535] 之间
|
||||
# (在第三版中新增)
|
||||
# sound_distance 8 位 支持到 255 即 16 格 合 1 字节(按值放大 15 倍存储,精度可达 1 / 15)
|
||||
# sound_azimuth 每个元素长 20 位 共 40 位 合 5 字节。每个值放大 2912 倍存储,即支持到 360.08756868131866 度,精度同理
|
||||
|
||||
return (
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
len(
|
||||
r := self.sound_name.encode(
|
||||
encoding="GB18030"
|
||||
)
|
||||
)
|
||||
<< 7
|
||||
)
|
||||
+ self.note_pitch
|
||||
)
|
||||
<< 17
|
||||
)
|
||||
+ self.start_tick
|
||||
)
|
||||
<< 17
|
||||
)
|
||||
+ self.duration
|
||||
)
|
||||
<< 1
|
||||
)
|
||||
+ self.percussive
|
||||
).to_bytes(6, "big")
|
||||
+ ((self.velocity << 1) + is_displacement_included).to_bytes(1, "big")
|
||||
# + self.track_no.to_bytes(1, "big")
|
||||
+ (
|
||||
self.high_precision_time.to_bytes(1, "big")
|
||||
if is_high_time_precision
|
||||
else b""
|
||||
)
|
||||
+ r
|
||||
+ (
|
||||
(
|
||||
round(self.sound_distance * 15).to_bytes(1, "big")
|
||||
+ (
|
||||
(round(self.sound_azimuth[0] * 2912) << 20)
|
||||
+ round(self.sound_azimuth[1] * 2912)
|
||||
).to_bytes(5, "big")
|
||||
)
|
||||
if is_displacement_included
|
||||
else b""
|
||||
)
|
||||
)
|
||||
|
||||
def set_info(self, key: Union[str, Sequence[str]], value: Any):
|
||||
"""设置附加信息"""
|
||||
if isinstance(key, str):
|
||||
self.extra_info[key] = value
|
||||
elif (
|
||||
isinstance(key, Sequence)
|
||||
and isinstance(value, Sequence)
|
||||
and (k := len(key)) == len(value)
|
||||
):
|
||||
for i in range(k):
|
||||
self.extra_info[key[i]] = value[i]
|
||||
else:
|
||||
# 提供简单报错就行了,如果放一堆 if 语句,降低处理速度
|
||||
raise TypeError("参数类型错误;键:`{}` 值:`{}`".format(key, value))
|
||||
|
||||
def get_info(self, key: str) -> Any:
|
||||
"""获取附加信息"""
|
||||
if key in self.extra_info:
|
||||
return self.extra_info[key]
|
||||
elif "EXTRA_INFO" in self.extra_info:
|
||||
if (
|
||||
isinstance(self.extra_info["EXTRA_INFO"], dict)
|
||||
and key in self.extra_info["EXTRA_INFO"]
|
||||
):
|
||||
return self.extra_info["EXTRA_INFO"].get(key)
|
||||
else:
|
||||
return self.extra_info["EXTRA_INFO"]
|
||||
else:
|
||||
return None
|
||||
|
||||
def stringize(
|
||||
self, include_displacement: bool = False, include_extra_data: bool = False
|
||||
) -> str:
|
||||
return (
|
||||
"{}Note(Instrument = {}, {}Velocity = {}, StartTick = {}, Duration = {}{}".format(
|
||||
"Percussive" if self.percussive else "",
|
||||
self.sound_name,
|
||||
"" if self.percussive else "NotePitch = {}, ".format(self.note_pitch),
|
||||
self.velocity,
|
||||
self.start_tick,
|
||||
self.duration,
|
||||
)
|
||||
+ (
|
||||
", SoundDistance = `r`{}, SoundAzimuth = (`αV`{}, `βH`{})".format(
|
||||
self.sound_distance, *self.sound_azimuth
|
||||
)
|
||||
if include_displacement
|
||||
else ""
|
||||
)
|
||||
+ (", ExtraData = {}".format(self.extra_info) if include_extra_data else "")
|
||||
+ ")"
|
||||
)
|
||||
|
||||
def tuplize(self, is_displacement: bool = False):
|
||||
tuplized = self.__tuple__()
|
||||
return tuplized[:-2] + (tuplized[-2:] if is_displacement else ())
|
||||
|
||||
def __list__(self) -> List:
|
||||
return (
|
||||
[
|
||||
self.percussive,
|
||||
self.sound_name,
|
||||
self.velocity,
|
||||
self.start_tick,
|
||||
self.duration,
|
||||
self.sound_distance,
|
||||
self.sound_azimuth,
|
||||
]
|
||||
if self.percussive
|
||||
else [
|
||||
self.percussive,
|
||||
self.sound_name,
|
||||
self.note_pitch,
|
||||
self.velocity,
|
||||
self.start_tick,
|
||||
self.duration,
|
||||
self.sound_distance,
|
||||
self.sound_azimuth,
|
||||
]
|
||||
)
|
||||
|
||||
def __tuple__(
|
||||
self,
|
||||
) -> Union[
|
||||
Tuple[bool, str, int, int, int, int, float, Tuple[float, float]],
|
||||
Tuple[bool, str, int, int, int, float, Tuple[float, float]],
|
||||
]:
|
||||
return (
|
||||
(
|
||||
self.percussive,
|
||||
self.sound_name,
|
||||
self.velocity,
|
||||
self.start_tick,
|
||||
self.duration,
|
||||
self.sound_distance,
|
||||
self.sound_azimuth,
|
||||
)
|
||||
if self.percussive
|
||||
else (
|
||||
self.percussive,
|
||||
self.sound_name,
|
||||
self.note_pitch,
|
||||
self.velocity,
|
||||
self.start_tick,
|
||||
self.duration,
|
||||
self.sound_distance,
|
||||
self.sound_azimuth,
|
||||
)
|
||||
)
|
||||
|
||||
def __dict__(self):
|
||||
return (
|
||||
{
|
||||
"Percussive": self.percussive,
|
||||
"Instrument": self.sound_name,
|
||||
"Velocity": self.velocity,
|
||||
"StartTick": self.start_tick,
|
||||
"Duration": self.duration,
|
||||
"SoundDistance": self.sound_distance,
|
||||
"SoundAzimuth": self.sound_azimuth,
|
||||
"ExtraData": self.extra_info,
|
||||
}
|
||||
if self.percussive
|
||||
else {
|
||||
"Percussive": self.percussive,
|
||||
"Instrument": self.sound_name,
|
||||
"Pitch": self.note_pitch,
|
||||
"Velocity": self.velocity,
|
||||
"StartTick": self.start_tick,
|
||||
"Duration": self.duration,
|
||||
"SoundDistance": self.sound_distance,
|
||||
"SoundAzimuth": self.sound_azimuth,
|
||||
"ExtraData": self.extra_info,
|
||||
}
|
||||
)
|
||||
|
||||
def __eq__(self, other) -> bool:
|
||||
if not isinstance(other, self.__class__):
|
||||
return False
|
||||
return self.tuplize() == other.tuplize()
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class MineCommand:
|
||||
"""存储单个指令的类"""
|
||||
|
||||
command_text: str
|
||||
"""指令文本"""
|
||||
|
||||
conditional: bool
|
||||
"""执行是否有条件"""
|
||||
|
||||
delay: int
|
||||
"""执行的延迟"""
|
||||
|
||||
annotation_text: str
|
||||
"""指令注释"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
command: str,
|
||||
condition: bool = False,
|
||||
tick_delay: int = 0,
|
||||
annotation: str = "",
|
||||
):
|
||||
"""
|
||||
存储单个指令的类
|
||||
|
||||
Parameters
|
||||
----------
|
||||
command: str
|
||||
指令
|
||||
condition: bool
|
||||
是否有条件
|
||||
tick_delay: int
|
||||
执行延时
|
||||
annotation: str
|
||||
注释
|
||||
"""
|
||||
self.command_text = command
|
||||
self.conditional = condition
|
||||
self.delay = tick_delay
|
||||
self.annotation_text = annotation
|
||||
|
||||
def copy(self):
|
||||
return MineCommand(
|
||||
command=self.command_text,
|
||||
condition=self.conditional,
|
||||
tick_delay=self.delay,
|
||||
annotation=self.annotation_text,
|
||||
)
|
||||
|
||||
@property
|
||||
def cmd(self) -> str:
|
||||
"""
|
||||
我的世界函数字符串(包含注释)
|
||||
"""
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self) -> str:
|
||||
"""
|
||||
转为我的世界函数文件格式(包含注释)
|
||||
"""
|
||||
return "# {cdt}<{delay}> {ant}\n{cmd}".format(
|
||||
cdt="[CDT]" if self.conditional else "",
|
||||
delay=self.delay,
|
||||
ant=self.annotation_text,
|
||||
cmd=self.command_text,
|
||||
)
|
||||
|
||||
def __eq__(self, other) -> bool:
|
||||
if not isinstance(other, self.__class__):
|
||||
return False
|
||||
return self.__str__() == other.__str__()
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class SingleNoteBox:
|
||||
"""存储单个音符盒"""
|
||||
|
||||
instrument_block: str
|
||||
"""乐器方块"""
|
||||
|
||||
note_value: int
|
||||
"""音符盒音高"""
|
||||
|
||||
annotation_text: str
|
||||
"""音符注释"""
|
||||
|
||||
is_percussion: bool
|
||||
"""是否为打击乐器"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
instrument_block_: str,
|
||||
note_value_: int,
|
||||
percussion: Optional[bool] = None,
|
||||
annotation: str = "",
|
||||
):
|
||||
"""
|
||||
用于存储单个音符盒的类
|
||||
|
||||
Parameters
|
||||
------------
|
||||
instrument_block_: str
|
||||
音符盒演奏所使用的乐器方块
|
||||
note_value_: int
|
||||
音符盒的演奏音高
|
||||
percussion: bool
|
||||
此音符盒乐器是否作为打击乐处理
|
||||
注:若为空,则自动识别是否为打击乐器
|
||||
annotation: Any
|
||||
音符注释
|
||||
|
||||
Returns
|
||||
---------
|
||||
SingleNoteBox 类
|
||||
"""
|
||||
|
||||
self.instrument_block = instrument_block_
|
||||
"""乐器方块"""
|
||||
self.note_value = note_value_
|
||||
"""音符盒音高"""
|
||||
self.annotation_text = annotation
|
||||
"""音符注释"""
|
||||
if percussion is None:
|
||||
self.is_percussion = percussion not in MC_PITCHED_INSTRUMENT_LIST
|
||||
else:
|
||||
self.is_percussion = percussion
|
||||
|
||||
@property
|
||||
def inst(self) -> str:
|
||||
"""获取音符盒下的乐器方块"""
|
||||
return self.instrument_block
|
||||
|
||||
@inst.setter
|
||||
def inst(self, inst_):
|
||||
self.instrument_block = inst_
|
||||
|
||||
@property
|
||||
def note(self) -> int:
|
||||
"""获取音符盒音调特殊值"""
|
||||
return self.note_value
|
||||
|
||||
@note.setter
|
||||
def note(self, note_):
|
||||
self.note_value = note_
|
||||
|
||||
@property
|
||||
def annotation(self) -> str:
|
||||
"""获取音符盒的备注"""
|
||||
return self.annotation_text
|
||||
|
||||
@annotation.setter
|
||||
def annotation(self, annotation_):
|
||||
self.annotation_text = annotation_
|
||||
|
||||
def copy(self):
|
||||
return SingleNoteBox(
|
||||
instrument_block_=self.instrument_block,
|
||||
note_value_=self.note_value,
|
||||
annotation=self.annotation_text,
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"Note(inst = {self.inst}, note = {self.note}, )"
|
||||
|
||||
def __tuple__(self) -> tuple:
|
||||
return self.inst, self.note, self.annotation
|
||||
|
||||
def __dict__(self) -> dict:
|
||||
return {
|
||||
"inst": self.inst,
|
||||
"note": self.note,
|
||||
"annotation": self.annotation,
|
||||
}
|
||||
|
||||
def __eq__(self, other) -> bool:
|
||||
if not isinstance(other, self.__class__):
|
||||
return False
|
||||
return self.__str__() == other.__str__()
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class ProgressBarStyle:
|
||||
"""进度条样式类"""
|
||||
|
||||
base_style: str
|
||||
"""基础样式"""
|
||||
|
||||
to_play_style: str
|
||||
"""未播放之样式"""
|
||||
|
||||
played_style: str
|
||||
"""已播放之样式"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
base_s: Optional[str] = None,
|
||||
to_play_s: Optional[str] = None,
|
||||
played_s: Optional[str] = None,
|
||||
):
|
||||
"""
|
||||
用于存储进度条样式的类
|
||||
|
||||
| 标识符 | 指定的可变量 |
|
||||
|---------|----------------|
|
||||
| `%%N` | 乐曲名(即传入的文件名)|
|
||||
| `%%s` | 当前计分板值 |
|
||||
| `%^s` | 计分板最大值 |
|
||||
| `%%t` | 当前播放时间 |
|
||||
| `%^t` | 曲目总时长 |
|
||||
| `%%%` | 当前进度比率 |
|
||||
| `_` | 用以表示进度条占位|
|
||||
|
||||
Parameters
|
||||
------------
|
||||
base_s: str
|
||||
基础样式,用以定义进度条整体
|
||||
to_play_s: str
|
||||
进度条样式:尚未播放的样子
|
||||
played_s: str
|
||||
已经播放的样子
|
||||
|
||||
Returns
|
||||
---------
|
||||
ProgressBarStyle 类
|
||||
"""
|
||||
|
||||
self.base_style = (
|
||||
base_s if base_s else r"▶ %%N [ %%s/%^s %%% §e__________§r %%t|%^t ]"
|
||||
)
|
||||
self.to_play_style = to_play_s if to_play_s else r"§7="
|
||||
self.played_style = played_s if played_s else r"="
|
||||
|
||||
@classmethod
|
||||
def from_tuple(cls, tuplized_style: Optional[Tuple[str, Tuple[str, str]]]):
|
||||
"""自旧版进度条元组表示法读入数据(已不建议使用)"""
|
||||
|
||||
if tuplized_style is None:
|
||||
return cls(
|
||||
r"▶ %%N [ %%s/%^s %%% §e__________§r %%t|%^t ]",
|
||||
r"§7=",
|
||||
r"=",
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
def set_to_play_style(self, value: str):
|
||||
"""设置未播放之样式"""
|
||||
self.to_play_style = value
|
||||
|
||||
def set_played_style(self, value: str):
|
||||
"""设置已播放之样式"""
|
||||
self.played_style = value
|
||||
|
||||
def copy(self):
|
||||
dst = ProgressBarStyle(self.base_style, self.to_play_style, self.played_style)
|
||||
return dst
|
||||
|
||||
def play_output(
|
||||
self,
|
||||
played_delays: int,
|
||||
total_delays: int,
|
||||
music_name: str = "无题",
|
||||
) -> str:
|
||||
"""
|
||||
直接依照此格式输出一个进度条
|
||||
|
||||
Parameters
|
||||
------------
|
||||
played_delays: int
|
||||
当前播放进度积分值
|
||||
total_delays: int
|
||||
乐器总延迟数(计分板值)
|
||||
music_name: str
|
||||
曲名
|
||||
|
||||
Returns
|
||||
---------
|
||||
str
|
||||
进度条字符串
|
||||
"""
|
||||
|
||||
return (
|
||||
self.base_style.replace(r"%%N", music_name)
|
||||
.replace(r"%%s", str(played_delays))
|
||||
.replace(r"%^s", str(total_delays))
|
||||
.replace(r"%%t", mctick2timestr(played_delays))
|
||||
.replace(r"%^t", mctick2timestr(total_delays))
|
||||
.replace(
|
||||
r"%%%",
|
||||
"{:0>5.2f}%".format(int(10000 * played_delays / total_delays) / 100),
|
||||
)
|
||||
.replace(
|
||||
"_",
|
||||
self.played_style,
|
||||
(played_delays * self.base_style.count("_") // total_delays) + 1,
|
||||
)
|
||||
.replace("_", self.to_play_style)
|
||||
)
|
||||
|
||||
|
||||
def mctick2timestr(mc_tick: int) -> str:
|
||||
"""
|
||||
将《我的世界》的游戏刻计转为表示时间的字符串
|
||||
"""
|
||||
return "{:0>2d}:{:0>2d}".format(mc_tick // 1200, (mc_tick // 20) % 60)
|
||||
|
||||
|
||||
DEFAULT_PROGRESSBAR_STYLE = ProgressBarStyle(
|
||||
r"▶ %%N [ %%s/%^s %%% §e__________§r %%t|%^t ]",
|
||||
r"§7=",
|
||||
r"=",
|
||||
)
|
||||
"""
|
||||
默认的进度条样式
|
||||
"""
|
||||
1029
old-things/Musicreater/utils.py
Normal file
1029
old-things/Musicreater/utils.py
Normal file
File diff suppressed because it is too large
Load Diff
BIN
old-things/Packer/MSCT_MAIN.MPK
Normal file
BIN
old-things/Packer/MSCT_MAIN.MPK
Normal file
Binary file not shown.
BIN
old-things/Packer/MSCT_PLUGIN.MPK
Normal file
BIN
old-things/Packer/MSCT_PLUGIN.MPK
Normal file
Binary file not shown.
1
old-things/Packer/MSCT_PLUGIN_FUNCTION.MPK
Normal file
1
old-things/Packer/MSCT_PLUGIN_FUNCTION.MPK
Normal file
@@ -0,0 +1 @@
|
||||
q@v,fxіБ<D196>Еџ<D095>лцmЩ5]Ќs"ЏџЦбBMXi<58>ЈnНхч<D185>Z8О=Г<7F>4<EFBFBD>PTUБQЈmтфджG<D0B6>жu_цп<D186>DS№|
|
||||
68
old-things/Packer/MSCT_Packer.py
Normal file
68
old-things/Packer/MSCT_Packer.py
Normal file
@@ -0,0 +1,68 @@
|
||||
import Musicreater.old_init as old_init
|
||||
import Musicreater.experiment
|
||||
import Musicreater.old_plugin
|
||||
|
||||
# import Musicreater.previous
|
||||
from Musicreater.old_plugin.addonpack import (
|
||||
to_addon_pack_in_delay,
|
||||
to_addon_pack_in_repeater,
|
||||
to_addon_pack_in_score,
|
||||
)
|
||||
from Musicreater.old_plugin.bdxfile import to_BDX_file_in_delay, to_BDX_file_in_score
|
||||
from Musicreater.old_plugin.mcstructfile import (
|
||||
to_mcstructure_file_in_delay,
|
||||
to_mcstructure_file_in_repeater,
|
||||
to_mcstructure_file_in_score,
|
||||
)
|
||||
|
||||
MSCT_MAIN = (
|
||||
old_init,
|
||||
old_init.experiment,
|
||||
# Musicreater.previous,
|
||||
)
|
||||
|
||||
MSCT_PLUGIN = (old_init.old_plugin,)
|
||||
|
||||
MSCT_PLUGIN_FUNCTION = (
|
||||
to_addon_pack_in_delay,
|
||||
to_addon_pack_in_repeater,
|
||||
to_addon_pack_in_score,
|
||||
to_mcstructure_file_in_delay,
|
||||
to_mcstructure_file_in_repeater,
|
||||
to_mcstructure_file_in_score,
|
||||
to_BDX_file_in_delay,
|
||||
to_BDX_file_in_score,
|
||||
)
|
||||
|
||||
import hashlib
|
||||
|
||||
import brotli
|
||||
import dill
|
||||
|
||||
|
||||
def enpack_msct_pack(sth, to_dist: str):
|
||||
packing_bytes = brotli.compress(
|
||||
dill.dumps(
|
||||
sth,
|
||||
)
|
||||
)
|
||||
with open(
|
||||
to_dist,
|
||||
"wb",
|
||||
) as f:
|
||||
f.write(packing_bytes)
|
||||
|
||||
return hashlib.sha256(packing_bytes)
|
||||
|
||||
|
||||
with open("./Packer/checksum.txt", "w", encoding="utf-8") as f:
|
||||
f.write("MSCT_MAIN:\n")
|
||||
f.write(enpack_msct_pack(MSCT_MAIN, "./Packer/MSCT_MAIN.MPK").hexdigest())
|
||||
f.write("\nMSCT_PLUGIN:\n")
|
||||
f.write(enpack_msct_pack(MSCT_PLUGIN, "./Packer/MSCT_PLUGIN.MPK").hexdigest())
|
||||
f.write("\nMSCT_PLUGIN_FUNCTION:\n")
|
||||
f.write(
|
||||
enpack_msct_pack(
|
||||
MSCT_PLUGIN_FUNCTION, "./Packer/MSCT_PLUGIN_FUNCTION.MPK"
|
||||
).hexdigest()
|
||||
)
|
||||
6
old-things/Packer/checksum.txt
Normal file
6
old-things/Packer/checksum.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
MSCT_MAIN:
|
||||
6b9f5a97d50beb07c834e375104c67ae44c57ae40f73fb71075b3668899029c7
|
||||
MSCT_PLUGIN:
|
||||
c280413a394a539438a5d10078c9b55f04bcd4cf6869c59a3f7a026039748cfc
|
||||
MSCT_PLUGIN_FUNCTION:
|
||||
40697f1d9b293268fe142fa3e9bffee2923a8f4811ec7bbdf7b14afb98723ef2
|
||||
0
old-things/bgArrayLib/__init__.py
Normal file
0
old-things/bgArrayLib/__init__.py
Normal file
67
old-things/bgArrayLib/bpm.py
Normal file
67
old-things/bgArrayLib/bpm.py
Normal file
@@ -0,0 +1,67 @@
|
||||
import mido
|
||||
import numpy
|
||||
|
||||
'''
|
||||
bpm
|
||||
bites per minutes
|
||||
每分钟的拍数
|
||||
'''
|
||||
|
||||
def mt2gt(mt, tpb_a, bpm_a):
|
||||
return round(mt / tpb_a / bpm_a * 60)
|
||||
|
||||
|
||||
def get(mid:mido.MidiFile) -> int:
|
||||
'''传入一个 MidiFile, 返回其音乐的bpm
|
||||
:param mid : mido.MidFile
|
||||
mido库识别的midi文件数据
|
||||
:return bpm : int
|
||||
'''
|
||||
# mid = mido.MidiFile(mf)
|
||||
length = mid.length
|
||||
tpb = mid.ticks_per_beat
|
||||
bpm = 20
|
||||
gotV = 0
|
||||
|
||||
for track in mid.tracks:
|
||||
global_time = 0
|
||||
for msg in track:
|
||||
global_time += msg.time
|
||||
if msg.type == "note_on" and msg.velocity > 0:
|
||||
gotV = mt2gt(global_time, tpb, bpm)
|
||||
errorV = numpy.fabs(gotV - length)
|
||||
last_dic = {bpm: errorV}
|
||||
if last_dic.get(bpm) > errorV:
|
||||
last_dic = {bpm: errorV}
|
||||
bpm += 2
|
||||
|
||||
while True:
|
||||
for track in mid.tracks:
|
||||
global_time = 0
|
||||
for msg in track:
|
||||
global_time += msg.time
|
||||
if msg.type == "note_on" and msg.velocity > 0:
|
||||
gotV = mt2gt(global_time, tpb, bpm)
|
||||
errorV = numpy.fabs(gotV - length)
|
||||
try:
|
||||
if last_dic.get(bpm - 2) > errorV:
|
||||
last_dic = {bpm: errorV}
|
||||
except TypeError:
|
||||
pass
|
||||
bpm += 2
|
||||
if bpm >= 252:
|
||||
break
|
||||
print(list(last_dic.keys())[0])
|
||||
return list(last_dic.keys())[0]
|
||||
|
||||
|
||||
def compute(mid:mido.MidiFile):
|
||||
answer = 60000000/mid.ticks_per_beat
|
||||
print(answer)
|
||||
return answer
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
mid = mido.MidiFile(r"C:\Users\lc\Documents\MuseScore3\乐谱\乐谱\Bad style - Time back.mid")
|
||||
get(mid)
|
||||
compute(mid)
|
||||
40
old-things/bgArrayLib/compute.py
Normal file
40
old-things/bgArrayLib/compute.py
Normal file
@@ -0,0 +1,40 @@
|
||||
def round_up(num, power=0):
|
||||
"""
|
||||
实现精确四舍五入,包含正、负小数多种场景
|
||||
:param num: 需要四舍五入的小数
|
||||
:param power: 四舍五入位数,支持0-∞
|
||||
:return: 返回四舍五入后的结果
|
||||
"""
|
||||
try:
|
||||
print(1 / 0)
|
||||
except ZeroDivisionError:
|
||||
digit = 10 ** power
|
||||
num2 = float(int(num * digit))
|
||||
# 处理正数,power不为0的情况
|
||||
if num >= 0 and power != 0:
|
||||
tag = num * digit - num2 + 1 / (digit * 10)
|
||||
if tag >= 0.5:
|
||||
return (num2 + 1) / digit
|
||||
else:
|
||||
return num2 / digit
|
||||
# 处理正数,power为0取整的情况
|
||||
elif num >= 0 and power == 0:
|
||||
tag = num * digit - int(num)
|
||||
if tag >= 0.5:
|
||||
return (num2 + 1) / digit
|
||||
else:
|
||||
return num2 / digit
|
||||
# 处理负数,power为0取整的情况
|
||||
elif power == 0 and num < 0:
|
||||
tag = num * digit - int(num)
|
||||
if tag <= -0.5:
|
||||
return (num2 - 1) / digit
|
||||
else:
|
||||
return num2 / digit
|
||||
# 处理负数,power不为0的情况
|
||||
else:
|
||||
tag = num * digit - num2 - 1 / (digit * 10)
|
||||
if tag <= -0.5:
|
||||
return (num2 - 1) / digit
|
||||
else:
|
||||
return num2 / digit
|
||||
130
old-things/bgArrayLib/instrumentConstant.py
Normal file
130
old-things/bgArrayLib/instrumentConstant.py
Normal file
@@ -0,0 +1,130 @@
|
||||
instrument_list = {
|
||||
"0": "harp",
|
||||
"1": "harp",
|
||||
"2": "pling",
|
||||
"3": "harp",
|
||||
"4": "pling",
|
||||
"5": "pling",
|
||||
"6": "harp",
|
||||
"7": "harp",
|
||||
"8": "share",
|
||||
"9": "harp",
|
||||
"10": "didgeridoo",
|
||||
"11": "harp",
|
||||
"12": "xylophone",
|
||||
"13": "chime",
|
||||
"14": "harp",
|
||||
"15": "harp",
|
||||
"16": "bass",
|
||||
"17": "harp",
|
||||
"18": "harp",
|
||||
"19": "harp",
|
||||
"20": "harp",
|
||||
"21": "harp",
|
||||
"22": "harp",
|
||||
"23": "guitar",
|
||||
"24": "guitar",
|
||||
"25": "guitar",
|
||||
"26": "guitar",
|
||||
"27": "guitar",
|
||||
"28": "guitar",
|
||||
"29": "guitar",
|
||||
"30": "guitar",
|
||||
"31": "bass",
|
||||
"32": "bass",
|
||||
"33": "bass",
|
||||
"34": "bass",
|
||||
"35": "bass",
|
||||
"36": "bass",
|
||||
"37": "bass",
|
||||
"38": "bass",
|
||||
"39": "bass",
|
||||
"40": "harp",
|
||||
"41": "harp",
|
||||
"42": "harp",
|
||||
"43": "harp",
|
||||
"44": "iron_xylophone",
|
||||
"45": "guitar",
|
||||
"46": "harp",
|
||||
"47": "harp",
|
||||
"48": "guitar",
|
||||
"49": "guitar",
|
||||
"50": "bit",
|
||||
"51": "bit",
|
||||
"52": "harp",
|
||||
"53": "harp",
|
||||
"54": "bit",
|
||||
"55": "flute",
|
||||
"56": "flute",
|
||||
"57": "flute",
|
||||
"58": "flute",
|
||||
"59": "flute",
|
||||
"60": "flute",
|
||||
"61": "flute",
|
||||
"62": "flute",
|
||||
"63": "flute",
|
||||
"64": "bit",
|
||||
"65": "bit",
|
||||
"66": "bit",
|
||||
"67": "bit",
|
||||
"68": "flute",
|
||||
"69": "harp",
|
||||
"70": "harp",
|
||||
"71": "flute",
|
||||
"72": "flute",
|
||||
"73": "flute",
|
||||
"74": "harp",
|
||||
"75": "flute",
|
||||
"76": "harp",
|
||||
"77": "harp",
|
||||
"78": "harp",
|
||||
"79": "harp",
|
||||
"80": "bit",
|
||||
"81": "bit",
|
||||
"82": "bit",
|
||||
"83": "bit",
|
||||
"84": "bit",
|
||||
"85": "bit",
|
||||
"86": "bit",
|
||||
"87": "bit",
|
||||
"88": "bit",
|
||||
"89": "bit",
|
||||
"90": "bit",
|
||||
"91": "bit",
|
||||
"92": "bit",
|
||||
"93": "bit",
|
||||
"94": "bit",
|
||||
"95": "bit",
|
||||
"96": "bit",
|
||||
"97": "bit",
|
||||
"98": "bit",
|
||||
"99": "bit",
|
||||
"100": "bit",
|
||||
"101": "bit",
|
||||
"102": "bit",
|
||||
"103": "bit",
|
||||
"104": "harp",
|
||||
"105": "banjo",
|
||||
"106": "harp",
|
||||
"107": "harp",
|
||||
"108": "harp",
|
||||
"109": "harp",
|
||||
"110": "harp",
|
||||
"111": "guitar",
|
||||
"112": "harp",
|
||||
"113": "bell",
|
||||
"114": "harp",
|
||||
"115": "cow_bell",
|
||||
"116": "basedrum",
|
||||
"117": "bass",
|
||||
"118": "bit",
|
||||
"119": "basedrum",
|
||||
"120": "guitar",
|
||||
"121": "harp",
|
||||
"122": "harp",
|
||||
"123": "harp",
|
||||
"124": "harp",
|
||||
"125": "hat",
|
||||
"126": "basedrum",
|
||||
"127": "snare",
|
||||
}
|
||||
250
old-things/bgArrayLib/namesConstant.py
Normal file
250
old-things/bgArrayLib/namesConstant.py
Normal file
@@ -0,0 +1,250 @@
|
||||
zip_name = {
|
||||
-1: "-1.Acoustic_Kit_打击乐.zip",
|
||||
0: "0.Acoustic_Grand_Piano_大钢琴.zip",
|
||||
1: "1.Bright_Acoustic_Piano_亮音大钢琴.zip",
|
||||
10: "10.Music_Box_八音盒.zip",
|
||||
100: "100.FX_brightness_合成特效-亮音.zip",
|
||||
101: "101.FX_goblins_合成特效-小妖.zip",
|
||||
102: "102.FX_echoes_合成特效-回声.zip",
|
||||
103: "103.FX_sci-fi_合成特效-科幻.zip",
|
||||
104: "104.Sitar_锡塔尔.zip",
|
||||
105: "105.Banjo_班卓.zip",
|
||||
106: "106.Shamisen_三味线.zip",
|
||||
107: "107.Koto_筝.zip",
|
||||
108: "108.Kalimba_卡林巴.zip",
|
||||
109: "109.Bagpipe_风笛.zip",
|
||||
11: "11.Vibraphone_电颤琴.zip",
|
||||
110: "110.Fiddle_古提琴.zip",
|
||||
111: "111.Shanai_唢呐.zip",
|
||||
112: "112.Tinkle_Bell_铃铛.zip",
|
||||
113: "113.Agogo_拉丁打铃.zip",
|
||||
114: "114.Steel_Drums_钢鼓.zip",
|
||||
115: "115.Woodblock_木块.zip",
|
||||
116: "116.Taiko_Drum_太鼓.zip",
|
||||
117: "117.Melodic_Tom_嗵鼓.zip",
|
||||
118: "118.Synth_Drum_合成鼓.zip",
|
||||
119: "119.Reverse_Cymbal_镲波形反转.zip",
|
||||
12: "12.Marimba_马林巴.zip",
|
||||
13: "13.Xylophone_木琴.zip",
|
||||
14: "14.Tubular_Bells_管钟.zip",
|
||||
15: "15.Dulcimer_扬琴.zip",
|
||||
16: "16.Drawbar_Organ_击杆风琴.zip",
|
||||
17: "17.Percussive_Organ_打击型风琴.zip",
|
||||
18: "18.Rock_Organ_摇滚风琴.zip",
|
||||
19: "19.Church_Organ_管风琴.zip",
|
||||
2: "2.Electric_Grand_Piano_电子大钢琴.zip",
|
||||
20: "20.Reed_Organ_簧风琴.zip",
|
||||
21: "21.Accordion_手风琴.zip",
|
||||
22: "22.Harmonica_口琴.zip",
|
||||
23: "23.Tango_Accordian_探戈手风琴.zip",
|
||||
24: "24.Acoustic_Guitar_(nylon)_尼龙弦吉他.zip",
|
||||
25: "25.Acoustic_Guitar(steel)_钢弦吉他.zip",
|
||||
26: "26.Electric_Guitar_(jazz)_爵士乐电吉他.zip",
|
||||
27: "27.Electric_Guitar_(clean)_清音电吉他.zip",
|
||||
28: "28.Electric_Guitar_(muted)_弱音电吉他.zip",
|
||||
29: "29.Overdriven_Guitar_驱动音效吉他.zip",
|
||||
3: "3.Honky-Tonk_Piano_酒吧钢琴.zip",
|
||||
30: "30.Distortion_Guitar_失真音效吉他.zip",
|
||||
31: "31.Guitar_Harmonics_吉他泛音.zip",
|
||||
32: "32.Acoustic_Bass_原声贝司.zip",
|
||||
33: "33.Electric_Bass(finger)_指拨电贝司.zip",
|
||||
34: "34.Electric_Bass(pick)_拨片拨电贝司.zip",
|
||||
35: "35.Fretless_Bass_无品贝司.zip",
|
||||
36: "36.Slap_Bass_A_击弦贝司A.zip",
|
||||
37: "37.Slap_Bass_B_击弦贝司B.zip",
|
||||
38: "38.Synth_Bass_A_合成贝司A.zip",
|
||||
39: "39.Synth_Bass_B_合成贝司B.zip",
|
||||
4: "4.Electric_Piano_1_电钢琴A.zip",
|
||||
40: "40.Violin_小提琴.zip",
|
||||
41: "41.Viola_中提琴.zip",
|
||||
42: "42.Cello_大提琴.zip",
|
||||
43: "43.Contrabass_低音提琴.zip",
|
||||
44: "44.Tremolo_Strings_弦乐震音.zip",
|
||||
45: "45.Pizzicato_Strings_弦乐拨奏.zip",
|
||||
46: "46.Orchestral_Harp_竖琴.zip",
|
||||
47: "47.Timpani_定音鼓.zip",
|
||||
48: "48.String_Ensemble_A_弦乐合奏A.zip",
|
||||
49: "49.String_Ensemble_B_弦乐合奏B.zip",
|
||||
5: "5.Electric_Piano_2_电钢琴B.zip",
|
||||
50: "50.SynthStrings_A_合成弦乐A.zip",
|
||||
51: "51.SynthStrings_B_合成弦乐B.zip",
|
||||
52: "52.Choir_Aahs_合唱“啊”音.zip",
|
||||
53: "53.Voice_Oohs_人声“哦”音.zip",
|
||||
54: "54.Synth_Voice_合成人声.zip",
|
||||
55: "55.Orchestra_Hit_乐队打击乐.zip",
|
||||
56: "56.Trumpet_小号.zip",
|
||||
57: "57.Trombone_长号.zip",
|
||||
58: "58.Tuba_大号.zip",
|
||||
59: "59.Muted_Trumpet_弱音小号.zip",
|
||||
6: "6.Harpsichord_拨弦古钢琴.zip",
|
||||
60: "60.French_Horn_圆号.zip",
|
||||
61: "61.Brass_Section_铜管组.zip",
|
||||
62: "62.Synth_Brass_A_合成铜管A.zip",
|
||||
63: "63.Synth_Brass_A_合成铜管B.zip",
|
||||
64: "64.Soprano_Sax_高音萨克斯.zip",
|
||||
65: "65.Alto_Sax_中音萨克斯.zip",
|
||||
66: "66.Tenor_Sax_次中音萨克斯.zip",
|
||||
67: "67.Baritone_Sax_上低音萨克斯.zip",
|
||||
68: "68.Oboe_双簧管.zip",
|
||||
69: "69.English_Horn_英国管.zip",
|
||||
7: "7.Clavinet_击弦古钢琴.zip",
|
||||
70: "70.Bassoon_大管.zip",
|
||||
71: "71.Clarinet_单簧管.zip",
|
||||
72: "72.Piccolo_短笛.zip",
|
||||
73: "73.Flute_长笛.zip",
|
||||
74: "74.Recorder_竖笛.zip",
|
||||
75: "75.Pan_Flute_排笛.zip",
|
||||
76: "76.Bottle_Blow_吹瓶口.zip",
|
||||
77: "77.Skakuhachi_尺八.zip",
|
||||
78: "78.Whistle_哨.zip",
|
||||
79: "79.Ocarina_洋埙.zip",
|
||||
8: "8.Celesta_钢片琴.zip",
|
||||
80: "80.Lead_square_合成主音-方波.zip",
|
||||
81: "81.Lead_sawtooth_合成主音-锯齿波.zip",
|
||||
82: "82.Lead_calliope_lead_合成主音-汽笛风琴.zip",
|
||||
83: "83.Lead_chiff_lead_合成主音-吹管.zip",
|
||||
84: "84.Lead_charang_合成主音5-吉他.zip",
|
||||
85: "85.Lead_voice_合成主音-人声.zip",
|
||||
86: "86.Lead_fifths_合成主音-五度.zip",
|
||||
87: "87.Lead_bass+lead_合成主音-低音加主音.zip",
|
||||
88: "88.Pad_new_age_合成柔音-新时代.zip",
|
||||
89: "89.Pad_warm_合成柔音-暖音.zip",
|
||||
9: "9.Glockenspiel_钟琴.zip",
|
||||
90: "90.Pad_polysynth_合成柔音-复合成.zip",
|
||||
91: "91.Pad_choir_合成柔音-合唱.zip",
|
||||
92: "92.Pad_bowed_合成柔音-弓弦.zip",
|
||||
93: "93.Pad_metallic_合成柔音-金属.zip",
|
||||
94: "94.Pad_halo_合成柔音-光环.zip",
|
||||
95: "95.Pad_sweep_合成柔音-扫弦.zip",
|
||||
96: "96.FX_rain_合成特效-雨.zip",
|
||||
97: "97.FX_soundtrack_合成特效-音轨.zip",
|
||||
98: "98.FX_crystal_合成特效-水晶.zip",
|
||||
99: "99.FX_atmosphere_合成特效-大气.zip",
|
||||
}
|
||||
|
||||
mcpack_name = {
|
||||
-1: "-1.Acoustic_Kit_打击乐.mcpack",
|
||||
0: "0.Acoustic_Grand_Piano_大钢琴.mcpack",
|
||||
1: "1.Bright_Acoustic_Piano_亮音大钢琴.mcpack",
|
||||
10: "10.Music_Box_八音盒.mcpack",
|
||||
100: "100.FX_brightness_合成特效-亮音.mcpack",
|
||||
101: "101.FX_goblins_合成特效-小妖.mcpack",
|
||||
102: "102.FX_echoes_合成特效-回声.mcpack",
|
||||
103: "103.FX_sci-fi_合成特效-科幻.mcpack",
|
||||
104: "104.Sitar_锡塔尔.mcpack",
|
||||
105: "105.Banjo_班卓.mcpack",
|
||||
106: "106.Shamisen_三味线.mcpack",
|
||||
107: "107.Koto_筝.mcpack",
|
||||
108: "108.Kalimba_卡林巴.mcpack",
|
||||
109: "109.Bagpipe_风笛.mcpack",
|
||||
11: "11.Vibraphone_电颤琴.mcpack",
|
||||
110: "110.Fiddle_古提琴.mcpack",
|
||||
111: "111.Shanai_唢呐.mcpack",
|
||||
112: "112.Tinkle_Bell_铃铛.mcpack",
|
||||
113: "113.Agogo_拉丁打铃.mcpack",
|
||||
114: "114.Steel_Drums_钢鼓.mcpack",
|
||||
115: "115.Woodblock_木块.mcpack",
|
||||
116: "116.Taiko_Drum_太鼓.mcpack",
|
||||
117: "117.Melodic_Tom_嗵鼓.mcpack",
|
||||
118: "118.Synth_Drum_合成鼓.mcpack",
|
||||
119: "119.Reverse_Cymbal_镲波形反转.mcpack",
|
||||
12: "12.Marimba_马林巴.mcpack",
|
||||
13: "13.Xylophone_木琴.mcpack",
|
||||
14: "14.Tubular_Bells_管钟.mcpack",
|
||||
15: "15.Dulcimer_扬琴.mcpack",
|
||||
16: "16.Drawbar_Organ_击杆风琴.mcpack",
|
||||
17: "17.Percussive_Organ_打击型风琴.mcpack",
|
||||
18: "18.Rock_Organ_摇滚风琴.mcpack",
|
||||
19: "19.Church_Organ_管风琴.mcpack",
|
||||
2: "2.Electric_Grand_Piano_电子大钢琴.mcpack",
|
||||
20: "20.Reed_Organ_簧风琴.mcpack",
|
||||
21: "21.Accordion_手风琴.mcpack",
|
||||
22: "22.Harmonica_口琴.mcpack",
|
||||
23: "23.Tango_Accordian_探戈手风琴.mcpack",
|
||||
24: "24.Acoustic_Guitar_(nylon)_尼龙弦吉他.mcpack",
|
||||
25: "25.Acoustic_Guitar(steel)_钢弦吉他.mcpack",
|
||||
26: "26.Electric_Guitar_(jazz)_爵士乐电吉他.mcpack",
|
||||
27: "27.Electric_Guitar_(clean)_清音电吉他.mcpack",
|
||||
28: "28.Electric_Guitar_(muted)_弱音电吉他.mcpack",
|
||||
29: "29.Overdriven_Guitar_驱动音效吉他.mcpack",
|
||||
3: "3.Honky-Tonk_Piano_酒吧钢琴.mcpack",
|
||||
30: "30.Distortion_Guitar_失真音效吉他.mcpack",
|
||||
31: "31.Guitar_Harmonics_吉他泛音.mcpack",
|
||||
32: "32.Acoustic_Bass_原声贝司.mcpack",
|
||||
33: "33.Electric_Bass(finger)_指拨电贝司.mcpack",
|
||||
34: "34.Electric_Bass(pick)_拨片拨电贝司.mcpack",
|
||||
35: "35.Fretless_Bass_无品贝司.mcpack",
|
||||
36: "36.Slap_Bass_A_击弦贝司A.mcpack",
|
||||
37: "37.Slap_Bass_B_击弦贝司B.mcpack",
|
||||
38: "38.Synth_Bass_A_合成贝司A.mcpack",
|
||||
39: "39.Synth_Bass_B_合成贝司B.mcpack",
|
||||
4: "4.Electric_Piano_1_电钢琴A.mcpack",
|
||||
40: "40.Violin_小提琴.mcpack",
|
||||
41: "41.Viola_中提琴.mcpack",
|
||||
42: "42.Cello_大提琴.mcpack",
|
||||
43: "43.Contrabass_低音提琴.mcpack",
|
||||
44: "44.Tremolo_Strings_弦乐震音.mcpack",
|
||||
45: "45.Pizzicato_Strings_弦乐拨奏.mcpack",
|
||||
46: "46.Orchestral_Harp_竖琴.mcpack",
|
||||
47: "47.Timpani_定音鼓.mcpack",
|
||||
48: "48.String_Ensemble_A_弦乐合奏A.mcpack",
|
||||
49: "49.String_Ensemble_B_弦乐合奏B.mcpack",
|
||||
5: "5.Electric_Piano_2_电钢琴B.mcpack",
|
||||
50: "50.SynthStrings_A_合成弦乐A.mcpack",
|
||||
51: "51.SynthStrings_B_合成弦乐B.mcpack",
|
||||
52: "52.Choir_Aahs_合唱“啊”音.mcpack",
|
||||
53: "53.Voice_Oohs_人声“哦”音.mcpack",
|
||||
54: "54.Synth_Voice_合成人声.mcpack",
|
||||
55: "55.Orchestra_Hit_乐队打击乐.mcpack",
|
||||
56: "56.Trumpet_小号.mcpack",
|
||||
57: "57.Trombone_长号.mcpack",
|
||||
58: "58.Tuba_大号.mcpack",
|
||||
59: "59.Muted_Trumpet_弱音小号.mcpack",
|
||||
6: "6.Harpsichord_拨弦古钢琴.mcpack",
|
||||
60: "60.French_Horn_圆号.mcpack",
|
||||
61: "61.Brass_Section_铜管组.mcpack",
|
||||
62: "62.Synth_Brass_A_合成铜管A.mcpack",
|
||||
63: "63.Synth_Brass_A_合成铜管B.mcpack",
|
||||
64: "64.Soprano_Sax_高音萨克斯.mcpack",
|
||||
65: "65.Alto_Sax_中音萨克斯.mcpack",
|
||||
66: "66.Tenor_Sax_次中音萨克斯.mcpack",
|
||||
67: "67.Baritone_Sax_上低音萨克斯.mcpack",
|
||||
68: "68.Oboe_双簧管.mcpack",
|
||||
69: "69.English_Horn_英国管.mcpack",
|
||||
7: "7.Clavinet_击弦古钢琴.mcpack",
|
||||
70: "70.Bassoon_大管.mcpack",
|
||||
71: "71.Clarinet_单簧管.mcpack",
|
||||
72: "72.Piccolo_短笛.mcpack",
|
||||
73: "73.Flute_长笛.mcpack",
|
||||
74: "74.Recorder_竖笛.mcpack",
|
||||
75: "75.Pan_Flute_排笛.mcpack",
|
||||
76: "76.Bottle_Blow_吹瓶口.mcpack",
|
||||
77: "77.Skakuhachi_尺八.mcpack",
|
||||
78: "78.Whistle_哨.mcpack",
|
||||
79: "79.Ocarina_洋埙.mcpack",
|
||||
8: "8.Celesta_钢片琴.mcpack",
|
||||
80: "80.Lead_square_合成主音-方波.mcpack",
|
||||
81: "81.Lead_sawtooth_合成主音-锯齿波.mcpack",
|
||||
82: "82.Lead_calliope_lead_合成主音-汽笛风琴.mcpack",
|
||||
83: "83.Lead_chiff_lead_合成主音-吹管.mcpack",
|
||||
84: "84.Lead_charang_合成主音5-吉他.mcpack",
|
||||
85: "85.Lead_voice_合成主音-人声.mcpack",
|
||||
86: "86.Lead_fifths_合成主音-五度.mcpack",
|
||||
87: "87.Lead_bass+lead_合成主音-低音加主音.mcpack",
|
||||
88: "88.Pad_new_age_合成柔音-新时代.mcpack",
|
||||
89: "89.Pad_warm_合成柔音-暖音.mcpack",
|
||||
9: "9.Glockenspiel_钟琴.mcpack",
|
||||
90: "90.Pad_polysynth_合成柔音-复合成.mcpack",
|
||||
91: "91.Pad_choir_合成柔音-合唱.mcpack",
|
||||
92: "92.Pad_bowed_合成柔音-弓弦.mcpack",
|
||||
93: "93.Pad_metallic_合成柔音-金属.mcpack",
|
||||
94: "94.Pad_halo_合成柔音-光环.mcpack",
|
||||
95: "95.Pad_sweep_合成柔音-扫弦.mcpack",
|
||||
96: "96.FX_rain_合成特效-雨.mcpack",
|
||||
97: "97.FX_soundtrack_合成特效-音轨.mcpack",
|
||||
98: "98.FX_crystal_合成特效-水晶.mcpack",
|
||||
99: "99.FX_atmosphere_合成特效-大气.mcpack",
|
||||
}
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(zip_name[0])
|
||||
134
old-things/bgArrayLib/pitchStrConstant.py
Normal file
134
old-things/bgArrayLib/pitchStrConstant.py
Normal file
@@ -0,0 +1,134 @@
|
||||
pitch = {
|
||||
"0": "0.0220970869120796",
|
||||
"1": "0.0234110480761981",
|
||||
"2": "0.0248031414370031",
|
||||
"3": "0.0262780129766786",
|
||||
"4": "0.0278405849418856",
|
||||
"5": "0.0294960722713029",
|
||||
"6": "0.03125",
|
||||
"7": "0.033108221698728",
|
||||
"8": "0.0350769390096679",
|
||||
"9": "0.037162722343835",
|
||||
"10": "0.0393725328092148",
|
||||
"11": "0.0417137454428136",
|
||||
"12": "0.0441941738241592",
|
||||
"13": "0.0468220961523963",
|
||||
"14": "0.0496062828740062",
|
||||
"15": "0.0525560259533572",
|
||||
"16": "0.0556811698837712",
|
||||
"17": "0.0589921445426059",
|
||||
"18": "0.0625",
|
||||
"19": "0.066216443397456",
|
||||
"20": "0.0701538780193358",
|
||||
"21": "0.0743254446876701",
|
||||
"22": "0.0787450656184296",
|
||||
"23": "0.0834274908856271",
|
||||
"24": "0.0883883476483184",
|
||||
"25": "0.0936441923047926",
|
||||
"26": "0.0992125657480125",
|
||||
"27": "0.105112051906714",
|
||||
"28": "0.111362339767542",
|
||||
"29": "0.117984289085212",
|
||||
"30": "0.125",
|
||||
"31": "0.132432886794912",
|
||||
"32": "0.140307756038672",
|
||||
"33": "0.14865088937534",
|
||||
"34": "0.157490131236859",
|
||||
"35": "0.166854981771254",
|
||||
"36": "0.176776695296637",
|
||||
"37": "0.187288384609585",
|
||||
"38": "0.198425131496025",
|
||||
"39": "0.210224103813429",
|
||||
"40": "0.222724679535085",
|
||||
"41": "0.235968578170423",
|
||||
"42": "0.25",
|
||||
"43": "0.264865773589824",
|
||||
"44": "0.280615512077343",
|
||||
"45": "0.29730177875068",
|
||||
"46": "0.314980262473718",
|
||||
"47": "0.333709963542509",
|
||||
"48": "0.353553390593274",
|
||||
"49": "0.37457676921917",
|
||||
"50": "0.39685026299205",
|
||||
"51": "0.420448207626857",
|
||||
"52": "0.44544935907017",
|
||||
"53": "0.471937156340847",
|
||||
"54": "0.5",
|
||||
"55": "0.529731547179648",
|
||||
"56": "0.561231024154687",
|
||||
"57": "0.594603557501361",
|
||||
"58": "0.629960524947437",
|
||||
"59": "0.667419927085017",
|
||||
"60": "0.707106781186548",
|
||||
"61": "0.749153538438341",
|
||||
"62": "0.7937005259841",
|
||||
"63": "0.840896415253715",
|
||||
"64": "0.890898718140339",
|
||||
"65": "0.943874312681694",
|
||||
"66": "1",
|
||||
"67": "1.0594630943593",
|
||||
"68": "1.12246204830937",
|
||||
"69": "1.18920711500272",
|
||||
"70": "1.25992104989487",
|
||||
"71": "1.33483985417003",
|
||||
"72": "1.4142135623731",
|
||||
"73": "1.49830707687668",
|
||||
"74": "1.5874010519682",
|
||||
"75": "1.68179283050743",
|
||||
"76": "1.78179743628068",
|
||||
"77": "1.88774862536339",
|
||||
"78": "2",
|
||||
"79": "2.11892618871859",
|
||||
"80": "2.24492409661875",
|
||||
"81": "2.37841423000544",
|
||||
"82": "2.51984209978975",
|
||||
"83": "2.66967970834007",
|
||||
"84": "2.82842712474619",
|
||||
"85": "2.99661415375336",
|
||||
"86": "3.1748021039364",
|
||||
"87": "3.36358566101486",
|
||||
"88": "3.56359487256136",
|
||||
"89": "3.77549725072677",
|
||||
"90": "4",
|
||||
"91": "4.23785237743718",
|
||||
"92": "4.48984819323749",
|
||||
"93": "4.75682846001088",
|
||||
"94": "5.03968419957949",
|
||||
"95": "5.33935941668014",
|
||||
"96": "5.65685424949238",
|
||||
"97": "5.99322830750673",
|
||||
"98": "6.3496042078728",
|
||||
"99": "6.72717132202972",
|
||||
"100": "7.12718974512272",
|
||||
"101": "7.55099450145355",
|
||||
"102": "8",
|
||||
"103": "8.47570475487436",
|
||||
"104": "8.97969638647498",
|
||||
"105": "9.51365692002177",
|
||||
"106": "10.079368399159",
|
||||
"107": "10.6787188333603",
|
||||
"108": "11.3137084989848",
|
||||
"109": "11.9864566150135",
|
||||
"110": "12.6992084157456",
|
||||
"111": "13.4543426440594",
|
||||
"112": "14.2543794902454",
|
||||
"113": "15.1019890029071",
|
||||
"114": "16",
|
||||
"115": "16.9514095097487",
|
||||
"116": "17.95939277295",
|
||||
"117": "19.0273138400435",
|
||||
"118": "20.158736798318",
|
||||
"119": "21.3574376667206",
|
||||
"120": "22.6274169979695",
|
||||
"121": "23.9729132300269",
|
||||
"122": "25.3984168314912",
|
||||
"123": "26.9086852881189",
|
||||
"124": "28.5087589804909",
|
||||
"125": "30.2039780058142",
|
||||
"126": "32",
|
||||
"127": "33.9028190194974",
|
||||
"128": "35.9187855458999",
|
||||
"129": "38.0546276800871",
|
||||
"130": "40.3174735966359",
|
||||
"131": "42.7148753334411",
|
||||
}
|
||||
208
old-things/bgArrayLib/reader.py
Normal file
208
old-things/bgArrayLib/reader.py
Normal file
@@ -0,0 +1,208 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
# from nmcsup.log import log
|
||||
import pickle
|
||||
|
||||
|
||||
class Note:
|
||||
def __init__(self, channel, pitch, velocity, time, time_position, instrument):
|
||||
self.channel = channel
|
||||
self.pitch = pitch
|
||||
self.velocity = velocity
|
||||
self.delay = time
|
||||
self.time_position = time_position
|
||||
self.instrument = instrument
|
||||
self.CD = "d"
|
||||
|
||||
def get_CD(self, start, end):
|
||||
if end - start > 1.00:
|
||||
self.CD = "c"
|
||||
else:
|
||||
self.CD = "d"
|
||||
|
||||
|
||||
def midiNewReader(midfile: str):
|
||||
import mido
|
||||
|
||||
# from msctspt.threadOpera import NewThread
|
||||
from bgArrayLib.bpm import get
|
||||
|
||||
def Time(mt, tpb_a, bpm_a):
|
||||
return round(mt / tpb_a / bpm_a * 60 * 20)
|
||||
|
||||
Notes = []
|
||||
tracks = []
|
||||
note_list = []
|
||||
close = []
|
||||
on = []
|
||||
off = []
|
||||
instruments = []
|
||||
isPercussion = False
|
||||
try:
|
||||
mid = mido.MidiFile(midfile)
|
||||
except Exception:
|
||||
print("找不到文件或无法读取文件" + midfile)
|
||||
return False
|
||||
tpb = mid.ticks_per_beat
|
||||
bpm = get(mid)
|
||||
# 解析
|
||||
# def loadMidi(track1):
|
||||
for track in mid.tracks:
|
||||
overallTime = 0.0
|
||||
instrument = 0
|
||||
for i in track:
|
||||
overallTime += i.time
|
||||
try:
|
||||
if i.channel != 9:
|
||||
# try:
|
||||
# log("event_type(事件): " + str(i.type) + " channel(音轨): " + str(i.channel) +
|
||||
# " note/pitch(音高): " +
|
||||
# str(i[2]) +
|
||||
# " velocity(力度): " + str(i.velocity) + " time(间隔时间): " + str(i.time) +
|
||||
# " overallTime/globalTime/timePosition: " + str(overallTime) + " \n")
|
||||
# except AttributeError:
|
||||
# log("event_type(事件): " + str(i.type) + " thing(内容):" + str(i) + " \n")
|
||||
if "program_change" in str(i):
|
||||
instrument = i.program
|
||||
if instrument > 119: # 音色不够
|
||||
pass
|
||||
else:
|
||||
instruments.append(i.program)
|
||||
if "note_on" in str(i) and i.velocity > 0:
|
||||
print(i)
|
||||
# print(i.note)
|
||||
# print([Note(i.channel, i.note, i.velocity, i.time, Time(overallTime, tpb, bpm), instrument)])
|
||||
tracks.append(
|
||||
[
|
||||
Note(
|
||||
i.channel,
|
||||
i.note,
|
||||
i.velocity,
|
||||
i.time,
|
||||
Time(overallTime, tpb, bpm),
|
||||
instrument,
|
||||
)
|
||||
]
|
||||
)
|
||||
note_list.append(
|
||||
[
|
||||
i.channel,
|
||||
i.note,
|
||||
i.velocity,
|
||||
i.time,
|
||||
Time(overallTime, tpb, bpm),
|
||||
instrument,
|
||||
]
|
||||
)
|
||||
on.append([i.note, Time(overallTime, tpb, bpm)])
|
||||
# return [Note(i.channel, i, i.velocity, i.time, Time(overallTime, tpb, bpm))]
|
||||
if "note_off" in str(i) or "note_on" in str(i) and i.velocity == 0:
|
||||
# print(i)
|
||||
# print([Note(i.channel, i.note, i.velocity, i.time, Time(overallTime, tpb, bpm))])
|
||||
close.append(
|
||||
[
|
||||
Note(
|
||||
i.channel,
|
||||
i.note,
|
||||
i.velocity,
|
||||
i.time,
|
||||
Time(overallTime, tpb, bpm),
|
||||
instrument,
|
||||
)
|
||||
]
|
||||
)
|
||||
off.append([i.note, Time(overallTime, tpb, bpm)])
|
||||
# return [Note(i.channel, i, i.velocity, i.time, Time(overallTime, tpb, bpm))]
|
||||
except AttributeError:
|
||||
pass
|
||||
if "note_on" in str(i) and i.channel == 9:
|
||||
if "note_on" in str(i) and i.velocity > 0:
|
||||
print(i)
|
||||
# print(i.note)
|
||||
# print([Note(i.channel, i.note, i.velocity, i.time, Time(overallTime, tpb, bpm), -1)])
|
||||
tracks.append(
|
||||
[
|
||||
Note(
|
||||
i.channel,
|
||||
i.note,
|
||||
i.velocity,
|
||||
i.time,
|
||||
Time(overallTime, tpb, bpm),
|
||||
-1,
|
||||
)
|
||||
]
|
||||
)
|
||||
note_list.append(
|
||||
[
|
||||
i.channel,
|
||||
i.note,
|
||||
i.velocity,
|
||||
i.time,
|
||||
Time(overallTime, tpb, bpm),
|
||||
-1,
|
||||
]
|
||||
)
|
||||
on.append([i.note, Time(overallTime, tpb, bpm)])
|
||||
isPercussion = True
|
||||
# return [Note(i.channel, i, i.velocity, i.time, Time(overallTime, tpb, bpm))]
|
||||
Notes.append(tracks)
|
||||
if instruments is []:
|
||||
instruments.append(0)
|
||||
instruments = list(set(instruments))
|
||||
with open("1.pkl", "wb") as b:
|
||||
pickle.dump([instruments, isPercussion], b)
|
||||
|
||||
# for j, track in enumerate(mid.tracks):
|
||||
# th = NewThread(loadMidi, (track,))
|
||||
# th.start()
|
||||
# Notes.append(th.getResult())
|
||||
|
||||
# print(Notes)
|
||||
print(Notes.__len__())
|
||||
# print(note_list)
|
||||
print(instruments)
|
||||
return Notes
|
||||
# return [Notes, note_list]
|
||||
|
||||
|
||||
def midiClassReader(midfile: str):
|
||||
import mido
|
||||
|
||||
from bgArrayLib.bpm import get
|
||||
|
||||
def Time(mt, tpb_a, bpm_a):
|
||||
return round(mt / tpb_a / bpm_a * 60 * 20)
|
||||
|
||||
Notes = []
|
||||
tracks = []
|
||||
try:
|
||||
mid = mido.MidiFile(filename=midfile, clip=True)
|
||||
except Exception:
|
||||
print("找不到文件或无法读取文件" + midfile)
|
||||
return False
|
||||
print("midi已经载入了。")
|
||||
tpb = mid.ticks_per_beat
|
||||
bpm = get(mid)
|
||||
for track in mid.tracks:
|
||||
overallTime = 0.0
|
||||
instrument = 0
|
||||
for i in track:
|
||||
overallTime += i.time
|
||||
if "note_on" in str(i) and i.velocity > 0:
|
||||
print(i)
|
||||
tracks.append(
|
||||
[
|
||||
Note(
|
||||
i.channel,
|
||||
i.note,
|
||||
i.velocity,
|
||||
i.time,
|
||||
Time(overallTime, tpb, bpm),
|
||||
instrument,
|
||||
)
|
||||
]
|
||||
)
|
||||
Notes.append(tracks)
|
||||
print(Notes.__len__())
|
||||
return Notes
|
||||
147
old-things/bgArrayLib/sy_resourcesPacker.py
Normal file
147
old-things/bgArrayLib/sy_resourcesPacker.py
Normal file
@@ -0,0 +1,147 @@
|
||||
import os
|
||||
import pickle
|
||||
import shutil
|
||||
|
||||
# import tkinter.filedialog
|
||||
# from namesConstant import zip_name
|
||||
# from namesConstant import mcpack_name
|
||||
import bgArrayLib.namesConstant
|
||||
|
||||
zipN = bgArrayLib.namesConstant.zip_name
|
||||
mpN = bgArrayLib.namesConstant.mcpack_name
|
||||
|
||||
manifest = {
|
||||
"format_version": 1,
|
||||
"header": {
|
||||
"name": "羽音缭绕-midiout_25.5--音创使用",
|
||||
"description": "羽音缭绕-midiout_25.0--音创使用",
|
||||
"uuid": "c1adbda4-3b3e-4e5b-a57e-cde8ac80ee19",
|
||||
"version": [25, 5, 0],
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"description": "羽音缭绕-midiout_25.0--音创使用",
|
||||
"type": "resources",
|
||||
"uuid": "c13455d5-b9f3-47f2-9706-c05ad86b3180 ",
|
||||
"version": [25, 5, 0],
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def resources_pathSetting(newPath: str = ""):
|
||||
if not os.path.isfile("./bgArrayLib/resourcesPath.rpposi") and newPath == "":
|
||||
return [False, 1] # 1:没有路径文件
|
||||
elif newPath != "": # not os.path.isfile("./bgArrayLib/resourcesPath.rpposi") and
|
||||
path = newPath
|
||||
print(path)
|
||||
with open("./bgArrayLib/resourcesPath.rpposi", "w") as w:
|
||||
w.write(path)
|
||||
if "mcpack(国际版推荐)格式_25.0" in os.listdir(
|
||||
path
|
||||
) and "zip格式_25.0" in os.listdir(path):
|
||||
return [True, path, 1] # 1:都有
|
||||
elif "mcpack(国际版推荐)格式_25.0" in os.listdir(
|
||||
path
|
||||
) and "zip格式_25.0" not in os.listdir(path):
|
||||
return [True, path, 2] # 2:有pack
|
||||
elif "mcpack(国际版推荐)格式_25.0" not in os.listdir(
|
||||
path
|
||||
) and "zip格式_25.0" in os.listdir(path):
|
||||
return [True, path, 3] # 3:有zip
|
||||
else:
|
||||
return [False, 2] # 2:路径文件指示错误
|
||||
if os.path.isfile("./bgArrayLib/resourcesPath.rpposi") and newPath == "":
|
||||
with open("./bgArrayLib/resourcesPath.rpposi", "r") as f:
|
||||
path = f.read()
|
||||
if "mcpack(国际版推荐)格式_25.0" in os.listdir(
|
||||
path
|
||||
) and "zip格式_25.0" in os.listdir(path):
|
||||
return [True, path, 1] # 1:都有
|
||||
elif "mcpack(国际版推荐)格式_25.0" in os.listdir(
|
||||
path
|
||||
) and "zip格式_25.0" not in os.listdir(path):
|
||||
return [True, path, 2] # 2:有pack
|
||||
elif "mcpack(国际版推荐)格式_25.0" not in os.listdir(
|
||||
path
|
||||
) and "zip格式_25.0" in os.listdir(path):
|
||||
return [True, path, 3] # 3:有zip
|
||||
else:
|
||||
return [False, 2] # 2:路径文件指示错误
|
||||
|
||||
raise
|
||||
|
||||
|
||||
def choose_resources():
|
||||
global zipN
|
||||
global mpN
|
||||
back_list = []
|
||||
try:
|
||||
with open(r"1.pkl", "rb") as rb:
|
||||
instrument = list(pickle.load(rb))
|
||||
print(instrument)
|
||||
except FileNotFoundError:
|
||||
with open(r"./nmcsup/1.pkl", "rb") as rb:
|
||||
instrument = list(pickle.load(rb))
|
||||
print(instrument)
|
||||
path = resources_pathSetting()
|
||||
if path.__len__() == 2:
|
||||
return path
|
||||
else:
|
||||
dataT = path[2]
|
||||
pathT = path[1]
|
||||
if dataT == 1:
|
||||
if instrument[1] is True: # 是否存在打击乐器
|
||||
index = zipN.get(-1, "")
|
||||
percussion_instrument = str(pathT) + "\\zip格式_25.0\\" + index
|
||||
# print(percussion_instrument)
|
||||
back_list.append(percussion_instrument)
|
||||
for i in instrument[0]:
|
||||
ins_p = str(pathT) + "\\zip格式_25.0\\" + str(zipN.get(i))
|
||||
# print(ins_p)
|
||||
back_list.append(ins_p)
|
||||
print(back_list)
|
||||
return back_list
|
||||
elif dataT == 2:
|
||||
if instrument[1] is True:
|
||||
index = mpN.get(-1, "")
|
||||
percussion_instrument = (
|
||||
str(pathT) + "\\mcpack(国际版推荐)格式_25.0\\" + index
|
||||
)
|
||||
# print(percussion_instrument)
|
||||
back_list.append(percussion_instrument)
|
||||
for i in instrument[0]:
|
||||
ins_p = str(pathT) + "\\mcpack(国际版推荐)格式_25.0\\" + str(mpN.get(i))
|
||||
# print(ins_p)
|
||||
back_list.append(ins_p)
|
||||
print(back_list)
|
||||
return back_list
|
||||
elif dataT == 3:
|
||||
if instrument[1] is True:
|
||||
index = zipN.get(-1, "")
|
||||
percussion_instrument = str(pathT) + "\\zip格式_25.0\\" + index
|
||||
# print(percussion_instrument)
|
||||
back_list.append(percussion_instrument)
|
||||
for i in instrument[0]:
|
||||
ins_p = str(pathT) + "\\zip格式_25.0\\" + str(zipN.get(i))
|
||||
# print(ins_p)
|
||||
back_list.append(ins_p)
|
||||
print(back_list)
|
||||
return back_list
|
||||
raise
|
||||
|
||||
|
||||
def scatteredPack(path):
|
||||
pack_list = choose_resources()
|
||||
print(pack_list)
|
||||
print(path)
|
||||
# os.close("L:/0WorldMusicCreater-MFMS new edition")
|
||||
# shutil.copy("L:\\shenyu\\音源的资源包\\羽音缭绕-midiout_25.0\\mcpack(国际版推荐)格式_25.0\\0.Acoustic_Grand_Piano_大钢琴.mcpack",
|
||||
# "L:/0WorldMusicCreater-MFMS new edition")
|
||||
for i in pack_list:
|
||||
shutil.copy(i, path)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# print(resources_pathSetting(r"L:\shenyu\音源的资源包\羽音缭绕-midiout_25.0"))
|
||||
choose_resources()
|
||||
248
old-things/example.py
Normal file
248
old-things/example.py
Normal file
@@ -0,0 +1,248 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 伶伦 开发交流群 861684859
|
||||
|
||||
|
||||
"""
|
||||
音·创 (Musicreater) 演示程序
|
||||
是一款免费开源的针对《我的世界》的midi音乐转换库
|
||||
Musicreater (音·创)
|
||||
A free open source library used for convert midi file into formats that is suitable for **Minecraft**.
|
||||
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 ./License.md
|
||||
Terms & Conditions: ./License.md
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
import Musicreater.old_init as old_init
|
||||
from Musicreater.old_plugin.addonpack import (
|
||||
to_addon_pack_in_delay,
|
||||
to_addon_pack_in_repeater,
|
||||
to_addon_pack_in_score,
|
||||
)
|
||||
from Musicreater.old_plugin.mcstructfile import (
|
||||
to_mcstructure_file_in_delay,
|
||||
to_mcstructure_file_in_repeater,
|
||||
to_mcstructure_file_in_score,
|
||||
)
|
||||
|
||||
from Musicreater.old_plugin.bdxfile import to_BDX_file_in_delay, to_BDX_file_in_score
|
||||
|
||||
# 获取midi列表
|
||||
midi_path = input(f"请输入MIDI路径:")
|
||||
|
||||
|
||||
# 获取输出地址
|
||||
out_path = input(f"请输入输出路径:")
|
||||
|
||||
|
||||
# 选择输出格式
|
||||
fileFormat = int(
|
||||
input(f"请输入输出格式[MCSTRUCTURE(2) 或 BDX(1) 或 MCPACK(0)]:").lower()
|
||||
)
|
||||
playerFormat = int(input(f"请选择播放方式[红石(2) 或 计分板(1) 或 延迟(0)]:").lower())
|
||||
|
||||
|
||||
# 真假字符串判断
|
||||
def bool_str(sth: str):
|
||||
try:
|
||||
return bool(float(sth))
|
||||
except:
|
||||
if str(sth).lower() in ("true", "真", "是", "y", "t"):
|
||||
return True
|
||||
elif str(sth).lower() in ("false", "假", "否", "f", "n"):
|
||||
return False
|
||||
else:
|
||||
raise ValueError("非法逻辑字串")
|
||||
|
||||
|
||||
def isin(sth: str, range_list: dict):
|
||||
sth = sth.lower()
|
||||
for bool_value, res_list in range_list.items():
|
||||
if sth in res_list:
|
||||
return bool_value
|
||||
raise ValueError(
|
||||
"不在可选范围内:{}".format([j for i in range_list.values() for j in i])
|
||||
)
|
||||
|
||||
|
||||
if os.path.exists("./demo_config.json"):
|
||||
import json
|
||||
|
||||
prompts = json.load(open("./demo_config.json", "r", encoding="utf-8"))
|
||||
else:
|
||||
prompts = []
|
||||
# 提示语 检测函数 错误提示语
|
||||
for args in [
|
||||
(
|
||||
f"最小播放音量:",
|
||||
float,
|
||||
),
|
||||
(
|
||||
f"播放速度:",
|
||||
float,
|
||||
),
|
||||
(
|
||||
f"是否启用进度条:",
|
||||
bool_str,
|
||||
),
|
||||
(
|
||||
(
|
||||
f"计分板名称:",
|
||||
str,
|
||||
)
|
||||
if playerFormat == 1
|
||||
else (
|
||||
f"玩家选择器:",
|
||||
str,
|
||||
)
|
||||
),
|
||||
(
|
||||
(
|
||||
f"是否自动重置计分板:",
|
||||
bool_str,
|
||||
)
|
||||
if playerFormat == 1
|
||||
else ()
|
||||
),
|
||||
(
|
||||
(
|
||||
f"BDX作者署名:",
|
||||
str,
|
||||
)
|
||||
if fileFormat == 1
|
||||
else (
|
||||
(
|
||||
"结构延展方向:",
|
||||
lambda a: isin(
|
||||
a,
|
||||
{
|
||||
"z+": ["z+", "Z+"],
|
||||
"x+": ["X+", "x+"],
|
||||
"z-": ["Z-", "z-"],
|
||||
"x-": ["x-", "X-"],
|
||||
},
|
||||
),
|
||||
)
|
||||
if (playerFormat == 2 and fileFormat == 2)
|
||||
else ()
|
||||
)
|
||||
),
|
||||
(
|
||||
()
|
||||
if playerFormat == 1
|
||||
else (
|
||||
(
|
||||
"基础空白方块:",
|
||||
str,
|
||||
)
|
||||
if (playerFormat == 2 and fileFormat == 2)
|
||||
else (
|
||||
f"最大结构高度:",
|
||||
int,
|
||||
)
|
||||
)
|
||||
),
|
||||
]:
|
||||
if args:
|
||||
try:
|
||||
prompts.append(args[1](input(args[0])))
|
||||
except Exception:
|
||||
print(args)
|
||||
|
||||
|
||||
print(f"正在处理 {midi_path} :")
|
||||
cvt_mid = old_init.MidiConvert.from_midi_file(
|
||||
midi_path, old_exe_format=False, min_volume=prompts[0], play_speed=prompts[1]
|
||||
)
|
||||
|
||||
|
||||
if fileFormat == 0:
|
||||
if playerFormat == 1:
|
||||
cvt_method = to_addon_pack_in_score
|
||||
elif playerFormat == 0:
|
||||
cvt_method = to_addon_pack_in_delay
|
||||
elif playerFormat == 2:
|
||||
cvt_method = to_addon_pack_in_repeater
|
||||
elif fileFormat == 2:
|
||||
if playerFormat == 1:
|
||||
cvt_method = to_mcstructure_file_in_score
|
||||
elif playerFormat == 0:
|
||||
cvt_method = to_mcstructure_file_in_delay
|
||||
elif playerFormat == 2:
|
||||
cvt_method = to_mcstructure_file_in_repeater
|
||||
|
||||
# 测试
|
||||
|
||||
# print(cvt_mid)
|
||||
|
||||
|
||||
print(
|
||||
" 指令总长:{},最高延迟:{}".format(
|
||||
*(
|
||||
cvt_method(
|
||||
cvt_mid,
|
||||
out_path,
|
||||
old_init.DEFAULT_PROGRESSBAR_STYLE if prompts[2] else None, # type: ignore
|
||||
*prompts[3:],
|
||||
)
|
||||
)
|
||||
)
|
||||
if fileFormat == 0
|
||||
else (
|
||||
" 指令总长:{},最高延迟:{},结构大小{},终点坐标{}".format(
|
||||
*(
|
||||
to_BDX_file_in_score(
|
||||
cvt_mid,
|
||||
out_path,
|
||||
old_init.DEFAULT_PROGRESSBAR_STYLE if prompts[2] else None,
|
||||
*prompts[3:],
|
||||
)
|
||||
if playerFormat == 1
|
||||
else to_BDX_file_in_delay(
|
||||
cvt_mid,
|
||||
out_path,
|
||||
old_init.DEFAULT_PROGRESSBAR_STYLE if prompts[2] else None,
|
||||
*prompts[3:],
|
||||
)
|
||||
)
|
||||
)
|
||||
if fileFormat == 1
|
||||
else (
|
||||
" 结构大小:{},延迟总数:{},指令数量:{}".format(
|
||||
*(
|
||||
cvt_method(
|
||||
cvt_mid,
|
||||
out_path,
|
||||
*prompts[3:],
|
||||
)
|
||||
)
|
||||
)
|
||||
if playerFormat == 1
|
||||
else " 结构大小:{},延迟总数:{}".format(
|
||||
*(
|
||||
cvt_method(
|
||||
cvt_mid,
|
||||
out_path,
|
||||
# Musicreater.DEFAULT_PROGRESSBAR_STYLE if prompts[2] else None, # type: ignore
|
||||
*prompts[3:],
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
exitSth = input("回车退出").lower()
|
||||
if exitSth == "record":
|
||||
import json
|
||||
|
||||
with open("./demo_config.json", "w", encoding="utf-8") as f:
|
||||
json.dump(prompts, f)
|
||||
elif exitSth == "delrec":
|
||||
os.remove("./demo_config.json")
|
||||
14
old-things/example_futureFunction.py
Normal file
14
old-things/example_futureFunction.py
Normal file
@@ -0,0 +1,14 @@
|
||||
import Musicreater.experiment
|
||||
import Musicreater.old_plugin
|
||||
import Musicreater.old_plugin.mcstructfile
|
||||
|
||||
print(
|
||||
Musicreater.old_plugin.mcstructfile.to_mcstructure_file_in_delay(
|
||||
Musicreater.experiment.FutureMidiConvertM4.from_midi_file(
|
||||
input("midi路径:"), old_exe_format=False
|
||||
),
|
||||
input("输出路径:"),
|
||||
# Musicreater.plugin.ConvertConfig(input("输出路径:"),),
|
||||
max_height=32,
|
||||
)
|
||||
)
|
||||
16
old-things/example_singleConvert.py
Normal file
16
old-things/example_singleConvert.py
Normal file
@@ -0,0 +1,16 @@
|
||||
import Musicreater.old_init as old_init
|
||||
import Musicreater.old_plugin
|
||||
import Musicreater.old_plugin.mcstructfile
|
||||
|
||||
print(
|
||||
old_init.old_plugin.mcstructfile.to_mcstructure_file_in_delay(
|
||||
old_init.MidiConvert.from_midi_file(
|
||||
input("midi路径:"),
|
||||
old_exe_format=False,
|
||||
# note_table_replacement={"note.harp": "note.flute"},
|
||||
),
|
||||
input("输出路径:"),
|
||||
# Musicreater.plugin.ConvertConfig(input("输出路径:"),),
|
||||
# max_height=32,
|
||||
)
|
||||
)
|
||||
24
old-things/example_websocket.py
Normal file
24
old-things/example_websocket.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import Musicreater.old_init as old_init
|
||||
import Musicreater.old_plugin
|
||||
import Musicreater.old_plugin.websocket
|
||||
|
||||
import os
|
||||
|
||||
dire = input("midi目录:")
|
||||
|
||||
print(
|
||||
old_init.old_plugin.websocket.to_websocket_server(
|
||||
[
|
||||
old_init.MidiConvert.from_midi_file(
|
||||
os.path.join(dire, names), old_exe_format=False
|
||||
)
|
||||
for names in os.listdir(
|
||||
dire,
|
||||
)
|
||||
if names.endswith((".mid", ".midi"))
|
||||
],
|
||||
input("服务器地址:"),
|
||||
int(input("服务器端口:")),
|
||||
old_init.DEFAULT_PROGRESSBAR_STYLE,
|
||||
)
|
||||
)
|
||||
1
old-things/fcwslib/LICENSE
Normal file
1
old-things/fcwslib/LICENSE
Normal file
@@ -0,0 +1 @@
|
||||
SEE: https://mingfengpigeon.mit-license.org/
|
||||
5
old-things/fcwslib/__init__.py
Normal file
5
old-things/fcwslib/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
__all__ = ['Server', 'Plugin', 'build_header']
|
||||
__version__ = '3.0.1'
|
||||
__author__ = ['mingfengpigeon <mingfengpigeon@gmail.com>',"Eilles Wan <EillesWan@outlook.com>"]
|
||||
|
||||
from .server import Server, Plugin, build_header
|
||||
142
old-things/fcwslib/server.py
Normal file
142
old-things/fcwslib/server.py
Normal file
@@ -0,0 +1,142 @@
|
||||
import asyncio
|
||||
import copy
|
||||
import json
|
||||
import uuid
|
||||
|
||||
import websockets
|
||||
|
||||
|
||||
class Server:
|
||||
sent_commands = {}
|
||||
subscribed_events = {}
|
||||
_plugins = []
|
||||
_connections = []
|
||||
|
||||
def __init__(self, server='0.0.0.0', port=8000, debug_mode=False):
|
||||
self._server = server
|
||||
self._port = port
|
||||
self._debug_mode = debug_mode
|
||||
|
||||
def handler(self):
|
||||
return copy.deepcopy(self._plugins)
|
||||
|
||||
def add_plugin(self, plugin):
|
||||
if self._plugins:
|
||||
for connection in self._connections:
|
||||
plugin_ = plugin()
|
||||
asyncio.create_task(plugin_.on_connect())
|
||||
connection.append(plugin_)
|
||||
self._plugins.append(plugin)
|
||||
|
||||
def remove_plugin(self, plugin):
|
||||
if self._connections:
|
||||
for connection in self._connections:
|
||||
for plugin_ in connection.plugins:
|
||||
if isinstance(plugin_, plugin):
|
||||
plugin_.remove(plugin_)
|
||||
break
|
||||
self._plugins.remove(plugin)
|
||||
|
||||
async def run_forever(self):
|
||||
self.running = True
|
||||
async with websockets.serve(self._on_connect, self._server, self._port):
|
||||
await asyncio.Future()
|
||||
|
||||
async def _on_connect(self, websocket, path):
|
||||
plugins = []
|
||||
self._connections.append({
|
||||
"websocket": websocket,
|
||||
"path": path,
|
||||
"plugins": plugins,
|
||||
})
|
||||
for plugin in self._plugins:
|
||||
plugins.append(plugin(websocket, path, self, self._debug_mode))
|
||||
for plugin in plugins:
|
||||
asyncio.create_task(plugin.on_connect())
|
||||
while self.running:
|
||||
try:
|
||||
response = json.loads(await websocket.recv())
|
||||
except (websockets.exceptions.ConnectionClosedOK, websockets.exceptions.ConnectionClosedError):
|
||||
tasks = []
|
||||
for plugin in plugins:
|
||||
tasks.append(plugin.on_disconnect())
|
||||
for task in tasks:
|
||||
await task
|
||||
break
|
||||
else:
|
||||
message_purpose = response['header']['messagePurpose']
|
||||
if message_purpose == 'commandResponse':
|
||||
request_id = response['header']['requestId']
|
||||
if request_id in self.sent_commands:
|
||||
asyncio.create_task(self.sent_commands[request_id](response))
|
||||
del self.sent_commands[request_id]
|
||||
else:
|
||||
try:
|
||||
event_name = response['header']['eventName']
|
||||
asyncio.create_task(self.subscribed_events[event_name](response))
|
||||
except KeyError:
|
||||
print("ERROR EVENT NAME:\n{}".format(response))
|
||||
|
||||
async def disconnect(self, websocket: websockets.WebSocketServerProtocol):
|
||||
self.running = False
|
||||
await websocket.close_connection()
|
||||
for number in range(len(self._connections) - 1):
|
||||
connection = self._connections[number]
|
||||
if connection['websocket'] == websocket:
|
||||
del self._connections[number]
|
||||
|
||||
|
||||
class Plugin:
|
||||
def __init__(self, websocket, path, server, debug_mode=False):
|
||||
self._websocket = websocket
|
||||
self._path = path
|
||||
self._server = server
|
||||
self._debug_mode = debug_mode
|
||||
|
||||
async def on_connect(self):
|
||||
pass
|
||||
|
||||
async def on_disconnect(self):
|
||||
pass
|
||||
|
||||
async def on_receive(self, response):
|
||||
pass
|
||||
|
||||
async def send_command(self, command, callback=None):
|
||||
request = {
|
||||
'body': {'commandLine': command},
|
||||
'header': build_header('commandRequest')
|
||||
}
|
||||
if callback:
|
||||
self._server.sent_commands[request['header']['requestId']] = callback
|
||||
await self._websocket.send(json.dumps(request, **{'indent': 4} if self._debug_mode else {}))
|
||||
|
||||
async def subscribe(self, event_name, callback):
|
||||
request = {
|
||||
'body': {'eventName': event_name},
|
||||
'header': build_header('subscribe')
|
||||
}
|
||||
self._server.subscribed_events[event_name] = callback
|
||||
await self._websocket.send(json.dumps(request, **{'indent': 4} if self._debug_mode else {}))
|
||||
|
||||
async def unsubscribe(self, event_name):
|
||||
request = {
|
||||
'body': {'eventName': event_name},
|
||||
'header': build_header('unsubscribe')
|
||||
}
|
||||
del self._server.subscribed_events[event_name]
|
||||
await self._websocket.send(json.dumps(request, **{'indent': 4} if self._debug_mode else {}))
|
||||
|
||||
async def disconnect(self):
|
||||
await self._server.disconnect(self._websocket)
|
||||
|
||||
|
||||
def build_header(message_purpose, request_id=None):
|
||||
if not request_id:
|
||||
request_id = str(uuid.uuid4())
|
||||
return {
|
||||
'requestId': request_id,
|
||||
'messagePurpose': message_purpose,
|
||||
'version': '1',
|
||||
'messageType': 'commandRequest',
|
||||
}
|
||||
163
old-things/let_future_java.py
Normal file
163
old-things/let_future_java.py
Normal file
@@ -0,0 +1,163 @@
|
||||
"""
|
||||
版权所有 © 2025 金羿 & 诸葛亮与八卦阵
|
||||
Copyright © 2025 Eilles & bgArray
|
||||
|
||||
开源相关声明请见 仓库根目录下的 License.md
|
||||
Terms & Conditions: License.md in the root directory
|
||||
"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
from typing import Optional, Tuple
|
||||
|
||||
import Musicreater.experiment
|
||||
from Musicreater.old_plugin.archive import compress_zipfile
|
||||
from Musicreater.utils import guess_deviation, is_in_diapason
|
||||
|
||||
|
||||
def to_zip_pack_in_score(
|
||||
midi_cvt: Musicreater.experiment.FutureMidiConvertJavaE,
|
||||
dist_path: str,
|
||||
progressbar_style: Optional[Musicreater.experiment.ProgressBarStyle],
|
||||
scoreboard_name: str = "mscplay",
|
||||
sound_source: str = "ambient",
|
||||
auto_reset: bool = False,
|
||||
) -> Tuple[int, int]:
|
||||
"""
|
||||
将midi以计分播放器形式转换为我的世界函数附加包
|
||||
|
||||
Parameters
|
||||
----------
|
||||
midi_cvt: MidiConvert 对象
|
||||
用于转换的MidiConvert对象
|
||||
dist_path: str
|
||||
转换结果输出的目标路径
|
||||
progressbar_style: ProgressBarStyle 对象
|
||||
进度条对象
|
||||
scoreboard_name: str
|
||||
我的世界的计分板名称
|
||||
auto_reset: bool
|
||||
是否自动重置计分板
|
||||
|
||||
Returns
|
||||
-------
|
||||
tuple[int指令数量, int音乐总延迟]
|
||||
"""
|
||||
|
||||
cmdlist, maxlen, maxscore = midi_cvt.to_command_list_in_java_score(
|
||||
scoreboard_name=scoreboard_name,
|
||||
source_of_sound=sound_source,
|
||||
)
|
||||
|
||||
# 当文件f夹{self.outputPath}/temp/mscplyfuncs存在时清空其下所有项目,然后创建
|
||||
if os.path.exists(f"{dist_path}/temp/mscplyfuncs/"):
|
||||
shutil.rmtree(f"{dist_path}/temp/mscplyfuncs/")
|
||||
os.makedirs(f"{dist_path}/temp/mscplyfuncs/mscplay")
|
||||
|
||||
# 写入stop.mcfunction
|
||||
with open(
|
||||
f"{dist_path}/temp/mscplyfuncs/stop.mcfunction", "w", encoding="utf-8"
|
||||
) as f:
|
||||
f.write("scoreboard players reset @a {}".format(scoreboard_name))
|
||||
|
||||
# 将命令列表写入文件
|
||||
index_file = open(
|
||||
f"{dist_path}/temp/mscplyfuncs/index.mcfunction", "w", encoding="utf-8"
|
||||
)
|
||||
for i in range(len(cmdlist)):
|
||||
index_file.write(f"function mscplyfuncs:mscplay/track{i + 1}\n")
|
||||
with open(
|
||||
f"{dist_path}/temp/mscplyfuncs/mscplay/track{i + 1}.mcfunction",
|
||||
"w",
|
||||
encoding="utf-8",
|
||||
) as f:
|
||||
f.write("\n".join([single_cmd.cmd for single_cmd in cmdlist[i]]))
|
||||
index_file.writelines(
|
||||
(
|
||||
"scoreboard players add @a[score_{0}_min=1] {0} 1\n".format(
|
||||
scoreboard_name
|
||||
),
|
||||
(
|
||||
"scoreboard players reset @a[score_{0}_min={1}] {0}\n".format(
|
||||
scoreboard_name, maxscore + 20
|
||||
)
|
||||
if auto_reset
|
||||
else ""
|
||||
),
|
||||
f"function mscplyfuncs:mscplay/progressShow\n" if progressbar_style else "",
|
||||
)
|
||||
)
|
||||
|
||||
if progressbar_style:
|
||||
with open(
|
||||
f"{dist_path}/temp/mscplyfuncs/mscplay/progressShow.mcfunction",
|
||||
"w",
|
||||
encoding="utf-8",
|
||||
) as f:
|
||||
f.writelines(
|
||||
"\n".join(
|
||||
[
|
||||
single_cmd.cmd
|
||||
for single_cmd in midi_cvt.form_java_progress_bar(
|
||||
maxscore, scoreboard_name, progressbar_style
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
index_file.close()
|
||||
|
||||
if os.path.exists(f"{dist_path}/{midi_cvt.music_name}.zip"):
|
||||
os.remove(f"{dist_path}/{midi_cvt.music_name}.zip")
|
||||
compress_zipfile(
|
||||
f"{dist_path}/temp/",
|
||||
f"{dist_path}/{midi_cvt.music_name}[JEscore].zip",
|
||||
)
|
||||
|
||||
shutil.rmtree(f"{dist_path}/temp/")
|
||||
|
||||
return maxlen, maxscore
|
||||
|
||||
|
||||
msc_cvt = Musicreater.experiment.FutureMidiConvertJavaE.from_midi_file(
|
||||
input("midi路径:"),
|
||||
play_speed=float(input("播放速度:")),
|
||||
old_exe_format=True,
|
||||
note_table_replacement=Musicreater.old_init.MC_EILLES_RTJE12_INSTRUMENT_REPLACE_TABLE,
|
||||
# pitched_note_table=Musicreater.MM_NBS_PITCHED_INSTRUMENT_TABLE,
|
||||
)
|
||||
|
||||
msc_cvt.set_deviation(
|
||||
guess_deviation(
|
||||
msc_cvt.total_note_count,
|
||||
len(msc_cvt.note_count_per_instrument),
|
||||
msc_cvt.note_count_per_instrument,
|
||||
music_channels=msc_cvt.channels,
|
||||
)
|
||||
)
|
||||
|
||||
in_diapason_count = 0
|
||||
for this_note in [k for j in msc_cvt.channels.values() for k in j]:
|
||||
if is_in_diapason(
|
||||
this_note.note_pitch + msc_cvt.music_deviation, this_note.sound_name
|
||||
):
|
||||
in_diapason_count += 1
|
||||
|
||||
|
||||
zip_res = to_zip_pack_in_score(
|
||||
msc_cvt,
|
||||
input("输出路径:"),
|
||||
Musicreater.experiment.ProgressBarStyle(),
|
||||
# Musicreater.plugin.ConvertConfig(input("输出路径:"),),
|
||||
scoreboard_name=input("计分板名称:"),
|
||||
sound_source=input("发音源:"),
|
||||
auto_reset=True,
|
||||
)
|
||||
print(
|
||||
"符合音符播放音高的音符数量:{}/{}({:.2f}%)".format(
|
||||
in_diapason_count,
|
||||
msc_cvt.total_note_count,
|
||||
in_diapason_count * 100 / msc_cvt.total_note_count,
|
||||
),
|
||||
"\n指令数量:{};音乐总延迟:{}".format(*zip_res),
|
||||
)
|
||||
39
old-things/test_fsq_opera.py
Normal file
39
old-things/test_fsq_opera.py
Normal file
@@ -0,0 +1,39 @@
|
||||
from rich.pretty import pprint
|
||||
|
||||
import Musicreater.old_init as old_init
|
||||
from Musicreater.utils import (
|
||||
load_decode_fsq_flush_release,
|
||||
load_decode_musicsequence_metainfo,
|
||||
)
|
||||
|
||||
msc_seq = old_init.MusicSequence.from_mido(
|
||||
old_init.mido.MidiFile(
|
||||
"./resources/测试片段.mid",
|
||||
),
|
||||
"TEST-测试片段",
|
||||
)
|
||||
|
||||
pprint("音乐源取入成功:")
|
||||
pprint(msc_seq)
|
||||
|
||||
with open("test.fsq", "wb") as f:
|
||||
f.write(fsq_bytes := msc_seq.encode_dump(flowing_codec_support=True))
|
||||
|
||||
with open("test.fsq", "rb") as f:
|
||||
msc_seq_r = old_init.MusicSequence.load_decode(f.read(), verify=True)
|
||||
|
||||
pprint("FSQ 传入类成功:")
|
||||
pprint(msc_seq_r)
|
||||
|
||||
|
||||
with open("test.fsq", "rb") as f:
|
||||
pprint("流式 FSQ 元数据:")
|
||||
pprint(metas := load_decode_musicsequence_metainfo(f))
|
||||
pprint("流式 FSQ 音符序列:")
|
||||
cnt = 0
|
||||
for i in load_decode_fsq_flush_release(f, metas[-2], metas[-3], metas[-1]):
|
||||
pprint(
|
||||
i,
|
||||
)
|
||||
cnt += 1
|
||||
pprint(f"共 {cnt} 个音符")
|
||||
33
old-things/test_future_kamires.py
Normal file
33
old-things/test_future_kamires.py
Normal file
@@ -0,0 +1,33 @@
|
||||
import Musicreater.experiment
|
||||
import Musicreater.old_plugin
|
||||
import Musicreater.old_plugin.mcstructfile
|
||||
|
||||
msct = Musicreater.experiment.FutureMidiConvertKamiRES.from_midi_file(
|
||||
input("midi路径:"), old_exe_format=False
|
||||
)
|
||||
|
||||
opt = input("输出路径:")
|
||||
|
||||
print(
|
||||
"乐器使用情况",
|
||||
)
|
||||
|
||||
for name in sorted(
|
||||
set(
|
||||
[
|
||||
n.split(".")[0].replace("c", "").replace("d", "")
|
||||
for n in msct.note_count_per_instrument.keys()
|
||||
]
|
||||
)
|
||||
):
|
||||
print("\t", name, flush=True)
|
||||
|
||||
print(
|
||||
"\n输出:",
|
||||
Musicreater.old_plugin.mcstructfile.to_mcstructure_file_in_delay(
|
||||
msct,
|
||||
opt,
|
||||
# Musicreater.plugin.ConvertConfig(input("输出路径:"),),
|
||||
max_height=32,
|
||||
),
|
||||
)
|
||||
33
old-things/test_future_lyric.py
Normal file
33
old-things/test_future_lyric.py
Normal file
@@ -0,0 +1,33 @@
|
||||
import Musicreater.experiment
|
||||
import Musicreater.old_plugin
|
||||
import Musicreater.old_plugin.mcstructfile
|
||||
|
||||
msct = Musicreater.experiment.FutureMidiConvertLyricSupport.from_midi_file(
|
||||
input("midi路径:"), old_exe_format=False
|
||||
)
|
||||
|
||||
opt = input("输出路径:")
|
||||
|
||||
# print(
|
||||
# "乐器使用情况",
|
||||
# )
|
||||
|
||||
# for name in sorted(
|
||||
# set(
|
||||
# [
|
||||
# n.split(".")[0].replace("c", "").replace("d", "")
|
||||
# for n in msct.note_count_per_instrument.keys()
|
||||
# ]
|
||||
# )
|
||||
# ):
|
||||
# print("\t", name, flush=True)
|
||||
|
||||
print(
|
||||
"\n输出:",
|
||||
Musicreater.old_plugin.mcstructfile.to_mcstructure_file_in_delay(
|
||||
msct,
|
||||
opt,
|
||||
# Musicreater.plugin.ConvertConfig(input("输出路径:"),),
|
||||
max_height=32,
|
||||
),
|
||||
)
|
||||
34
old-things/test_msq_opera.py
Normal file
34
old-things/test_msq_opera.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from rich.pretty import pprint
|
||||
|
||||
import Musicreater.old_init as old_init
|
||||
from Musicreater.utils import (
|
||||
load_decode_msq_flush_release,
|
||||
load_decode_musicsequence_metainfo,
|
||||
)
|
||||
|
||||
msc_seq = old_init.MusicSequence.from_mido(
|
||||
old_init.mido.MidiFile(
|
||||
"./resources/测试片段.mid",
|
||||
),
|
||||
"TEST-测试片段",
|
||||
)
|
||||
|
||||
pprint("音乐源取入成功:")
|
||||
pprint(msc_seq)
|
||||
|
||||
with open("test.msq", "wb") as f:
|
||||
f.write(msq_bytes := msc_seq.encode_dump())
|
||||
|
||||
with open("test.msq", "rb") as f:
|
||||
msc_seq_r = old_init.MusicSequence.load_decode(f.read())
|
||||
|
||||
pprint("常规 MSQ 读取成功:")
|
||||
pprint(msc_seq_r)
|
||||
|
||||
|
||||
with open("test.msq", "rb") as f:
|
||||
pprint("流式 MSQ 元数据:")
|
||||
pprint(metas := load_decode_musicsequence_metainfo(f))
|
||||
pprint("流式 MSQ 音符序列:")
|
||||
for i in load_decode_msq_flush_release(f, metas[-2], metas[-3], metas[-1]):
|
||||
pprint(i)
|
||||
Reference in New Issue
Block a user