diff --git a/plugin_market/SuperSoundMixer/__init__.py b/plugin_market/SuperSoundMixer/__init__.py deleted file mode 100644 index 73b03df6..00000000 --- a/plugin_market/SuperSoundMixer/__init__.py +++ /dev/null @@ -1,224 +0,0 @@ -# Author: SuperScript -# Description: SuperSoundMixer -# PLUGIN TYPE: def -# if 1 == 0: from dotcs_editor import * # 不可能加载成功的库! 仅供VSCode编辑时看着顺眼, 不要出现这么多未定义波浪线 - -from tooldelta import Print, plugins -from tooldelta.plugin_load import tellrawText, sendcmd, player_message - -plugins.require("brotli") - -import threading -import time -import os, traceback -import ujson as json -from json import JSONDecodeError -from .bdx_work_shop.canvas import Canvas -from .bdx_work_shop.canvas import irio -from collections import defaultdict -from .bdx_work_shop.artists.cmd_midi_music import Artist as MidiDo - -__plugin_meta__ = { - "name": "音效器", - "version": "0.0.1", - "author": "SuperScript", -} - - -path = os.path.join("插件配置文件", "SuperSoundMixer"), os.path.join( - "插件配置文件", "SuperSoundMixer", "SoundCmds" -) - - -if not os.path.isdir(path[0]): - os.mkdir(path[0]) -if not os.path.exists(path[1]): - os.mkdir(path[1]) - with open( - os.path.join("插件配置文件", "SuperSoundMixer", "readme.txt"), - "w", - encoding="utf-8", - ) as txt: - txt.write( - """-SuperSoundMixer- - - 本插件可用作租赁服命令方块播放音效的扩展:使用命令方块控制机器人向玩家播放音效或音乐. - - 支持的音乐文件种类:.mid(MIDI) - - 音乐文件放置的位置: 插件配置文件/SuperSoundMixer/ - - 详情请看使用说明""" - ) - txt.close() - - -class SuperSoundMixer: - def __init__(self): - self.SuperSoundMixer_threadings_num: int = 0 - self.SuperSoundMixer_ThreadMusic = [] - - def mixer_sound( - self, - sound_name, - target="@p", - instrument="note.pling", - ignore_high=None, - speed=1, - loop=False, - ): - """使用这个函数以播放音乐: 会自动创建一个线程. - >>> SuperSoundMixer.mixer_sound(音乐名: str, 播放目标: str, 乐器: str, 忽略高音: None | float, 音高倍率: float, 循环播放: bool) - """ - sound_thread = threading.Thread( - target=self.__mixer__, - args=(sound_name, target, instrument, ignore_high, speed, loop), - ) - sound_thread.start() - - def del_sound_thread(self, sound_name): - """使用这个函数以停止一个音乐线程(音乐名)""" - result = 0 - while sound_name in self.SuperSoundMixer_ThreadMusic: - self.SuperSoundMixer_ThreadMusic.remove(sound_name) - result += 1 - return result - - def __mixer__( - self, - sound_name, - targ="@a", - instrument="note.pling", - ignore_high=None, - speed=1, - loop=False, - ): - self.SuperSoundMixer_threadings_num += 1 - self.SuperSoundMixer_ThreadMusic.append(sound_name) - with open( - "插件配置文件/SuperSoundMixer/SoundCmds/%s.txt" % sound_name, - "r", - encoding="utf-8", - ) as music_txt: - music_cmds = music_txt.read().split("\n") - music_txt.close() - while 1: - lastTip = 0 - for i in music_cmds: - try: - if not sound_name in self.SuperSoundMixer_ThreadMusic: - break # 直接跳出线程 - tip, _, note, vol = eval(i) - time.sleep((tip - lastTip) / 20 * (1 / speed)) - if vol > 0: - if ignore_high: - if note < ignore_high: - sendcmd( - "/execute {who} ~~~ playsound {ins} @s ~~~ {vol} {note}".format( - who=targ, - ins=instrument, - vol=vol, - note=note * speed, - ) - ) - else: - sendcmd( - "/execute {who} ~~~ playsound {ins} @s ~~~ {vol} {note}".format( - who=targ, ins=instrument, vol=vol, note=note * speed - ) - ) - lastTip = tip - except: - pass # 遇到音符读取错误的情况 - if not loop: - break - elif not sound_name in self.SuperSoundMixer_ThreadMusic: - break # 直接跳出线程 - self.SuperSoundMixer_threadings_num -= 1 - - -def updateMidifile(): - for i in os.listdir("插件配置文件/SuperSoundMixer"): - if i.endswith(".mid"): - midi_input = "插件配置文件/SuperSoundMixer/" + i - canvas = Canvas() - p = canvas - artist = MidiDo(canvas=canvas, y=p.y + 10) - music_cmds = artist.convert_music_to_mc_sound( - midi_input, - instrumentes_mapping=defaultdict( - lambda: [(30, None), (127, "pling"), (128, None)] - ), - ) - with open( - "插件配置文件/SuperSoundMixer/SoundCmds/%s.txt" - % i.replace(".mid", ""), - "w", - encoding="utf-8", - ) as musicfile: - for tip, _ins, note, vol in music_cmds: - musicfile.write( - """({}, "{}", {}, {})""".format(tip, _ins, note, vol) + "\n" - ) - musicfile.close() - os.remove("插件配置文件/SuperSoundMixer/" + i) - - -updateMidifile() -Print.print_war( - "§bSuperSoundMixer>> §a打开 §e插件配置文件/SuperSoundMixer 文件夹 §a查看使用说明!." -) -time.sleep(0.5) - - -# 加载此插件后 -# 可以使用如下示例方法直接向对象播放音乐: -# SuperSoundMixer.mixer_sound("C:/恶臭的BGM.mid", "@a[name=art]", "note.bass") -@player_message() -async def _(playername, msg): - if playername.replace("§r", "").replace("§f", "") == "sound": - exception: str = "" - try: - exception = "JSON语法有误" - get_sound_data = json.loads(msg) - exception = "缺少音效MIDI音乐名" - midi_file = get_sound_data["name"] - exception = "缺少播放对相:应是玩家名或mc的目标选择器" - PlaySound_targ = get_sound_data["target"] - except: - tellrawText("@a", "§cSuperSoundMixer§f>> §4不正确的语法: %s." % exception) - return - finally: - del exception - try: - if os.path.exists( - "插件配置文件/SuperSoundMixer/SoundCmds/%s.txt" - % get_sound_data["name"] - ): - try: - ignore_high = get_sound_data["ignore_pitch"] - except KeyError: - ignore_high = None - try: - pitch = get_sound_data["pitch"] - except KeyError: - pitch = 1 - try: - instrument = get_sound_data["instrument"] - except KeyError: - instrument = "note.pling" - try: - instrument = get_sound_data["ignore_low"] - except KeyError: - instrument = None - if not "@" in PlaySound_targ: - Print.print_err( - "§cSuperSoundMixer§f>> %s -> %s" % (midi_file, PlaySound_targ) - ) - # 音乐文件名(无mid后缀) 播放的对象 乐器 忽略高音 速度 - else: - if os.path.exists( - "插件配置文件/SuperSoundMixer/%s.mid" % get_sound_data[2] - ): - updateMidifile() - tellrawText("@a", "§cSuperSoundMixer§f>> §6文件正在初始化") - else: - tellrawText("@a", "§cSuperSoundMixer§f>> §4音效MIDI文件不存在") - except: - print("SuperScript", traceback.format_exc()) diff --git a/plugin_market/SuperSoundMixer/bdx_work_shop/Sample00_bdx_encode_and_decode.py b/plugin_market/SuperSoundMixer/bdx_work_shop/Sample00_bdx_encode_and_decode.py deleted file mode 100644 index 49c33c7b..00000000 --- a/plugin_market/SuperSoundMixer/bdx_work_shop/Sample00_bdx_encode_and_decode.py +++ /dev/null @@ -1,102 +0,0 @@ -import os -import json - -from canvas import BdxEncoder -from canvas import BdxDecoder - -# 根据官网 bdump 格式,https://github.com/LNSSPsd/PhoenixBuilder/blob/main/BDump%20File%20Format.md -# decoder 将 bdx 文件解码为 操作列表,作者,缓存/调色板中方块 的字典 -# decoder 输出格式为 op_code, op_name, params -# encoder 将操作列表编码为bdx 但是支持较为宽松的格式 (见示列) -# decoder 和 encoder 都支持验证签名/添加签名 -# decoder 和 encoder 都支持生成易于人类阅读的日志文件,并可以配置输出哪些操作的信息,在一些情况下,知道究竟发生了什么可能很有帮助 -# 将 decoder 的输出作为encoder的输入时,保证可以生成和fb源文件一样的压缩文件(本文件) -# 缺陷是,decoder和encoder都偏底层,没有提供官网之外的高级操作的api,这部分需要自己实现 - -decoder_input_bdx='data/silo.bdx' -decoder_output_cmds='output/sample00/decoder_out_cmds.json' -decoder_output_logs='output/sample00/decoder_out_logs.txt' - -encoder_output_logs='output/sample00/encoder_out_logs.txt' -encoder_output_bdx='output/sample00/encoder_out_bdx.bdx' - -os.makedirs('output/sample00',exist_ok=True) - -# 配置bdx解析器 配置日志输出位置,为None时输出到屏幕 配置是否验证签名 -decoder = BdxDecoder(decoder_output_logs, need_verify=True) -# 过滤日志输出内容 -# decoder.log_nothing() -decoder.log_command_block_only() -# decoder.log_everthing() -# decoder.log_level.update({'place_block':0}) - -# 打开目标bdx,并解码 -print('decoding...') -with open(decoder_input_bdx, 'rb') as f: - # 解码后生成为操作列表(list),作者,缓存/调色板中方块,最终位置构成的字典 - # 每项操作的格式为 op_code, op_name, params - # 其中,op 没有参数时 params 为 None - # op 参数一个时 params 为参数(i.e., block_data:int) - # op 参数超过一个时 params 为tuple - decode_out = decoder.decode(f) - print('decoding done, write file...') - with open(decoder_output_cmds, 'w') as f: - json.dump(decode_out, f) - print('decoded cmds dumped!') - -# 配置bdx编码器 配置日志输出位置,为None时输出到屏幕 配置是否验证签名 -# 签名所需fbtoken 默认为 fb 存放token的位置,也可以将字符串或者路径传入 -encoder = BdxEncoder(need_sign=True, log_path=encoder_output_logs, author='2401PT',sign_token=None) -# 过滤日志输出内容,和上面一样 -# encoder.log_nothing() -encoder.log_command_block_only() -# encoder.log_everthing() - - -print('encoding...') -# 将操作列表(cmds list)编码为bdx -# 每项操作格式可以为 op_code, op_name, params; 也可以为 op_code, params; 也可以为 op_name, params; -# op 中 params 可以为列表也可以为字典; -# op 中 block可以为调色板中的序号也可以为方块名 -# author,palette 是可选的, -# sign_token为None时默认查找fb自动生成的token -# encode_out 就是生成的bdx文件二进制信息,直接wb写到文件中即可 -encoded_out_bytes = encoder.encode(cmds=decode_out["cmds"], - author=decode_out["author"], - palette=None, # decode_out['palette'], 该参数是可选的,仅在命令中包含也可 - sign_token=None) -print('encoding done, write file...') -with open(encoder_output_bdx, 'wb') as f: - f.write(encoded_out_bytes) - print('encoded bdx saved!') - - -def compare_bytes_array(array_1,array_2): - ok = True - if len(array_1) != len(array_2): - print(f'length_mismathced {len(array_1)} {len(array_2)}') - ok = False - for i, (e, d) in enumerate(zip(array_1, array_2)): - if e != d: - print(f'error occur at {i}') - print(f'{array_1[max(0, i - 20):min(len(array_2), i + 10)]}') - print(f'{array_1[max(0, i - 20):min(len(array_2), i + 10)]}') - ok = False - break - print('pass' if ok else 'fail') - - -# encode_bdx_bytes 为bdx文件(未压缩)从 BDX\x00 之后到文件最后 -encode_bdx_bytes = encoder.bdx_bytes -# decode_bdx_bytes 为bdx文件(解压缩)从 BDX\x00 之后到文件最后 -decode_bdx_bytes = decoder.bdx_bytes - -print('check if the binary code of uncompressed cmds by encoder/decoder is correct') -compare_bytes_array(encode_bdx_bytes,decode_bdx_bytes) - -print('check if the binary code of bdx file outputted by decoder is correct') -with open(decoder_input_bdx, 'rb') as f: - original_bdx_bytes = f.read() -compare_bytes_array(original_bdx_bytes,encoded_out_bytes) - -print('all done') \ No newline at end of file diff --git a/plugin_market/SuperSoundMixer/bdx_work_shop/Sample01_ir_irio_bdx.py b/plugin_market/SuperSoundMixer/bdx_work_shop/Sample01_ir_irio_bdx.py deleted file mode 100644 index fa5acaa3..00000000 --- a/plugin_market/SuperSoundMixer/bdx_work_shop/Sample01_ir_irio_bdx.py +++ /dev/null @@ -1,76 +0,0 @@ -import os -import json - -from canvas import IR -from canvas import irio - -# IR (即,中间表示) (ir.py) 是稀疏矩阵建筑表示 -# 其意义是通过这种中间表示,可以脱离指令,以一种更通用/高级的表示操作方块 -# 同时,numpy的使用提高了操作效率 -# ir 还提供一个rearrange方法,通过重排完成对bdx文件的优化(导入顺序) - -# 稀疏矩阵表示为: -# ir.ir_blocks 稀疏矩阵,numpy 格式,4列 -# [ -# [x,y,z,bid], block0, first import/gen -# [x,y,z,bid], block1, second import/gen -# ... -# ] -# bid 映射表 -# ir.ir_blocks=[ -# [name,val,cb_data] # bid 0 -# [name,val,cb_data] # bid 1 -# ... -# ] -# 对于normal block: cb_data=None,对于命令块,请参照ir.py - -# 为了保持 ir 的简洁性,ir 和 ir到其他结构文件的转换被分别放在 ir.py 和 irio.py 中 - -ir_in_bdx = 'data/silo.bdx' -ir_out_direct_bdx = 'output/sample01/ir_out_bdx[direct].bdx' -ir_out_rearranged_bdx = 'output/sample01/ir_out_bdx[rearranged].bdx' - -os.makedirs('output/sample01', exist_ok=True) - -# 从 bdx 文件创建 -# irio.create_ir_from_cmds(cmds) -ir = irio.create_ir_from_bdx(ir_in_bdx, need_verify=True) -# irio.create_ir_from_mcstructruce(mc_structure_file) - -# 导出 -# irio.dump_ir_to_schem(ir,our_schem_file,rearrange=False) - -# 导出时使用 rearrange 方法并不影响ir中的数据 -irio.dump_ir_to_bdx(ir, ir_out_rearranged_bdx, rearrange=True, - need_sign=True, author='2401PT', sign_token=None) -# 在不使用 rearrange 时,保证生成的文件和fb完全相同 -# irio.dump_ir_to_cmds(ir,rearrange=False) -irio.dump_ir_to_bdx(ir, ir_out_direct_bdx, rearrange=False, - need_sign=True, author='2401PT', sign_token=None) - - -def compare_bytes_array(array_1, array_2): - ok = True - if len(array_1) != len(array_2): - print(f'length_mismathced {len(array_1)} {len(array_2)}') - ok = False - for i, (e, d) in enumerate(zip(array_1, array_2)): - if e != d: - print(f'error occur at {i}') - print(f'{array_1[max(0, i - 20):min(len(array_2), i + 10)]}') - print(f'{array_1[max(0, i - 20):min(len(array_2), i + 10)]}') - ok = False - break - print('pass' if ok else 'fail') - - -print('check if bdx->ir->no rearrange out bdx has exactly same bytes') -with open(ir_in_bdx, 'rb') as f: - original_bdx_bytes = f.read() - -with open(ir_out_direct_bdx, 'rb') as f: - ir_directly_ou_bdx_bytes = f.read() - -compare_bytes_array(original_bdx_bytes, ir_directly_ou_bdx_bytes) - -print('all done') diff --git a/plugin_market/SuperSoundMixer/bdx_work_shop/Sample02_mcstructure_to_bdx.py b/plugin_market/SuperSoundMixer/bdx_work_shop/Sample02_mcstructure_to_bdx.py deleted file mode 100644 index 4cf3afc4..00000000 --- a/plugin_market/SuperSoundMixer/bdx_work_shop/Sample02_mcstructure_to_bdx.py +++ /dev/null @@ -1,18 +0,0 @@ -import os -from canvas import IR -from canvas import irio - -mcstructure_file = 'data/27-2x3TrapDoorDoor.mcstructure' -ir_out_bdx = 'output/sample02/ir_out_bdx[direct].bdx' - -os.makedirs('output/sample02', exist_ok=True) - - -ir = irio.create_ir_from_mcstructruce(mcstructure_file, ignore=['air'], - user_define_mapping={ - 'seaLeatern_1': {(('key1'), ('value1')): 1, - (('key2'), ('value2')): 2, }, - 'some_block': 0 -} -) -irio.dump_ir_to_bdx(ir, out_bdx_file=ir_out_bdx, author='2401PT') diff --git a/plugin_market/SuperSoundMixer/bdx_work_shop/Sample03_schematic_io.py b/plugin_market/SuperSoundMixer/bdx_work_shop/Sample03_schematic_io.py deleted file mode 100644 index 93ba97d9..00000000 --- a/plugin_market/SuperSoundMixer/bdx_work_shop/Sample03_schematic_io.py +++ /dev/null @@ -1,21 +0,0 @@ -import os -from canvas import IR -from canvas import irio - -input_schematic_file = 'data/城市书店1.schematic' -ir_in_bdx = 'data/silo.bdx' -output_bdx_file = 'output/sample03/output.bdx' -output_schematic_file = 'output/sample03/output_schematic.schematic' -output_bdx_file_converted_from_bdx = 'output/sample03/from_bdx.schematic' -os.makedirs('output/sample03', exist_ok=True) - -# 先演示 加载 schematic,并保存为 bdx -ir = irio.create_ir_from_schematic(input_schematic_file, ignore=['air']) -irio.dump_ir_to_bdx(ir, out_bdx_file=output_bdx_file, author='2401PT') - -# 这个被加载的数据 ir 可以被保存为 schematic -irio.dump_ir_to_schematic(ir, output_schematic_file) - -# 当然,也可以先将bdx载入为ir再保存为 schematic -ir = irio.create_ir_from_bdx(ir_in_bdx, need_verify=True) -irio.dump_ir_to_schematic(ir, output_bdx_file_converted_from_bdx) diff --git a/plugin_market/SuperSoundMixer/bdx_work_shop/Sample04_canvas.py b/plugin_market/SuperSoundMixer/bdx_work_shop/Sample04_canvas.py deleted file mode 100644 index a295cf26..00000000 --- a/plugin_market/SuperSoundMixer/bdx_work_shop/Sample04_canvas.py +++ /dev/null @@ -1,119 +0,0 @@ -import os -import sys -from canvas import irio -from canvas import Canvas - -import_bdx_file1 = 'data/silo.bdx' -import_bdx_file2 = 'data/silo.bdx' -mcstructure_file1 = 'data/27-2x3TrapDoorDoor.mcstructure' -input_schematic_file = 'data/城市书店1.schematic' - -canvas_output = 'output/sample04/canvas_output.bdx' -canvas_output_schematic = 'output/sample04/canvas_output_schematic.schematic' -os.makedirs('output/sample04', exist_ok=True) - -# 创建一个工作区,可以往工作区中导入多个建筑文件(目前支持:bdx, mcstructure) -# setblock, fill,move,clone replace放置命令块, 清除区域内方块, -# 最后导出一个导入顺序优化过的的bdx文件(参见昨天的部分,check.py) -# 上述命令都支持 相对和绝对位置 当一个xyz内被多次设置方块时,以最后一次为准 - -# mcstructure 为有限支持,因为其方块表示和 基岩版的 name value 形式不能完全匹配 -# 使用时会在屏幕上输出程序推断的格式 - -canvas = Canvas() -# 坐标,只是为了方便 -p = canvas - -# 所有操作都有坐标(绝对坐标),留空时以最后一次move的位置为准 -# 移动到 ~1 2 ~ 处,和tp指令还是有点像的吧 -# 但是实际上有很灵活的操作方式 -canvas.move_to(p.x + 1, y=2) -canvas.move_to(5, 5, 5) -canvas.move_to(z=0) -canvas.move_to(y=p.y+3) - - -# 放置三个命令块 当前位置 ~~~3 处向上叠3个 -for i in range(3): - canvas.place_command_block_with_data(z=p.z + 3, - y=p.y + i, - facing=p.FACE_UP, - cb_mode=p.MODE_CHAIN_CB, - command='kill @e[type=tnt]', - cb_name='kill tnt cb1', - tick_delay=10, - track_output=True) -# 移动 -canvas.move_to(10, 5, 5) - -# 放置方块,重叠时以最后一次操作为准 -canvas.setblock('grass', 0, y=p.y + 10) -canvas.setblock('stone', 0) -canvas.setblock('wool') -canvas.setblock('wool', 2, p.x, p.y, p.z + 1) -canvas.setblock('wool', 3, p.x, p.y, p.z + 5) - -# replace wordwide 支持宽泛的格式 -# 尝试完全匹配给定的方块,并将目标方块部分替换 -# ori_block glass -> match (glass,0,None), (glass,1,None) -# ori_block (glass,1) -> match (glass,1,None) mismatch (glass,2,None) -# new_block wool => (glass,1,None)->(glass,1,None);(glass,2,None)->(glass,2,None) -# new_block (wool,0) => (glass,1,None)->(glass,0,None);(glass,2,None)->(glass,0,None) -canvas.replace_wordwide('glass', ('stained_glass', 0)) -canvas.replace_wordwide(('wool', 0), 'quartz_block') -canvas.replace_wordwide(('wool', 2, None), ('quartz_block', 0, None)) - -# 清除一个小区域 -canvas.fill(ex=p.x + 2, ey=p.y + 2, ez=p.z + 2, remove=True) - -# 移动 -canvas.move_to(p.x + 5) - -# 清除一个方块 -canvas.setblock(p.x, p.y, p.z + 5, remove=True) - -# 放置几个命令块 -canvas.setblock('glass', 0, p.x, p.y, p.z + 10) -canvas.fill('quartz_block', - 0, - x=p.x, - y=p.y, - z=p.z, - ex=p.x + 3, - ey=p.y + 4, - ez=p.z + 5) - -# 在工作区(画布)上加载一个或者多个文件 -# 载入一个 bdx 文件 -canvas.load_ir(ir=irio.create_ir_from_mcstructruce(mcstructure_file1, ignore=['air']), - ox=p.x + 5) -# 载入一个 bdx 文件 -canvas.load_ir(ir=irio.create_ir_from_bdx(import_bdx_file1, need_verify=True), - ox=p.x+10) - -canvas.load_ir(ir=irio.create_ir_from_bdx(import_bdx_file1, need_verify=True), - ox=p.x+10, oy=p.y + 10) - -# 载入一个 schematic 文件 -canvas.load_ir(ir=irio.create_ir_from_schematic( - input_schematic_file, ignore=['air']), oz=p.z+20, oy=p.y + 10) - -# 基于 selector 实现的复杂操作,建议阅读 selector 实现确定如何使用 -# block 和 bid 都会生效,坐标留空时默认为整个工作区的起点/终点 -# 注意!copy 和 move 都是基于 offset 的,而不是指定新的起点坐标 -canvas.move_to(p.x+20) -indices = canvas.select() -canvas.fill(block_name='glass', x=p.x, y=p.y, - z=p.z, ex=p.x+5, ey=p.y+5, ez=p.z+5) -canvas.replace(('stained_glass', 1), sx=p.x+1, ex=p.x+4, - sy=p.y+2, orig_blocks=[('glass', 0), ('stone', 0)]) -canvas.copy(sx=p.x, sy=p.y, sz=p.z, ex=p.x+5, ey=p.y+5, ez=p.z+5, offset_x=3, - offset_y=3, offset_z=3) # can filter by ,blocks=[('glass',0)]) -canvas.move(sx=p.x, ex=p.x+10, ey=p.y+5, offset_y=15, blocks=['stained_block']) - -# 将工作区导出为优化导入顺序后的bdx文件 -final_ir = canvas.done() -irio.dump_ir_to_bdx(final_ir, canvas_output, need_sign=True, author='2401PT') - -# 也可以导出为 schematic 文件,就是命令块数据会丢失 -irio.dump_ir_to_schematic(final_ir, canvas_output_schematic) diff --git a/plugin_market/SuperSoundMixer/bdx_work_shop/Sample05_snake_folding.py b/plugin_market/SuperSoundMixer/bdx_work_shop/Sample05_snake_folding.py deleted file mode 100644 index 02aad172..00000000 --- a/plugin_market/SuperSoundMixer/bdx_work_shop/Sample05_snake_folding.py +++ /dev/null @@ -1,50 +0,0 @@ -import os -from canvas import irio -from canvas import Canvas - -canvas_output = 'output/sample05/canvas_output.bdx' -os.makedirs('output/sample05', exist_ok=True) - -canvas = Canvas() -p = canvas -cbs_array = [ - {'cb_mode': p.MODE_REPEAT_CB, 'command': 'cmd', - 'cb_name': f'cb{0}', 'conditional': False} -] -cb_i = 1 -for _ in range(10): - for i in range(2): - cbs_array.append( - {'command': 'cmd', 'cb_name': f'cb{cb_i}', 'conditional': True, 'tick_delay': 10}) - cb_i += 1 - for i in range(3): - cbs_array.append( - {'command': 'cmd', 'cb_name': f'cb{cb_i}', 'conditional': False, 'tick_delay': 20}) - cb_i += 1 - - -# 现在的问题是,一直线的排列命令块显然是不合适的, -# 我们需要命令块首先在一层堆叠,(dir1,dir2) -# 当堆叠满一层后再移动到下一层 (dir3) -# 第二个问题是,有条件命令块在拐角时无法正常工作,所以需要重排 -# 即,适当时插入多个空连锁命令块,直到可以分配位置为止 -# x,y,z 代表堆叠的起点位置 -canvas.snake_folding_cmds( - x=0, y=20, z=0, - dir1=(1, 0, 0), dir1_lim=4, - dir2=(0, 0, 1), dir2_lim=4, - dir3=(0, 1, 0), - cbs_array=cbs_array -) - -# 也可以这么指定方向 -canvas.snake_folding_cmds( - x=10, y=20, z=0, - dir1=(1, 0, 0), dir1_lim=4, - dir2=(0, 0, -1), dir2_lim=4, - dir3=(0, -1, 0), - cbs_array=cbs_array -) - -final_ir = canvas.done() -irio.dump_ir_to_bdx(final_ir, canvas_output, need_sign=True, author='2401PT') diff --git a/plugin_market/SuperSoundMixer/bdx_work_shop/Sample06_artist_sample.py b/plugin_market/SuperSoundMixer/bdx_work_shop/Sample06_artist_sample.py deleted file mode 100644 index 5a5b63e0..00000000 --- a/plugin_market/SuperSoundMixer/bdx_work_shop/Sample06_artist_sample.py +++ /dev/null @@ -1,33 +0,0 @@ -import os -from canvas import Canvas -from artists.basic import Artist as BasicArtist -from canvas import irio - -canvas_output = 'output/sample06/canvas_output.bdx' -os.makedirs('output/sample06', exist_ok=True) - -canvas = Canvas() -p = canvas - -# Artist 的目的是将复杂而高级的操作从 canvas 抽离出来, -# 避免 canvas 的成员函数过于复杂 -# 并允许用户自行定义复杂的操作 -# 初始化时需要告诉 artist 目标工作区,并指定创作空间和 canvas 的偏移 -artist = BasicArtist(canvas=canvas, y=p.y+10) - -# 通过 artist 将复杂的操作进行封装 -artist.draw_cubic(block_name='stained_glass', - block_val=0, x=5, ex=15, ey=10, ez=artist.z+10) - -# artist 维护一个自己的坐标系,与工作区隔离 -artist.move_to(x=artist.x+10) - -# 同上 -artist.draw_cubic(block_name='stained_glass', - block_val=1, x=15, ex=25, ey=10, ez=artist.z+10) - -# 所有 artist 都应使用该函数作为收尾工作 -artist.to_canvas() - -final_ir = canvas.done() -irio.dump_ir_to_bdx(final_ir, canvas_output, need_sign=True, author='2401PT') diff --git a/plugin_market/SuperSoundMixer/bdx_work_shop/Sample07_cmd_music.py b/plugin_market/SuperSoundMixer/bdx_work_shop/Sample07_cmd_music.py deleted file mode 100644 index b9f5f795..00000000 --- a/plugin_market/SuperSoundMixer/bdx_work_shop/Sample07_cmd_music.py +++ /dev/null @@ -1,55 +0,0 @@ -import os -from canvas import Canvas -from canvas import irio -from collections import defaultdict -from artists.cmd_midi_music import Artist as CmdMusicArtist - -midi_input = 'data/Undertale.mid' -canvas_output = 'output/sample07/midi_music_output.bdx' -os.makedirs('output/sample07', exist_ok=True) - -canvas = Canvas() -p = canvas - - -artist = CmdMusicArtist(canvas=canvas, y=p.y+10) - -# 问题在于乐器的映射 -# 这是默认的映射方式,所有通道一样处理 -# 高音部由 bell, 中音部由 piano(harp) 低音部由 bass 三个构成的组合 -music_cmds = artist.convert_music_to_mc_sound( - midi_input, - instrumentes_mapping=defaultdict(lambda :[ # 所有通道都采用一样的处理方式 - (30,None), # <30 不处理 - (54,'note.bass'), # 30~54 bass - (78,'note.harp'), # 54~78 harp 钢琴 - (102,'note.bell'), # 78~102 bell - (128,None) # 128< 不处理 - ]) -) - -# 中音部由 pling (电子琴) 构成 -music_cmds = artist.convert_music_to_mc_sound( - midi_input, - instrumentes_mapping=defaultdict(lambda :[ # 所有通道都采用一样的处理方式 - # (30,None), - (54,'note.bass'), # 0~54 bass - (78,'note.pling'), # 54~78 pling 电子琴 - (102,'note.bell'), # <78~102 bell - # (128,None) - ]) -) - - -# 也可以接收音乐,会先将音乐转化为 midi -# music_cmds = artist.convert_music_to_mc_sound(music_input, pling=True) - - -artist.write_to_cbs(music_cmds, x=0, y=0, z=0, - dir1=(1, 0, 0), dir1_lim=16, - dir2=(0, 0, 1), dir2_lim=16, - dir3=(0, 1, 0), cmds_wrapper="execute @a ~~~ playsound {} @s ~~~ {:.3f} {:.3f}") -artist.to_canvas() - -final_ir = canvas.done() -irio.dump_ir_to_bdx(final_ir, canvas_output, need_sign=True, author='2401PT') diff --git a/plugin_market/SuperSoundMixer/bdx_work_shop/Sample08_map _art.py b/plugin_market/SuperSoundMixer/bdx_work_shop/Sample08_map _art.py deleted file mode 100644 index d534e9c9..00000000 --- a/plugin_market/SuperSoundMixer/bdx_work_shop/Sample08_map _art.py +++ /dev/null @@ -1,50 +0,0 @@ -import os -from canvas import Canvas -from canvas import irio -from collections import defaultdict -from artists.map_art import Artist as MapArtArtist - -image_input="data\QQ图片20220115231611.jpg" -output_dir= 'output/sample08' -os.makedirs(output_dir,exist_ok=True) - -# 2D -canvas = Canvas() -p = canvas -artist = MapArtArtist(canvas=canvas,y=0) - -artist.add_img(img_path=image_input, - level_x=2,level_y=2, # 希望用几张地图实现呢? - d3=False, - save_resized_file_to=os.path.join(output_dir,'resized_img.png'), #只是缩放了图片 - save_preview_to=os.path.join(output_dir,"preview.png"), # 效果预览图,不出意外导入游戏就是这样的 - ) -artist.to_canvas() - -final_ir = canvas.done() -irio.dump_ir_to_bdx(final_ir, - os.path.join(output_dir,"map.bdx"), # 保存文件路径 - need_sign=True, - author='2401PT') - - - -# 3D, also takes y space -canvas = Canvas() -p = canvas -artist = MapArtArtist(canvas=canvas,y=0) - -artist.add_img(img_path=image_input, - level_x=2,level_y=2, # 希望用几张地图实现呢? - d3=True, # 通过利用阴影算法,扩展颜色空间 - save_resized_file_to=os.path.join(output_dir,'resized_img_3d.png'), #只是缩放了图片 - save_preview_to=os.path.join(output_dir,"preview_3d.png"), # 效果预览图,不出意外导入游戏就是这样的 - y_max=200 # 运行使用的最大y空间, 比如说,导入的y高度为20,最大可用到220 - ) -artist.to_canvas() - -final_ir = canvas.done() -irio.dump_ir_to_bdx(final_ir, - os.path.join(output_dir,"map_3d.bdx"), # 保存文件路径 - need_sign=True, - author='2401PT') \ No newline at end of file diff --git a/plugin_market/SuperSoundMixer/bdx_work_shop/Sample09_json_to_bdx.py b/plugin_market/SuperSoundMixer/bdx_work_shop/Sample09_json_to_bdx.py deleted file mode 100644 index 2d199e6a..00000000 --- a/plugin_market/SuperSoundMixer/bdx_work_shop/Sample09_json_to_bdx.py +++ /dev/null @@ -1,34 +0,0 @@ -import json -import os -from canvas import irio -from canvas import Canvas - -import_json_file = 'data/六分之一的小岛.json' -canvas_output = 'output/sample09/六分之一的小岛.bdx' -os.makedirs('output/sample09', exist_ok=True) - -canvas = Canvas() -p = canvas -with open(import_json_file,"r") as f: - inBlocks=json.load(f) - print(f"{len(inBlocks)} blocks in total") - for block in inBlocks: - name=block["name"][10:] - x,y,z=block["x"],block["y"],block["z"] - data=block["aux"] - if not "command" in name: - canvas.setblock(name, data, x,y,z) - else: - canvas.place_command_block_with_data( - x=x, y=y, z=z, - block_name=name, - facing=int(block["facing"]), - cb_mode=None, - command=block["command"], cb_name=block["name"], - tick_delay=int(block["tick_delay"]), - execute_on_first_tick=False, - track_output=bool(int(block["track_output"])), - conditional=bool(int(block["cb_mode"])), - needRedstone=bool(int(block["need_redstone"])),) -final_ir = canvas.done() -irio.dump_ir_to_bdx(final_ir, canvas_output, need_sign=True, author='2401PT') \ No newline at end of file diff --git a/plugin_market/SuperSoundMixer/bdx_work_shop/artists/basic.py b/plugin_market/SuperSoundMixer/bdx_work_shop/artists/basic.py deleted file mode 100644 index d2f886cf..00000000 --- a/plugin_market/SuperSoundMixer/bdx_work_shop/artists/basic.py +++ /dev/null @@ -1,33 +0,0 @@ -from canvas import Canvas - - -class Artist(Canvas): - def __init__(self, canvas: Canvas, x=None, y=None, z=None): - ''' - Artist 的目的是将复杂而高级的操作从 canvas 抽离出来, - 避免 canvas 的成员函数过于复杂 - 并允许用户自行定义复杂的操作 - 可以看到Artist关联的canvas有两个,一个是目标工作区的,一个是自己的 - Artist 可以使用也可以不使用自己的画布 - 但是,无论如何,都不应该修改工作区 canvas 的坐标 - ''' - super().__init__() - self.target_canvas = canvas - self.target_xyz = {'ox': x, 'oy': y, 'oz': z} - - def draw_cubic(self, block_name='air', block_val=0, - x=None, y=None, z=None, - ex=None, ey=None, ez=None): - '''一个示例功能,此时是绘制在自己管理的canvas中''' - self.fill(block_name, block_val, x, y, z, ex, ey, ez) - return self - - def to_canvas(self): - ''' - Artist 类应该提供一个 to_canvas 函数作为收尾 - 这个函数用于使所有的操作实质性生效 - 例如,将自己管理的canvas内容复制到目标canvas中 - ''' - self_host_ir = self.done() - self.target_canvas.load_ir(self_host_ir, merge=True, **self.target_xyz) - return self diff --git a/plugin_market/SuperSoundMixer/bdx_work_shop/artists/cmap.json b/plugin_market/SuperSoundMixer/bdx_work_shop/artists/cmap.json deleted file mode 100644 index a1191acd..00000000 --- a/plugin_market/SuperSoundMixer/bdx_work_shop/artists/cmap.json +++ /dev/null @@ -1,706 +0,0 @@ -[ - [ - [ - "stone", - 0 - ], - [ - 89, - 89, - 89 - ] - ], - [ - [ - "stone", - 1 - ], - [ - 135, - 102, - 76 - ] - ], - [ - [ - "stone", - 3 - ], - [ - 237, - 235, - 229 - ] - ], - [ - [ - "stone", - 5 - ], - [ - 104, - 104, - 104 - ] - ], - [ - [ - "grass", - 0 - ], - [ - 144, - 174, - 94 - ] - ], - [ - [ - "planks", - 0 - ], - [ - 129, - 112, - 73 - ] - ], - [ - [ - "planks", - 1 - ], - [ - 114, - 81, - 51 - ] - ], - [ - [ - "planks", - 2 - ], - [ - 228, - 217, - 159 - ] - ], - [ - [ - "planks", - 4 - ], - [ - 71, - 71, - 71 - ] - ], - [ - [ - "planks", - 5 - ], - [ - 91, - 72, - 50 - ] - ], - [ - [ - "leaves", - 0 - ], - [ - 64, - 85, - 32 - ] - ], - [ - [ - "leaves", - 1 - ], - [ - 54, - 75, - 50 - ] - ], - [ - [ - "leaves", - 2 - ], - [ - 68, - 83, - 47 - ] - ], - [ - [ - "leaves", - 14 - ], - [ - 58, - 71, - 40 - ] - ], - [ - [ - "leaves", - 15 - ], - [ - 55, - 73, - 28 - ] - ], - [ - [ - "sponge", - 0 - ], - [ - 183, - 183, - 70 - ] - ], - [ - [ - "lapis_block", - 0 - ], - [ - 69, - 101, - 198 - ] - ], - [ - [ - "noteblock", - 0 - ], - [ - 111, - 95, - 63 - ] - ], - [ - [ - "web", - 0 - ], - [ - 159, - 159, - 159 - ] - ], - [ - [ - "wool", - 0 - ], - [ - 205, - 205, - 205 - ] - ], - [ - [ - "wool", - 1 - ], - [ - 163, - 104, - 54 - ] - ], - [ - [ - "wool", - 2 - ], - [ - 132, - 65, - 167 - ] - ], - [ - [ - "wool", - 3 - ], - [ - 91, - 122, - 169 - ] - ], - [ - [ - "wool", - 5 - ], - [ - 115, - 162, - 53 - ] - ], - [ - [ - "wool", - 6 - ], - [ - 182, - 106, - 131 - ] - ], - [ - [ - "wool", - 7 - ], - [ - 60, - 60, - 60 - ] - ], - [ - [ - "wool", - 8 - ], - [ - 123, - 123, - 123 - ] - ], - [ - [ - "wool", - 9 - ], - [ - 69, - 100, - 121 - ] - ], - [ - [ - "wool", - 10 - ], - [ - 94, - 52, - 137 - ] - ], - [ - [ - "wool", - 11 - ], - [ - 45, - 59, - 137 - ] - ], - [ - [ - "wool", - 12 - ], - [ - 78, - 61, - 43 - ] - ], - [ - [ - "wool", - 13 - ], - [ - 85, - 100, - 49 - ] - ], - [ - [ - "wool", - 14 - ], - [ - 113, - 46, - 44 - ] - ], - [ - [ - "wool", - 15 - ], - [ - 20, - 20, - 20 - ] - ], - [ - [ - "gold_block", - 0 - ], - [ - 198, - 191, - 84 - ] - ], - [ - [ - "iron_block", - 0 - ], - [ - 134, - 134, - 134 - ] - ], - [ - [ - "double_stone_slab", - 1 - ], - [ - 196, - 187, - 136 - ] - ], - [ - [ - "double_stone_slab", - 6 - ], - [ - 204, - 202, - 196 - ] - ], - [ - [ - "double_stone_slab", - 7 - ], - [ - 81, - 11, - 5 - ] - ], - [ - [ - "tnt", - 0 - ], - [ - 188, - 39, - 26 - ] - ], - [ - [ - "mossy_cobblestone", - 0 - ], - [ - 131, - 134, - 146 - ] - ], - [ - [ - "diamond_block", - 0 - ], - [ - 102, - 173, - 169 - ] - ], - [ - [ - "farmland", - 0 - ], - [ - 116, - 88, - 65 - ] - ], - [ - [ - "ice", - 0 - ], - [ - 149, - 149, - 231 - ] - ], - [ - [ - "pumpkin", - 1 - ], - [ - 189, - 122, - 62 - ] - ], - [ - [ - "monster_egg", - 1 - ], - [ - 153, - 156, - 169 - ] - ], - [ - [ - "red_mushroom_block", - 0 - ], - [ - 131, - 53, - 50 - ] - ], - [ - [ - "vine", - 1 - ], - [ - 68, - 89, - 34 - ] - ], - [ - [ - "brewing_stand", - 6 - ], - [ - 155, - 155, - 155 - ] - ], - [ - [ - "double_wooden_slab", - 1 - ], - [ - 98, - 70, - 44 - ] - ], - [ - [ - "emerald_block", - 0 - ], - [ - 77, - 171, - 67 - ] - ], - [ - [ - "light_weighted_pressure_plate", - 7 - ], - [ - 231, - 221, - 99 - ] - ], - [ - [ - "stained_hardened_clay", - 0 - ], - [ - 237, - 237, - 237 - ] - ], - [ - [ - "stained_hardened_clay", - 2 - ], - [ - 154, - 76, - 194 - ] - ], - [ - [ - "stained_hardened_clay", - 4 - ], - [ - 213, - 213, - 82 - ] - ], - [ - [ - "stained_hardened_clay", - 6 - ], - [ - 211, - 123, - 153 - ] - ], - [ - [ - "stained_hardened_clay", - 8 - ], - [ - 142, - 142, - 142 - ] - ], - [ - [ - "stained_hardened_clay", - 10 - ], - [ - 110, - 62, - 160 - ] - ], - [ - [ - "slime", - 0 - ], - [ - 109, - 141, - 60 - ] - ], - [ - [ - "packed_ice", - 0 - ], - [ - 128, - 128, - 199 - ] - ], - [ - [ - "repeating_command_block", - 1 - ], - [ - 77, - 43, - 112 - ] - ], - [ - [ - "chain_command_block", - 1 - ], - [ - 70, - 82, - 40 - ] - ], - [ - [ - "nether_wart_block", - 0 - ], - [ - 93, - 38, - 36 - ] - ], - [ - [ - "bone_block", - 0 - ], - [ - 160, - 153, - 112 - ] - ] -] \ No newline at end of file diff --git a/plugin_market/SuperSoundMixer/bdx_work_shop/artists/cmd_midi_music.py b/plugin_market/SuperSoundMixer/bdx_work_shop/artists/cmd_midi_music.py deleted file mode 100644 index 76a5bbba..00000000 --- a/plugin_market/SuperSoundMixer/bdx_work_shop/artists/cmd_midi_music.py +++ /dev/null @@ -1,194 +0,0 @@ -import collections -import os -from ..canvas import Canvas -import mido -from collections import defaultdict -# try: -# from piano_transcription_inference import PianoTranscription, sample_rate, load_audio -# except: -# print('you may need to install piano_transcription_inference first if you want programe convert your music to midi automatically ') - - -class Artist(Canvas): - def __init__(self, canvas: Canvas, x=None, y=None, z=None): - super().__init__() - self.target_canvas = canvas - self.target_xyz = {'ox': x, 'oy': y, 'oz': z} - - # 表示对应音效 最高阶,中间阶(为1时),和最低阶,每一阶频率变换是 2^(1/12) - self.instruments = { - 'bell': (102, 90, 78), - 'harp': (78, 66, 54), - 'pling': (78, 66, 54), - 'bass': (54, 42, 30), - 'guitar': (66, 54, 42), - 'bit': (78, 66, 54) #-SuperScript: 加了这个就是打算把乐器加上一个正弦方波(音符盒绿宝石块演奏的音效).. - } - - self.default_instrumentes_mapping=defaultdict(lambda :[ - (30,None), - (54,'bass'), - (78,'harp'), - (102,'bell'), - (128,None) - ]) - - def get_simple_music_represet(self, midi_msgs): - # 所以按照 midi 的意思,不同的channel 可能是不同的乐器? - # 那我还是先按照 channel 将 所有的 notes 分开吧 - channels_msgs = defaultdict(lambda: []) - duration = 0.0 - for msg in midi_msgs: - duration += msg.time - if not (msg.type == 'note_on' or msg.type == 'note_off'): - print(f'meta : {msg},ignored') - continue - else: - # 怎么channel全是0 啊 - # print(msg.channel) - dict_msg = {'channel': msg.channel, - 'note': msg.bytes()[1], - 'velocity': msg.bytes()[2], - 'off': msg.type == 'note_off', - 'time': duration} - channels_msgs[msg.channel].append(dict_msg) - print(f'duration : {duration:.2f}s') - print( - f'notes : {sum([len(notes) for notes in channels_msgs.values()])}') - print(f'channels :{len(channels_msgs)}') - return channels_msgs - - def align_note(self, notes_by_tick, tick, dict_note): - # 这里会发生一个小问题,由于时间和游戏刻对齐了 - # 可能导致多个note挤在一个游戏刻里, - # 所以我们需要处理这种情况 - note, velocity, time, note_off = dict_note['note'], dict_note[ - 'velocity'], dict_note['time'], dict_note['off'] - - if not (note, velocity, note_off) in notes_by_tick[tick]: - notes_by_tick[tick].append((note, velocity, note_off)) - # if velocity > 0: - # for cmp_note in notes_by_tick[tick]: - # if cmp_note[1] == 0 and note in [n[0] for n in notes_by_tick[tick] if n[1] > 0]: - # notes_by_tick[tick-1].append(cmp_note) - # notes_by_tick[tick].remove(cmp_note) - # else: - # for cmp_note in notes_by_tick[tick]: - # if cmp_note[1] == 0 and note in [n[0] for n in notes_by_tick[tick] if n[1] > 0]: - # notes_by_tick[tick+1].append(cmp_note) - # notes_by_tick[tick].remove(cmp_note) - - def translate_notes_in_one_channel_to_cmds(self, notes_by_tick, instruments): - # 暂且先只考虑 高音部由 bell, 中音部由 piano/pling, 低音部由 bass 三个构成的组合吧 - cmds = [] - for tick, notes in notes_by_tick.items(): - for note, velocity, _ in notes: - velocity /= 128 - for max_note,instrument_name in instruments: - if note < max_note: - if instrument_name is None: - print(f'cannot handle note: {note}') - else: - pitch = 2**((note-self.instruments[instrument_name][1])/12) - cmds.append((tick, instrument_name, pitch, velocity)) - break - # if note > 102 or note < 30: - # print(f'note too high/low, cannot handle {note}') - # continue - # if note > 78: - # pitch = 2**((note-self.instruments['bell'][1])/12) - # cmds.append((tick, 'bell', pitch, velocity)) - # elif note < 54: - # pitch = 2**((note-self.instruments['bass'][1])/12) - # cmds.append((tick, 'bass', pitch, velocity)) - # else: - # pitch = 2**((note-self.instruments['harp'][1])/12) - # if pling: - # cmds.append((tick, 'pling', pitch, velocity)) - # else: - # cmds.append((tick, 'harp', pitch, velocity)) - return cmds - - def convert_music_to_mc_sound(self, music_file: str, instrumentes_mapping=None): - # 太多问题搞不明白了,暂且先只考虑 高音部由 bell, 中音部由 piano/pling, 低音部由 bass 三个构成的组合吧 - if instrumentes_mapping is None: - instrumentes_mapping=self.default_instrumentes_mapping - if not music_file.endswith('.mid'): - file_name = os.path.split(music_file)[-1] - if '.' in file_name: - file_name = '.'.join(file_name.split('.')[:-1]) - file_name += '.mid' - if os.path.exists(file_name): - print(f'It seems that you have already convert tht music {music_file} to {file_name}') - else: - pass - # try: - # from piano_transcription_inference import PianoTranscription, sample_rate, load_audio - # import torch - # device = 'cuda' if torch.cuda.is_available() else 'cpu' - # print("Let's convert your file to midi first, so you can directly use it the next time") - # except: - # print('you may need to install piano_transcription_inference first if you want programe convert your music to midi automatically ') - # raise ImportError - # (audio, _) = load_audio(music_file, sr=sample_rate, mono=True) - # transcriptor = PianoTranscription( - # device=device, checkpoint_path=None) - # transcribed_dict = transcriptor.transcribe(audio, file_name) - # midi_file = file_name - else: - midi_file = music_file - channels_msgs = self.get_simple_music_represet( - mido.MidiFile(midi_file, clip = True)) - - # 在游戏的每个tick的所有note - # mixed_notes_by_tick = defaultdict(lambda: []) - all_note_cmds = [] - - # 逐channel进行操作,按照midi的想法,理论上不同的channel可以用不同的乐器? - # 但是我没有找到多个channel - for channel_i, channel_msgs in channels_msgs.items(): - # 先看看这个channel 是什么情况,别到时候超了范围都不知道 - all_notes = [msg['note'] for msg in channel_msgs] - max_note, min_note = max(all_notes), min(all_notes) - print( - f'channel {channel_i} max note : {max_note} min note : {min_note}') - # 把所有同一个 tick 的 note 放在一起 - notes_by_tick = defaultdict(lambda: []) - - for dict_note in channel_msgs: - time = dict_note['time'] - tick = round(time*20)/20 - # 这里会发生一个小问题,由于时间和游戏刻对齐了,可能导致多个note挤在一个游戏刻里,所以我们需要处理这种情况 - self.align_note(notes_by_tick, tick, dict_note) - - all_note_cmds += self.translate_notes_in_one_channel_to_cmds( - notes_by_tick, instrumentes_mapping[channel_i]) - return sorted(all_note_cmds, key=lambda x: x[0]) - - def write_to_cbs(self, - cmds, - cmds_wrapper="execute @a ~~~ playsound note.{} @s ~~~ {:.3f} {:.3f}", - x=None, y=None, z=None, - dir1=(1, 0, 0), dir2=(0, 0, 1), dir3=(0, 1, 0), - dir1_lim=8, dir2_lim=8,): - - cbs_array = [{'cb_mode': self.MODE_CB, 'command': '', - 'cb_name': f'start', 'conditional': False, 'needRedstone': True}] - current_tick = 0 - for tick, instrument, pitch, velocity in cmds: - delay = tick-current_tick - current_tick = tick - cbs_array.append({'cb_mode': self.MODE_CHAIN_CB, - 'cb_name': f'{tick/20:.2f}s', - 'command': cmds_wrapper.format(instrument, velocity, pitch), - 'tick_delay': delay}) - return self.snake_folding_cmds(x, y, z, - dir1=dir1, dir2=dir2, dir3=dir3, - dir1_lim=dir1_lim, dir2_lim=dir2_lim, array_is_cond_cb=None, cbs_array=cbs_array) - def returnSelf(self): - return self - - def to_canvas(self): - self_host_ir = self.done() - self.target_canvas.load_ir(self_host_ir, merge=True, **self.target_xyz) - return self diff --git a/plugin_market/SuperSoundMixer/bdx_work_shop/artists/map_art.py b/plugin_market/SuperSoundMixer/bdx_work_shop/artists/map_art.py deleted file mode 100644 index 4ec0e7d0..00000000 --- a/plugin_market/SuperSoundMixer/bdx_work_shop/artists/map_art.py +++ /dev/null @@ -1,204 +0,0 @@ -from importlib import import_module -from PIL import Image -import numpy as np -from numba import jit -from canvas import Canvas -import json,os - -with open(os.path.join(os.path.dirname(__file__), "cmap.json"),'r') as f: - cmap=json.load(f) -def light_pixel(rgb): - return [round(255/220*rgb[0]), 255/220*rgb[1], 255/220*rgb[2]] - - -def darkPixel(rgb): - return [round(180/220*rgb[0]), 180/220*rgb[1], 180/220*rgb[2]] - - -color_list = [c[1] for c in cmap] -color_list = np.array(color_list).astype(np.float32) - -color_list_d3 = [] -block_names = [] -for block_def, rgb in cmap: - color_list_d3.append(rgb) - color_list_d3.append(darkPixel(rgb)) - color_list_d3.append(light_pixel(rgb)) - block_names.append(block_def) -color_list_d3 = np.clip(np.array(color_list_d3),0,255).astype(np.float32) -# block_name=[c[0] for c in cmap] - - -@jit(nopython=True) -def closest_color(target_rgb, color_list): - delta = np.inf - best_match = None - target_rgb = np.clip(target_rgb, 0, 255) - tr, tg, tb = target_rgb - for i, (r, g, b) in enumerate(color_list): - if tr+r > 256: - d = 2*((tr-r)**2)+4*((tg-g)**2)+3*((tb-b)**2) - else: - d = 3*((tr-r)**2)+4*((tg-g)**2)+2*((tb-b)**2) - if d < delta: - delta = d - best_match = (i, color_list[i]) - return best_match - - -overflow_distance_factor = np.array([2, 4, 3], dtype=np.float32) -non_overflow_distance_factor = np.array([3, 4, 2], dtype=np.float32) - - -@jit(nopython=True) -def closest_color_np(target_rgb, color_list: np.ndarray): - target_rgb = np.clip(target_rgb, 0, 255) - diff_rgb = target_rgb-color_list.copy() - diff_rgb = diff_rgb**2 - overflow_mask = target_rgb[0]+color_list[:, 0] - diff_rgb[overflow_mask] *= overflow_distance_factor - diff_rgb[~overflow_mask] *= non_overflow_distance_factor - i = np.argmin(diff_rgb) - return (i, color_list[i]) - - -@jit(nopython=True) -def convert_palette(color_list, data: np.ndarray): - converted_data = data.copy().astype(np.float32) - block_map = np.zeros(data.shape[:2], dtype=np.uint8) - flatten_data = converted_data.reshape((-1, 3)) - flatten_block_map = block_map.reshape((-1,)) - converted_data.reshape((-1, 3)) - h, w, _ = converted_data.shape - for pi, rgb in enumerate(flatten_data): - mi, mrgb = closest_color(rgb, color_list) - # mi_,mrgb_ = closest_color_np(rgb,color_list) - # if mi!=mi_ or mrgb!=mrgb_: - # print(f"{pi}") - # (r,g,b),(mr,mg,mb)=rgb,mrgb - drgb = rgb-mrgb - if (pi+1) % w: - flatten_data[pi+1] += (7/16)*drgb - elif pi < (h-1)*w: - pj = pi+w - flatten_data[pj] += (5/16)*drgb - if (pi+1) % w: - pj = pi+w+1 - flatten_data[pj] += (1/16)*drgb - if pi % w: - pj = pi+w-1 - flatten_data[pj] += (3/16)*drgb - flatten_data[pi] = mrgb - flatten_block_map[pi] = mi - converted_data = flatten_data.reshape((h, w, 3)).astype(np.uint8) - block_map = flatten_block_map.reshape((h, w)) - return (block_map, converted_data) - - -def convert_img(img: Image, level_x=2, level_y=2, d3=False): - resized_img = img.resize((level_x*128, level_y*128)) - resized_img_np = np.array(resized_img) - block_map, converted_img = convert_palette( - color_list_d3 if d3 else color_list, resized_img_np) - converted_img = Image.fromarray(converted_img) - return block_map, converted_img, resized_img - - -@jit(nopython=True) -def split_Y_Map(block_map: np.ndarray): - ymap = np.zeros_like(block_map) - h, w = block_map.shape - yhmap = np.zeros(shape=(h+1,), dtype=np.int32) - for x in range(w): - yhmap[0] = 0 - for z in range(h): - bi = block_map[z, x] - t = bi % 3 - if t == 0: - yhmap[z+1] = yhmap[z] - elif t == 1: - yhmap[z+1] = yhmap[z]-2 - else: - yhmap[z+1] = yhmap[z]+2 - yhmap -= np.min(yhmap) - ymap[:, x] = yhmap[1:] - return ymap, block_map//3 - - -def write_blocks(canvas: Canvas, block_map: np.ndarray): - h, w = block_map.shape - for z in range(h): - for x in range(w): - name, val = block_names[block_map[z, x]] - canvas.setblock(name, val, x, 0, z) - if name == "sweet_berry_bush": - canvas.setblock("grass", 0, x, -1, z) - if name == "leaves": - canvas.setblock("log", 0, x, -1, z) - else: - canvas.setblock("wool",0, x, -1, z) - - -def write_blocks_3d(canvas: Canvas, ymap: np.ndarray, zx_map: np.ndarray): - h, w = zx_map.shape - for z in range(h): - for x in range(w): - name, val = block_names[zx_map[z, x]] - y = ymap[z, x]+1 - canvas.setblock(name, val, x, y, z) - if name == "sweet_berry_bush": - canvas.setblock("grass", 0, x, y-1, z) - if name == "leaves": - canvas.setblock("log", 0, x, y-1, z) - else: - canvas.setblock("wool",0, x, y-1, z) - -# to bdx, it's trivial - - -class Artist(Canvas): - def __init__(self, canvas: Canvas, x=None, y=None, z=None): - super().__init__() - self.target_canvas = canvas - self.target_xyz = {'ox': x, 'oy': y, 'oz': z} - self.block_names = block_names - - def to_canvas(self, x=None, y=None, z=None): - if x: - self.target_xyz['ox'] = x - if y: - self.target_xyz['oy'] = y - if z: - self.target_xyz['oz'] = z - self_host_ir = self.done() - self.target_canvas.load_ir(self_host_ir, merge=True, **self.target_xyz) - return self - - def auto_adjust_img(self,img:Image,raito): - img_np = np.array(img) - h,w,_=img_np.shape - if h/w>raito: - sh=int((h-raito*w)/2) - img_np=img_np[sh:min(sh+int(raito*w),h),:] - elif h/w sx) - slice = slice if ex is None else slice & (self.ir.ir_matrix[:, 0] < ex) - slice = slice if sy is None else slice & (self.ir.ir_matrix[:, 1] > sy) - slice = slice if ey is None else slice & (self.ir.ir_matrix[:, 1] < ey) - slice = slice if sz is None else slice & (self.ir.ir_matrix[:, 2] > sz) - slice = slice if ez is None else slice & (self.ir.ir_matrix[:, 2] < ez) - if (in_blocks is not None) or (in_bids is not None): - matrix_bids = self.ir.ir_matrix[slice, 3] - matrix_bids_slice = np.zeros_like(matrix_bids, dtype=bool) - for bid in bids: - matrix_bids_slice[matrix_bids == bid] = True - slice[slice] = matrix_bids_slice - if np.any(slice): - return slice - else: - print('empty selection') - return None - - def move(self, blocks=None, bids=None, - sx=None, ex=None, - sy=None, ey=None, - sz=None, ez=None, - offset_x=None, offset_y=None, offset_z=None): - ''' - move 指令和游戏中的 clone/move 指令不同,指定的是offset, - 根本原因是,游戏使用矩阵表示区块内信息,而这里使用稀疏 - ''' - slice = self.select(blocks, bids, sx, ex, sy, ey, sz, ez) - if slice is None: - return self - self.ir.ir_matrix[slice, :] += [offset_x, offset_y, offset_z, 0] - return self - - def copy(self, blocks=None, bids=None, - sx=None, ex=None, - sy=None, ey=None, - sz=None, ez=None, - offset_x=None, offset_y=None, offset_z=None): - slice = self.select(blocks, bids, sx, ex, sy, ey, sz, ez) - if slice is None: - return self - increasement = self.ir.ir_matrix[slice, :].copy() - increasement = increasement+[offset_x, offset_y, offset_z, 0] - self.ir.ir_matrix = np.vstack([self.ir.ir_matrix, increasement]) - return self - - def replace(self, new_block, orig_blocks=None, orig_bids=None, - sx=None, ex=None, - sy=None, ey=None, - sz=None, ez=None): - '''注意,replace 和 replace wordwide 行为不同,新方块选择更接近游戏里的逻辑''' - if isinstance(new_block, str): - new_block = (new_block, 0, None) - bid = self.get_bid(new_block) - slice = self.select(orig_blocks, orig_bids, sx, ex, sy, ey, sz, ez) - if slice is None: - return self - self.ir.ir_matrix[slice, 3] = bid - return self - - def snake_folding_cmds(self, x=None, y=None, z=None, - dir1=(1, 0, 0), dir2=(0, 0, 1), dir3=(0, 1, 0), - dir1_lim=8, dir2_lim=8, array_is_cond_cb=None, cbs_array=None): - x = self.x if x is None else x - y = self.y if y is None else y - z = self.z if z is None else z - start_point = np.array([x, y, z]) - if array_is_cond_cb is None: - array_is_cond_cb = [] - for cb in cbs_array: - cond = cb.get('conditional') - if cond is None or not cond: - array_is_cond_cb.append(False) - else: - array_is_cond_cb.append(True) - else: - assert len(array_is_cond_cb) == len(cbs_array),\ - f'len(array_is_cond_cb)[{len(array_is_cond_cb)}]!=len(cbs_array)[{len(cbs_array)}]' - dir1_lim, dir2_lim = abs(dir1_lim), abs(dir2_lim) - dir1, dir2, dir3 = np.array(dir1), np.array(dir2), np.array(dir3) - sub_arrays = [] - sub_array = [] - for i, cb in enumerate(cbs_array): - if not array_is_cond_cb[i]: - sub_arrays.append(sub_array) - sub_array = [] - sub_array.append(cb) - sub_arrays.append(sub_array) - sub_arrays = [arr for arr in sub_arrays if arr != []] - max_sub_arr = max([len(arr) for arr in sub_arrays]) - assert max_sub_arr < max( - dir1_lim, dir2_lim) and abs(dir1_lim) != 1 and abs(dir2_lim) != 1, f'dir_lim too small! at least need {max_sub_arr+1} to ensure conditional command block to correctly work!' - - def compute_cmd_pos(block_n): - num_cbs_in_one_layer = dir1_lim*dir2_lim - num_layers = block_n//num_cbs_in_one_layer - num_cbs_in_last_layer = block_n % num_cbs_in_one_layer - dir3_p = (num_layers)*dir3 - # pos=0 positive, pos=1 negative - dir2_pos = num_layers % 2 - num_rows = num_cbs_in_last_layer//dir1_lim - num_cbs_in_last_row = num_cbs_in_last_layer % dir1_lim - dir2_p = (num_rows)*dir2 - if dir2_pos: - dir2_p = (dir2_lim-1)*dir2-dir2_p - if num_rows % 2: - dir1_p = ((dir1_lim-1)-num_cbs_in_last_row)*dir1 - else: - dir1_p = (num_cbs_in_last_row)*dir1 - return dir1_p+dir2_p+dir3_p+start_point - - sub_array = sub_arrays.pop(0) - require_len = len(sub_array) - - real_cbs = [] - last_dir = None - same_dir_len = 0 - while True: - this_cb_pos = compute_cmd_pos(len(real_cbs)) - next_cb_pos = compute_cmd_pos(len(real_cbs)+1) - cb_dir = next_cb_pos-this_cb_pos - face = { - (0, 1, 0): self.FACE_UP, - (0, -1, 0): self.FACE_DOWN, - (1, 0, 0): self.FACE_XPP, - (-1, 0, 0): self.FACE_XNN, - (0, 0, 1): self.FACE_ZPP, - (0, 0, -1): self.FACE_ZNN, - }[tuple(cb_dir.astype(int))] - if last_dir is None: - last_dir = face - if last_dir == face: - same_dir_len += 1 - else: - same_dir_len = 1 - last_dir = face - real_cbs.append({ - 'x': this_cb_pos[0], - 'y': this_cb_pos[1], - 'z': this_cb_pos[2], - 'facing': face, - 'cb_mode': self.MODE_CHAIN_CB - }) - if same_dir_len == require_len: - for sub_i, cb in enumerate(sub_array): - real_cbs[-(require_len-sub_i)].update(cb) - same_dir_len = 0 - if sub_arrays == []: - break - else: - sub_array = sub_arrays.pop(0) - require_len = len(sub_array) - for cb in real_cbs: - self.place_command_block_with_data(**cb) diff --git a/plugin_market/SuperSoundMixer/bdx_work_shop/canvas/decode_bdx.py b/plugin_market/SuperSoundMixer/bdx_work_shop/canvas/decode_bdx.py deleted file mode 100644 index 1830dab6..00000000 --- a/plugin_market/SuperSoundMixer/bdx_work_shop/canvas/decode_bdx.py +++ /dev/null @@ -1,457 +0,0 @@ -import sys -import brotli -import struct -import json -import base64 -from hashlib import sha256 -import requests - - -class BdxDecoder(object): - def __init__(self, - log_path=None, - need_verify=False, - log_level=None) -> None: - self.log_file = None - if log_path is not None: - self.log_file = open(log_path, 'w') - else: - print('decoder log file not set, send to screen') - self.log_level = { - 'RESERVED': 1, - 'DEPRECATED': 1, - 'cache': 1, - 'place_block': 0, - 'add_and_back': 1, - 'shift_and_back': 1, - 'add_unsigned': 1, - 'add_unsigned_big': 1, - 'shift': 1, - 'add_small': 1, - 'add': 1, - 'add_big': 1, - 'assign_command_block_data': 1, - 'place_command_block_with_data': 1, - 'nop': 1 - } - if log_level is not None: - self.log_level.update(log_level) - - # [l][b][s] len, big_edian, sign - self.dtype_len_fmt = { - 1: { - True: { - True: '>b', - False: '>B' - }, - False: { - True: 'h', - False: '>H' - }, - False: { - True: 'i', - False: '>I' - }, - False: { - True: 'l', - False: '>L' - }, - False: { - True: ' 127||wrap < -127""" - offset = int(self._get_val(l=1, s=True)) - self.pos[axis] += offset - self.log(f" offset: {offset} @ ", end="") - self._print_pos() - return offset - - def add(self, axis): - # here fb use int(int16(binary.BigEndian.Uint16())) - # to conver it triple times, but we use sign=true - offset = int(self._get_val(l=2, s=True)) - self.pos[axis] += offset - self.log(f" offset: {offset} @ ", end="") - self._print_pos() - return offset - - def add_big(self, axis): - # here fb use int(int32(binary.BigEndian.Uint32())) - # to conver it triple times, but we use sign=true - offset = int(self._get_val(l=4, s=True)) - self.pos[axis] += offset - self.log(f" offset: {offset} @ ", end="") - self._print_pos() - return offset - - def assign_command_block_data(self): - cb_mode = self._get_val(l=4) - mode_name = self.cb_mode[cb_mode] - command = self._read_str() - cb_name = self._read_str() - lastout = self._read_str() - tick_delay = self._get_val(l=4, s=True) - first_tick = self._get_val(l=1) == 1 - track_out = self._get_val(l=1) == 1 - conditional = self._get_val(l=1) == 1 - redstone = self._get_val(l=1) == 1 - self._print_pos() - self.log(f'mode={mode_name}') - self.log(f'command={command}') - self.log(f'cb_name={cb_name}') - self.log(f'lastout={lastout}') - self.log( - f'delay={tick_delay}, first_tick={first_tick}, track_out={track_out}, conditional={conditional}, redstone={redstone}\n' - ) - return cb_mode, command, cb_name, lastout, tick_delay, first_tick, track_out, conditional, redstone - - def place_command_block_with_data(self): - block_id = self._get_be_uint_16() - block_name = self.cached_blocks[block_id] - block_val = self._get_be_uint_16() - cb_mode = self._get_val(l=4) - mode_name = self.cb_mode[cb_mode] - command = self._read_str() - cb_name = self._read_str() - lastout = self._read_str() - tick_delay = self._get_val(l=4, s=True) - first_tick = self._get_val(l=1) == 1 - track_out = self._get_val(l=1) == 1 - conditional = self._get_val(l=1) == 1 - redstone = self._get_val(l=1) == 1 - self._print_pos() - self.log(f'{block_name}[{block_id}]({block_val}) mode={mode_name}') - print(command) - self.log(f'command={command}') - self.log(f'cb_name={cb_name}') - self.log(f'lastout={lastout}') - self.log( - f'delay={tick_delay}, first_tick={first_tick}, track_out={track_out}, conditional={conditional}, redstone={redstone}\n' - ) - return block_id, block_val, cb_mode, command, cb_name, lastout, tick_delay, first_tick, track_out, conditional, redstone - - def get_op_table(self): - return { - 1: ('cache', 'addToBlockPalette', self.cache_block), - 2: ('DEPRECATED', 'addX', self.DEPRECATED), - 3: ('DEPRECATED', 'X++', self.DEPRECATED), - 4: ('DEPRECATED', 'addY', self.DEPRECATED), - 5: ('DEPRECATED', 'Y++', self.DEPRECATED), - 6: ('add_unsigned', 'addZ', lambda: self.add_unsigned(self.Z)), - 7: ('place_block', 'placeBlock', self.place_block), - 8: ('shift', 'Z++', lambda: self.shift(self.Z, self.P)), - 9: ('nop', 'NOP', self.nop), - 10: ('DEPRECATED', 'jumpX', self.DEPRECATED), - 11: ('DEPRECATED', 'jumpY', self.DEPRECATED), - 12: ('add_unsigned_big', 'jumpZ', - lambda: self.add_unsigned_big(self.Z)), - 13: ('RESERVED', 'RESERVED', self.RESERVED), - 14: ('shift', '*X++', lambda: self.shift(self.X, self.P)), - 15: ('shift', '*X--', lambda: self.shift(self.X, self.N)), - 16: ('shift', '*Y++', lambda: self.shift(self.Y, self.P)), - 17: ('shift', '*Y--', lambda: self.shift(self.Y, self.N)), - 18: ('shift', '*Z++', lambda: self.shift(self.Z, self.P)), - 19: ('shift', '*Z--', lambda: self.shift(self.Z, self.N)), - 20: ('add', '*addX', lambda: self.add(self.X)), - 21: ('add_big', '*addBigX', lambda: self.add_big(self.X)), - 22: ('add', '*addY', lambda: self.add(self.Y)), - 23: ('add_big', '*addBigY', lambda: self.add_big(self.Y)), - 24: ('add', '*addZ', lambda: self.add(self.Z)), - 25: ('add_big', '*addBigZ', lambda: self.add_big(self.Z)), - 26: ('assign_command_block_data', 'assignCommandBlockData', - self.assign_command_block_data), - 27: ('place_command_block_with_data', 'placeCommandBlockWithData', - self.place_command_block_with_data), - 28: ('add_small', 'addSmallX', lambda: self.add_small(self.X)), - 29: ('add_small', 'addSmallY', lambda: self.add_small(self.Y)), - 30: ('add_small', 'addSmallZ', lambda: self.add_small(self.Z)), - } - - def read_cmds(self, need_verify): - bdx_bytes_len = len(self.bdx_bytes) - decode_out = [] - self.author = self._read_str() - self.log(f'author (in file):' + self.author) - if need_verify: - self.log(f'author (responsed by fb server):{self.server_author} ') - if not self.author == self.server_author: - ValueError('verify fail') - self.log('cmd begin') - line_no = 1 - while self.curr != bdx_bytes_len: - op_code = self._get_op_code() - if op_code == 88: - self._need_log = True - self.log('cmd end (end mark)') - return decode_out - op_group, op_name, op = self.op_table[op_code] - if self.log_level[op_group] > 0: - self._need_log = True - else: - self._need_log = False - self.log(f"{line_no:<5d} {op_name:20s} :", end="") - line_no += 1 - ret = op() - decode_out.append((op_code, op_name, ret)) - self._need_log = True - self.log('cmd end (reach border)') - return decode_out - - -if __name__ == '__main__': - if len(sys.argv) == 1: - print('at least tell me what .bdx to decode') - print( - 'python3 thisfile.py somebdx_in.bdx rigmarole_out.json readable_out.txt ' - ) - exit(0) - - in_bdx_name = sys.argv[1] - out_file_name = 'decode_out.json' - log_file_name = None - - if len(sys.argv) > 2: - out_file_name = sys.argv[2] - if len(sys.argv) > 3: - log_file_name = sys.argv[3] - - decoder = BdxDecoder(log_file_name, need_verify=True) - # decoder.log_command_block_only() - - with open(in_bdx_name, 'rb') as f: - decode_out = decoder.decode(f) - with open(out_file_name, 'w') as f: - json.dump(decode_out, f) diff --git a/plugin_market/SuperSoundMixer/bdx_work_shop/canvas/encode_bdx.py b/plugin_market/SuperSoundMixer/bdx_work_shop/canvas/encode_bdx.py deleted file mode 100644 index 53d106a6..00000000 --- a/plugin_market/SuperSoundMixer/bdx_work_shop/canvas/encode_bdx.py +++ /dev/null @@ -1,584 +0,0 @@ -import sys -import os -import brotli -import struct -import json -import base64 -from hashlib import sha256 -import requests - - -class BdxEncoder(object): - # command block - CB = 'command_block' - # repeat command block - REPEAT_CB = 'repeating_command_block' - # chain commnad block - CHAIN_CB = 'chain_command_block' - - MODE_CB = 0 - MODE_REPEAT_CB = 1 - MODE_CHAIN_CB = 2 - - # face down - FACE_DOWN = 0 - FACE_UPPER = 1 - # z-- - FACE_NORTH = 2 - FACE_ZNN = 2 - # z++ - FACE_SOUTH = 3 - FACE_ZPP = 3 - # x-- - FACE_WEST = 4 - FACE_XNN = 4 - # x++ - FACE_EAST = 5 - FACE_XPP = 5 - - cb_mode = ['Impulse', 'Repeat', 'Chain'] - cb_face = [ - 'down', 'up', 'north (z-)', 'source (z+)', 'west (x-)', 'east (x+)' - ] - - def __init__(self, - author=None, - need_sign=True, - sign_token=None, - log_path=None, - log_level=None) -> None: - super().__init__() - self.dtype_len_fmt = { - 1: { - True: { - True: '>b', - False: '>B' - }, - False: { - True: 'h', - False: '>H' - }, - False: { - True: 'i', - False: '>I' - }, - False: { - True: 'l', - False: '>L' - }, - False: { - True: ' 1: - self.log_cmd_op(1, f'cache') - self._write_op(1) - if self.log_level['cache'] > 1: - self.log_cmd_args(f'{block_name} as {block_id}') - self.block_id_name_mapping.append(block_name) - self.block_name_id_mapping[block_name] = block_id - self._write_str(block_name) - return block_id - - def write_cmd(self, op_code, op_group, op_name, op, params): - if self.log_level[op_group] > 0: - self._need_log = True - if op_code == 26: - op_name = 'assign CB + data' - if op_code == 27: - op_name = 'place CB + data' - self.log_cmd_op(op_code, op_name) - else: - self._need_log = False - if op_code != 1: - # sometimes the block is already cached - self._write_op(op_code) - if params is None: - op() - elif isinstance(params, list) or isinstance(params, tuple): - op(*params) - elif isinstance(params, dict): - op(**params) - else: - op(params) - - def write_cmds(self, cmds, palette): - self.block_name_id_mapping = {} - self.block_id_name_mapping = [] - self.bdx_cmd_bytes = [] - self.log(f'author : {self.author}\t[', end='') - self._write_str(self.author) - self.log(f']', end='') - self.log_off = True - for k, v in self.log_level.items(): - if v > 0: - self.log_off = False - break - assert len(palette) == len(list(set(palette))) - if palette is not None: - self._need_log = self.log_level['cache'] > 1 - for block_name in palette: - self.add_to_block_palette(block_name) - - # create look up table first - op_name_code_mapping = {} - op_code_name_mapping = {} - for op_code, (op_group, op_name, op) in self.op_table.items(): - op_code_name_mapping[op_name] = op_code - op_name_code_mapping[op_code] = op_name - - cmd0 = cmds[0] - if len(cmd0) == 3: - # op_code, op_name, params format - for (op_code, _op_name, params) in cmds: - op_group, op_name, op = self.op_table[op_code] - assert _op_name == op_name, f'{_op_name} {op_name} mismatch' - self.write_cmd(op_code, op_group, op_name, op, params) - elif len(cmd0) == 2: - if isinstance(cmd0[0], str): - # op_name params format - for (op_name, params) in cmds: - op_code = op_code_name_mapping[op_name] - op_group, op_name, op = self.op_table[op_code] - self.write_cmd(op_code, op_group, op_name, op, params) - else: - # op_code params format - for (op_code, params) in cmds: - op_group, op_name, op = self.op_table[op_code] - self.write_cmd(op_code, op_group, op_name, op, params) - else: - raise NotImplementedError("unsupport format") - - self._need_log = True - print() - - -if __name__ == '__main__': - if len(sys.argv) == 1: - print('at least tell me what .json to encode') - print('python3 thisfile.py rigmarole_in.json encoded.bdx log.txt') - exit(0) - - in_json_name = sys.argv[1] - out_bdx_name = 'encode_out.bdx' - log_file_name = None - - if len(sys.argv) > 2: - out_bdx_name = sys.argv[2] - if len(sys.argv) > 3: - log_file_name = sys.argv[3] - - encoder = BdxEncoder(need_sign=True, - log_path=log_file_name, - author='2401PT') - encoder.log_nothing() - encoder.log_command_block_only() - - with open(in_json_name, 'r') as f: - data_to_write = json.load(f) - - cmds = data_to_write["cmds"] - palette = None - author = encoder.author - fb_token = None - # it is ok to include palette here or just in cmds - # if 'palette' in data_to_write.keys(): - # palette = data_to_write["palette"] - if 'author' in data_to_write.keys(): - author = data_to_write["author"] - if 'fb_token' in data_to_write.keys(): - fb_token = data_to_write['fb_token'] - bdx_bytes = encoder.encode(cmds=cmds, - author=author, - palette=palette, - sign_token=fb_token) - - with open(out_bdx_name, 'wb') as f: - f.write(bdx_bytes) \ No newline at end of file diff --git a/plugin_market/SuperSoundMixer/bdx_work_shop/canvas/ir.py b/plugin_market/SuperSoundMixer/bdx_work_shop/canvas/ir.py deleted file mode 100644 index 9175eae5..00000000 --- a/plugin_market/SuperSoundMixer/bdx_work_shop/canvas/ir.py +++ /dev/null @@ -1,155 +0,0 @@ -import numpy as np - -class IR(object): - def __init__(self) -> None: - '''使用稀疏矩阵和映射表表达的建筑结构 [中间表示] IR''' - # block : [name,val,cb_data] - # normal block: cb_data=None - # cb block cb_data=(cb_mode, - # command='', - # cb_name='', - # lastout='', - # tick_delay=0, - # first_tick=False, - # track_out=False, - # conditional=False, - # redstone=False) - # cb_data must be tuple! - # 给出block描述,搜索block_id (bid) - self.ir_lookup = {} - # 给出bid,获得block描述 - self.ir_blocks = [] - # 稀疏矩阵,numpy 格式,4列 - # [ - # [x,y,z,bid], - # [x,y,z,bid] - # ] - # 当 bid=-1时,表示这个位置的方块被清除(相当于结构空位) - self.ir_matrix = np.zeros((0, 4), dtype=int) - - # fb Z方向->Y方向->X方向 - # 当生成指令时,移动顺序为:Y->区块内X->区块内Z->X方向下一个区块->Z方向下一区块 - # 另:蛇形移动,有助于在加载当前区块时已经准备好下一区块的数据 - self.CHUNK_SIZE = 8 - - def get_block_bid(self, block): - '''block can be anything, as long as it can be correctly hashed''' - bid = self.ir_lookup.get(block) - if bid is None: - bid = len(self.ir_blocks) - self.ir_lookup[block] = bid - self.ir_blocks.append(block) - return bid - else: - return bid - - def rebuild_bid_lookup(self,blocks=None): - '''利用映射表 ir_blocks 的信息重构 ir_lookup 查找表, 但是并不重构matrix中的值''' - if blocks is not None: - self.ir_blocks=blocks - self.ir_lookup = {k: i for i, k in enumerate(self.ir_blocks)} - return self - - def rebuild_bid(self): - '''如果ir出现了重复的block,可以用这个去除冗余的bid''' - print('rebuild ir bid ...') - old_matrix_bid = self.ir_matrix[:, 3].copy() - new_matrix_bid = self.ir_matrix[:, 3].copy() - old_blocks=self.ir_blocks - new_blocks=[] - new_ir_lookup={} - for old_bid,block in enumerate(self.ir_blocks): - index = old_matrix_bid == old_bid - # remove not use bid key - if not np.any(index): - print(f'bid rebuid : ({block}) {old_bid} not use, removed') - continue - old_block=old_blocks[old_bid] - new_bid = new_ir_lookup.get(old_block) - if new_bid is None: - new_bid=len(new_blocks) - new_ir_lookup[block]=new_bid - new_blocks.append(block) - if new_bid!=old_bid: - print(f'bid rebuid : ({block}) {old_bid} -> {new_bid}') - new_matrix_bid[index]=new_bid - self.ir_matrix[:,3]=new_matrix_bid - self.ir_blocks=new_blocks - self.ir_lookup=new_ir_lookup - print('rebuild ir bid done') - return self - - def rearrange(self): - # 首先,我们对稀疏矩阵中所有方块进行重新排列 - print('rearranging') - rearranged_blocks = [] - xz_matrix = self.ir_matrix[:, [0, 2]] - xz_chunk_matrix = xz_matrix // self.CHUNK_SIZE - # 0:trunk_x,1:trunk_z,2:x,3:y,4:z,5:bid - operation_order = np.arange(self.ir_matrix.shape[0]) - operation_order = operation_order.reshape((-1, 1)) - matrix_with_trunk = np.concatenate( - [xz_chunk_matrix, self.ir_matrix, operation_order], axis=1) - unique_trunk = np.unique(xz_chunk_matrix, axis=0) - # 我们移动顺序为: - # Y->区块内X->区块内Z->X方向下一个区块->Z方向下一区块 - # 所以我们选择顺序是它的逆序: - # Z区块->X区块->Z->X->Y - unique_trunk_z = np.sort(np.unique(unique_trunk[:, 1])) - for itz, trunk_z in enumerate(unique_trunk_z): - # print(f'trunk z @ {trunk_z}') - trunk_z_matrix = matrix_with_trunk[\ - matrix_with_trunk[:,1] == trunk_z] - trunk_z_unique_trunk_x = np.sort(np.unique(unique_trunk[\ - unique_trunk[:, 1] == trunk_z][:,0])) - if itz % 2: - trunk_z_unique_trunk_x = trunk_z_unique_trunk_x[::-1] - for itx, trunk_x in enumerate(trunk_z_unique_trunk_x): - # print(f'\ttrunk x @ {trunk_x} [{trunk_z},{trunk_x}]') - trunk_matrix=trunk_z_matrix[\ - trunk_z_matrix[:,0]==trunk_x] - # 到此为止,我们找出了一个区块的所有方块 - # 如果我们放弃方向性,可以使用多列联合排序 - # 但是我们这里就不这么干了 - trunk_unique_z = np.sort(np.unique(trunk_matrix[:, 4])) - if itx % 2: - trunk_unique_z = trunk_unique_z[::-1] - for iz, z_at_trunk in enumerate(trunk_unique_z): - # print(f'\t\tz @ {z_at_trunk}') - xy_matrix_at_trunk = trunk_matrix[\ - trunk_matrix[:,4] == z_at_trunk] - unique_x_at_xy_matrix = np.sort(np.unique(\ - xy_matrix_at_trunk[:,2])) - if iz % 2: - unique_x_at_xy_matrix = unique_x_at_xy_matrix[::-1] - for ix, x_at_xy_matrix in enumerate(unique_x_at_xy_matrix): - # print(f'\t\t\tx@ {x_at_xy_matrix}') - y_array_at_xy_matrix=xy_matrix_at_trunk[\ - xy_matrix_at_trunk[:,2]==x_at_xy_matrix] - unique_y = np.sort( - np.unique(y_array_at_xy_matrix[:, 3])) - if ix % 2: - unique_y = unique_y[::-1] - for _y in unique_y: - # print(f'\t\t\t\ty@ {_y}') - blocks_at_cell = y_array_at_xy_matrix[\ - y_array_at_xy_matrix[:,3]==_y] - if blocks_at_cell.shape[0] == 1: - # 该位置只有一个方块,没什么好说的 - block_at_cell = blocks_at_cell[0] - else: - # 该位置只有多个方块,我们只保留最后一个的 - block_arg = blocks_at_cell[:, -1].argsort()[-1] - block_at_cell = blocks_at_cell[block_arg, :] - if block_at_cell[-2] != -1: - # 如果值为-1,就认为这个位置的方块已经被删除 - rearranged_blocks.append(block_at_cell) - rearranged_blocks = np.vstack(rearranged_blocks) - rearranged_blocks = rearranged_blocks[:, 2:-1] - now_blocks = len(rearranged_blocks) - orig_blocks = len(self.ir_matrix) - self.ir_matrix = rearranged_blocks - self.rebuild_bid() - print(f'rearrange completed! {orig_blocks - now_blocks} duplicated blocks ignored') - return self - diff --git a/plugin_market/SuperSoundMixer/bdx_work_shop/canvas/irio.py b/plugin_market/SuperSoundMixer/bdx_work_shop/canvas/irio.py deleted file mode 100644 index 53a43e18..00000000 --- a/plugin_market/SuperSoundMixer/bdx_work_shop/canvas/irio.py +++ /dev/null @@ -1,514 +0,0 @@ -import numpy as np -from numpy.core.shape_base import block -from .ir import IR -from .decode_bdx import BdxDecoder -from .encode_bdx import BdxEncoder -from .blocks import blocks - - -def create_ir_from_cmds(cmds): - '''从decoder的输出中构建ir''' - ir = IR() - ir.ir_lookup = {} - ir.ir_blocks = [] - ir_matrix = [] - ir_x, ir_y, ir_z = 0, 0, 0 - palette = [] - for op_code, op_name, params in cmds: - if op_code == 1: - if params in palette: - print(f'warning! find redundant key {params}') - palette.append(params) - elif op_code == 7: - blk_id, blk_val = params - blk_name = palette[blk_id] - bid = ir.get_block_bid((blk_name, blk_val, None)) - ir_matrix.append([ir_x, ir_y, ir_z, bid]) - elif op_code == 8: - ir_z += 1 - elif op_code == 9: - pass - elif op_code == 14: - ir_x += 1 - elif op_code == 15: - ir_x -= 1 - elif op_code == 16: - ir_y += 1 - elif op_code == 17: - ir_y -= 1 - elif op_code == 18: - ir_z += 1 - elif op_code == 19: - ir_z -= 1 - elif op_code in [20, 21, 28]: - ir_x += params - elif op_code in [22, 23, 29]: - ir_y += params - elif op_code in [6, 12, 24, 25, 30]: - ir_z += params - elif op_code == 26: - assert isinstance(params, tuple) - cb_data = params - blk_name, blk_val = None, None - found_blk = None - # 搜索究竟给哪个cb block进行赋值 - for x, y, z, bid in ir_matrix[::-1]: - if (x, y, z) == (ir_x, ir_y, ir_z): - found_blk = bid - break - if found_blk is not None: - blk_name, blk_val, _ = ir.ir_blocks[bid] - else: - print( - "can't found the block you assign, I sure hope you know what you are doing" - ) - bid = ir.get_block_bid((blk_name, blk_val, cb_data)) - ir_matrix.append([ir_x, ir_y, ir_z, bid]) - elif op_code == 27: - assert isinstance(params, tuple) - cb_data = tuple(params[2:]) - blk_id, blk_val = params[:2] - blk_name = palette[blk_id] - bid = ir.get_block_bid((blk_name, blk_val, cb_data)) - ir_matrix.append([ir_x, ir_y, ir_z, bid]) - else: - raise NotImplementedError( - f"don't know how to handle {op_name}[{op_code}]") - ir.ir_matrix = np.array(ir_matrix, dtype=np.int32).conjugate() - return ir - - -def create_ir_from_bdx(bdx_file, need_verify=True): - '''将一个bdx文件加载为 ir''' - print('decoding bdx...') - decoder = BdxDecoder(None, need_verify=need_verify) - decoder.log_nothing() - with open(bdx_file, 'rb') as f: - decode_out = decoder.decode(f) - print('decoding done') - ir = create_ir_from_cmds(decode_out['cmds']) - print('ir initialized') - return ir - - -def translate_block(block, user_define_mapping=None): - '''推测一个mcstructure的block在基岩版中的名字和数据值''' - from thefuzz import fuzz - from nbtlib import tag - - block_mapping_name_description_val = blocks.name_description_val_mapping - block_names = blocks.names - - if user_define_mapping is None: - user_define_mapping = {} - print(block) - block_name = block['name'] - block_name = block_name.replace('minecraft:', '') - status = block['states'] - status = dict(status) - - block_lookup = user_define_mapping.get(block_name) - if block_lookup is None: - block_lookup = block_mapping_name_description_val.get(block_name) - if block_lookup is None: - score_name_mapping = [(fuzz.ratio(block_name, n), n) - for n in block_names] - score_name_mapping.sort(key=lambda x: x[0], reverse=True) - block_name = score_name_mapping[0][1] - print( - f'!cannot find the actually name mapping of {block["name"]}, I guess it is {block_name}') - block_lookup = block_mapping_name_description_val.get(block_name) - # if isinstance(block_lookup,tuple): - # print(f'I think it is {block_lookup}') - # return block_lookup - if len(status) == 0: - print(f'I think it could be {block_name} ({0})') - return block_name, 0 - if isinstance(block_lookup, int): - print(f'I think it could be {block_name} ({block_lookup})') - return block_name, block_lookup - if isinstance(block_lookup, tuple): - print(f'I think it could be {block_lookup}') - return block_lookup - - possible_names = [] - possible_values = [] - occourd_keys = [] - for kvs, block_value in block_lookup.items(): - possible_name = [] - possible_values.append(block_value) - for kv in kvs: - possible_name += kv - occourd_keys.append(kv[1]) - possible_names.append(possible_name) - - has_dir = True - string_dir_names = ['down', 'up', 'north', 'south', 'west', 'east'] - if 'down' in occourd_keys: - dir_remapping = {i: string_dir_names[i] for i in range(6)} - elif 'up' in occourd_keys: - dir_remapping = {i: string_dir_names[i + 1] for i in range(5)} - elif 'north' in occourd_keys: - dir_remapping = {i: string_dir_names[i + 2] for i in range(4)} - else: - has_dir = False - - status_fuzzy = [] - for k, v in status.items(): - status_fuzzy.append(k) - if isinstance(v, tag.String): - v = str(v) - if 'north_south' in v: - status_fuzzy += ['z'] * 3 - if 'west_east' in v: - status_fuzzy += ['x'] * 3 - if 'top' in v: - status_fuzzy.append('up') - if 'default' in v: - status_fuzzy.append(block['name']) - status_fuzzy.append(v) - elif isinstance(v, tag.Byte): - v = 'true' if v == 1 else 'false' - status_fuzzy.append(v) - else: - try: - if has_dir and v < len(dir_remapping): - status_fuzzy.append(dir_remapping[v]) - v = str(int(v)) - status_fuzzy.append(v) - except: - print(f'pass k {k}') - scores = [] - # print(status_fuzzy) - for possible_name in possible_names: - # score=0 - fuzzy_status = '_'.join(status_fuzzy) - fuzzy_name = '_'.join(possible_name) - # for status_name in status_fuzzy: - # if status_name in possible_names: - # score+=1 - # p=possible_name_.find(status_name) - # if p !=-1: - # score+=1 - # possible_name_=possible_name_[p+len(status_name):] - - scores.append(fuzz.ratio(fuzzy_status, fuzzy_name)) - # names.append(possible_name) - max_s = max(scores) - # if max_s==0: - # print(f'? not find, use: {matchs[0][0]}[{names[0]}') - # return matchs[0] - # else: - for ib, v in enumerate(scores): - if v == max_s: - print( - f'? possible is: {block_name}{possible_names[ib]} ({possible_values[ib]})') - return (block_name, possible_values[ib]) - - assert False, 'this should not happen, my fault' - - # print(f'? not find excatly match, use: {matchs[0][0]}[{names[0]}') - # return matchs[0] - - -def create_ir_from_mcstructruce(mc_structure_file, ignore=None, user_define_mapping=None): - if ignore is None: - ignore = [] - if user_define_mapping is None: - user_define_mapping = {} - try: - import nbtlib - from nbtlib import tag - except: - print('Please install nbtlib first (pip install nbtlib) ... load mcstructure require this') - exit(-1) - - try: - from thefuzz import fuzz - except: - print('Please install thefuzzy first (pip install thefuzzy) ... matching mcstructure blocks require this') - exit(-1) - - nbt = nbtlib.load(mc_structure_file, byteorder='little') - try: - if 'structure' not in nbt.keys(): - nbt = nbt[''] - structure = nbt['structure'] - lx, ly, lz = list(map(int, nbt['size'])) - palette = nbt['structure']["palette"]["default"]["block_palette"] - except: - raise ValueError('structure missing') - - blocks = list(map(int, structure["block_indices"][0])) - matrix = np.zeros((lx * ly * lz, 4), dtype=np.int32) - matrix[:, 3] = blocks - matrix_view = matrix.view() - matrix_view.shape = (lx * ly, lz, 4) - matrix_view[:, :, 2] = np.arange(lz) - matrix_view.shape = (lx, ly * lz, 4) - matrix_view[:, :, 1] = np.arange(ly).repeat(lz) - matrix[:, 0] = np.arange(lx).repeat(ly * lz) - - def translate_palette(palette, ignore=None, user_define_mapping=None): - ignored_bids = [] - ir_blocks = [] - if ignore is None: - ignore = [] - for bid, block in enumerate(palette): - block_name = block['name'] - new_name, block_val = translate_block(block, user_define_mapping) - if (new_name in ignore) or (block_name in ignore): - ignored_bids.append(bid) - ir_blocks.append((new_name, block_val, None)) - return ignored_bids, ir_blocks - - ignored_bids, ir_blocks = translate_palette( - palette, ignore, user_define_mapping) - for ignored_bid in ignored_bids: - matrix = matrix[matrix[:, 3] != ignored_bid, :] - ir = IR() - ir.ir_matrix = matrix - ir.ir_blocks = ir_blocks - ir.rebuild_bid_lookup() - return ir - - -def create_ir_from_schematic(schematic_file, ignore=None): - try: - import nbtlib as nbt - from nbtlib import tag - except: - print('Please install nbtlib first (pip install nbtlib) ... load mcstructure require this') - exit(-1) - root_tag = nbt.load(filename=schematic_file, gzipped=True, byteorder='big') - assert root_tag.root_name == 'Schematic', 'this is not a schematic file!' - shape = (int(root_tag['Height']), int( - root_tag['Length']), int(root_tag['Width'])) - ly, lz, lx = shape - src_blocks = np.asarray(root_tag['Blocks'], order='C', - dtype=np.uint8) # .reshape(shape, order='C') - src_datas = np.asarray(root_tag['Data'], order='C', - dtype=np.uint8) # .reshape(shape, order='C') - # schema = { - # 'Height': nbt.Short, #y - # 'Length': nbt.Short, #z - # 'Width': nbt.Short, #x - # 'Materials': nbt.String, - # 'Blocks': nbt.ByteArray, - # 'Data': nbt.ByteArray, - # 'Entities': nbt.List[Entity], - # 'TileEntities': nbt.List[BlockEntity] - # } - meterials = str(root_tag['Materials']) - - # sparse_matrix=np.zeros((np.product(shape), 4), dtype=np.int32) - # matrix_view = sparse_matrix.view() - # matrix_view.shape = (ly * lz,lx , 4) - # matrix_view[:, :, 0] = np.arange(lx) - # matrix_view.shape = (ly, lx * lz, 4) - # matrix_view[:, :, 2] = np.arange(ly).repeat(lx) - # sparse_matrix[:, 1] = np.arange(ly).repeat(lx * lz) - # 算了,我还是老实点吧,毕竟求bid还是要遍历的嘛 - - blocks_id_name_mapping = blocks.id_name_mapping - ir = IR() - - if ignore is None: - ignore = [] - bid_mapping = {} - ir_matrix = [] - for i, (src_block, src_data) in enumerate(zip(src_blocks, src_datas)): - bid = bid_mapping.get((src_block, src_data)) - if bid is None: - block_name = blocks_id_name_mapping[src_block] - if block_name in ignore or (block_name, src_data) in ignore: - bid_mapping[(src_block, src_data)] = -1 - bid = ir.get_block_bid((block_name, src_data, None)) - bid_mapping[(src_block, src_data)] = bid - if bid == -1: - pass - else: - y, z, x = i//(lz*lx), (i % (lz*lx))//lx, i % lx - ir_matrix.append([x, y, z, bid]) - ir.ir_matrix = np.array(ir_matrix, dtype=np.int32).conjugate() - return ir - - -class IR_BDX_Exportor(IR): - def __init__(self, ir: IR): - super(IR_BDX_Exportor, self).__init__() - # data may assigned during exporting, so we do this - self.ir_blocks = ir.ir_blocks - self.ir_lookup = ir.ir_lookup - self.ir_matrix = ir.ir_matrix - self.CHUNK_SIZE = ir.CHUNK_SIZE - - self.X, self.Y, self.Z = 0, 1, 2 - self.move_keys = { - # 感谢群友 CL_P 的思路 - # ++, --, addSmall(-128~127), add(-32768~32767), addBig(-2147483648~2147483647) - self.X: [14, 15, 28, 20, 21], - self.Y: [16, 17, 29, 22, 23], - self.Z: [18, 19, 30, 24, 25], - } - self.SAME_AS_FB = True - - def move(self, x, y, z, bx, by, bz): - # op_code,op_name,offset - move_ops = [] - if x != bx: - offset = x - bx - move_ops.append(self.obtain_move_op_code(offset, self.X)) - if y != by: - offset = y - by - move_ops.append(self.obtain_move_op_code(offset, self.Y)) - if z != bz: - offset = z - bz - move_ops.append(self.obtain_move_op_code(offset, self.Z)) - return move_ops - - def generate_palette(self): - print('generating palette...') - palette = [] - cmds = [] - palette_look_up_table = {} - bid_palette_mapping = {} - for bid, (name, val, cb_data) in enumerate(self.ir_blocks): - palette_id = palette_look_up_table.get(name) - if palette_id is None: - palette_id = len(palette) - palette_look_up_table[name] = palette_id - palette.append(name) - cmds.append((1, name)) - bid_palette_mapping[bid] = palette_id - print('palette generated') - return bid_palette_mapping, cmds, palette - - def obtain_move_op_code(self, offset: int, axis: int): - """ - 感谢群友 CL_P 的思路,这里是用了类似的实现,比较简洁 - ++,--, - addSmall(-128~127), add(-32768~32767), addBig(-2147483648~2147483647) - """ - if offset == 1: - return self.move_keys[axis][0], None - elif offset == -1: - return self.move_keys[axis][1], None - - elif axis == self.Y and (offset > 2**15 - or offset < 2**15) \ - and self.SAME_AS_FB: - return 23, offset - - # note: not >= or <=, but > and < though sign is -128~127 - elif offset > -2**7 and offset < 2**7: - return self.move_keys[axis][2], offset - elif offset > -2**15 and offset < 2**15: - return self.move_keys[axis][3], offset - elif offset > -2**31 and offset < 2**31: - return self.move_keys[axis][4], offset - - def dump_to_cmds(self): - print('ir -> cmds, converting... ') - bid_palette_mapping, cache_cmds, palette = self.generate_palette() - cmds = cache_cmds - bx, by, bz = 0, 0, 0 - for x, y, z, bid in self.ir_matrix: - cmds += self.move(x, y, z, bx, by, bz) - bx, by, bz = x, y, z - block_name, val, cb_data = self.ir_blocks[bid] - palette_id = bid_palette_mapping[bid] - if cb_data is None: - cmds.append((7, (palette_id, val))) - elif block_name is not None: - cmds.append((27, (palette_id, val, *cb_data))) - else: - cmds.append((26, cb_data)) - print('converting done') - return cmds - - def dump_to_bdx(self, - out_bdx_file, - need_sign=True, - author=None, - sign_token=None): - - gen_cmds = self.dump_to_cmds() - print('encoding...') - encoder = BdxEncoder(need_sign=need_sign, - log_path=None, - author=author, - sign_token=sign_token) - encoder.log_nothing() - encode_out = encoder.encode(cmds=gen_cmds) - print('encoding done, write file...') - with open(out_bdx_file, 'wb') as f: - f.write(encode_out) - print('finished!') - - -def dump_ir_to_cmds(ir, rearrange=False): - exportor = IR_BDX_Exportor(ir) - if rearrange: - exportor.rearrange() - return exportor.dump_to_cmds() - - -def dump_ir_to_bdx(ir, out_bdx_file, rearrange=False, need_sign=True, author=None, sign_token=None): - exportor = IR_BDX_Exportor(ir) - if rearrange: - exportor.rearrange() - exportor.dump_to_bdx(out_bdx_file=out_bdx_file, - need_sign=need_sign, author=author, sign_token=sign_token) - - -def dump_ir_to_schematic(ir: IR, out_schem_file): - try: - import nbtlib as nbt - from nbtlib import File - except: - print('Please install nbtlib first (pip install nbtlib) ... load mcstructure require this') - exit(-1) - matrix = ir.ir_matrix.copy() - min_x, max_x = np.min(matrix[:, 0]), np.max(matrix[:, 0]) - min_y, max_y = np.min(matrix[:, 1]), np.max(matrix[:, 1]) - min_z, max_z = np.min(matrix[:, 2]), np.max(matrix[:, 2]) - lx, ly, lz = max_x-min_x+1, max_y-min_y+1, max_z-min_z+1 - matrix -= [min_x, min_y, min_z, 0] - ir_blocks = ir.ir_blocks - - s_blocks = np.zeros((np.product((lx, ly, lz)),), dtype=np.uint8) - s_datas = np.zeros((np.product((lx, ly, lz)),), dtype=np.uint8) - blocks_name_id_mapping = blocks.name_id_mapping - - bid_lookup = {} - for bid, (block_name, block_val, _) in enumerate(ir_blocks): - block_id = blocks_name_id_mapping.get(block_name) - if block_id is None: - print(f'block {block_name} is not supported by schematic file') - print(f'it will be replaced by stained_glass {block_val}') - block_id = blocks_name_id_mapping.get('stained_glass') - bid_lookup[bid] = (block_id, block_val) - - for x, y, z, bid in matrix: - pos_id = y * lx * lz + z * lx + x - # -1 为被删除的方块 - if bid == -1: - s_blocks[pos_id] = 0 - s_datas[pos_id] = 0 - else: - block_id, block_val = bid_lookup[bid] - s_blocks[pos_id] = block_id - s_datas[pos_id] = block_val - - file = File({ - 'Height': nbt.Short(ly), - 'Length': nbt.Short(lz), - 'Width': nbt.Short(lx), - 'Materials': nbt.String('Alpha'), - 'Blocks': nbt.ByteArray(s_blocks), - 'Data': nbt.ByteArray(s_datas), - 'Entities': nbt.List[nbt.Compound]([]), - 'TileEntities': nbt.List[nbt.Byte]([]) - }, root_name='Schematic') - file.save(out_schem_file, gzipped=True, byteorder='big') diff --git a/plugin_market/market_tree.json b/plugin_market/market_tree.json index 5aecdbd0..100ee7f7 100644 --- a/plugin_market/market_tree.json +++ b/plugin_market/market_tree.json @@ -48,20 +48,12 @@ }, "plugin-type": "injected" }, - "SuperSoundMixer": { - "author": "SuperScript/wling", - "version": "0.0.1", - "description": "midi播放前置", - "limit_launcher": null, - "pre-plugins": {}, - "plugin-type": "injected" - }, "井字棋": { "author": "SuperScript/wling", "version": "0.0.1", "description": "娱乐小游戏3x3井字棋", "limit_launcher": null, - "pre-plugins": {"SuperSoundMixer": "0.0.1"}, + "pre-plugins": {}, "plugin-type": "injected" }, "清空末影箱": { diff --git "a/plugin_market/\344\272\225\345\255\227\346\243\213/__init__.py" "b/plugin_market/\344\272\225\345\255\227\346\243\213/__init__.py" index 9c04a68f..050c9f51 100644 --- "a/plugin_market/\344\272\225\345\255\227\346\243\213/__init__.py" +++ "b/plugin_market/\344\272\225\345\255\227\346\243\213/__init__.py" @@ -1,7 +1,5 @@ -from ..SuperSoundMixer import SuperSoundMixer from tooldelta.plugin_load import player_message, sendcmd, get_all_player, rawText,repeat -chess_group = SuperSoundMixer() __plugin_meta__ = { "name": "井字棋", "version": "1.0", @@ -84,7 +82,6 @@ def 重置(self, done=False): ] if done: self.turn = 0 - chess_group.del_sound_thread("fc中国象棋") def Timer(self, time=None): if time: @@ -123,8 +120,6 @@ async def _(playername: str, msg: str): if to_who in get_all_player(): JZQ_Rooms.append([playername, to_who]) rawText(playername, "§a井字棋§f>> §a成功开启游戏.") - chess_group.mixer_sound("fc中国象棋", playername, loop=True) - chess_group.mixer_sound("fc中国象棋", to_who, loop=True) else: rawText(playername, "§a井字棋§f>> §c玩家未找到!.") else: @@ -160,13 +155,11 @@ async def _(playername: str, msg: str): Game_JZQ.stage_display(i, playername) sendcmd("/title %s title §e井字棋" % playername) sendcmd("/title %s subtitle §a祝贺!你赢了!" % playername) - chess_group.mixer_sound("井字棋胜利", playername) nexPlayer = i[Game_JZQ.轮流()] Game_JZQ.stage_display(i, nexPlayer) sendcmd("/title %s title §e井字棋" % nexPlayer) sendcmd("/title %s subtitle §7惜败.." % nexPlayer) - chess_group.mixer_sound("井字棋失败", nexPlayer) JZQ_Rooms.remove(i) Game_JZQ.重置(True) continue