Musicreater/nmcsup/trans.py

246 lines
9.9 KiB
Python
Raw Normal View History

2021-11-21 00:59:15 +08:00
"""音创系列的转换功能"""
2022-01-19 17:48:47 +08:00
# 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日
# 统计致命三级错误0个警告二级错误2个语法一级错误192个
2021-11-21 00:59:15 +08:00
from nmcsup.log import log
2022-01-19 17:48:47 +08:00
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
2021-11-21 00:59:15 +08:00
# 输入一个列表 [ [str, float ], [], ... ] 音符str 值为持续时间float
2022-01-19 17:48:47 +08:00
def note2list(Notes: list) -> list:
2021-11-21 00:59:15 +08:00
from nmcsup.const import notes
2022-01-19 17:48:47 +08:00
2021-11-21 00:59:15 +08:00
def change(base):
enwo = {
2022-01-19 17:48:47 +08:00
'a': 'A',
'b': 'B',
'c': 'C',
'd': "D",
"e": "E",
'f': 'F',
'g': "G"
2021-11-21 00:59:15 +08:00
}
nuwo = {
2022-01-19 17:48:47 +08:00
'6': 'A',
'7': 'B',
'1': 'C',
'2': "D",
"3": "E",
'4': 'F',
'5': "G"
2021-11-21 00:59:15 +08:00
}
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
2022-01-19 17:48:47 +08:00
2021-11-21 00:59:15 +08:00
res = []
log(" === 音符列表=>音调列表")
for i in Notes:
s2 = change(i[0])
2022-01-19 17:48:47 +08:00
log(' === 正在操作音符' + i[0] + '->' + s2)
2021-11-21 00:59:15 +08:00
if s2 in notes.keys():
2022-01-19 17:48:47 +08:00
log(" === 找到此音符,加入:" + str(notes[s2][0]))
2021-11-21 00:59:15 +08:00
res.append([notes[s2][0], float(i[1])])
else:
2022-01-19 17:48:47 +08:00
log(' === ' + s2 + '不在音符表内,此处自动替换为 休止符0 ')
2021-11-21 00:59:15 +08:00
res.append(['0', float(i[1])])
2022-01-19 17:48:47 +08:00
log(' === 最终反回' + str(res))
2021-11-21 00:59:15 +08:00
return res
def mcnote2freq(Notes):
from nmcsup.const import notes
mcnback = {}
2022-01-19 17:48:47 +08:00
for i, j in notes.items():
2021-11-21 00:59:15 +08:00
mcnback[j[0]] = i
res = []
log(" === 我的世界音调表=>频率列表")
for i in Notes:
2022-01-19 17:48:47 +08:00
log(' === 正在操作音符' + i[0] + '->' + mcnback[i[0]])
2021-11-21 00:59:15 +08:00
res.append([notes[mcnback[i[0]]][1], float(i[1])])
2022-01-19 17:48:47 +08:00
log(' === 最终反回' + str(res))
2021-11-21 00:59:15 +08:00
return res
2022-01-19 17:48:47 +08:00
# MP3文件转midi文件
2021-11-21 00:59:15 +08:00
def Mp32Mid(mp3File, midFile):
from piano_transcription_inference import PianoTranscription, sample_rate, load_audio
# 加载
2022-01-19 17:48:47 +08:00
(audio, _) = load_audio(mp3File, sr=sample_rate) # , mono=True
2021-11-21 00:59:15 +08:00
# 实例化并转换
PianoTranscription(device="cpu").transcribe(audio, midFile)
2022-01-19 17:48:47 +08:00
# 传入一个音符列表转为指令列表
def Note2Cmd(Notes: list, ScoreboardName: str, Instrument: str, PlayerSelect: str = '',
isProsess: bool = False) -> list:
2021-11-21 00:59:15 +08:00
commands = []
a = 0.0
if isProsess:
length = len(Notes)
j = 1
2022-01-19 17:48:47 +08:00
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")
2021-11-21 00:59:15 +08:00
return commands
2022-01-19 17:48:47 +08:00
# 简单载入方块
# level.set_version_block(posx,posy,posz,"minecraft:overworld",("bedrock", (1, 16, 20)),Block(namespace, name))
2021-11-21 00:59:15 +08:00
2022-01-19 17:48:47 +08:00
# 转入指令列表与位置信息转至世界
def Cmd2World(cmd: list, world: str, dire: list):
"""将指令以命令链的形式载入世界\n
2021-11-21 00:59:15 +08:00
cmd指令列表位为一个序列中包含指令字符串\n
2022-01-19 17:48:47 +08:00
world为地图所在位置需要指向文件夹dire为指令方块生成之位置"""
2021-11-21 00:59:15 +08:00
level = amulet.load_level(world)
cdl = []
for i in cmd:
2022-01-19 17:48:47 +08:00
e = True
2021-11-21 00:59:15 +08:00
try:
2022-01-19 17:48:47 +08:00
if (i[:i.index('#')].replace(' ', '') != '\n') and (i[:i.index('#')].replace(' ', '') != ''):
2021-11-21 00:59:15 +08:00
cdl.append(i[:i.index('#')])
2022-01-19 17:48:47 +08:00
e = False
except ValueError:
2021-11-21 00:59:15 +08:00
cdl.append(i)
2022-01-19 17:48:47 +08:00
finally:
if e is True:
cdl.append(i)
2021-11-21 00:59:15 +08:00
i = 0
2022-01-19 17:48:47 +08:00
# 第一个是特殊
universal_block = Block('universal_minecraft', 'command_block',
{'conditional': TAG_String("false"), 'facing': TAG_String('up'),
'mode': TAG_String("repeating")})
2021-11-21 00:59:15 +08:00
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
2022-01-19 17:48:47 +08:00
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))})})))
2021-11-21 00:59:15 +08:00
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
2022-01-19 17:48:47 +08:00
# 集体上移
dire[1] += 1
# 真正开始
2021-11-21 00:59:15 +08:00
down = False
for j in cdl:
2022-01-19 17:48:47 +08:00
if dire[1] + i >= 255:
dire[0] += 1
i = 0
2021-11-21 00:59:15 +08:00
down = not down
2022-01-19 17:48:47 +08:00
# 定义此方块
if dire[1] + i == 254:
universal_block = Block('universal_minecraft', 'command_block',
{'conditional': TAG_String("false"), 'facing': TAG_String('east'),
'mode': TAG_String("chain")})
2021-11-21 00:59:15 +08:00
else:
if down:
2022-01-19 17:48:47 +08:00
universal_block = Block('universal_minecraft', 'command_block',
{'conditional': TAG_String("false"), 'facing': TAG_String('down'),
'mode': TAG_String("chain")})
2021-11-21 00:59:15 +08:00
else:
2022-01-19 17:48:47 +08:00
universal_block = Block('universal_minecraft', 'command_block',
{'conditional': TAG_String("false"), 'facing': TAG_String('up'),
'mode': TAG_String("chain")})
2021-11-21 00:59:15 +08:00
cx, cz = block_coords_to_chunk_coords(dire[0], dire[2])
2022-01-19 17:48:47 +08:00
# 获取区块
2021-11-21 00:59:15 +08:00
chunk = level.get_chunk(cx, cz, "minecraft:overworld")
offset_x, offset_z = dire[0] - 16 * cx, dire[2] - 16 * cz
if down:
2022-01-19 17:48:47 +08:00
# 定义方块实体
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
2021-11-21 00:59:15 +08:00
else:
2022-01-19 17:48:47 +08:00
# 定义方块实体
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
# 设置为已更新区块
2021-11-21 00:59:15 +08:00
chunk.changed = True
2022-01-19 17:48:47 +08:00
i += 1
2021-11-21 00:59:15 +08:00
del i, cdl
2022-01-19 17:48:47 +08:00
# 保存世界并退出
2021-11-21 00:59:15 +08:00
level.save()
level.close()
2022-01-19 17:48:47 +08:00
# 音符转成方块再加载到世界里头
def Blocks2World(world: str, dire: list, Datas: list):
2021-11-21 00:59:15 +08:00
from nmcsup.const import Blocks
level = amulet.load_level(world)
i = 0
2022-01-19 17:48:47 +08:00
def setblock(block: str, pos: list):
"""pos : list[int,int,int]"""
2021-11-21 00:59:15 +08:00
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
2022-01-19 17:48:47 +08:00
chunk.blocks[offset_x, pos[1], offset_z] = level.block_palette.get_add_block(Block("minecraft", block))
2021-11-21 00:59:15 +08:00
chunk.changed = True
2022-01-19 17:48:47 +08:00
2021-11-21 00:59:15 +08:00
for j in Datas:
2022-01-19 17:48:47 +08:00
if dire[1] + 1 >= 255:
2021-11-21 00:59:15 +08:00
i = 0
2022-01-19 17:48:47 +08:00
dire[0] += 1
setblock(Blocks[j[0]], [dire[0], dire[1] + i, dire[2]])
i = int(i + j[1] + 0.5) # 四舍五入
2021-11-21 00:59:15 +08:00
level.save()
level.close()
2022-01-19 17:48:47 +08:00
# 传入音符列表制作播放器指令
def Notes2Player(Note, dire: list, CmdData: dict):
"""传入音符列表、坐标、指令数据,生成播放器指令"""
2021-11-21 00:59:15 +08:00
Notes = {}
for i in Note:
Notes[i[0]] = ''
Notes = list(Notes.keys())
from nmcsup.const import Blocks
Cmds = []
for j in Notes:
2022-01-19 17:48:47 +08:00
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']
2021-11-21 00:59:15 +08:00
return Cmds
2022-01-19 17:48:47 +08:00
# 传入音符列表生成方块至世界
def Datas2BlkWorld(NoteData, world: str, dire: list):
2021-11-21 00:59:15 +08:00
for i in range(len(NoteData)):
2022-01-19 17:48:47 +08:00
Blocks2World(world, [dire[0], dire[1], dire[2] + i], NoteData[i])