2022-01-27 21:21:25 +08:00
|
|
|
|
"""音创系列的转换功能"""
|
|
|
|
|
# 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日
|
|
|
|
|
# 统计:致命(三级)错误:0个;警告(二级)错误:2个;语法(一级)错误:192个
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from nmcsup.log import log
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import amulet
|
|
|
|
|
import amulet_nbt
|
|
|
|
|
from amulet.api.block import Block
|
|
|
|
|
from amulet.api.block_entity import BlockEntity
|
|
|
|
|
from amulet.utils.world_utils import block_coords_to_chunk_coords
|
|
|
|
|
from amulet_nbt import TAG_String, TAG_Compound, TAG_Byte
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 输入一个列表 [ [str, float ], [], ... ] 音符str 值为持续时间float
|
|
|
|
|
def note2list(Notes: list) -> list:
|
|
|
|
|
from nmcsup.const import notes
|
|
|
|
|
|
|
|
|
|
def change(base):
|
|
|
|
|
enwo = {
|
|
|
|
|
'a': 'A',
|
|
|
|
|
'b': 'B',
|
|
|
|
|
'c': 'C',
|
|
|
|
|
'd': "D",
|
|
|
|
|
"e": "E",
|
|
|
|
|
'f': 'F',
|
|
|
|
|
'g': "G"
|
|
|
|
|
}
|
|
|
|
|
nuwo = {
|
|
|
|
|
'6': 'A',
|
|
|
|
|
'7': 'B',
|
|
|
|
|
'1': 'C',
|
|
|
|
|
'2': "D",
|
|
|
|
|
"3": "E",
|
|
|
|
|
'4': 'F',
|
|
|
|
|
'5': "G"
|
|
|
|
|
}
|
|
|
|
|
for k, v in enwo.items():
|
|
|
|
|
if k in base:
|
|
|
|
|
base = base.replace(k, v)
|
|
|
|
|
for k, v in nuwo.items():
|
|
|
|
|
if k in base:
|
|
|
|
|
base = base.replace(k, v)
|
|
|
|
|
return base
|
|
|
|
|
|
|
|
|
|
res = []
|
|
|
|
|
log(" === 音符列表=>音调列表")
|
|
|
|
|
for i in Notes:
|
|
|
|
|
s2 = change(i[0])
|
|
|
|
|
log(' === 正在操作音符' + i[0] + '->' + s2)
|
|
|
|
|
if s2 in notes.keys():
|
|
|
|
|
log(" === 找到此音符,加入:" + str(notes[s2][0]))
|
|
|
|
|
res.append([notes[s2][0], float(i[1])])
|
|
|
|
|
else:
|
|
|
|
|
log(' === ' + s2 + '不在音符表内,此处自动替换为 休止符0 ')
|
|
|
|
|
res.append(['0', float(i[1])])
|
|
|
|
|
log(' === 最终反回' + str(res))
|
|
|
|
|
return res
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def mcnote2freq(Notes):
|
|
|
|
|
from nmcsup.const import notes
|
|
|
|
|
mcnback = {}
|
|
|
|
|
for i, j in notes.items():
|
|
|
|
|
mcnback[j[0]] = i
|
|
|
|
|
res = []
|
|
|
|
|
log(" === 我的世界音调表=>频率列表")
|
|
|
|
|
for i in Notes:
|
|
|
|
|
log(' === 正在操作音符' + i[0] + '->' + mcnback[i[0]])
|
|
|
|
|
res.append([notes[mcnback[i[0]]][1], float(i[1])])
|
|
|
|
|
log(' === 最终反回' + str(res))
|
|
|
|
|
return res
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# MP3文件转midi文件
|
|
|
|
|
def Mp32Mid(mp3File, midFile):
|
|
|
|
|
from piano_transcription_inference import PianoTranscription, sample_rate, load_audio
|
|
|
|
|
# 加载
|
|
|
|
|
(audio, _) = load_audio(mp3File, sr=sample_rate) # , mono=True
|
|
|
|
|
# 实例化并转换
|
|
|
|
|
PianoTranscription(device="cpu").transcribe(audio, midFile)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 传入一个音符列表转为指令列表
|
|
|
|
|
def Note2Cmd(Notes: list, ScoreboardName: str, Instrument: str, PlayerSelect: str = '',
|
|
|
|
|
isProsess: bool = False) -> list:
|
|
|
|
|
commands = []
|
|
|
|
|
a = 0.0
|
|
|
|
|
length = len(Notes)
|
|
|
|
|
j = 1
|
|
|
|
|
for i in range(len(Notes)):
|
|
|
|
|
commands.append("execute @a" + PlayerSelect + " ~ ~ ~ execute @s[scores={" + ScoreboardName + "=" + str(
|
|
|
|
|
int((a + 2) * 5 + int(Notes[i][1] * 5))) + "}] ~ ~ ~ playsound " + Instrument + " @s ~ ~ ~ 1000 " + str(
|
|
|
|
|
Notes[i][0]) + " 1000\n")
|
|
|
|
|
a += Notes[i][1]
|
|
|
|
|
if isProsess:
|
|
|
|
|
commands.append("execute @a" + PlayerSelect + " ~ ~ ~ execute @s[scores={" + ScoreboardName + "=" + str(
|
|
|
|
|
int((a + 2) * 5 + int(Notes[i][1] * 5))) + "}] ~ ~ ~ title @s actionbar §e▶ 播放中: §a" + str(
|
|
|
|
|
j) + "/" + str(length) + " || " + str(int(j / length * 1000) / 10) + "\n")
|
|
|
|
|
j += 1
|
|
|
|
|
commands.append("\n\n# 凌云我的世界开发团队 x 凌云软件开发团队 : W-YI(金羿)\n")
|
|
|
|
|
return commands
|
|
|
|
|
# def newDataStructureCounterChange():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def classList_conversion(List: list, ScoreboardName: str,
|
|
|
|
|
isProsess: bool = False) -> list:
|
|
|
|
|
from bgArrayLib.compute import round_up
|
|
|
|
|
commands = []
|
|
|
|
|
length = len(List)
|
|
|
|
|
j = 1
|
|
|
|
|
print(List)
|
|
|
|
|
for k in range(len(List)):
|
|
|
|
|
i = List[k][0]
|
|
|
|
|
print(i)
|
|
|
|
|
print(type(i))
|
|
|
|
|
try:
|
|
|
|
|
if i.instrument > 119:
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
commands.append("execute @e[scores={" +
|
|
|
|
|
ScoreboardName + "=" + str(round_up(i.time_position)).replace(".0", "") + "}] ~ ~" +
|
|
|
|
|
str(127 - i.velocity) +
|
|
|
|
|
" ~ playsound " +
|
|
|
|
|
str(i.instrument) +
|
|
|
|
|
str(i.CD) + "." +
|
|
|
|
|
str(i.pitch)
|
|
|
|
|
+ " @a ~ ~ ~ 1000 1.0 1000\n")
|
|
|
|
|
if isProsess:
|
|
|
|
|
commands.append("execute @a"" ~ ~ ~ execute @s[scores={" + ScoreboardName + "=" +
|
|
|
|
|
str(round_up(i.time_position)).replace(".0", "") +
|
|
|
|
|
"}] ~ ~ ~ title @s actionbar §e▶ 播放中: §a" +
|
|
|
|
|
str(j) + "/" + str(length) + " || " + str(int(j / length * 1000) / 10) + "\n")
|
|
|
|
|
j += 1
|
|
|
|
|
except AttributeError:
|
|
|
|
|
pass
|
|
|
|
|
# a += List[i][1]
|
|
|
|
|
commands.append("\n\n# 凌云我的世界开发团队 x 凌云软件开发团队 : W-YI(金羿)\n")
|
|
|
|
|
print(commands)
|
|
|
|
|
return commands
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 简单载入方块
|
|
|
|
|
# level.set_version_block(posx,posy,posz,"minecraft:overworld",("bedrock", (1, 16, 20)),Block(namespace, name))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 转入指令列表与位置信息转至世界
|
|
|
|
|
def Cmd2World(cmd: list, world: str, dire: list):
|
|
|
|
|
"""将指令以命令链的形式载入世界\n
|
|
|
|
|
cmd指令列表位为一个序列,中包含指令字符串\n
|
|
|
|
|
world为地图所在位置,需要指向文件夹,dire为指令方块生成之位置"""
|
|
|
|
|
level = amulet.load_level(world)
|
|
|
|
|
cdl = []
|
|
|
|
|
for i in cmd:
|
|
|
|
|
# e = True
|
|
|
|
|
try:
|
|
|
|
|
if (i[:i.index('#')].replace(' ', '') != '\n') and (i[:i.index('#')].replace(' ', '') != ''):
|
|
|
|
|
cdl.append(i[:i.index('#')])
|
|
|
|
|
# e = False
|
|
|
|
|
except:
|
|
|
|
|
cdl.append(i)
|
|
|
|
|
# finally:
|
|
|
|
|
# if e is True:
|
|
|
|
|
# cdl.append(i)
|
|
|
|
|
i = 0
|
|
|
|
|
# 第一个是特殊
|
|
|
|
|
universal_block = Block('universal_minecraft', 'command_block',
|
|
|
|
|
{'conditional': TAG_String("false"), 'facing': TAG_String('up'),
|
|
|
|
|
'mode': TAG_String("repeating")})
|
|
|
|
|
cx, cz = block_coords_to_chunk_coords(dire[0], dire[2])
|
|
|
|
|
chunk = level.get_chunk(cx, cz, "minecraft:overworld")
|
|
|
|
|
offset_x, offset_z = dire[0] - 16 * cx, dire[2] - 16 * cz
|
|
|
|
|
universal_block_entity = BlockEntity('universal_minecraft', 'command_block', dire[0], dire[1], dire[2],
|
|
|
|
|
amulet_nbt.NBTFile(TAG_Compound({'utags': TAG_Compound(
|
|
|
|
|
{'auto': TAG_Byte(0), 'Command': TAG_String(cdl.pop(0))})})))
|
|
|
|
|
chunk.blocks[offset_x, dire[1], offset_z] = level.block_palette.get_add_block(universal_block)
|
|
|
|
|
chunk.block_entities[(dire[0], dire[1], dire[2])] = universal_block_entity
|
|
|
|
|
chunk.changed = True
|
|
|
|
|
# 集体上移
|
|
|
|
|
dire[1] += 1
|
|
|
|
|
# 真正开始
|
|
|
|
|
down = False
|
|
|
|
|
for j in cdl:
|
|
|
|
|
if dire[1] + i >= 255:
|
|
|
|
|
dire[0] += 1
|
|
|
|
|
i = 0
|
|
|
|
|
down = not down
|
|
|
|
|
# 定义此方块
|
|
|
|
|
if dire[1] + i == 254:
|
|
|
|
|
universal_block = Block('universal_minecraft', 'command_block',
|
|
|
|
|
{'conditional': TAG_String("false"), 'facing': TAG_String('east'),
|
|
|
|
|
'mode': TAG_String("chain")})
|
|
|
|
|
else:
|
|
|
|
|
if down:
|
|
|
|
|
universal_block = Block('universal_minecraft', 'command_block',
|
|
|
|
|
{'conditional': TAG_String("false"), 'facing': TAG_String('down'),
|
|
|
|
|
'mode': TAG_String("chain")})
|
|
|
|
|
else:
|
|
|
|
|
universal_block = Block('universal_minecraft', 'command_block',
|
|
|
|
|
{'conditional': TAG_String("false"), 'facing': TAG_String('up'),
|
|
|
|
|
'mode': TAG_String("chain")})
|
|
|
|
|
cx, cz = block_coords_to_chunk_coords(dire[0], dire[2])
|
|
|
|
|
# 获取区块
|
|
|
|
|
chunk = level.get_chunk(cx, cz, "minecraft:overworld")
|
|
|
|
|
offset_x, offset_z = dire[0] - 16 * cx, dire[2] - 16 * cz
|
|
|
|
|
if down:
|
|
|
|
|
# 定义方块实体
|
|
|
|
|
universal_block_entity = BlockEntity('universal_minecraft', 'command_block', dire[0], 254 - i, dire[2],
|
|
|
|
|
amulet_nbt.NBTFile(TAG_Compound({'utags': TAG_Compound(
|
|
|
|
|
{'auto': TAG_Byte(1), 'Command': TAG_String(j)})})))
|
|
|
|
|
|
|
|
|
|
# 将方块加入世界
|
|
|
|
|
chunk.blocks[offset_x, 254 - i, offset_z] = level.block_palette.get_add_block(universal_block)
|
|
|
|
|
chunk.block_entities[(dire[0], 254 - i, dire[2])] = universal_block_entity
|
|
|
|
|
else:
|
|
|
|
|
# 定义方块实体
|
|
|
|
|
universal_block_entity = BlockEntity('universal_minecraft', 'command_block', dire[0], dire[1] + i, dire[2],
|
|
|
|
|
amulet_nbt.NBTFile(TAG_Compound({'utags': TAG_Compound(
|
|
|
|
|
{'auto': TAG_Byte(1), 'Command': TAG_String(j)})})))
|
|
|
|
|
|
|
|
|
|
# 将方块加入世界
|
|
|
|
|
chunk.blocks[offset_x, dire[1] + i, offset_z] = level.block_palette.get_add_block(universal_block)
|
|
|
|
|
chunk.block_entities[(dire[0], dire[1] + i, dire[2])] = universal_block_entity
|
|
|
|
|
# 设置为已更新区块
|
|
|
|
|
chunk.changed = True
|
|
|
|
|
i += 1
|
|
|
|
|
del i, cdl
|
|
|
|
|
# 保存世界并退出
|
|
|
|
|
level.save()
|
|
|
|
|
level.close()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 音符转成方块再加载到世界里头
|
|
|
|
|
def Blocks2World(world: str, dire: list, Datas: list):
|
|
|
|
|
from nmcsup.const import Blocks
|
|
|
|
|
level = amulet.load_level(world)
|
|
|
|
|
i = 0
|
|
|
|
|
|
|
|
|
|
def setblock(block: str, pos: list):
|
|
|
|
|
"""pos : list[int,int,int]"""
|
|
|
|
|
cx, cz = block_coords_to_chunk_coords(pos[0], pos[2])
|
|
|
|
|
chunk = level.get_chunk(cx, cz, "minecraft:overworld")
|
|
|
|
|
offset_x, offset_z = pos[0] - 16 * cx, pos[2] - 16 * cz
|
|
|
|
|
chunk.blocks[offset_x, pos[1], offset_z] = level.block_palette.get_add_block(Block("minecraft", block))
|
|
|
|
|
chunk.changed = True
|
|
|
|
|
|
|
|
|
|
for j in Datas:
|
|
|
|
|
if dire[1] + 1 >= 255:
|
|
|
|
|
i = 0
|
|
|
|
|
dire[0] += 1
|
|
|
|
|
setblock(Blocks[j[0]], [dire[0], dire[1] + i, dire[2]])
|
|
|
|
|
i = int(i + j[1] + 0.5) # 四舍五入
|
|
|
|
|
level.save()
|
|
|
|
|
level.close()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 传入音符列表制作播放器指令
|
|
|
|
|
def Notes2Player(Note, dire: list, CmdData: dict):
|
|
|
|
|
"""传入音符列表、坐标、指令数据,生成播放器指令"""
|
|
|
|
|
Notes = {}
|
|
|
|
|
for i in Note:
|
|
|
|
|
Notes[i[0]] = ''
|
|
|
|
|
Notes = list(Notes.keys())
|
|
|
|
|
from nmcsup.const import Blocks
|
|
|
|
|
Cmds = []
|
|
|
|
|
for j in Notes:
|
|
|
|
|
Cmds.append('execute @e[x=' + str(dire[0]) + ',y=' + str(dire[1]) + ',z=' + str(dire[2]) + ',dy=' + str(
|
|
|
|
|
255 - dire[1]) + ',name=' + CmdData['Ent'] + '] ~ ~ ~ detect ~ ~ ~ ' + Blocks[j] + ' 0 execute @a ' +
|
|
|
|
|
CmdData['Pls'] + ' ~ ~ ~ playsound ' + CmdData['Ins'] + ' @s ~ ~ ~ 1000 ' + str(j) + ' 1000\n')
|
|
|
|
|
Cmds += ['#本函数由 金羿 音·创 生成\n', 'execute @e[y=' + str(dire[1]) + ',dy=' + str(255 - dire[1]) + ',name=' + CmdData[
|
|
|
|
|
'Ent'] + '] ~ ~ ~ tp ~ ~1 ~\n',
|
|
|
|
|
'execute @e[y=255,dy=100,name=' + CmdData['Ent'] + '] ~ ~ ~ tp ~1 ' + str(dire[1]) + ' ~\n',
|
|
|
|
|
'#音·创 开发交流群 861684859']
|
|
|
|
|
return Cmds
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 传入音符列表生成方块至世界
|
|
|
|
|
def Datas2BlkWorld(NoteData, world: str, dire: list):
|
|
|
|
|
for i in range(len(NoteData)):
|
|
|
|
|
Blocks2World(world, [dire[0], dire[1], dire[2] + i], NoteData[i])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
from nmcreader import midi_conversion
|
|
|
|
|
path = "L:\\0WorldMusicCreater-MFMS new edition\\框架\\v0.3.2\\Musicreater\\测试用\\同道殊途标准.mid"
|
|
|
|
|
b = midi_conversion(path)
|
|
|
|
|
classList_conversion(b, "n")
|