"""音创系列的转换功能""" from nmcsup.log import log # 输入一个列表 [ [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 if isProsess: 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 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 #简单载入方块 #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: try: if (i[:i.index('#')].replace(' ','') != '\n') and(i[:i.index('#')].replace(' ','') != ''): cdl.append(i[:i.index('#')]) except: 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:Block,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) 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]) def World2Rys(world:str,startp:list,endp:list,isAir:bool=False ): level = amulet.load_level(world) RyStruct = {} for x in range(startp[0],endp[0]): for y in range(startp[1],endp[1]): for z in range(startp[2],endp[2]): RyStructBlock = {} cx, cz = block_coords_to_chunk_coords(x, z) chunk = level.get_chunk(cx, cz, "minecraft:overworld") universal_block = chunk.block_palette[chunk.blocks[x - 16 * cx, y, z - 16 * cz]] if universal_block == Block("universal_minecraft","air") and isAir: continue universal_block_entity = chunk.block_entities.get((x, y, z), None) universal_block.namespace universal_block_entity.namespace #not be finished ''' RyStruct = { (0,0,0) = { "block":{ "namespace":"", "base_name":"", "properties":{} }, "block_entity":{ "namespace":"", "base_name":"", } } } '''