mirror of
https://github.com/TriM-Organization/Musicreater.git
synced 2025-09-05 11:56:23 +00:00
Merge branch 'master' of https://gitee.com/EillesWan/Musicreater
This commit is contained in:
BIN
msctspt/__init__.pyc
Normal file
BIN
msctspt/__init__.pyc
Normal file
Binary file not shown.
@ -1,221 +1,221 @@
|
||||
import os
|
||||
import brotli
|
||||
|
||||
'''感谢由 Charlie_Ping “查理平” 带来的bdx转换代码'''
|
||||
|
||||
|
||||
# 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日
|
||||
# 统计:致命(三级)错误:0个;警告(二级)错误:0个;语法(一级)错误:7个
|
||||
|
||||
|
||||
class BdxConverter:
|
||||
__header = "BD@"
|
||||
__bin_header = b"BDX"
|
||||
__generator_author = b"&Charlie_Ping"
|
||||
|
||||
keys = {
|
||||
# x--, x++, addSmallX(-128~127), addX(-32768~32767), addBigX(-2147483648~2147483647)
|
||||
"x": [b"\x0f", b"\x0e", b"\x1c", b"\x14", b"\x15"],
|
||||
"y": [b"\x11", b"\x10", b"\x1d", b"\x16", b"\x17"],
|
||||
"z": [b"\x13", b"\x12", b"\x1e", b"\x18", b"\x19"],
|
||||
"end": b"\x58",
|
||||
"isSigned": b"\x5a",
|
||||
"placeCommandBlockWithData": b"\x1b",
|
||||
"placeBlock": b"\x07"
|
||||
}
|
||||
|
||||
def __init__(self, file_path: str, author: str, blocks):
|
||||
self.author = author
|
||||
self.blocks = blocks
|
||||
self.file_path = file_path
|
||||
self.direction = [0, 0, 0]
|
||||
self.block_type = self.get_block_type
|
||||
self.__file = self.create_and_upload_file
|
||||
|
||||
@property
|
||||
def get_block_type(self):
|
||||
"""
|
||||
blocks
|
||||
[
|
||||
{
|
||||
"direction": [x: int, y: int, z: int],
|
||||
block_name: str,
|
||||
particular_value: int,
|
||||
}
|
||||
]
|
||||
:return: list 给出的所有方块种类名称
|
||||
"""
|
||||
block_type = set()
|
||||
for block_ in self.blocks:
|
||||
block_type.add(block_["block_name"])
|
||||
block_type = list(block_type)
|
||||
return block_type
|
||||
|
||||
@property
|
||||
def create_and_upload_file(self):
|
||||
"""
|
||||
(瞎用property? 害怕
|
||||
创建一个bdx文件
|
||||
要close!
|
||||
:return: 一个文件对象
|
||||
"""
|
||||
_dir = os.path.dirname(self.file_path)
|
||||
if not os.path.isdir(_dir):
|
||||
os.makedirs(_dir)
|
||||
_bytes = self.__bin_header
|
||||
_bytes += b"\x00"
|
||||
_bytes += self.author.encode("utf-8") + self.__generator_author
|
||||
for i in self.block_type:
|
||||
_bytes += b"\x00\x01"
|
||||
_bytes += bytes(i, encoding="utf-8")
|
||||
_bytes += b"\x00"
|
||||
_bytes += self.upload_blocks()
|
||||
_bytes += b"X"
|
||||
with open(self.file_path, "w+") as f:
|
||||
f.write("BD@")
|
||||
f.close()
|
||||
with open(self.file_path, "ab+") as f:
|
||||
f.write(brotli.compress(_bytes))
|
||||
f.close()
|
||||
return
|
||||
|
||||
def upload_blocks(self):
|
||||
"""
|
||||
计算差值
|
||||
写入移动过程
|
||||
写入方块
|
||||
更新差值
|
||||
:return:
|
||||
"""
|
||||
_types = b""
|
||||
for block_ in self.blocks:
|
||||
# print(f"当前方块:{block['block_name']}, 位置: {block['direction']}]")
|
||||
diff = self.move_pointer(self.direction, block_["direction"])
|
||||
_types += diff
|
||||
if block_["block_name"] in ["command_block",
|
||||
"chain_command_block",
|
||||
"repeating_command_block"]:
|
||||
_types += self.obtain_command_block(block_)
|
||||
else:
|
||||
_types += self.obtain_universal_block(block_)
|
||||
self.direction = block_["direction"]
|
||||
return _types
|
||||
|
||||
def move_pointer(self, direction: list, new_direction):
|
||||
"""
|
||||
给出 两个[x, y, z]坐标,返回pointer的移动过程
|
||||
:param direction: 坐标 1
|
||||
:param new_direction: 坐标 2
|
||||
:return: bytes
|
||||
"""
|
||||
_bytes = b""
|
||||
for i, sign in enumerate(["x", "y", "z"]):
|
||||
# print(f"<{sign}> 新-旧={new_direction[i]-direction[i]}")
|
||||
distance = new_direction[i] - direction[i]
|
||||
if distance == 0:
|
||||
# print("距离是0?跳过了")
|
||||
continue
|
||||
_bytes += self.obtain_pointer_type(distance, sign)
|
||||
# print(f"向 {sign} 运动了 {distance} 格子")
|
||||
return _bytes
|
||||
|
||||
@classmethod
|
||||
def obtain_pointer_type(cls, num: int, coordinate: str):
|
||||
"""
|
||||
|
||||
用于确定辅助玩家以某一数据类型走指定长度
|
||||
|
||||
-1 -> 0
|
||||
1 -> 1
|
||||
[128, 127] -> 2
|
||||
[-32768, 32767] -> 3
|
||||
[-2147483648, 2147483647] -> 4
|
||||
:param num:
|
||||
:param coordinate: 坐标轴种类,x y 或 z
|
||||
:return:
|
||||
"""
|
||||
if num == 0:
|
||||
return
|
||||
pointer = 0
|
||||
condition = (num != -1, # byte=0, pointer=1
|
||||
num < -1 or num > 1, # byte=1, pointer=2
|
||||
num < -128 or num > 127, # byte=2, pointer=3
|
||||
num < -32768 or num > 32767, # byte=4, pointer=4
|
||||
)
|
||||
for i in condition:
|
||||
if i:
|
||||
pointer += 1
|
||||
pointer_type = cls.keys[coordinate][pointer]
|
||||
|
||||
byte_len = 2 ** (pointer - 2)
|
||||
if byte_len >= 1:
|
||||
num_byte = num.to_bytes(byte_len, byteorder="big", signed=True)
|
||||
return pointer_type + num_byte
|
||||
return pointer_type
|
||||
|
||||
def obtain_universal_block(self, block1):
|
||||
"""
|
||||
给定一个方块, 返回此方块在这个bdx中的id和方块data
|
||||
:param block1: {block_name: str,particular_value: int}
|
||||
:return: bytes
|
||||
"""
|
||||
block_id = b"\x07" + self.block_type.index(block1["block_name"]).to_bytes(2, byteorder="big", signed=False)
|
||||
particular_value = block1["particular_value"].to_bytes(2, byteorder="big", signed=False)
|
||||
block_header = block_id + particular_value
|
||||
return block_header
|
||||
|
||||
def obtain_command_block(self, block1):
|
||||
"""
|
||||
给定一个命令方块,返回命令方块各种数据
|
||||
:param block1: {
|
||||
"direction": [x: int, y: int, z: int]
|
||||
"block_name": str,
|
||||
"particular_value": int,
|
||||
"impluse": int, # unsigned_int32
|
||||
"command": str,
|
||||
"customName": str,
|
||||
"lastOutput": str, # 没特殊要求写个\x00就得了
|
||||
"tickdelay": int, # int32
|
||||
"executeOnFirstTick": int, # 1 bytes
|
||||
"trackOutput": int, # 1 bytes
|
||||
"conditional": int, # 1 bytes
|
||||
"needRedstone": int # 1 bytes
|
||||
}
|
||||
:return: bytes of command_block
|
||||
"""
|
||||
|
||||
block_id = b"\x1b" + self.block_type.index(block1["block_name"]).to_bytes(2, byteorder="big", signed=False)
|
||||
particular_value = block1["particular_value"].to_bytes(2, byteorder="big", signed=False)
|
||||
block_header = block_id + particular_value
|
||||
for i in [
|
||||
block1["impluse"].to_bytes(4, byteorder="big", signed=False),
|
||||
bytes(block1["command"], encoding="utf-8") + b"\x00",
|
||||
bytes(block1["customName"], encoding="utf-8") + b"\x00",
|
||||
bytes(block1["lastOutput"], encoding="utf-8") + b"\x00",
|
||||
block1["tickdelay"].to_bytes(4, byteorder="big", signed=True),
|
||||
block1["executeOnFirstTick"].to_bytes(1, byteorder="big"),
|
||||
block1["trackOutput"].to_bytes(1, byteorder="big"),
|
||||
block1["conditional"].to_bytes(1, byteorder="big"),
|
||||
block1["needRedstone"].to_bytes(1, byteorder="big")
|
||||
]:
|
||||
block_header += i
|
||||
return block_header
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
block = [{"direction": [-1, -1, -1], "block_name": "concrete", "particular_value": 5},
|
||||
{"direction": [1, 5, 1], "block_name": "stained_glass", "particular_value": 7},
|
||||
{"direction": [2, 4, 1], "block_name": "command_block", "particular_value": 3,
|
||||
"impluse": 0,
|
||||
"command": "say A generator test",
|
||||
"customName": "test",
|
||||
"lastOutput": "",
|
||||
"tickdelay": 24,
|
||||
"executeOnFirstTick": 0,
|
||||
"trackOutput": 0,
|
||||
"conditional": 0,
|
||||
"needRedstone": 1
|
||||
},
|
||||
{"direction": [3, 4, 1], "block_name": "concrete", "particular_value": 6},
|
||||
{"direction": [-123412133, 4, 1], "block_name": "concrete", "particular_value": 7}]
|
||||
bdx = BdxConverter("./test02.bdx", "Charlie_Ping", block)
|
||||
import os
|
||||
import brotli
|
||||
|
||||
'''感谢由 Charlie_Ping “查理平” 带来的bdx转换代码'''
|
||||
|
||||
|
||||
# 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日
|
||||
# 统计:致命(三级)错误:0个;警告(二级)错误:0个;语法(一级)错误:7个
|
||||
|
||||
|
||||
class BdxConverter:
|
||||
__header = "BD@"
|
||||
__bin_header = b"BDX"
|
||||
__generator_author = b"&Charlie_Ping"
|
||||
|
||||
keys = {
|
||||
# x--, x++, addSmallX(-128~127), addX(-32768~32767), addBigX(-2147483648~2147483647)
|
||||
"x": [b"\x0f", b"\x0e", b"\x1c", b"\x14", b"\x15"],
|
||||
"y": [b"\x11", b"\x10", b"\x1d", b"\x16", b"\x17"],
|
||||
"z": [b"\x13", b"\x12", b"\x1e", b"\x18", b"\x19"],
|
||||
"end": b"\x58",
|
||||
"isSigned": b"\x5a",
|
||||
"placeCommandBlockWithData": b"\x1b",
|
||||
"placeBlock": b"\x07"
|
||||
}
|
||||
|
||||
def __init__(self, file_path: str, author: str, blocks):
|
||||
self.author = author
|
||||
self.blocks = blocks
|
||||
self.file_path = file_path
|
||||
self.direction = [0, 0, 0]
|
||||
self.block_type = self.get_block_type
|
||||
self.__file = self.create_and_upload_file
|
||||
|
||||
@property
|
||||
def get_block_type(self):
|
||||
"""
|
||||
blocks
|
||||
[
|
||||
{
|
||||
"direction": [x: int, y: int, z: int],
|
||||
block_name: str,
|
||||
particular_value: int,
|
||||
}
|
||||
]
|
||||
:return: list 给出的所有方块种类名称
|
||||
"""
|
||||
block_type = set()
|
||||
for block_ in self.blocks:
|
||||
block_type.add(block_["block_name"])
|
||||
block_type = list(block_type)
|
||||
return block_type
|
||||
|
||||
@property
|
||||
def create_and_upload_file(self):
|
||||
"""
|
||||
(瞎用property? 害怕
|
||||
创建一个bdx文件
|
||||
要close!
|
||||
:return: 一个文件对象
|
||||
"""
|
||||
_dir = os.path.dirname(self.file_path)
|
||||
if not os.path.isdir(_dir):
|
||||
os.makedirs(_dir)
|
||||
_bytes = self.__bin_header
|
||||
_bytes += b"\x00"
|
||||
_bytes += self.author.encode("utf-8") + self.__generator_author
|
||||
for i in self.block_type:
|
||||
_bytes += b"\x00\x01"
|
||||
_bytes += bytes(i, encoding="utf-8")
|
||||
_bytes += b"\x00"
|
||||
_bytes += self.upload_blocks()
|
||||
_bytes += b"X"
|
||||
with open(self.file_path, "w+") as f:
|
||||
f.write("BD@")
|
||||
f.close()
|
||||
with open(self.file_path, "ab+") as f:
|
||||
f.write(brotli.compress(_bytes))
|
||||
f.close()
|
||||
return
|
||||
|
||||
def upload_blocks(self):
|
||||
"""
|
||||
计算差值
|
||||
写入移动过程
|
||||
写入方块
|
||||
更新差值
|
||||
:return:
|
||||
"""
|
||||
_types = b""
|
||||
for block_ in self.blocks:
|
||||
# print(f"当前方块:{block['block_name']}, 位置: {block['direction']}]")
|
||||
diff = self.move_pointer(self.direction, block_["direction"])
|
||||
_types += diff
|
||||
if block_["block_name"] in ["command_block",
|
||||
"chain_command_block",
|
||||
"repeating_command_block"]:
|
||||
_types += self.obtain_command_block(block_)
|
||||
else:
|
||||
_types += self.obtain_universal_block(block_)
|
||||
self.direction = block_["direction"]
|
||||
return _types
|
||||
|
||||
def move_pointer(self, direction: list, new_direction):
|
||||
"""
|
||||
给出 两个[x, y, z]坐标,返回pointer的移动过程
|
||||
:param direction: 坐标 1
|
||||
:param new_direction: 坐标 2
|
||||
:return: bytes
|
||||
"""
|
||||
_bytes = b""
|
||||
for i, sign in enumerate(["x", "y", "z"]):
|
||||
# print(f"<{sign}> 新-旧={new_direction[i]-direction[i]}")
|
||||
distance = new_direction[i] - direction[i]
|
||||
if distance == 0:
|
||||
# print("距离是0?跳过了")
|
||||
continue
|
||||
_bytes += self.obtain_pointer_type(distance, sign)
|
||||
# print(f"向 {sign} 运动了 {distance} 格子")
|
||||
return _bytes
|
||||
|
||||
@classmethod
|
||||
def obtain_pointer_type(cls, num: int, coordinate: str):
|
||||
"""
|
||||
|
||||
用于确定辅助玩家以某一数据类型走指定长度
|
||||
|
||||
-1 -> 0
|
||||
1 -> 1
|
||||
[128, 127] -> 2
|
||||
[-32768, 32767] -> 3
|
||||
[-2147483648, 2147483647] -> 4
|
||||
:param num:
|
||||
:param coordinate: 坐标轴种类,x y 或 z
|
||||
:return:
|
||||
"""
|
||||
if num == 0:
|
||||
return
|
||||
pointer = 0
|
||||
condition = (num != -1, # byte=0, pointer=1
|
||||
num < -1 or num > 1, # byte=1, pointer=2
|
||||
num < -128 or num > 127, # byte=2, pointer=3
|
||||
num < -32768 or num > 32767, # byte=4, pointer=4
|
||||
)
|
||||
for i in condition:
|
||||
if i:
|
||||
pointer += 1
|
||||
pointer_type = cls.keys[coordinate][pointer]
|
||||
|
||||
byte_len = 2 ** (pointer - 2)
|
||||
if byte_len >= 1:
|
||||
num_byte = num.to_bytes(byte_len, byteorder="big", signed=True)
|
||||
return pointer_type + num_byte
|
||||
return pointer_type
|
||||
|
||||
def obtain_universal_block(self, block1):
|
||||
"""
|
||||
给定一个方块, 返回此方块在这个bdx中的id和方块data
|
||||
:param block1: {block_name: str,particular_value: int}
|
||||
:return: bytes
|
||||
"""
|
||||
block_id = b"\x07" + self.block_type.index(block1["block_name"]).to_bytes(2, byteorder="big", signed=False)
|
||||
particular_value = block1["particular_value"].to_bytes(2, byteorder="big", signed=False)
|
||||
block_header = block_id + particular_value
|
||||
return block_header
|
||||
|
||||
def obtain_command_block(self, block1):
|
||||
"""
|
||||
给定一个命令方块,返回命令方块各种数据
|
||||
:param block1: {
|
||||
"direction": [x: int, y: int, z: int]
|
||||
"block_name": str,
|
||||
"particular_value": int,
|
||||
"impluse": int, # unsigned_int32
|
||||
"command": str,
|
||||
"customName": str,
|
||||
"lastOutput": str, # 没特殊要求写个\x00就得了
|
||||
"tickdelay": int, # int32
|
||||
"executeOnFirstTick": int, # 1 bytes
|
||||
"trackOutput": int, # 1 bytes
|
||||
"conditional": int, # 1 bytes
|
||||
"needRedstone": int # 1 bytes
|
||||
}
|
||||
:return: bytes of command_block
|
||||
"""
|
||||
|
||||
block_id = b"\x1b" + self.block_type.index(block1["block_name"]).to_bytes(2, byteorder="big", signed=False)
|
||||
particular_value = block1["particular_value"].to_bytes(2, byteorder="big", signed=False)
|
||||
block_header = block_id + particular_value
|
||||
for i in [
|
||||
block1["impluse"].to_bytes(4, byteorder="big", signed=False),
|
||||
bytes(block1["command"], encoding="utf-8") + b"\x00",
|
||||
bytes(block1["customName"], encoding="utf-8") + b"\x00",
|
||||
bytes(block1["lastOutput"], encoding="utf-8") + b"\x00",
|
||||
block1["tickdelay"].to_bytes(4, byteorder="big", signed=True),
|
||||
block1["executeOnFirstTick"].to_bytes(1, byteorder="big"),
|
||||
block1["trackOutput"].to_bytes(1, byteorder="big"),
|
||||
block1["conditional"].to_bytes(1, byteorder="big"),
|
||||
block1["needRedstone"].to_bytes(1, byteorder="big")
|
||||
]:
|
||||
block_header += i
|
||||
return block_header
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
block = [{"direction": [-1, -1, -1], "block_name": "concrete", "particular_value": 5},
|
||||
{"direction": [1, 5, 1], "block_name": "stained_glass", "particular_value": 7},
|
||||
{"direction": [2, 4, 1], "block_name": "command_block", "particular_value": 3,
|
||||
"impluse": 0,
|
||||
"command": "say A generator test",
|
||||
"customName": "test",
|
||||
"lastOutput": "",
|
||||
"tickdelay": 24,
|
||||
"executeOnFirstTick": 0,
|
||||
"trackOutput": 0,
|
||||
"conditional": 0,
|
||||
"needRedstone": 1
|
||||
},
|
||||
{"direction": [3, 4, 1], "block_name": "concrete", "particular_value": 6},
|
||||
{"direction": [-123412133, 4, 1], "block_name": "concrete", "particular_value": 7}]
|
||||
bdx = BdxConverter("./test02.bdx", "Charlie_Ping", block)
|
||||
|
@ -1,130 +1,130 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
"""提供错误报告的基本操作及方法 顺便提供版本更新、安装库等功能"""
|
||||
|
||||
# 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日
|
||||
# 统计:致命(三级)错误:0个;警告(二级)错误:1个;语法(一级)错误:72个
|
||||
import os
|
||||
import zipfile
|
||||
|
||||
|
||||
def makeZip(sourceDir, outFilename, compression=8, exceptFile=None):
|
||||
"""使用compression指定的算法打包目录为zip文件\n
|
||||
默认算法为DEFLATED(8),可用算法如下:\n
|
||||
STORED = 0\n
|
||||
DEFLATED = 8\n
|
||||
BZIP2 = 12\n
|
||||
LZMA = 14\n
|
||||
"""
|
||||
zipf = zipfile.ZipFile(outFilename, 'w', compression)
|
||||
pre_len = len(os.path.dirname(sourceDir))
|
||||
for parent, dirnames, filenames in os.walk(sourceDir):
|
||||
for filename in filenames:
|
||||
if filename == exceptFile:
|
||||
continue
|
||||
print(filename)
|
||||
pathfile = os.path.join(parent, filename)
|
||||
arcname = pathfile[pre_len:].strip(os.path.sep) # 相对路径
|
||||
zipf.write(pathfile, arcname)
|
||||
|
||||
zipf.close()
|
||||
del zipf, pre_len
|
||||
|
||||
|
||||
# 以上函数节选并修改自 正在攀登的小蜗牛 的博客:https://blog.csdn.net/qq_21127151/article/details/107503942
|
||||
|
||||
|
||||
class report:
|
||||
"""发送报告以及相应的任务处理"""
|
||||
|
||||
def __init__(self, senderName: str = 'Unknown', senderContact: str = 'None', describetion: str = ''):
|
||||
""":param senderName 发送者名称
|
||||
:param senderContact 发送者联系方式
|
||||
:param describetion 问题描述"""
|
||||
self.senderName = senderName
|
||||
self.senderContact = senderContact
|
||||
self.describetion = describetion
|
||||
if not self.senderName:
|
||||
self.senderName = 'Unknown'
|
||||
if not self.senderContact:
|
||||
self.senderContact = 'None'
|
||||
|
||||
def emailReport(self):
|
||||
"""使用E-mail方法发送当前的日志和临时文件等"""
|
||||
import smtplib
|
||||
from email.mime.text import MIMEText
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.header import Header
|
||||
from nmcsup.log import log
|
||||
log("发送错误报告")
|
||||
import os
|
||||
log("添加标题与正文")
|
||||
msg = MIMEMultipart()
|
||||
# 发送者与接收者显示名称
|
||||
msg["From"] = Header(self.senderName, 'utf-8')
|
||||
msg["To"] = Header("W-YI (QQ2647547478)", 'utf-8')
|
||||
# 标题
|
||||
msg["Subject"] = '音·创 - 来自 ' + self.senderName + ' 的错误报告'
|
||||
# 正文
|
||||
msg.attach(
|
||||
MIMEText("来自" + self.senderName + "( " + self.senderContact + " )的错误描述:\n" + self.describetion,
|
||||
'utf-8'))
|
||||
log("添加完毕,正在生成压缩包...")
|
||||
makeZip("./", "Temps&Logs.zip", exceptFile="Temps&Logs.zip")
|
||||
attafile = MIMEText(str(open("Temps&Logs.zip", 'rb').read()), "base64", 'gb2312')
|
||||
attafile["Content-Type"] = 'application/octet-stream'
|
||||
attafile["Content-Disposition"] = 'attachmentfilename="BugReport_from_' + self.senderName + '.zip"'
|
||||
msg.attach(attafile)
|
||||
log("完毕,准备发送")
|
||||
try:
|
||||
smtp = smtplib.SMTP()
|
||||
smtp.connect("smtp.163.com")
|
||||
# smtp.login("RyounDevTeam@163.com","RyounDaiYi99")
|
||||
# SIQQKQQYCZRVIDFJ是授权密码
|
||||
smtp.login("RyounDevTeam@163.com", "SIQQKQQYCZRVIDFJ")
|
||||
smtp.sendmail("RyounDevTeam@163.com", ["RyounDevTeam@163.com", ], msg.as_string())
|
||||
log("错误汇报邮件已发送")
|
||||
except smtplib.SMTPException as e:
|
||||
log("错误汇报邮件发送失败:\n" + str(e))
|
||||
log("清空内存和临时文件")
|
||||
del msg, attafile
|
||||
os.remove("./Temps&Logs.zip")
|
||||
|
||||
|
||||
class version:
|
||||
libraries = (
|
||||
'mido', 'amulet', 'amulet-core', 'amulet-nbt', 'piano_transcription_inference', 'pypinyin',
|
||||
'pyinstaller','py7zr','websockets', 'torch'
|
||||
)
|
||||
"""当前所需库,有一些是开发用的,用户不需要安装"""
|
||||
|
||||
version = ('0.0.1', 'Delta',)
|
||||
"""当前版本"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
|
||||
self.libraries = version.libraries
|
||||
"""当前所需库,有一些是开发用的,用户不需要安装"""
|
||||
|
||||
self.version = version.version
|
||||
"""当前版本"""
|
||||
|
||||
def installLibraries(self):
|
||||
"""安装全部开发用库"""
|
||||
from sys import platform
|
||||
import os
|
||||
if platform == 'win32':
|
||||
import shutil
|
||||
try:
|
||||
shutil.rmtree(os.getenv('APPDATA') + '\\Musicreater\\')
|
||||
except FloatingPointError:
|
||||
pass
|
||||
for i in self.libraries:
|
||||
print("安装库:" + i)
|
||||
os.system("python -m pip install " + i + " -i https://pypi.tuna.tsinghua.edu.cn/simple")
|
||||
elif platform == 'linux':
|
||||
os.system("sudo apt-get install python3-pip")
|
||||
os.system("sudo apt-get install python3-tk")
|
||||
os.system("sudo apt-get install python3-tkinter")
|
||||
for i in self.libraries:
|
||||
print("安装库:" + i)
|
||||
os.system("sudo python3 -m pip install " + i + " -i https://pypi.tuna.tsinghua.edu.cn/simple")
|
||||
# -*- coding: UTF-8 -*-
|
||||
"""提供错误报告的基本操作及方法 顺便提供版本更新、安装库等功能"""
|
||||
|
||||
# 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日
|
||||
# 统计:致命(三级)错误:0个;警告(二级)错误:1个;语法(一级)错误:72个
|
||||
import os
|
||||
import zipfile
|
||||
|
||||
|
||||
def makeZip(sourceDir, outFilename, compression=8, exceptFile=None):
|
||||
"""使用compression指定的算法打包目录为zip文件\n
|
||||
默认算法为DEFLATED(8),可用算法如下:\n
|
||||
STORED = 0\n
|
||||
DEFLATED = 8\n
|
||||
BZIP2 = 12\n
|
||||
LZMA = 14\n
|
||||
"""
|
||||
zipf = zipfile.ZipFile(outFilename, 'w', compression)
|
||||
pre_len = len(os.path.dirname(sourceDir))
|
||||
for parent, dirnames, filenames in os.walk(sourceDir):
|
||||
for filename in filenames:
|
||||
if filename == exceptFile:
|
||||
continue
|
||||
print(filename)
|
||||
pathfile = os.path.join(parent, filename)
|
||||
arcname = pathfile[pre_len:].strip(os.path.sep) # 相对路径
|
||||
zipf.write(pathfile, arcname)
|
||||
|
||||
zipf.close()
|
||||
del zipf, pre_len
|
||||
|
||||
|
||||
# 以上函数节选并修改自 正在攀登的小蜗牛 的博客:https://blog.csdn.net/qq_21127151/article/details/107503942
|
||||
|
||||
|
||||
class report:
|
||||
"""发送报告以及相应的任务处理"""
|
||||
|
||||
def __init__(self, senderName: str = 'Unknown', senderContact: str = 'None', describetion: str = ''):
|
||||
""":param senderName 发送者名称
|
||||
:param senderContact 发送者联系方式
|
||||
:param describetion 问题描述"""
|
||||
self.senderName = senderName
|
||||
self.senderContact = senderContact
|
||||
self.describetion = describetion
|
||||
if not self.senderName:
|
||||
self.senderName = 'Unknown'
|
||||
if not self.senderContact:
|
||||
self.senderContact = 'None'
|
||||
|
||||
def emailReport(self):
|
||||
"""使用E-mail方法发送当前的日志和临时文件等"""
|
||||
import smtplib
|
||||
from email.mime.text import MIMEText
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.header import Header
|
||||
from nmcsup.log import log
|
||||
log("发送错误报告")
|
||||
import os
|
||||
log("添加标题与正文")
|
||||
msg = MIMEMultipart()
|
||||
# 发送者与接收者显示名称
|
||||
msg["From"] = Header(self.senderName, 'utf-8')
|
||||
msg["To"] = Header("W-YI (QQ2647547478)", 'utf-8')
|
||||
# 标题
|
||||
msg["Subject"] = '音·创 - 来自 ' + self.senderName + ' 的错误报告'
|
||||
# 正文
|
||||
msg.attach(
|
||||
MIMEText("来自" + self.senderName + "( " + self.senderContact + " )的错误描述:\n" + self.describetion,
|
||||
'utf-8'))
|
||||
log("添加完毕,正在生成压缩包...")
|
||||
makeZip("./", "Temps&Logs.zip", exceptFile="Temps&Logs.zip")
|
||||
attafile = MIMEText(str(open("Temps&Logs.zip", 'rb').read()), "base64", 'gb2312')
|
||||
attafile["Content-Type"] = 'application/octet-stream'
|
||||
attafile["Content-Disposition"] = 'attachmentfilename="BugReport_from_' + self.senderName + '.zip"'
|
||||
msg.attach(attafile)
|
||||
log("完毕,准备发送")
|
||||
try:
|
||||
smtp = smtplib.SMTP()
|
||||
smtp.connect("smtp.163.com")
|
||||
# smtp.login("RyounDevTeam@163.com","RyounDaiYi99")
|
||||
# SIQQKQQYCZRVIDFJ是授权密码
|
||||
smtp.login("RyounDevTeam@163.com", "SIQQKQQYCZRVIDFJ")
|
||||
smtp.sendmail("RyounDevTeam@163.com", ["RyounDevTeam@163.com", ], msg.as_string())
|
||||
log("错误汇报邮件已发送")
|
||||
except smtplib.SMTPException as e:
|
||||
log("错误汇报邮件发送失败:\n" + str(e))
|
||||
log("清空内存和临时文件")
|
||||
del msg, attafile
|
||||
os.remove("./Temps&Logs.zip")
|
||||
|
||||
|
||||
class version:
|
||||
libraries = (
|
||||
'mido', 'amulet', 'amulet-core', 'amulet-nbt', 'piano_transcription_inference', 'pypinyin',
|
||||
'pyinstaller','py7zr','websockets', 'torch'
|
||||
)
|
||||
"""当前所需库,有一些是开发用的,用户不需要安装"""
|
||||
|
||||
version = ('0.0.1', 'Delta',)
|
||||
"""当前版本"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
|
||||
self.libraries = version.libraries
|
||||
"""当前所需库,有一些是开发用的,用户不需要安装"""
|
||||
|
||||
self.version = version.version
|
||||
"""当前版本"""
|
||||
|
||||
def installLibraries(self):
|
||||
"""安装全部开发用库"""
|
||||
from sys import platform
|
||||
import os
|
||||
if platform == 'win32':
|
||||
import shutil
|
||||
try:
|
||||
shutil.rmtree(os.getenv('APPDATA') + '\\Musicreater\\')
|
||||
except FloatingPointError:
|
||||
pass
|
||||
for i in self.libraries:
|
||||
print("安装库:" + i)
|
||||
os.system("python -m pip install " + i + " -i https://pypi.tuna.tsinghua.edu.cn/simple")
|
||||
elif platform == 'linux':
|
||||
os.system("sudo apt-get install python3-pip")
|
||||
os.system("sudo apt-get install python3-tk")
|
||||
os.system("sudo apt-get install python3-tkinter")
|
||||
for i in self.libraries:
|
||||
print("安装库:" + i)
|
||||
os.system("sudo python3 -m pip install " + i + " -i https://pypi.tuna.tsinghua.edu.cn/simple")
|
||||
|
@ -1,233 +1,301 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""音·创 的函数操作和一些其他功能"""
|
||||
# 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日
|
||||
# 统计:致命(三级)错误:0个;警告(二级)错误:0个;语法(一级)错误:91个
|
||||
|
||||
|
||||
from nmcsup.log import log
|
||||
|
||||
|
||||
def delPart(Data, starter, ender, includeStart: bool = True, includend: bool = True):
|
||||
"""删除序列从starter物件到ender物件之间的部分\n
|
||||
includeStart与inclodend分别控制此函数是否包括starter和ender物件所在部分,默认为真\n
|
||||
starter与ender若为None则默认从首或尾开始"""
|
||||
e = True
|
||||
try:
|
||||
if starter is None:
|
||||
includeStart = True
|
||||
starter = Data[0]
|
||||
if ender is None:
|
||||
includend = True
|
||||
ender = Data[len(Data) - 1]
|
||||
if includend:
|
||||
if includeStart:
|
||||
e = False
|
||||
return Data[Data.index(starter):len(Data) - Data[len(Data)::-1].index(ender)]
|
||||
else:
|
||||
e = False
|
||||
return Data[Data.index(starter) + 1:len(Data) - Data[len(Data)::-1].index(ender)]
|
||||
else:
|
||||
if includeStart:
|
||||
e = False
|
||||
return Data[Data.index(starter):len(Data) - Data[len(Data)::-1].index(ender) - 1]
|
||||
else:
|
||||
e = False
|
||||
return Data[Data.index(starter) + 1:len(Data) - Data[len(Data)::-1].index(ender) - 1]
|
||||
except ValueError:
|
||||
return 0
|
||||
finally:
|
||||
if e is True:
|
||||
return 0
|
||||
|
||||
|
||||
def keepart(Data, starter, ender, includeStart: bool = True, includend: bool = True):
|
||||
"""保留序列从starter物件到ender物件之间的部分\n
|
||||
includeStart与inclodend分别控制此函数是否包括starter和ender物件所在部分,默认为真\n
|
||||
starter与ender若为None则默认从首或尾开始"""
|
||||
e = True
|
||||
try:
|
||||
if starter is None:
|
||||
includeStart = True
|
||||
starter = Data[0]
|
||||
if ender is None:
|
||||
includend = True
|
||||
ender = Data[len(Data) - 1]
|
||||
if includend:
|
||||
if includeStart:
|
||||
e = False
|
||||
return Data[Data.index(starter):Data.index(ender) + 1]
|
||||
else:
|
||||
e = False
|
||||
return Data[Data.index(starter) + 1:Data.index(ender) + 1]
|
||||
else:
|
||||
if includeStart:
|
||||
e = False
|
||||
return Data[Data.index(starter):Data.index(ender)]
|
||||
else:
|
||||
e = False
|
||||
return Data[Data.index(starter) + 1:Data.index(ender)]
|
||||
except ValueError:
|
||||
return 0
|
||||
finally:
|
||||
if e is True:
|
||||
return 0
|
||||
|
||||
|
||||
def lenFunction(fun) -> int:
|
||||
"""取得函数指令部分长度,即忽略#开头的注释"""
|
||||
e = True
|
||||
try:
|
||||
f = 0
|
||||
for i in fun:
|
||||
if i.replace(" ", '')[0] == '#':
|
||||
f += 1
|
||||
e = False
|
||||
return len(fun) - f
|
||||
except IndexError:
|
||||
return -1
|
||||
finally:
|
||||
if e is True:
|
||||
return -1
|
||||
|
||||
|
||||
def funSplit(bigFile, maxCmdLen: int = 10000):
|
||||
"""分割bigFile大的函数文件,bigFile需要读入文件流\n
|
||||
返回的部分,每行指令皆带有行尾换行符\\n\n
|
||||
返回-1为大小低于maxCmdLen最长函数指令长度"""
|
||||
bigFile = bigFile.readlines()
|
||||
if lenFunction(bigFile) < maxCmdLen:
|
||||
return -1
|
||||
part = []
|
||||
parts = []
|
||||
h = 0
|
||||
for i in bigFile:
|
||||
if i.replace(" ", '')[0] == '#':
|
||||
part.append(i + '\n')
|
||||
else:
|
||||
part.append(i + '\n')
|
||||
h += 1
|
||||
if h >= 10000:
|
||||
parts.append(part)
|
||||
part = []
|
||||
h = 0
|
||||
return parts
|
||||
|
||||
|
||||
def makeFuncFiles(musicset, path='./'):
|
||||
"""在指定目录下生成函数文件"""
|
||||
from nmcsup.trans import Note2Cmd
|
||||
commands = []
|
||||
starts = []
|
||||
log("=========================正在在此处生成文件:" + path)
|
||||
maxlen = -1
|
||||
for i in range(len(musicset['musics'])):
|
||||
log('写入第' + str(i) + '个数据')
|
||||
commands.append("scoreboard players add @e[name=\"" + musicset['musics'][i]['set']['EntityName'] + "\"] " +
|
||||
musicset['musics'][i]['set']['ScoreboardName'] + " 1\n")
|
||||
commands.append("execute @e[name=\"" + musicset['musics'][i]['set']['EntityName'] + "\",scores={" +
|
||||
musicset['musics'][i]['set']['ScoreboardName'] + "=1..10}] ~~~ title @a" + musicset['mainset'][
|
||||
'PlayerSelect'] + " title " + musicset['mainset']['MusicTitle'] + "\n")
|
||||
commands.append("execute @e[name=\"" + musicset['musics'][i]['set']['EntityName'] + "\",scores={" +
|
||||
musicset['musics'][i]['set']['ScoreboardName'] + "=1..10}] ~~~ title @a" + musicset['mainset'][
|
||||
'PlayerSelect'] + " subtitle 本函数乐曲由§b§l凌云§r§3函数音乐创建§r生成\n")
|
||||
if len(musicset['musics'][i]['notes']) > maxlen:
|
||||
maxlen = len(musicset['musics'][i]['notes'])
|
||||
starts.append("scoreboard objectives add " + musicset['musics'][i]['set']['ScoreboardName'] + " dummy\n")
|
||||
starts.append("summon armor_stand " + musicset['musics'][i]['set']['EntityName'] + '\n')
|
||||
with open(path + musicset['mainset']['MusicTitle'] + '_Part' + str(i) + '.mcfunction', 'w',
|
||||
encoding='UTF-8') as f:
|
||||
f.writelines(Note2Cmd(musicset['musics'][i]['notes'], musicset['musics'][i]['set']['ScoreboardName'],
|
||||
musicset['musics'][i]['set']['Instrument'], musicset['mainset']['PlayerSelect'],
|
||||
True))
|
||||
if musicset['mainset']['IsRepeat']:
|
||||
log("增加重复语句")
|
||||
for i in range(len(musicset['musics'])):
|
||||
commands.append("execute @e[name=\"" + musicset['musics'][i]['set']['EntityName'] + "\",scores={" +
|
||||
musicset['musics'][i]['set']['ScoreboardName'] + "=" + str(
|
||||
(maxlen + 2) * 10) + "}] ~~~ scoreboard players set @e[name=\"" + musicset['musics'][i]['set'][
|
||||
'EntityName'] + "\"] " + musicset['musics'][i]['set']['ScoreboardName'] + " -1\n")
|
||||
log("增加版权语句")
|
||||
commands.append("\n\n# 凌云我的世界开发团队 x 凌云软件开发团队 : W-YI(金羿)\n")
|
||||
starts.append("\n\n# 凌云我的世界开发团队 x 凌云软件开发团队 : W-YI(金羿)\n")
|
||||
log("写入支持文件")
|
||||
with open(path + musicset['mainset']['MusicTitle'] + '_Support.mcfunction', 'w', encoding='UTF-8') as f:
|
||||
f.writelines(commands)
|
||||
log("写入开始文件")
|
||||
with open(path + 'Start_' + musicset['mainset']['MusicTitle'] + '.mcfunction', 'w', encoding='UTF-8') as f:
|
||||
f.writelines(starts)
|
||||
del commands, starts, maxlen
|
||||
log("完成============================")
|
||||
|
||||
|
||||
def makeFunDir(musicset, path='./'):
|
||||
"""在指定目录下生成函数包文件夹"""
|
||||
import os
|
||||
import uuid
|
||||
log("=============================生成函数包文件夹")
|
||||
# note,packname="Ryoun",FileName="Music",EntityName_='music_support',ScoreboardName_='music_support',
|
||||
# MusicTitle_='Noname',PlayerSelect_='',Repeat_=False,Instrument_='harp'
|
||||
try:
|
||||
os.makedirs(path + musicset['mainset']['PackName'] + "Pack/behavior_packs/" + musicset['mainset'][
|
||||
'PackName'] + "/functions")
|
||||
log("已创建目录" + path + musicset['mainset']['PackName'] + "Pack/behavior_packs/" + musicset['mainset'][
|
||||
'PackName'] + "/functions")
|
||||
except FileExistsError:
|
||||
log("目录已有无需创建")
|
||||
pass
|
||||
# 判断文件皆存在
|
||||
if not (os.path.exists(
|
||||
path + musicset['mainset']['PackName'] + "Pack/world_behavior_packs.json") and os.path.exists(
|
||||
path + musicset['mainset']['PackName'] + "Pack/behavior_packs/" + musicset['mainset'][
|
||||
'PackName'] + "/manifest.json")):
|
||||
log("创建manifest.json以及world_behavior_packs.json")
|
||||
behaviorUuid = uuid.uuid4()
|
||||
with open(path + musicset['mainset']['PackName'] + "Pack/world_behavior_packs.json", "w") as f:
|
||||
f.write("[\n {\"pack_id\": \"" + str(behaviorUuid) + "\",\n \"version\": [ 0, 0, 1 ]}\n]")
|
||||
p = path + musicset['mainset']['PackName'] + "Pack/behavior_packs/" + musicset['mainset']['PackName'] + \
|
||||
"/manifest.json"
|
||||
with open(p, "w") as f:
|
||||
f.write("{\n \"format_version\": 1,\n \"header\": {\n \"description\": \"" + musicset['mainset'][
|
||||
'PackName'] + " Pack : behavior pack\",\n \"version\": [ 0, 0, 1 ],\n \"name\": \"" +
|
||||
musicset['mainset']['PackName'] + "Pack\",\n \"uuid\": \"" + str(
|
||||
behaviorUuid) + "\"\n },\n \"modules\": [\n {\n \"description\": \"" + musicset['mainset'][
|
||||
'PackName'] + " Pack : behavior pack\",\n \"type\": \"data\",\n \"version\":"
|
||||
" [ 0, 0, 1 ],\n \"uuid\": \"" + str(
|
||||
uuid.uuid4()) + "\"\n }\n ]\n}")
|
||||
makeFuncFiles(musicset, path + musicset['mainset']['PackName'] + "Pack/behavior_packs/" + musicset['mainset'][
|
||||
'PackName'] + "/functions/")
|
||||
log("完成============================")
|
||||
|
||||
|
||||
"""
|
||||
这里是往事,用于记载一些用不到的功能
|
||||
|
||||
#存在于 Musicreater.py 播放(试听)音乐
|
||||
def PlayNote(Notes, t=480): # Notes是音符列表,t是一拍占有的毫秒数
|
||||
tkinter.messagebox.showinfo(title='提示!', message="播放发音不一定标准\n说不定还会坏音响/(ㄒoㄒ)/~~qwq\n请注意。")
|
||||
import winsound
|
||||
import time
|
||||
from nmcsup.trans import mcnote2freq
|
||||
Notes = mcnote2freq(Notes)
|
||||
for frequency, duration in Notes:
|
||||
log("播放:"+str([int(frequency), int(duration*t)]))
|
||||
if int(frequency) != 0:
|
||||
winsound.Beep(int(frequency), int(duration*t))
|
||||
elif int(frequency) == 0:
|
||||
time.sleep(duration*t/1000)
|
||||
|
||||
#同上,执行播放命令
|
||||
def PlayOne():
|
||||
log("试听")
|
||||
tkinter.messagebox.showwarning(title="警告⚠", message="试听音质可能引起您的不适,更可能引起您的扬声器的不适,请酌情播放。")
|
||||
global NowMusic
|
||||
PlayNote(dataset[0]['musics'][NowMusic]['notes'])
|
||||
|
||||
|
||||
|
||||
#同上,是早期 MinecraftMusicFunctionMaker.py (函数音创)的代码转移至音·创时的注解
|
||||
n2c(dataset[0]['musics'][i]['notes'],EntityName=dataset[0]['musics'][i]['set']['EntityName'],ScoreboardName=dataset[0]['
|
||||
musics'][i]['set']['ScoreboardName'],PlayerSelect=dataset[0]['mainset']['PlayerSelect'],Instrument=dataset[0]['musics']
|
||||
i]['set']["Instrument"])
|
||||
|
||||
|
||||
"""
|
||||
# -*- coding: utf-8 -*-
|
||||
"""音·创 的函数操作和一些其他功能"""
|
||||
# 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日
|
||||
# 统计:致命(三级)错误:0个;警告(二级)错误:0个;语法(一级)错误:91个
|
||||
|
||||
|
||||
from nmcsup.log import log
|
||||
|
||||
|
||||
def delPart(Data, starter, ender, includeStart: bool = True, includend: bool = True):
|
||||
"""删除序列从starter物件到ender物件之间的部分\n
|
||||
includeStart与inclodend分别控制此函数是否包括starter和ender物件所在部分,默认为真\n
|
||||
starter与ender若为None则默认从首或尾开始"""
|
||||
try:
|
||||
if starter is None:
|
||||
includeStart = True
|
||||
starter = Data[0]
|
||||
if ender is None:
|
||||
includend = True
|
||||
ender = Data[len(Data) - 1]
|
||||
if includend:
|
||||
if includeStart:
|
||||
return Data[Data.index(starter):len(Data) - Data[len(Data)::-1].index(ender)]
|
||||
else:
|
||||
return Data[Data.index(starter) + 1:len(Data) - Data[len(Data)::-1].index(ender)]
|
||||
else:
|
||||
if includeStart:
|
||||
return Data[Data.index(starter):len(Data) - Data[len(Data)::-1].index(ender) - 1]
|
||||
else:
|
||||
return Data[Data.index(starter) + 1:len(Data) - Data[len(Data)::-1].index(ender) - 1]
|
||||
except:
|
||||
return 0
|
||||
|
||||
|
||||
def keepart(Data, starter, ender, includeStart: bool = True, includend: bool = True):
|
||||
"""保留序列从starter物件到ender物件之间的部分\n
|
||||
includeStart与inclodend分别控制此函数是否包括starter和ender物件所在部分,默认为真\n
|
||||
starter与ender若为None则默认从首或尾开始"""
|
||||
try:
|
||||
if starter is None:
|
||||
includeStart = True
|
||||
starter = Data[0]
|
||||
if ender is None:
|
||||
includend = True
|
||||
ender = Data[len(Data) - 1]
|
||||
if includend:
|
||||
if includeStart:
|
||||
return Data[Data.index(starter):Data.index(ender) + 1]
|
||||
else:
|
||||
return Data[Data.index(starter) + 1:Data.index(ender) + 1]
|
||||
else:
|
||||
if includeStart:
|
||||
return Data[Data.index(starter):Data.index(ender)]
|
||||
else:
|
||||
return Data[Data.index(starter) + 1:Data.index(ender)]
|
||||
except:
|
||||
return 0
|
||||
|
||||
|
||||
def lenFunction(fun) -> int:
|
||||
"""取得函数指令部分长度,即忽略#开头的注释"""
|
||||
try:
|
||||
f = 0
|
||||
for i in fun:
|
||||
if i.replace(" ", '')[0] == '#':
|
||||
f += 1
|
||||
return len(fun) - f
|
||||
except:
|
||||
return -1
|
||||
|
||||
|
||||
def funSplit(bigFile, maxCmdLen: int = 10000):
|
||||
"""分割bigFile大的函数文件,bigFile需要读入文件流\n
|
||||
返回的部分,每行指令皆带有行尾换行符\\n\n
|
||||
返回-1为大小低于maxCmdLen最长函数指令长度"""
|
||||
bigFile = bigFile.readlines()
|
||||
if lenFunction(bigFile) < maxCmdLen:
|
||||
return -1
|
||||
part = []
|
||||
parts = []
|
||||
h = 0
|
||||
for i in bigFile:
|
||||
if i.replace(" ", '')[0] == '#':
|
||||
part.append(i + '\n')
|
||||
else:
|
||||
part.append(i + '\n')
|
||||
h += 1
|
||||
if h >= 10000:
|
||||
parts.append(part)
|
||||
part = []
|
||||
h = 0
|
||||
return parts
|
||||
|
||||
|
||||
def makeFuncFiles(musicset, path='./'):
|
||||
"""在指定目录下生成函数文件"""
|
||||
from nmcsup.trans import Note2Cmd
|
||||
commands = []
|
||||
starts = []
|
||||
log("=========================正在在此处生成文件:" + path)
|
||||
maxlen = -1
|
||||
for i in range(len(musicset['musics'])):
|
||||
log('写入第' + str(i) + '个数据')
|
||||
commands.append("scoreboard players add @e[name=\"" + musicset['musics'][i]['set']['EntityName'] + "\"] " +
|
||||
musicset['musics'][i]['set']['ScoreboardName'] + " 1\n")
|
||||
commands.append("execute @e[name=\"" + musicset['musics'][i]['set']['EntityName'] + "\",scores={" +
|
||||
musicset['musics'][i]['set']['ScoreboardName'] + "=1..10}] ~~~ title @a" + musicset['mainset'][
|
||||
'PlayerSelect'] + " title " + musicset['mainset']['MusicTitle'] + "\n")
|
||||
commands.append("execute @e[name=\"" + musicset['musics'][i]['set']['EntityName'] + "\",scores={" +
|
||||
musicset['musics'][i]['set']['ScoreboardName'] + "=1..10}] ~~~ title @a" + musicset['mainset'][
|
||||
'PlayerSelect'] + " subtitle 本函数乐曲由§b§l凌云§r§3函数音乐创建§r生成\n")
|
||||
if len(musicset['musics'][i]['notes']) > maxlen:
|
||||
maxlen = len(musicset['musics'][i]['notes'])
|
||||
starts.append("scoreboard objectives add " + musicset['musics'][i]['set']['ScoreboardName'] + " dummy\n")
|
||||
starts.append("summon armor_stand " + musicset['musics'][i]['set']['EntityName'] + '\n')
|
||||
with open(path + musicset['mainset']['MusicTitle'] + '_Part' + str(i) + '.mcfunction', 'w',
|
||||
encoding='UTF-8') as f:
|
||||
f.writelines(Note2Cmd(musicset['musics'][i]['notes'], musicset['musics'][i]['set']['ScoreboardName'],
|
||||
musicset['musics'][i]['set']['Instrument'], musicset['mainset']['PlayerSelect'],
|
||||
True))
|
||||
if musicset['mainset']['IsRepeat']:
|
||||
log("增加重复语句")
|
||||
for i in range(len(musicset['musics'])):
|
||||
commands.append("execute @e[name=\"" + musicset['musics'][i]['set']['EntityName'] + "\",scores={" +
|
||||
musicset['musics'][i]['set']['ScoreboardName'] + "=" + str(
|
||||
(maxlen + 2) * 10) + "}] ~~~ scoreboard players set @e[name=\"" + musicset['musics'][i]['set'][
|
||||
'EntityName'] + "\"] " + musicset['musics'][i]['set']['ScoreboardName'] + " -1\n")
|
||||
log("增加版权语句")
|
||||
commands.append("\n\n# 凌云我的世界开发团队 x 凌云软件开发团队 : W-YI(金羿)\n")
|
||||
starts.append("\n\n# 凌云我的世界开发团队 x 凌云软件开发团队 : W-YI(金羿)\n")
|
||||
log("写入支持文件")
|
||||
with open(path + musicset['mainset']['MusicTitle'] + '_Support.mcfunction', 'w', encoding='UTF-8') as f:
|
||||
f.writelines(commands)
|
||||
log("写入开始文件")
|
||||
with open(path + 'Start_' + musicset['mainset']['MusicTitle'] + '.mcfunction', 'w', encoding='UTF-8') as f:
|
||||
f.writelines(starts)
|
||||
del commands, starts, maxlen
|
||||
log("完成============================")
|
||||
|
||||
|
||||
def makeNewFuncFiles(musicset, path='./'):
|
||||
"""在指定目录下生成函数文件"""
|
||||
from nmcsup.trans import classList_conversion
|
||||
commands = []
|
||||
starts = []
|
||||
starts.__len__()
|
||||
starts.append("scoreboard objectives add " + musicset['musics'][0]['set']['ScoreboardName'] + " dummy\n")
|
||||
starts.append("summon armor_stand " + musicset['musics'][0]['set']['EntityName'] + '\n')
|
||||
starts.append("scoreboard objectives setdisplay sidebar " + musicset['musics'][0]['set']['ScoreboardName'] + '\n')
|
||||
starts.append("scoreboard players set @e[type=armor_stand, name=\"" + musicset['musics'][0]['set']['EntityName'] +
|
||||
"\"] " + musicset['musics'][0]['set']['ScoreboardName'] + " 0" + '\n')
|
||||
log("=========================正在在此处生成文件:" + path)
|
||||
commands.append("scoreboard players add @e[name=\"" + musicset['musics'][0]['set']['EntityName'] + "\"] " +
|
||||
musicset['musics'][0]['set']['ScoreboardName'] + " 1\n")
|
||||
maxlen = -1
|
||||
for i in range(len(musicset['musics'])):
|
||||
log('写入第' + str(i) + '个数据')
|
||||
# commands.append("execute @e[name=\"" + musicset['musics'][i]['set']['EntityName'] + "\",scores={" +
|
||||
# musicset['musics'][i]['set']['ScoreboardName'] + "=1..10}] ~~~ title @a" + musicset['mainset'][
|
||||
# 'PlayerSelect'] + " title " + musicset['mainset']['MusicTitle'] + "\n")
|
||||
# commands.append("execute @e[name=\"" + musicset['musics'][i]['set']['EntityName'] + "\",scores={" +
|
||||
# musicset['musics'][i]['set']['ScoreboardName'] + "=1..10}] ~~~ title @a" + musicset['mainset'][
|
||||
# 'PlayerSelect'] + " subtitle 本函数乐曲由§b§l凌云§r§3函数音乐创建§r生成\n")
|
||||
if len(musicset['musics'][i]['notes']) > maxlen:
|
||||
maxlen = len(musicset['musics'][i]['notes'])
|
||||
with open(path + musicset['mainset']['MusicTitle'] + '_Part' + str(i) + '.mcfunction', 'w',
|
||||
encoding='UTF-8') as f:
|
||||
f.writelines(classList_conversion(musicset['musics'][i]['notes'],
|
||||
musicset['musics'][i]['set']['ScoreboardName']))
|
||||
if musicset['mainset']['IsRepeat']:
|
||||
log("增加重复语句")
|
||||
for i in range(len(musicset['musics'])):
|
||||
commands.append("execute @e[name=\"" + musicset['musics'][i]['set']['EntityName'] + "\",scores={" +
|
||||
musicset['musics'][i]['set']['ScoreboardName'] + "=" + str(
|
||||
(maxlen + 2) * 10) + "}] ~~~ scoreboard players set @e[name=\"" + musicset['musics'][i]['set'][
|
||||
'EntityName'] + "\"] " + musicset['musics'][i]['set']['ScoreboardName'] + " -1\n")
|
||||
log("增加版权语句")
|
||||
commands.append("\n\n# 凌云我的世界开发团队 x 凌云软件开发团队 : W-YI(金羿),bgArray(诸葛亮与八卦阵)\n")
|
||||
starts.append("\n\n# 凌云我的世界开发团队 x 凌云软件开发团队 : W-YI(金羿),bgArray(诸葛亮与八卦阵)\n")
|
||||
log("写入支持文件")
|
||||
with open(path + musicset['mainset']['MusicTitle'] + '_Support.mcfunction', 'w', encoding='UTF-8') as f:
|
||||
f.writelines(commands)
|
||||
log("写入开始文件")
|
||||
with open(path + 'Start_' + musicset['mainset']['MusicTitle'] + '.mcfunction', 'w', encoding='UTF-8') as f:
|
||||
f.writelines(starts)
|
||||
del commands, starts, maxlen
|
||||
log("完成============================")
|
||||
|
||||
|
||||
def makeNewFunDir(musicset, path='./'):
|
||||
"""在指定目录下生成函数包文件夹"""
|
||||
import os
|
||||
import uuid
|
||||
log("=============================生成函数包文件夹")
|
||||
# note,packname="Ryoun",FileName="Music",EntityName_='music_support',ScoreboardName_='music_support',
|
||||
# MusicTitle_='Noname',PlayerSelect_='',Repeat_=False,Instrument_='harp'
|
||||
try:
|
||||
os.makedirs(path + musicset['mainset']['PackName'] + "Pack/behavior_packs/" + musicset['mainset'][
|
||||
'PackName'] + "/functions")
|
||||
log("已创建目录" + path + musicset['mainset']['PackName'] + "Pack/behavior_packs/" + musicset['mainset'][
|
||||
'PackName'] + "/functions")
|
||||
except FileExistsError:
|
||||
log("目录已有无需创建")
|
||||
pass
|
||||
# 判断文件皆存在
|
||||
if not (os.path.exists(
|
||||
path + musicset['mainset']['PackName'] + "Pack/world_behavior_packs.json") and os.path.exists(
|
||||
path + musicset['mainset']['PackName'] + "Pack/behavior_packs/" + musicset['mainset'][
|
||||
'PackName'] + "/manifest.json")):
|
||||
log("创建manifest.json以及world_behavior_packs.json")
|
||||
behaviorUuid = uuid.uuid4()
|
||||
with open(path + musicset['mainset']['PackName'] + "Pack/world_behavior_packs.json", "w") as f:
|
||||
f.write("[\n {\"pack_id\": \"" + str(behaviorUuid) + "\",\n \"version\": [ 0, 0, 1 ]}\n]")
|
||||
p = path + musicset['mainset']['PackName'] + "Pack/behavior_packs/" + musicset['mainset']['PackName'] + \
|
||||
"/manifest.json"
|
||||
with open(p, "w") as f:
|
||||
f.write("{\n \"format_version\": 1,\n \"header\": {\n \"description\": \"" + musicset['mainset'][
|
||||
'PackName'] + " Pack : behavior pack\",\n \"version\": [ 0, 0, 1 ],\n \"name\": \"" +
|
||||
musicset['mainset']['PackName'] + "Pack\",\n \"uuid\": \"" + str(
|
||||
behaviorUuid) + "\"\n },\n \"modules\": [\n {\n \"description\": \"" + musicset['mainset'][
|
||||
'PackName'] + " Pack : behavior pack\",\n \"type\": \"data\",\n \"version\":"
|
||||
" [ 0, 0, 1 ],\n \"uuid\": \"" + str(
|
||||
uuid.uuid4()) + "\"\n }\n ]\n}")
|
||||
makeNewFuncFiles(musicset, path + musicset['mainset']['PackName'] + "Pack/behavior_packs/" + musicset['mainset'][
|
||||
'PackName'] + "/functions/")
|
||||
log("完成============================")
|
||||
|
||||
|
||||
def makeFunDir(musicset, path='./'):
|
||||
"""在指定目录下生成函数包文件夹"""
|
||||
import os
|
||||
import uuid
|
||||
log("=============================生成函数包文件夹")
|
||||
# note,packname="Ryoun",FileName="Music",EntityName_='music_support',ScoreboardName_='music_support',
|
||||
# MusicTitle_='Noname',PlayerSelect_='',Repeat_=False,Instrument_='harp'
|
||||
try:
|
||||
os.makedirs(path + musicset['mainset']['PackName'] + "Pack/behavior_packs/" + musicset['mainset'][
|
||||
'PackName'] + "/functions")
|
||||
log("已创建目录" + path + musicset['mainset']['PackName'] + "Pack/behavior_packs/" + musicset['mainset'][
|
||||
'PackName'] + "/functions")
|
||||
except FileExistsError:
|
||||
log("目录已有无需创建")
|
||||
pass
|
||||
# 判断文件皆存在
|
||||
if not (os.path.exists(
|
||||
path + musicset['mainset']['PackName'] + "Pack/world_behavior_packs.json") and os.path.exists(
|
||||
path + musicset['mainset']['PackName'] + "Pack/behavior_packs/" + musicset['mainset'][
|
||||
'PackName'] + "/manifest.json")):
|
||||
|
||||
log("创建manifest.json以及world_behavior_packs.json")
|
||||
behaviorUuid = uuid.uuid4()
|
||||
with open(path + musicset['mainset']['PackName'] + "Pack/world_behavior_packs.json", "w") as f:
|
||||
f.write("[\n {\"pack_id\": \"" + str(behaviorUuid) + "\",\n \"version\": [ 0, 0, 1 ]}\n]")
|
||||
p = path + musicset['mainset']['PackName'] + "Pack/behavior_packs/" + musicset['mainset']['PackName'] + \
|
||||
"/manifest.json"
|
||||
with open(p, "w") as f:
|
||||
f.write("{\n \"format_version\": 1,\n \"header\": {\n \"description\": \"" + musicset['mainset'][
|
||||
'PackName'] + " Pack : behavior pack\",\n \"version\": [ 0, 0, 1 ],\n \"name\": \"" +
|
||||
musicset['mainset']['PackName'] + "Pack\",\n \"uuid\": \"" + str(
|
||||
behaviorUuid) + "\"\n },\n \"modules\": [\n {\n \"description\": \"" + musicset['mainset'][
|
||||
'PackName'] + " Pack : behavior pack\",\n \"type\": \"data\",\n \"version\":"
|
||||
" [ 0, 0, 1 ],\n \"uuid\": \"" + str(
|
||||
uuid.uuid4()) + "\"\n }\n ]\n}")
|
||||
makeFuncFiles(musicset, path + musicset['mainset']['PackName'] + "Pack/behavior_packs/" + musicset['mainset'][
|
||||
'PackName'] + "/functions/")
|
||||
log("完成============================")
|
||||
|
||||
|
||||
"""
|
||||
这里是往事,用于记载一些用不到的功能
|
||||
|
||||
#存在于 Musicreater.py 播放(试听)音乐
|
||||
def PlayNote(Notes, t=480): # Notes是音符列表,t是一拍占有的毫秒数
|
||||
tkinter.messagebox.showinfo(title='提示!', message="播放发音不一定标准\n说不定还会坏音响/(ㄒoㄒ)/~~qwq\n请注意。")
|
||||
import winsound
|
||||
import time
|
||||
from nmcsup.trans import mcnote2freq
|
||||
Notes = mcnote2freq(Notes)
|
||||
for frequency, duration in Notes:
|
||||
log("播放:"+str([int(frequency), int(duration*t)]))
|
||||
if int(frequency) != 0:
|
||||
winsound.Beep(int(frequency), int(duration*t))
|
||||
elif int(frequency) == 0:
|
||||
time.sleep(duration*t/1000)
|
||||
|
||||
#同上,执行播放命令
|
||||
def PlayOne():
|
||||
log("试听")
|
||||
tkinter.messagebox.showwarning(title="警告⚠", message="试听音质可能引起您的不适,更可能引起您的扬声器的不适,请酌情播放。")
|
||||
global NowMusic
|
||||
PlayNote(dataset[0]['musics'][NowMusic]['notes'])
|
||||
|
||||
|
||||
|
||||
#同上,是早期 MinecraftMusicFunctionMaker.py (函数音创)的代码转移至音·创时的注解
|
||||
n2c(dataset[0]['musics'][i]['notes'],EntityName=dataset[0]['musics'][i]['set']['EntityName'],ScoreboardName=dataset[0]['
|
||||
musics'][i]['set']['ScoreboardName'],PlayerSelect=dataset[0]['mainset']['PlayerSelect'],Instrument=dataset[0]['musics']
|
||||
i]['set']["Instrument"])
|
||||
|
||||
|
||||
"""
|
||||
|
@ -1,31 +1,31 @@
|
||||
# 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日
|
||||
# 统计:致命(三级)错误:0个;警告(二级)错误:0个;语法(一级)错误:9个--未解决1个
|
||||
|
||||
|
||||
import threading
|
||||
|
||||
|
||||
class NewThread(threading.Thread):
|
||||
"""新建一个进程来运行函数,函数运行完毕后可以使用.getResult方法获取其返回值"""
|
||||
|
||||
def __init__(self, func, args=()):
|
||||
super(NewThread, self).__init__()
|
||||
self.func = func
|
||||
self.args = args
|
||||
|
||||
def run(self):
|
||||
self.result = self.func(*self.args)
|
||||
|
||||
def getResult(self):
|
||||
threading.Thread.join(self) # 等待线程执行完毕
|
||||
try:
|
||||
return self.result
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
#
|
||||
# ————————————————
|
||||
# 版权声明:上面的类NewThread修改自CSDN博主「星火燎愿」的原创文章中的内容,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
|
||||
# 原文链接:https://blog.csdn.net/xpt211314/article/details/109543014
|
||||
# ————————————————
|
||||
#
|
||||
# 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日
|
||||
# 统计:致命(三级)错误:0个;警告(二级)错误:0个;语法(一级)错误:9个--未解决1个
|
||||
|
||||
|
||||
import threading
|
||||
|
||||
|
||||
class NewThread(threading.Thread):
|
||||
"""新建一个进程来运行函数,函数运行完毕后可以使用.getResult方法获取其返回值"""
|
||||
|
||||
def __init__(self, func, args=()):
|
||||
super(NewThread, self).__init__()
|
||||
self.func = func
|
||||
self.args = args
|
||||
|
||||
def run(self):
|
||||
self.result = self.func(*self.args)
|
||||
|
||||
def getResult(self):
|
||||
threading.Thread.join(self) # 等待线程执行完毕
|
||||
try:
|
||||
return self.result
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
#
|
||||
# ————————————————
|
||||
# 版权声明:上面的类NewThread修改自CSDN博主「星火燎愿」的原创文章中的内容,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
|
||||
# 原文链接:https://blog.csdn.net/xpt211314/article/details/109543014
|
||||
# ————————————————
|
||||
#
|
||||
|
@ -1,343 +1,342 @@
|
||||
"""音·创 的转换工具库"""
|
||||
|
||||
|
||||
# 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日
|
||||
# 统计:致命(三级)错误:0个;警告(二级)错误:4个--未解决1个;语法(一级)错误:302个
|
||||
|
||||
|
||||
import amulet
|
||||
from amulet.api.block import Block
|
||||
from amulet.utils.world_utils import block_coords_to_chunk_coords as bc2cc
|
||||
from amulet_nbt import TAG_String as ts
|
||||
from nmcsup.log import log
|
||||
|
||||
|
||||
def hans2pinyin(hans, style=3):
|
||||
"""将汉字字符串转化为拼音字符串"""
|
||||
from pypinyin import lazy_pinyin
|
||||
result = lazy_pinyin(hans=hans, style=style)
|
||||
final = ''
|
||||
for i in result:
|
||||
final += i
|
||||
return final
|
||||
|
||||
|
||||
def formCmdBlock(direction: list, command: str, particularValue: int, impluse: int, condition: bool = False,
|
||||
needRedstone: bool = True, tickDelay: int = 0, customName: str = '', lastOutput: str = '',
|
||||
executeOnFirstTick: bool = False, trackOutput: bool = True):
|
||||
"""
|
||||
使用指定项目返回指定的指令方块格式字典
|
||||
:param trackOutput:
|
||||
:param executeOnFirstTick:
|
||||
:param lastOutput:
|
||||
:param customName:
|
||||
:param tickDelay:
|
||||
:param needRedstone:
|
||||
:param condition:
|
||||
:param impluse:
|
||||
:param particularValue:
|
||||
:param command:
|
||||
:param direction:
|
||||
|
||||
:return: 指令方块字典结构
|
||||
"""
|
||||
"""
|
||||
:param block: {
|
||||
"direction": [x: int, y: int, z: int] #方块位置
|
||||
"block_name": str, #方块名称(无需指定,默认为command_block)
|
||||
"particular_value": int, #方块特殊值
|
||||
"impluse": int, #方块类型0脉冲 1循环 2连锁 unsigned_int32
|
||||
"command": str, #指令
|
||||
"customName": str, #悬浮字
|
||||
"lastOutput": str, #上次输出
|
||||
"tickdelay": int, #方块延时 int32
|
||||
"executeOnFirstTick": int, #执行第一个选项 1 bytes
|
||||
"trackOutput": int, #是否输出 1 bytes
|
||||
"conditional": int, #是否有条件 1 bytes
|
||||
"needRedstone": int #是否需要红石 1 bytes
|
||||
}
|
||||
"""
|
||||
return {"direction": direction,
|
||||
"block_name": "command_block",
|
||||
"particular_value": particularValue,
|
||||
"impluse": impluse,
|
||||
"command": command,
|
||||
"customName": customName,
|
||||
"lastOutput": lastOutput,
|
||||
"tickdelay": tickDelay,
|
||||
"executeOnFirstTick": executeOnFirstTick,
|
||||
"trackOutput": trackOutput,
|
||||
"conditional": condition,
|
||||
"needRedstone": needRedstone
|
||||
}
|
||||
|
||||
|
||||
def note2bdx(filePath: str, dire: list, Notes: list, ScoreboardName: str, Instrument: str, PlayerSelect: str = '',
|
||||
isProsess: bool = False, height: int = 200):
|
||||
"""使用方法同Note2Cmd
|
||||
:param 参数说明:
|
||||
filePath: 生成.bdx文件的位置
|
||||
dire: 指令方块在地图中生成的起始位置(相对位置)
|
||||
Notes: 以 list[ list[ float我的世界playsound指令音调 , float延续时常(单位s) ] ] 格式存储的音符列表
|
||||
例如Musicreater.py的(dataset[0]['musics'][NowMusic]['notes'])
|
||||
ScoreboardName: 用于执行的计分板名称
|
||||
Instrument: 播放的乐器
|
||||
PlayerSelect: 执行的玩家选择器
|
||||
isProsess: 是否显示进度条(会很卡)
|
||||
height: 生成结构的最高高度
|
||||
:return 返回一个BdxConverter类(实际上没研究过),同时在指定位置生成.bdx文件"""
|
||||
|
||||
from msctspt.transfer import formCmdBlock
|
||||
from nmcsup.trans import Note2Cmd
|
||||
from msctspt.bdxOpera_CP import BdxConverter
|
||||
cmd = Note2Cmd(Notes, ScoreboardName, Instrument, PlayerSelect, isProsess)
|
||||
cdl = []
|
||||
for i in cmd:
|
||||
e = True
|
||||
try:
|
||||
if (i[:i.index('#')].replace(' ', '') != '\n') and (i[:i.index('#')].replace(' ', '') != ''):
|
||||
cdl.append(i[:i.index('#')])
|
||||
e = False
|
||||
except ValueError:
|
||||
cdl.append(i)
|
||||
finally:
|
||||
if e is True:
|
||||
cdl.append(i)
|
||||
i = 0
|
||||
down = False
|
||||
blocks = [formCmdBlock(dire, cdl.pop(0), 1, 1)]
|
||||
dire[1] += 1
|
||||
for j in cdl:
|
||||
if dire[1] + i > height:
|
||||
dire[0] += 1
|
||||
i = 0
|
||||
down = not down
|
||||
if dire[1] + i == height:
|
||||
blocks.append(formCmdBlock([dire[0], dire[1] + i, dire[2]], j, 5, 2, False, False))
|
||||
else:
|
||||
if down:
|
||||
blocks.append(formCmdBlock([dire[0], dire[1] + i, dire[2]], j, 0, 2, False, False))
|
||||
else:
|
||||
blocks.append(formCmdBlock([dire[0], dire[1] + i, dire[2]], j, 1, 2, False, False))
|
||||
i += 1
|
||||
del i, cdl, down, cmd
|
||||
return BdxConverter(filePath, 'Build by RyounMusicreater', blocks)
|
||||
|
||||
|
||||
def note2webs(Notes: list, Instrument: str, speed: float = 5.0, PlayerSelect: str = '', isProsess: bool = False):
|
||||
"""传入音符,在oaclhost:8080上建立websocket服务器以供我的世界connect/wssever指令连接
|
||||
:param 参数说明:
|
||||
Notes: 以 list[ list[ float我的世界playsound指令音调 , float延续时常(单位s) ] ] 格式存储的音符列表
|
||||
例如Musicreater.py的(dataset[0]['musics'][NowMusic]['notes'])
|
||||
Instrument: 播放的乐器
|
||||
speed: 用于控制播放速度,数值越大,播放速度越快,相当于把一秒变为几拍
|
||||
PlayerSelect: 执行的玩家选择器
|
||||
isProsess: 是否显示进度条
|
||||
:return None"""
|
||||
|
||||
import time
|
||||
import fcwslib
|
||||
import asyncio
|
||||
from nmcsup.log import log
|
||||
from nmcsup.vers import VER
|
||||
|
||||
async def run_server(websocket): # , path
|
||||
log('服务器连接创建')
|
||||
await fcwslib.tellraw(websocket, '已连接服务器——音·创' + VER[1] + VER[0] + ' 作者:金羿(W-YI)')
|
||||
length = len(Notes)
|
||||
j = 1
|
||||
if isProsess:
|
||||
length = len(Notes)
|
||||
j = 1
|
||||
for i in range(len(Notes)):
|
||||
await fcwslib.send_command(websocket,
|
||||
f'execute @a{PlayerSelect} ~ ~ ~ playsound {Instrument} @s ~ ~ ~ 1000 {Notes[i][0]} 1000')
|
||||
if isProsess:
|
||||
fcwslib.send_command(websocket,
|
||||
'execute @a' + PlayerSelect + ' ~ ~ ~ title @s actionbar §e▶ 播放中: §a' + str(
|
||||
j) + '/' + str(length) + ' || ' + str(int(j / length * 1000) / 10))
|
||||
j += 1
|
||||
time.sleep(Notes[i][1] / speed)
|
||||
|
||||
fcwslib.run_server(run_server)
|
||||
|
||||
|
||||
def note2RSworld(world: str, startpos: list, notes: list, instrument: str, speed: float = 2.5,
|
||||
posadder: list = [1, 0, 0], baseblock: str = 'stone'): # -> bool
|
||||
"""传入音符,生成以音符盒存储的红石音乐
|
||||
:param 参数说明:
|
||||
world: 地图文件的路径
|
||||
startpos: list[int,int,int] 开始生成的坐标
|
||||
notes: list[list[float,float]] 以 list[ list[ float我的世界playsound指令音调 , float延续时常(单位s) ] ]
|
||||
格式存储的音符列表 例如Musicreater.py的dataset[0]['musics'][NowMusic]['notes']
|
||||
instrument: 播放的乐器
|
||||
speed: 一拍占多少个中继器延迟(红石刻/rt)
|
||||
posadder: list[int,int,int] 坐标增加规律,即红石的延长时按照此增加规律增加坐标
|
||||
baseblock: 在中继器下垫着啥方块呢~
|
||||
:return 是否生成成功
|
||||
"""
|
||||
|
||||
from msctspt.values import height2note, instuments
|
||||
|
||||
def formNoteBlock(note: int, instrument1: str = 'note.harp', powered: bool = False):
|
||||
"""生成音符盒方块
|
||||
:param powered:
|
||||
:param instrument1:
|
||||
:param note: 0~24
|
||||
:return Block()"""
|
||||
if powered:
|
||||
powered = 'true'
|
||||
else:
|
||||
powered = 'false'
|
||||
return Block('universal_minecraft', 'noteblock',
|
||||
{"instrument": ts(instrument1.replace("note.", '')), 'note': ts(str(note)),
|
||||
'powered': ts(powered)})
|
||||
|
||||
def formRepeater(delay: int, facing: str, locked: bool = False, powered: bool = False):
|
||||
"""生成中继器方块
|
||||
:param powered:
|
||||
:param locked:
|
||||
:param facing:
|
||||
:param delay: 1~4
|
||||
:return Block()"""
|
||||
if powered:
|
||||
powered = 'true'
|
||||
else:
|
||||
powered = 'false'
|
||||
if locked:
|
||||
locked = 'true'
|
||||
else:
|
||||
locked = 'false'
|
||||
return Block('universal_minecraft', 'repeater',
|
||||
{"delay": ts(str(delay)), 'facing': ts(facing), 'locked': ts(locked), 'powered': ts(powered)})
|
||||
|
||||
level = amulet.load_level(world)
|
||||
|
||||
def setblock(block: Block, pos: list):
|
||||
"""pos : list[int,int,int]"""
|
||||
cx, cz = bc2cc(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
|
||||
|
||||
# 1拍 x 2.5 rt
|
||||
def placeNoteBlock():
|
||||
for i in notes:
|
||||
error = True
|
||||
try:
|
||||
setblock(formNoteBlock(height2note[i[0]], instrument), [startpos[0], startpos[1] + 1, startpos[2]])
|
||||
setblock(Block("universal_minecraft", instuments[i[0]][1]), startpos)
|
||||
error = False
|
||||
except ValueError:
|
||||
log("无法放置音符:" + str(i) + '于' + str(startpos))
|
||||
setblock(Block("universal_minecraft", baseblock), startpos)
|
||||
setblock(Block("universal_minecraft", baseblock), [startpos[0], startpos[1] + 1, startpos[2]])
|
||||
finally:
|
||||
if error is True:
|
||||
log("无法放置音符:" + str(i) + '于' + str(startpos))
|
||||
setblock(Block("universal_minecraft", baseblock), startpos)
|
||||
setblock(Block("universal_minecraft", baseblock), [startpos[0], startpos[1] + 1, startpos[2]])
|
||||
delay = int(i[1] * speed + 0.5)
|
||||
if delay <= 4:
|
||||
startpos[0] += 1
|
||||
setblock(formRepeater(delay, 'west'), [startpos[0], startpos[1] + 1, startpos[2]])
|
||||
setblock(Block("universal_minecraft", baseblock), startpos)
|
||||
else:
|
||||
for j in range(int(delay / 4)):
|
||||
startpos[0] += 1
|
||||
setblock(formRepeater(4, 'west'), [startpos[0], startpos[1] + 1, startpos[2]])
|
||||
setblock(Block("universal_minecraft", baseblock), startpos)
|
||||
if delay % 4 != 0:
|
||||
startpos[0] += 1
|
||||
setblock(formRepeater(delay % 4, 'west'), [startpos[0], startpos[1] + 1, startpos[2]])
|
||||
setblock(Block("universal_minecraft", baseblock), startpos)
|
||||
startpos[0] += posadder[0]
|
||||
startpos[1] += posadder[1]
|
||||
startpos[2] += posadder[2]
|
||||
|
||||
e = True
|
||||
try:
|
||||
placeNoteBlock()
|
||||
e = False
|
||||
except ValueError:
|
||||
log("无法放置方块了,可能是因为区块未加载叭")
|
||||
finally:
|
||||
if e:
|
||||
log("无法放置方块了,可能是因为区块未加载叭")
|
||||
level.save()
|
||||
level.close()
|
||||
|
||||
|
||||
class ryStruct:
|
||||
|
||||
def __init__(self, world: str) -> None:
|
||||
|
||||
self.RyStruct = dict()
|
||||
self._world = world
|
||||
self._level = amulet.load_level(world)
|
||||
|
||||
def reloadLevel(self):
|
||||
e = True
|
||||
try:
|
||||
self._level = amulet.load_level(self.world)
|
||||
e = False
|
||||
except ValueError:
|
||||
log("无法重载地图")
|
||||
finally:
|
||||
if e:
|
||||
log("无法重载地图")
|
||||
|
||||
def closeLevel(self):
|
||||
e = True
|
||||
try:
|
||||
self._level.close()
|
||||
e = False
|
||||
except ValueError:
|
||||
log("无法关闭地图")
|
||||
finally:
|
||||
if e:
|
||||
log("无法重载地图")
|
||||
|
||||
def world2Rys(self, startp: list, endp: list, includeAir: bool = False):
|
||||
"""将世界转换为RyStruct字典,注意,此函数运行成功后将关闭地图,若要打开需要运行 reloadLevel
|
||||
:param startp: [x,y,z] 转化的起始坐标
|
||||
:param endp : [x,y,z] 转换的终止坐标,注意,终止坐标需要大于起始坐标,且最终结果包含终止坐标
|
||||
:param includeAir : bool = False 是否包含空气,即空气是否在生成之时覆盖地图内容
|
||||
:return dict RyStruct """
|
||||
|
||||
level = self._level
|
||||
|
||||
for x in range(startp[0], endp[0] + 1):
|
||||
for y in range(startp[1], endp[1] + 1):
|
||||
for z in range(startp[2], endp[2] + 1):
|
||||
|
||||
RyStructBlock = dict()
|
||||
|
||||
cx, cz = bc2cc(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 includeAir:
|
||||
continue
|
||||
universal_block_entity = chunk.block_entities.get((x, y, z), None)
|
||||
|
||||
RyStructBlock["block"] = str(universal_block)
|
||||
RyStructBlock["blockEntity"] = str(universal_block_entity)
|
||||
|
||||
log("载入方块数据" + str(RyStructBlock))
|
||||
|
||||
self.RyStruct[(x, y, z)] = RyStructBlock
|
||||
|
||||
level.close()
|
||||
|
||||
return self.RyStruct
|
||||
|
||||
|
||||
"""
|
||||
RyStruct = {
|
||||
(0,0,0) = {
|
||||
"block": str 完整的方块结构
|
||||
"blockEntity": str | 'None'
|
||||
}
|
||||
}
|
||||
"""
|
||||
"""音·创 的转换工具库"""
|
||||
|
||||
|
||||
# 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日
|
||||
# 统计:致命(三级)错误:0个;警告(二级)错误:4个--未解决1个;语法(一级)错误:302个
|
||||
|
||||
|
||||
import amulet
|
||||
from amulet.api.block import Block
|
||||
from amulet.utils.world_utils import block_coords_to_chunk_coords as bc2cc
|
||||
from amulet_nbt import TAG_String as ts
|
||||
from nmcsup.log import log
|
||||
|
||||
|
||||
def hans2pinyin(hans, style=3):
|
||||
"""将汉字字符串转化为拼音字符串"""
|
||||
from pypinyin import lazy_pinyin
|
||||
result = lazy_pinyin(hans=hans, style=style)
|
||||
final = ''
|
||||
for i in result:
|
||||
final += i
|
||||
return final
|
||||
|
||||
|
||||
def formCmdBlock(direction: list, command: str, particularValue: int, impluse: int, condition: bool = False,
|
||||
needRedstone: bool = True, tickDelay: int = 0, customName: str = '', lastOutput: str = '',
|
||||
executeOnFirstTick: bool = False, trackOutput: bool = True):
|
||||
"""
|
||||
使用指定项目返回指定的指令方块格式字典
|
||||
:param trackOutput:
|
||||
:param executeOnFirstTick:
|
||||
:param lastOutput:
|
||||
:param customName:
|
||||
:param tickDelay:
|
||||
:param needRedstone:
|
||||
:param condition:
|
||||
:param impluse:
|
||||
:param particularValue:
|
||||
:param command:
|
||||
:param direction:
|
||||
|
||||
:return: 指令方块字典结构
|
||||
"""
|
||||
"""
|
||||
:param block: {
|
||||
"direction": [x: int, y: int, z: int] #方块位置
|
||||
"block_name": str, #方块名称(无需指定,默认为command_block)
|
||||
"particular_value": int, #方块特殊值
|
||||
"impluse": int, #方块类型0脉冲 1循环 2连锁 unsigned_int32
|
||||
"command": str, #指令
|
||||
"customName": str, #悬浮字
|
||||
"lastOutput": str, #上次输出
|
||||
"tickdelay": int, #方块延时 int32
|
||||
"executeOnFirstTick": int, #执行第一个选项 1 bytes
|
||||
"trackOutput": int, #是否输出 1 bytes
|
||||
"conditional": int, #是否有条件 1 bytes
|
||||
"needRedstone": int #是否需要红石 1 bytes
|
||||
}
|
||||
"""
|
||||
return {"direction": direction,
|
||||
"block_name": "command_block",
|
||||
"particular_value": particularValue,
|
||||
"impluse": impluse,
|
||||
"command": command,
|
||||
"customName": customName,
|
||||
"lastOutput": lastOutput,
|
||||
"tickdelay": tickDelay,
|
||||
"executeOnFirstTick": executeOnFirstTick,
|
||||
"trackOutput": trackOutput,
|
||||
"conditional": condition,
|
||||
"needRedstone": needRedstone
|
||||
}
|
||||
|
||||
|
||||
def note2bdx(filePath: str, dire: list, Notes: list, ScoreboardName: str, Instrument: str, PlayerSelect: str = '',
|
||||
isProsess: bool = False, height: int = 200):
|
||||
"""使用方法同Note2Cmd
|
||||
:param 参数说明:
|
||||
filePath: 生成.bdx文件的位置
|
||||
dire: 指令方块在地图中生成的起始位置(相对位置)
|
||||
Notes: 以 list[ list[ float我的世界playsound指令音调 , float延续时常(单位s) ] ] 格式存储的音符列表
|
||||
例如Musicreater.py的(dataset[0]['musics'][NowMusic]['notes'])
|
||||
ScoreboardName: 用于执行的计分板名称
|
||||
Instrument: 播放的乐器
|
||||
PlayerSelect: 执行的玩家选择器
|
||||
isProsess: 是否显示进度条(会很卡)
|
||||
height: 生成结构的最高高度
|
||||
:return 返回一个BdxConverter类(实际上没研究过),同时在指定位置生成.bdx文件"""
|
||||
|
||||
# from msctspt.transfer import formCmdBlock
|
||||
from nmcsup.trans import Note2Cmd
|
||||
from msctspt.bdxOpera_CP import BdxConverter
|
||||
cmd = Note2Cmd(Notes, ScoreboardName, Instrument, PlayerSelect, isProsess)
|
||||
cdl = []
|
||||
for i in cmd:
|
||||
# e = True
|
||||
try:
|
||||
if (i[:i.index('#')].replace(' ', '') != '\n') and (i[:i.index('#')].replace(' ', '') != ''):
|
||||
cdl.append(i[:i.index('#')])
|
||||
# e = False
|
||||
except: # ValueError
|
||||
cdl.append(i)
|
||||
# finally:
|
||||
# if e is True:
|
||||
# cdl.append(i)
|
||||
i = 0
|
||||
down = False
|
||||
blocks = [formCmdBlock(dire, cdl.pop(0), 1, 1)]
|
||||
dire[1] += 1
|
||||
for j in cdl:
|
||||
if dire[1] + i > height:
|
||||
dire[0] += 1
|
||||
i = 0
|
||||
down = not down
|
||||
if dire[1] + i == height:
|
||||
blocks.append(formCmdBlock([dire[0], dire[1] + i, dire[2]], j, 5, 2, False, False))
|
||||
else:
|
||||
if down:
|
||||
blocks.append(formCmdBlock([dire[0], dire[1] + i, dire[2]], j, 0, 2, False, False))
|
||||
else:
|
||||
blocks.append(formCmdBlock([dire[0], dire[1] + i, dire[2]], j, 1, 2, False, False))
|
||||
i += 1
|
||||
del i, cdl, down, cmd
|
||||
return BdxConverter(filePath, 'Build by RyounMusicreater', blocks)
|
||||
|
||||
|
||||
def note2webs(Notes: list, Instrument: str, speed: float = 5.0, PlayerSelect: str = '', isProsess: bool = False):
|
||||
"""传入音符,在oaclhost:8080上建立websocket服务器以供我的世界connect/wssever指令连接
|
||||
:param 参数说明:
|
||||
Notes: 以 list[ list[ float我的世界playsound指令音调 , float延续时常(单位s) ] ] 格式存储的音符列表
|
||||
例如Musicreater.py的(dataset[0]['musics'][NowMusic]['notes'])
|
||||
Instrument: 播放的乐器
|
||||
speed: 用于控制播放速度,数值越大,播放速度越快,相当于把一秒变为几拍
|
||||
PlayerSelect: 执行的玩家选择器
|
||||
isProsess: 是否显示进度条
|
||||
:return None"""
|
||||
|
||||
import time
|
||||
import fcwslib
|
||||
# import asyncio
|
||||
from nmcsup.log import log
|
||||
from nmcsup.vers import VER
|
||||
|
||||
async def run_server(websocket): # , path
|
||||
log('服务器连接创建')
|
||||
await fcwslib.tellraw(websocket, '已连接服务器——音·创' + VER[1] + VER[0] + ' 作者:金羿(W-YI)')
|
||||
length = len(Notes)
|
||||
j = 1
|
||||
for i in range(len(Notes)):
|
||||
await fcwslib.send_command(websocket,
|
||||
f'execute @a{PlayerSelect} ~ ~ ~ playsound {Instrument} @s ~ ~ ~ 1000 '
|
||||
f'{Notes[i][0]} 1000')
|
||||
if isProsess:
|
||||
await fcwslib.send_command(websocket,
|
||||
'execute @a' + PlayerSelect + ' ~ ~ ~ title @s actionbar §e▶ 播放中: §a' +
|
||||
str(
|
||||
j) + '/' + str(length) + ' || ' + str(int(j / length * 1000) / 10))
|
||||
j += 1
|
||||
time.sleep(Notes[i][1] / speed)
|
||||
|
||||
fcwslib.run_server(run_server)
|
||||
|
||||
|
||||
def note2RSworld(world: str, startpos: list, notes: list, instrument: str, speed: float = 2.5,
|
||||
posadder: list = [1, 0, 0], baseblock: str = 'stone'): # -> bool
|
||||
"""传入音符,生成以音符盒存储的红石音乐
|
||||
:param 参数说明:
|
||||
world: 地图文件的路径
|
||||
startpos: list[int,int,int] 开始生成的坐标
|
||||
notes: list[list[float,float]] 以 list[ list[ float我的世界playsound指令音调 , float延续时常(单位s) ] ]
|
||||
格式存储的音符列表 例如Musicreater.py的dataset[0]['musics'][NowMusic]['notes']
|
||||
instrument: 播放的乐器
|
||||
speed: 一拍占多少个中继器延迟(红石刻/rt)
|
||||
posadder: list[int,int,int] 坐标增加规律,即红石的延长时按照此增加规律增加坐标
|
||||
baseblock: 在中继器下垫着啥方块呢~
|
||||
:return 是否生成成功
|
||||
"""
|
||||
|
||||
from msctspt.values import height2note, instuments
|
||||
|
||||
def formNoteBlock(note: int, instrument1: str = 'note.harp', powered: bool = False):
|
||||
"""生成音符盒方块
|
||||
:param powered:
|
||||
:param instrument1:
|
||||
:param note: 0~24
|
||||
:return Block()"""
|
||||
if powered:
|
||||
powered = 'true'
|
||||
else:
|
||||
powered = 'false'
|
||||
return Block('universal_minecraft', 'noteblock',
|
||||
{"instrument": ts(instrument1.replace("note.", '')), 'note': ts(str(note)),
|
||||
'powered': ts(powered)})
|
||||
|
||||
def formRepeater(delay: int, facing: str, locked: bool = False, powered: bool = False):
|
||||
"""生成中继器方块
|
||||
:param powered:
|
||||
:param locked:
|
||||
:param facing:
|
||||
:param delay: 1~4
|
||||
:return Block()"""
|
||||
if powered:
|
||||
powered = 'true'
|
||||
else:
|
||||
powered = 'false'
|
||||
if locked:
|
||||
locked = 'true'
|
||||
else:
|
||||
locked = 'false'
|
||||
return Block('universal_minecraft', 'repeater',
|
||||
{"delay": ts(str(delay)), 'facing': ts(facing), 'locked': ts(locked), 'powered': ts(powered)})
|
||||
|
||||
level = amulet.load_level(world)
|
||||
|
||||
def setblock(block: Block, pos: list):
|
||||
"""pos : list[int,int,int]"""
|
||||
cx, cz = bc2cc(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
|
||||
|
||||
# 1拍 x 2.5 rt
|
||||
def placeNoteBlock():
|
||||
for i in notes:
|
||||
error = True
|
||||
try:
|
||||
setblock(formNoteBlock(height2note[i[0]], instrument), [startpos[0], startpos[1] + 1, startpos[2]])
|
||||
setblock(Block("universal_minecraft", instuments[i[0]][1]), startpos)
|
||||
error = False
|
||||
except ValueError:
|
||||
log("无法放置音符:" + str(i) + '于' + str(startpos))
|
||||
setblock(Block("universal_minecraft", baseblock), startpos)
|
||||
setblock(Block("universal_minecraft", baseblock), [startpos[0], startpos[1] + 1, startpos[2]])
|
||||
finally:
|
||||
if error is True:
|
||||
log("无法放置音符:" + str(i) + '于' + str(startpos))
|
||||
setblock(Block("universal_minecraft", baseblock), startpos)
|
||||
setblock(Block("universal_minecraft", baseblock), [startpos[0], startpos[1] + 1, startpos[2]])
|
||||
delay = int(i[1] * speed + 0.5)
|
||||
if delay <= 4:
|
||||
startpos[0] += 1
|
||||
setblock(formRepeater(delay, 'west'), [startpos[0], startpos[1] + 1, startpos[2]])
|
||||
setblock(Block("universal_minecraft", baseblock), startpos)
|
||||
else:
|
||||
for j in range(int(delay / 4)):
|
||||
startpos[0] += 1
|
||||
setblock(formRepeater(4, 'west'), [startpos[0], startpos[1] + 1, startpos[2]])
|
||||
setblock(Block("universal_minecraft", baseblock), startpos)
|
||||
if delay % 4 != 0:
|
||||
startpos[0] += 1
|
||||
setblock(formRepeater(delay % 4, 'west'), [startpos[0], startpos[1] + 1, startpos[2]])
|
||||
setblock(Block("universal_minecraft", baseblock), startpos)
|
||||
startpos[0] += posadder[0]
|
||||
startpos[1] += posadder[1]
|
||||
startpos[2] += posadder[2]
|
||||
|
||||
# e = True
|
||||
try:
|
||||
placeNoteBlock()
|
||||
# e = False
|
||||
except: # ValueError
|
||||
log("无法放置方块了,可能是因为区块未加载叭")
|
||||
# finally:
|
||||
# if e:
|
||||
# log("无法放置方块了,可能是因为区块未加载叭")
|
||||
level.save()
|
||||
level.close()
|
||||
|
||||
|
||||
class ryStruct:
|
||||
|
||||
def __init__(self, world: str) -> None:
|
||||
|
||||
self.RyStruct = dict()
|
||||
self._world = world
|
||||
self._level = amulet.load_level(world)
|
||||
|
||||
def reloadLevel(self):
|
||||
# e = True
|
||||
try:
|
||||
self._level = amulet.load_level(self.world)
|
||||
# e = False
|
||||
except: # ValueError
|
||||
log("无法重载地图")
|
||||
# finally:
|
||||
# if e:
|
||||
# log("无法重载地图")
|
||||
|
||||
def closeLevel(self):
|
||||
# e = True
|
||||
try:
|
||||
self._level.close()
|
||||
# e = False
|
||||
except: # ValueError
|
||||
log("无法关闭地图")
|
||||
# finally:
|
||||
# if e:
|
||||
# log("无法重载地图")
|
||||
|
||||
def world2Rys(self, startp: list, endp: list, includeAir: bool = False):
|
||||
"""将世界转换为RyStruct字典,注意,此函数运行成功后将关闭地图,若要打开需要运行 reloadLevel
|
||||
:param startp: [x,y,z] 转化的起始坐标
|
||||
:param endp : [x,y,z] 转换的终止坐标,注意,终止坐标需要大于起始坐标,且最终结果包含终止坐标
|
||||
:param includeAir : bool = False 是否包含空气,即空气是否在生成之时覆盖地图内容
|
||||
:return dict RyStruct """
|
||||
|
||||
level = self._level
|
||||
|
||||
for x in range(startp[0], endp[0] + 1):
|
||||
for y in range(startp[1], endp[1] + 1):
|
||||
for z in range(startp[2], endp[2] + 1):
|
||||
|
||||
RyStructBlock = dict()
|
||||
|
||||
cx, cz = bc2cc(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 includeAir:
|
||||
continue
|
||||
universal_block_entity = chunk.block_entities.get((x, y, z), None)
|
||||
|
||||
RyStructBlock["block"] = str(universal_block)
|
||||
RyStructBlock["blockEntity"] = str(universal_block_entity)
|
||||
|
||||
log("载入方块数据" + str(RyStructBlock))
|
||||
|
||||
self.RyStruct[(x, y, z)] = RyStructBlock
|
||||
|
||||
level.close()
|
||||
|
||||
return self.RyStruct
|
||||
|
||||
|
||||
"""
|
||||
RyStruct = {
|
||||
(0,0,0) = {
|
||||
"block": str 完整的方块结构
|
||||
"blockEntity": str | 'None'
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
@ -1,56 +1,56 @@
|
||||
# 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日
|
||||
# 统计:致命(三级)错误:0个;警告(二级)错误:0个;语法(一级)错误:40个
|
||||
|
||||
instuments = {
|
||||
'note.banjo': ['班卓琴', 'hay_block'],
|
||||
'note.bass': ['贝斯', 'planks'],
|
||||
'note.bassattack': ['低音鼓/贝斯', 'log'],
|
||||
'note.bd': ['底鼓', 'stone'], # 即basedrum
|
||||
'note.bell': ['铃铛/钟琴', 'gold_block'],
|
||||
'note.bit': ['比特/“芯片”(方波)', 'emerald_block'],
|
||||
'note.chime': ['管钟', 'packed_ice'],
|
||||
'note.cow_bell': ['牛铃', 'soul_sand'],
|
||||
'note.didgeridoo': ['迪吉里杜管', 'pumpkin'],
|
||||
'note.flute': ['长笛', 'clay'],
|
||||
'note.guitar': ['吉他', 'wool'],
|
||||
'note.harp': ['竖琴/钢琴', 'concrete'], # 任意其他类型的方块皆可
|
||||
'note.hat': ['击鼓沿/架子鼓', 'glass'],
|
||||
'note.iron_xylophone': ['“铁木琴”(颤音琴)', 'iron_block'],
|
||||
'note.pling': ['“扣弦”(电钢琴)', 'glowstone'],
|
||||
'note.snare': ['小军鼓', 'sand'],
|
||||
'note.xylophone': ['木琴', 'bone_block']
|
||||
}
|
||||
'''乐器对照表\n
|
||||
乐器英文:[中文, 对应音符盒下方块名称]
|
||||
注:方块仅取一个'''
|
||||
|
||||
height2note = {
|
||||
0.5: 0,
|
||||
0.53: 1,
|
||||
0.56: 2,
|
||||
0.6: 3,
|
||||
0.63: 4,
|
||||
0.67: 5,
|
||||
0.7: 6,
|
||||
0.75: 7,
|
||||
0.8: 8,
|
||||
0.84: 9,
|
||||
0.9: 10,
|
||||
0.94: 11,
|
||||
1.0: 12,
|
||||
|
||||
1.05: 13,
|
||||
1.12: 14,
|
||||
1.2: 15,
|
||||
1.25: 16,
|
||||
1.33: 17,
|
||||
1.4: 18,
|
||||
1.5: 19,
|
||||
1.6: 20,
|
||||
1.7: 21,
|
||||
1.8: 22,
|
||||
1.9: 23,
|
||||
2.0: 24,
|
||||
}
|
||||
'''音高对照表\n
|
||||
MC音高:音符盒音调'''
|
||||
# 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日
|
||||
# 统计:致命(三级)错误:0个;警告(二级)错误:0个;语法(一级)错误:40个
|
||||
|
||||
instuments = {
|
||||
'note.banjo': ['班卓琴', 'hay_block'],
|
||||
'note.bass': ['贝斯', 'planks'],
|
||||
'note.bassattack': ['低音鼓/贝斯', 'log'],
|
||||
'note.bd': ['底鼓', 'stone'], # 即basedrum
|
||||
'note.bell': ['铃铛/钟琴', 'gold_block'],
|
||||
'note.bit': ['比特/“芯片”(方波)', 'emerald_block'],
|
||||
'note.chime': ['管钟', 'packed_ice'],
|
||||
'note.cow_bell': ['牛铃', 'soul_sand'],
|
||||
'note.didgeridoo': ['迪吉里杜管', 'pumpkin'],
|
||||
'note.flute': ['长笛', 'clay'],
|
||||
'note.guitar': ['吉他', 'wool'],
|
||||
'note.harp': ['竖琴/钢琴', 'concrete'], # 任意其他类型的方块皆可
|
||||
'note.hat': ['击鼓沿/架子鼓', 'glass'],
|
||||
'note.iron_xylophone': ['“铁木琴”(颤音琴)', 'iron_block'],
|
||||
'note.pling': ['“扣弦”(电钢琴)', 'glowstone'],
|
||||
'note.snare': ['小军鼓', 'sand'],
|
||||
'note.xylophone': ['木琴', 'bone_block']
|
||||
}
|
||||
'''乐器对照表\n
|
||||
乐器英文:[中文, 对应音符盒下方块名称]
|
||||
注:方块仅取一个'''
|
||||
|
||||
height2note = {
|
||||
0.5: 0,
|
||||
0.53: 1,
|
||||
0.56: 2,
|
||||
0.6: 3,
|
||||
0.63: 4,
|
||||
0.67: 5,
|
||||
0.7: 6,
|
||||
0.75: 7,
|
||||
0.8: 8,
|
||||
0.84: 9,
|
||||
0.9: 10,
|
||||
0.94: 11,
|
||||
1.0: 12,
|
||||
|
||||
1.05: 13,
|
||||
1.12: 14,
|
||||
1.2: 15,
|
||||
1.25: 16,
|
||||
1.33: 17,
|
||||
1.4: 18,
|
||||
1.5: 19,
|
||||
1.6: 20,
|
||||
1.7: 21,
|
||||
1.8: 22,
|
||||
1.9: 23,
|
||||
2.0: 24,
|
||||
}
|
||||
'''音高对照表\n
|
||||
MC音高:音符盒音调'''
|
||||
|
Reference in New Issue
Block a user