提交包模式的更新

This commit is contained in:
EillesWan 2022-04-05 23:43:03 +08:00
parent ae83f9c21e
commit 6cb5c9ba89
145 changed files with 234 additions and 8300 deletions

Binary file not shown.

View File

@ -1,221 +0,0 @@
# -*- coding: utf-8 -*-
# W-YI 金羿
# QQ 2647547478
# 音·创 开发交流群 861684859
# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com
# 版权所有 Team-Ryoun 金羿("Eilles Wan")
# 若需转载或借鉴 请附作者
"""
·创自动安装器 (Musicreater Auto Installer)
对音·创的自动安装提供支持的独立软件
Musicreater Auto Installer (·创自动安装器)
A software that used for installing Musicreater automatically
Copyright 2022 Team-Ryoun
Licensed under the Apache License, Version 2.0 (the 'License');
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an 'AS IS' BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
# 代码写的并非十分的漂亮还请大佬多多包涵本软件源代码依照Apache软件协议公开
# 下面为正文
from sys import platform
from platform import architecture
import urllib.request
import zipfile
from os import system as srun
from os import walk, rename, remove, path, chdir, listdir
from shutil import rmtree, move
if platform == "win32":
nowpath = __file__[: len(__file__) - __file__[len(__file__) :: -1].index('\\')]
if srun('python -V'):
print('\033[7m{}\033[0m'.format("正在下载python\nDownloading Python"))
try:
urllib.request.urlretrieve(
"https://www.python.org/ftp/python/3.8.10/python-3.8.10.exe"
if architecture()[0] == "32bit"
else "https://www.python.org/ftp/python/3.8.10/python-3.8.10-amd64.exe",
"./pythonInstaller.exe",
)
# urllib.request.urlretrieve("https://www.python.org/ftp/python/3.8.10/python-3.8.10.exe","./pythonInstaller.exe")
except Exception as E:
input(str(E) + "\n自动下载失败,按下回车取消")
exit()
print('正在安装python\nInstalling Python')
# open('install.bat','w').write(f'.\\pythonInstaller.exe /passive InstallAllUsers=0 TargetDir="{nowpath}python38" DefaultJustForMeTargetDir="{nowpath}python38" AssociateFiles=0 CompileAll=1 PrependPath=0 Shortcuts=0 Include_doc=0 Include_launcher=0 InstallLauncherAllUsers=0 Include_test=0 Include_tools=0')
srun(
f'.\\pythonInstaller.exe /passive InstallAllUsers=1 AssociateFiles=1 CompileAll=1 PrependPath=1 Shortcuts=1 Include_doc=0 Include_exe=1 Include_pip=1 Include_lib=1 Include_tcltk=1 Include_launcher=1 InstallLauncherAllUsers=1 Include_test=0 Include_tools=0'
)
remove('./pythonInstaller.exe')
# print('\033[7m{}\033[0m'.format("正在下载pip安装工具\nDownloading get-pip tool"))
# try:
# urllib.request.urlretrieve(
# "https://bootstrap.pypa.io/get-pip.py", "./python38/get-pip.py"
# )
# except Exception as E:
# input(str(E) + "\n自动下载失败按下回车取消")
# exit()
# print('\033[7m{}\033[0m'.format("正在下载pip\nDownloading pip"))
# chdir('./python38')
# srun(r'".\python.exe get-pip.py')
# print('\033[7m{}\033[0m'.format('正在安装pip\nInstalling pip'))
# for dire in listdir('./Lib/site-packages/'):
# move('./Lib/site-packages/'+dire,'./'+dire)
# print('\033[7m{}\033[0m'.format("完成!"))
# chdir('../')
try:
choseurl = int(
input(
'\033[7m{}\033[0m'.format(
"""请选择 音·创 下载源,默认为0
Please choose a download source of Musicreater(default 0)
[0] 私有服务器<暂无> | Private Server<Haven't been built>
[1] Gitee
[2] Github\n:"""
)
)
)
except Exception as E:
print('\033[7m{}\033[0m'.format(str(E) + "\n将使用默认源\nUsing default source"))
choseurl = 0
myurl = ""
Giteeurl = "https://gitee.com/EillesWan/Musicreater/repository/blazearchive/master.zip?Expires=1647771436&Signature=%2BkqLHwmvzScCd4cPQDP0LHLpqeZUxOrOv17QpRy%2FTzs%3D"
Githuburl = (
"https://codeload.github.com/EillesWan/Musicreater/zip/refs/heads/master"
)
url = (
myurl
if choseurl == 0
else Giteeurl
if choseurl == 1
else Githuburl
if choseurl == 2
else myurl
)
print('\033[7m{}\033[0m'.format("正在下载音·创\nDownloading Musicreater"))
try:
urllib.request.urlretrieve(url, "./master.zip")
except Exception as E:
input('\033[0{}\033[0m'.format(str(E) + "\n自动下载失败,按下回车取消"))
exit()
print('\033[7m{}\033[0m'.format("安装音·创\nInstalling Musicreater"))
zipfile.ZipFile("./master.zip", "r").extractall()
remove("./master.zip")
try:
rmtree("./Musicreater")
except:
pass
rename("./Musicreater-master/", "./Musicreater/")
elif platform == 'linux':
srun("sudo apt-get install python3")
srun("sudo apt-get install python3-pip")
srun("sudo apt-get install git")
try:
choseurl = int(
input(
'\033[0{}\033[0m'.format(
"""请选择 音·创 下载源,默认为1
Please choose a download source of Musicreater(default 1)
[1] Gitee
[2] Github\n:"""
)
)
)
except Exception as E:
print(str(E) + "\n将使用默认源\nUsing default source")
choseurl = 1
url = (
"https://gitee.com/EillesWan/Musicreater.git"
if choseurl == 1
else "https://github.com/EillesWan/Musicreater.git"
if choseurl == 2
else "https://gitee.com/EillesWan/Musicreater.git"
)
srun(f"sudo git clone {url}")
print('\033[7m{}\033[0m'.format("编译音·创\nCompiling Musicreater"))
if platform == "linux":
srun("python3 -O -m compileall -b ./Musicreater/")
elif platform == "win32":
srun("python -O -m compileall -b ./Musicreater/")
for parent, dirnames, filenames in walk("./Musicreater"):
for filename in filenames:
if filename[-3:] == ".py":
fn = path.join(parent, filename)
remove(fn)
print(f"删除文件 {fn}")
for dirname in dirnames:
if dirname == "__pycache__":
pn = path.join(parent, dirname)
rmtree(pn)
print(f"删除目录 {pn}")
print(
'\033[7m{}\033[0m'.format(
"""您可以开始使用音·创了
我们将在后台为您安装各项支持库
您可以运行Musicreater文件夹中的Musicreater.pyc文件来运行音·
You can use Musicreater now,
We will setup the libraries ineed for you in background,
You can now open Musicreater.PYC in the directory of ./Musicreater to run Musicreater
"""
)
)
if platform == "linux":
srun("python3 ./Musicreater/补全库.pyc")
elif platform == "win32":
srun("python ./Musicreater/补全库.pyc")

View File

@ -1,98 +0,0 @@
# -*- coding: utf-8 -*-
# W-YI 金羿
# QQ 2647547478
# 音·创 开发交流群 861684859
# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com
# 版权所有 Team-Ryoun 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray")
# 若需转载或借鉴 请附作者
"""
· (Musicreater)
一款免费开源的 我的世界基岩版 音乐制作软件
Musicreater (·)
A free opensource software which is used for creating all kinds of musics in Minecraft
Copyright 2022 Team-Ryoun
Licensed under the Apache License, Version 2.0 (the 'License');
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an 'AS IS' BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
# 代码写的并非十分的漂亮还请大佬多多包涵本软件源代码依照Apache软件协议公开
# 下面为正文
from msctspt.bugReporter import version
__ver__ = f'{version.version[1]} {version.version[0]}'
__author__ = '金羿Eilles'
from msctLib.display import *
from msctLib.function import *
from msctLib.data import uniteIO
hb = r''' __ __
/\ \/\ \
\ \ \_\ \ __ _____ _____ __ __
\ \ _ \ /'__`\ /\ '__`\ /\ '__`\ /\ \/\ \
\ \ \ \ \ /\ \L\.\_\ \ \L\ \\ \ \L\ \\ \ \_\ \
\ \_\ \_\\ \__/.\_\\ \ ,__/ \ \ ,__/ \/`____ \
\/_/\/_/ \/__/\/_/ \ \ \/ \ \ \/ `/___/> \
\ \_\ \ \_\ /\___/
\/_/ \/_/ \/__/
____ __ __ __
/\ _`\ __ /\ \__ /\ \ /\ \
\ \ \L\ \ /\_\ _ __ \ \ ,_\\ \ \___ \_\ \ __ __ __
\ \ _ <'\/\ \ /\`'__\\ \ \/ \ \ _ `\ /'_` \ /'__`\ /\ \/\ \
\ \ \L\ \\ \ \\ \ \/ \ \ \_ \ \ \ \ \ /\ \L\ \ /\ \L\.\_\ \ \_\ \
\ \____/ \ \_\\ \_\ \ \__\ \ \_\ \_\\ \___,_\\ \__/.\_\\/`____ \
\/___/ \/_/ \/_/ \/__/ \/_/\/_/ \/__,_ / \/__/\/_/ `/___/> \
/\___/
\/__/ '''
def __main__():
import datetime,time,random,os,sys,zhdate
if datetime.date.today().month == 4 and datetime.date.today().day == 3:
if sys.platform == 'win32':
os.system('color 4e')
os.system('cls')
for i in range(len(hb)):
print(hb[i], end='', flush=True)
time.sleep(random.random() * 0.001)
input("金羿 生日快乐!")
elif '三月初五' in zhdate.ZhDate.today().chinese():
input('缅怀先祖 祭祀忠勇 勿忘国耻 振兴中华')
else:
disp()
if __name__ == '__main__':
__main__()

File diff suppressed because it is too large Load Diff

114
README.md
View File

@ -17,13 +17,13 @@
简体中文🇨🇳 | [English🇬🇧](README_EN.md)
## 软件介绍🚀
## 介绍🚀
音·创 Musicreater 是一款免费开源的 **《我的世界:基岩版》** 音乐制作软件
欢迎加群:[861684859](https://jq.qq.com/?_wv=1027&k=hpeRxrYr)
**注意注意注意!!!本程序尚在测试与开发阶段,且代码重构未完成,请自行定夺使用。**
**此分支为音·创的包版本即便于其他软件使用的可被import版本**
## 软件作者✒
@ -33,86 +33,23 @@
## 软件架构🏢
软件采用 *Python* 作为第一语言目前还没有使用其他语言辅助。使用可更换的UI结构库即开发人员可以通过更换display.py文件随心所欲地切换UI库后期将支持插件自加载。
支持 Windows7+ 以及各个支持 Python3.6+ 的 Linux
***各位开发人员注意!!!多语言支持请使用函数`_`加载文字!!!如需补充,请在简体中文的语言文件(zh-CN.lang)中补充!!!***
这是一个简单的Python包
## 使用教程📕
### 安装教程
下载[音·创自动安装器](https://gitee.com/EillesWan/Musicreater/releases/v0.2.0.0-Delta),将其放在你希望安装音·创的位置,运行后将自动安装。
提示:下载源最好选择\"2 GitHub\"。
### 从源代码运行教程
#### Windows7+
0. [Gitee下载需要登陆](https://gitee.com/EillesWan/Musicreater)
[Github下载](https://github.com/EillesWan/Musicreater)本程序源代码
1. 安装Python 3.8.10
[下载64位Python安装包](https://www.python.org/ftp/python/3.8.10/python-3.8.10-amd64.exe)
[下载32位Python安装包](https://www.python.org/ftp/python/3.8.10/python-3.8.10.exe)
2. 以管理员身份运行 补全库.py :
- 点击 “开始” 菜单,搜索 `命令提示符`
- 右键点击 `命令提示符` 左键点击 “以管理员身份运行”
- 将 “补全库.py” 拖拽入开启的窗口,按下回车
3. 等待安装完成后,双击运行 Musicreater.py
#### Linux
0. 若你没有足够优秀的环境,推荐先在终端敲:
```bash
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install python3
sudo apt-get install python3-pip
sudo apt-get install git
```
1. 若你足够自信,该整的都整了,就在你想下载此程序的地方打开终端,敲:
```bash
sudo git clone https://gitee.com/EillesWan/Musicreater.git
cd Musicreater
python3 补全库.py
python3 Musicreater.py
```
### 使用说明
1. 直接运行就好
2. 后期会出详细的使用教程
3. 如果在使用过程中发现了bug拜托请上报给我详见下方联系方式
## 诸葛亮与八卦阵的关于羽音缭绕资源包应用地说明(不必要)📖
1. 首先!这里的提示是给想使用多音色资源包的人的,如果你想用就请下载 [神羽资源包(神羽自己的链接)](https://pan.baidu.com/s/11uoq5zwN7c3rX-98DqVpJg)提取码:ek3t
2. 下载到你自己电脑上某个位置,可以不放置于本项目下。音色资源包较大,可以选取只下载:
`神羽资源包_乐器、音源的资源包\羽音缭绕-midiout_25.0` 这个文件夹,再嫌麻烦的话,也可以只下载其中的:
`神羽资源包_乐器\音源的资源包\羽音缭绕-midiout_25.0\mcpack(国际版推荐)格式_25.0` 或者:
`神羽资源包_乐器\音源的资源包\羽音缭绕-midiout_25.0\zip格式_25.0`
4. 接下来就是关键了:在*音创*中绑定资源包
首先,先打开 *音创*->帮助与疑问->\[神羽资源包位置选择\]:选择文件夹... 这时候,会跳出选择框
关键来了,选择:***您下载的`羽音缭绕-midiout_25.0`文件夹,或者`mcpack(国际版推荐)格式_25.0`或`zip格式_25.0`的上级目录***
举个例子:我的文件路径是这样的:
`L:\shenyu\音源的资源包\羽音缭绕-midiout_25.0`这里面有:`神羽资源包_25.0_使用方法.xls`、
`mcpack(国际版推荐)格式_25.0`、`zip格式_25.0`两个文件夹和一个.xls文件而你在音创中
也应该选择这个文件夹:**L:\shenyu\音源的资源包\羽音缭绕-midiout_25.0**
6. 如果你想使用音色资源包来制作函数,那么解析时你应该用 *音创*->编辑->从midi导入音轨且用新方法解析
然后再使用 *音创*->函数(包)->下面的四个新函数
> 正在到来
## 致谢🙏
1. 感谢由 [Fuckcraft](https://github.com/fuckcraft) “鸣凤鸽子”等 带来的我的世界websocket服务器功能
2. 感谢 昀梦\<QQ1515399885\> 找出指令生成错误bug并指正
3. 感谢由 Charlie_Ping “查理平” 带来的bdx转换功能
4. 感谢由 CMA_2401PT 带来的 BDXWorkShop 供本程序对于bdx操作的指导
5. 感谢由 Miracle Plume “神羽” \<QQshenyu40403\>带来的羽音缭绕基岩版音色资源包
6. 感谢 Arthur Morgan 对本程序的排错提出了最大的支持
7. 感谢广大群友为此程序提供的测试等支持
8. 若您对我们有所贡献但您的名字没有显示在此列表中,请联系我!
- 感谢由 [Fuckcraft](https://github.com/fuckcraft) “鸣凤鸽子”等 带来的我的世界websocket服务器功能
- 感谢 昀梦\<QQ1515399885\> 找出指令生成错误bug并指正
- 感谢由 Charlie_Ping “查理平” 带来的bdx转换功能
- 感谢由 CMA_2401PT 带来的 BDXWorkShop 供本程序对于bdx操作的指导
- 感谢由 Miracle Plume “神羽” \<QQshenyu40403\>带来的羽音缭绕基岩版音色资源包
- 感谢由 Dislink Sforza \<QQ1600515314\>带来的midi转换算法我们将其加入了我们众多算法之一
- 感谢 Arthur Morgan 对本程序的排错提出了最大的支持
- 感谢广大群友为此程序提供的测试等支持
- 若您对我们有所贡献但您的名字没有显示在此列表中,请联系我!
## 联系我们📞
@ -126,31 +63,6 @@ python3 Musicreater.py
1. QQ 4740437765
## 待办事项
* - [x] 可以使用由神羽提供的音乐资源包
* - [x] 支持多语言
* - [x] 支持创建可被Fastbuilder导入的.BDX文件支持
* - [ ] 1.可以导出自定义的结构文件用于存储要导入地图中的结构
* - [ ] 2.进度条
* - [ ] 3.可以将音乐写入音符盒(红乐)
* - [ ] 4.修改UI界面使之适应当前功能
* - [ ] 5.支持自动给音符盒绑定更多的音色
* - [ ] 6.可以由.schematic文件导入地图亦可反向处理
* - [x] 7.制作软件下载器使用户更直观地操作
* - [x] 8.支持自定义创建websockeet服务器播放音乐
* - [ ] 9.支持使用红石播放音乐
* - [ ] 10.支持采用延时的播放器
* - [ ] 11.支持使用bdx导出结构
* - [ ] 12.支持采用tp的方法播放
* - [ ] 13.支持识别曲谱(简谱)图片解析音乐
* - [ ] 14.支持使用瀑布流的方式播放音乐
* - [ ] 15.支持读入Everyone Piano的曲谱文件.eop
* - [ ] 16.支持读入Musescore的通用曲谱文件即musicXML.mscz、.mscx
* - [ ] 17.支持自动搜寻地图目录位置(网易&微软)
* - [ ] 18.支持读入JPword曲谱文件.jpd
* - [ ] 19.新的UI设计以及UI主题文件
* - [ ] 20.以小节为单位做音符播放时间对标
[Bilibili: 凌云金羿]: https://img.shields.io/badge/Bilibili-%E5%87%8C%E4%BA%91%E9%87%91%E7%BE%BF-00A1E7?style=for-the-badge

View File

@ -25,7 +25,7 @@ Musicreater(音·创) is an free open source software which is used for making a
Welcome to join our QQ group: [861684859](https://jq.qq.com/?_wv=1027&k=hpeRxrYr)
**ATTENTION!** This software is under testing and developing, there is still a lot of bugs needed to be fixed. Please use it wisely.
>>>>>
### Authors✒
@ -35,86 +35,24 @@ bgArray "诸葛亮与八卦阵": Fix bugs, improve code aesthetics, add new func
### Framework🏢
Developed under *Python3.8 3.9*. However, theoretically support Python3.6+.
Support Windows7+ && Linux (that supports Python3.6+)
***ATTENTION TO DEVELOPERS!!! TO SUPPORT DIFFERENT LANGUAGES, PLEASE USE FUNCTION(METHOD) `_` TO LOAD TEXTs!!! IF YOU NEED TO SUPPLEMENT, PLEASE ADD THEM IN SIMPLEFIED CHINESE\'S LANGUAGE FILE(zh-CN.lang), WHEATHER WHAT LANGUAGE YOU USE!!!***
>>>>>
## Instructions📕
### Installation
Download the *[MSCT Auto Installer](https://github.com/EillesWan/Musicreater/releases/tag/v0.2.0.0-Delta)*, put it in a directory that you want to install *Musicreater* into. Then run the auto installer and it will help you to install the *Musicreator* as well as Python3.8(if you haven\'t install it)
Tips: You'd better choose the \"2 GitHub\" download source
### Run with Source Code
#### Windows7+
0. First, download the source code pack of Musicreater.
[Download from Gitee (Need to Login)](https://gitee.com/EillesWan/Musicreater/repository/archive/master.zip)
[Download from Github](https://github.com/EillesWan/Musicreater/archive/refs/heads/master.zip)
1. Install Python 3.8.10
[Download the 64-bit Python Installer](https://www.python.org/ftp/python/3.8.10/python-3.8.10-amd64.exe)
[Download the 32-bit Python Installer](https://www.python.org/ftp/python/3.8.10/python-3.8.10.exe)
2. After completing installation, we need to install the libraries :
- Open "Start Menu" and find `cmd`
- Run `cmd` as Administrator
- Drag "补全库.py" into the opened window and press Enter
3. After completing installationdouble click Musicreater.py to run
#### Linux
0. If you 're not sure whether your environment is good enough, please run these commands on Terminal
```bash
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install python3
sudo apt-get install python3-pip
sudo apt-get install git
```
1. Now if you are confident enough about your runtime environment, open Terminal on the place which you want to download Musicreater, and run these
```bash
sudo git clone https://gitee.com/EillesWan/Musicreater.git
cd Musicreater
python3 补全库.py
python3 Musicreater.py
```
### Instructions of Using
1. Just run Musicreater.pyc(or .py) if you have installed well
2. Detailed instructions is coming soon
3. If you find a bug, could you please report it to me? My contact info is right below.
## Explanation of the use of *PlumeAudioSurrounding Resource Pack* by bgArray (unnecessary)📖
1. First! The tips here are for those who want to use the multi tone resource package, [Shenyu resource package (Shenyu's own link)](https://pan.baidu.com/s/11uoq5zwN7c3rX-98DqVpJg) \(Extraction code: `ek3t`\)
2. Download it to any location on your PC. Note that it does ***not*** need to be placed in the directory where *Musicreater* are. The audio resource package is large, so you can choose to download only:`神羽资源包_乐器、音源的资源包\羽音缭绕-midiout_25.0`.
Also, you can download only `神羽资源包_乐器\音源的资源包\羽音缭绕-midiout_25.0\mcpack(国际版推荐)格式_25.0` or
`神羽资源包_乐器\音源的资源包\羽音缭绕-midiout_25.0\zip格式_25.0`.
4. The next step is the most IMPORTANT: to bind the resource package to *Musicreater*
First, open *Musicreater*->Q&A->Select \[MiraclePlumeResourcePack\]... .At this time, in the selection box,
the IMPORTANT step comes, select: ***The directory you downloaded: `羽音缭绕-midiout_25.0`, or also the parent directory `mcpack(国际版推荐)格式_25.0`or`zip格式_25.0`***
For example, my file path is as follows:
`L:\shenyu\音源的资源包\羽音缭绕-midiout_25.0` and in the directory, there are two folders and one .xls file:
`神羽资源包_25.0_使用方法.xls`, `mcpack(国际版推荐)格式_25.0` and `zip格式_25.0`, so in *Musicreater* you should also select this folder: **L:\shenyu\音源的资源包\羽音缭绕-midiout_25.0**
6. If you want to use the Miracle Plume Bedrock Edition Audio Resource Pack to make .mcfunction s, you should use Musicreater -> Edit - > Import audio tracks from MIDI and parse them with a new method, and then use it
Musicreater - > function (package) - > the following four new functions
>>>>>
## Thanks🙏
1. Thank [Fuckcraft](https://github.com/fuckcraft) *(“鸣凤鸽子” ,etc)* for the function of Creating the Websocket Server for Minecraft: Bedrock Edition.
Thank [Fuckcraft](https://github.com/fuckcraft) *(“鸣凤鸽子” ,etc)* for the function of Creating the Websocket Server for Minecraft: Bedrock Edition.
- *!! They have given me the rights to directly copy the lib into Musicreater*
2. Thank *昀梦*\<QQ1515399885\> for finding and correcting the bugs in the commands that *Musicreater* Created.
3. Thank *Charlie_Ping “查理平”* for bdx convert funtion.
4. Thank *CMA_2401PT* for BDXWorkShop as the .bdx structure's operation guide.
5. Thank *Miracle Plume “神羽”* \<QQshenyu40403\> for the Miracle Plume Bedrock Edition Audio Resource Pack
6. Thank *Arthur Morgan* for his/her biggest support for the debugging of Musicreater
7. Thanks for a lot of groupmates who support me and help me to test the program.
8. If you have give me some help but u haven't been in the list, please contact me.
Thank *昀梦*\<QQ1515399885\> for finding and correcting the bugs in the commands that *Musicreater* Created.
Thank *Charlie_Ping “查理平”* for bdx convert funtion.
Thank *CMA_2401PT* for BDXWorkShop as the .bdx structure's operation guide.
Thank *Miracle Plume “神羽”* \<QQshenyu40403\> for the Miracle Plume Bedrock Edition Audio Resource Pack
感谢由 Dislink Sforza \<QQ1600515314\>带来的midi转换算法我们将其加入了我们众多算法之一
Thank *Arthur Morgan* for his/her biggest support for the debugging of Musicreater
Thanks for a lot of groupmates who support me and help me to test the program.
If you have give me some help but u haven't been in the list, please contact me.
## Contact Information📞
@ -130,8 +68,6 @@ Musicreater - > function (package) - > the following four new functions
[Bilibili: Eilles]: https://img.shields.io/badge/Bilibili-%E5%87%8C%E4%BA%91%E9%87%91%E7%BE%BF-00A1E7?style=for-the-badge
[Bilibili: bgArray]: https://img.shields.io/badge/Bilibili-%E8%AF%B8%E8%91%9B%E4%BA%AE%E4%B8%8E%E5%85%AB%E5%8D%A6%E9%98%B5-00A1E7?style=for-the-badge
[CodeStyle: black]: https://img.shields.io/badge/code%20style-black-121110.svg?style=for-the-badge

31
__init__.py Normal file
View File

@ -0,0 +1,31 @@
#-*- coding:utf-8 -*-
'''一个简单的基于音·创的我的世界音频操作工具'''
__version__ = '0.0.1'
__all__ = []
__author__ = (('金羿','Eilles Wan'),('诸葛亮与八卦阵','bgArray'),('鸣凤鸽子','MingFengPigeon'))
"""
Copyright © 2022 Team-Ryoun
Licensed under the Apache License, Version 2.0 (the 'License');
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an 'AS IS' BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
print('此工具由凌天之云创新团队开发,版权归本团队参与开发的人员共同所有。')
print('This tool is developed by Team-Ryoun, copyright belongs to the team members who developed the tool.')
from main import *

Binary file not shown.

Binary file not shown.

View File

View File

@ -1,67 +0,0 @@
import mido
import numpy
'''
bpm
bites per minutes
每分钟的拍数
'''
def mt2gt(mt, tpb_a, bpm_a):
return round(mt / tpb_a / bpm_a * 60)
def get(mid:mido.MidiFile) -> int:
'''传入一个 MidiFile, 返回其音乐的bpm
:param mid : mido.MidFile
mido库识别的midi文件数据
:return bpm : int
'''
# mid = mido.MidiFile(mf)
long = mid.length
tpb = mid.ticks_per_beat
bpm = 20
gotV = 0
for track in mid.tracks:
global_time = 0
for msg in track:
global_time += msg.time
if msg.type == "note_on" and msg.velocity > 0:
gotV = mt2gt(global_time, tpb, bpm)
errorV = numpy.fabs(gotV - long)
last_dic = {bpm: errorV}
if last_dic.get(bpm) > errorV:
last_dic = {bpm: errorV}
bpm += 2
while True:
for track in mid.tracks:
global_time = 0
for msg in track:
global_time += msg.time
if msg.type == "note_on" and msg.velocity > 0:
gotV = mt2gt(global_time, tpb, bpm)
errorV = numpy.fabs(gotV - long)
try:
if last_dic.get(bpm - 2) > errorV:
last_dic = {bpm: errorV}
except TypeError:
pass
bpm += 2
if bpm >= 252:
break
print(list(last_dic.keys())[0])
return list(last_dic.keys())[0]
def compute(mid:mido.MidiFile):
answer = 60000000/mid.ticks_per_beat
print(answer)
return answer
if __name__ == '__main__':
mid = mido.MidiFile(r"C:\Users\lc\Documents\MuseScore3\乐谱\乐谱\Bad style - Time back.mid")
get(mid)
compute(mid)

View File

@ -1,40 +0,0 @@
def round_up(num, power=0):
"""
实现精确四舍五入包含正负小数多种场景
:param num: 需要四舍五入的小数
:param power: 四舍五入位数支持0-
:return: 返回四舍五入后的结果
"""
try:
print(1 / 0)
except ZeroDivisionError:
digit = 10 ** power
num2 = float(int(num * digit))
# 处理正数power不为0的情况
if num >= 0 and power != 0:
tag = num * digit - num2 + 1 / (digit * 10)
if tag >= 0.5:
return (num2 + 1) / digit
else:
return num2 / digit
# 处理正数power为0取整的情况
elif num >= 0 and power == 0:
tag = num * digit - int(num)
if tag >= 0.5:
return (num2 + 1) / digit
else:
return num2 / digit
# 处理负数power为0取整的情况
elif power == 0 and num < 0:
tag = num * digit - int(num)
if tag <= -0.5:
return (num2 - 1) / digit
else:
return num2 / digit
# 处理负数power不为0的情况
else:
tag = num * digit - num2 - 1 / (digit * 10)
if tag <= -0.5:
return (num2 - 1) / digit
else:
return num2 / digit

View File

@ -1,24 +0,0 @@
instrument_list = {'0': 'harp', '1': 'harp', '2': 'pling', '3': 'harp', '4': 'pling', '5': 'pling', '6': 'harp',
'7': 'harp',
'8': 'share', '9': 'harp', '10': 'didgeridoo', '11': 'harp', '12': 'xylophone', '13': 'chime',
'14': 'harp', '15': 'harp', '16': 'bass', '17': 'harp', '18': 'harp', '19': 'harp', '20': 'harp',
'21': 'harp', '22': 'harp', '23': 'guitar', '24': 'guitar', '25': 'guitar', '26': 'guitar',
'27': 'guitar', '28': 'guitar', '29': 'guitar', '30': 'guitar', '31': 'bass', '32': 'bass',
'33': 'bass',
'34': 'bass', '35': 'bass', '36': 'bass', '37': 'bass', '38': 'bass', '39': 'bass', '40': 'harp',
'41': 'harp', '42': 'harp', '43': 'harp', '44': 'iron_xylophone', '45': 'guitar', '46': 'harp',
'47': 'harp', '48': 'guitar', '49': 'guitar', '50': 'bit', '51': 'bit', '52': 'harp', '53': 'harp',
'54': 'bit', '55': 'flute', '56': 'flute', '57': 'flute', '58': 'flute', '59': 'flute',
'60': 'flute',
'61': 'flute', '62': 'flute', '63': 'flute', '64': 'bit', '65': 'bit', '66': 'bit', '67': 'bit',
'68': 'flute', '69': 'harp', '70': 'harp', '71': 'flute', '72': 'flute', '73': 'flute', '74': 'harp',
'75': 'flute', '76': 'harp', '77': 'harp', '78': 'harp', '79': 'harp', '80': 'bit', '81': 'bit',
'82': 'bit', '83': 'bit', '84': 'bit', '85': 'bit', '86': 'bit', '87': 'bit', '88': 'bit',
'89': 'bit',
'90': 'bit', '91': 'bit', '92': 'bit', '93': 'bit', '94': 'bit', '95': 'bit', '96': 'bit',
'97': 'bit',
'98': 'bit', '99': 'bit', '100': 'bit', '101': 'bit', '102': 'bit', '103': 'bit', '104': 'harp',
'105': 'banjo', '106': 'harp', '107': 'harp', '108': 'harp', '109': 'harp', '110': 'harp',
'111': 'guitar', '112': 'harp', '113': 'bell', '114': 'harp', '115': 'cow_bell', '116': 'basedrum',
'117': 'bass', '118': 'bit', '119': 'basedrum', '120': 'guitar', '121': 'harp', '122': 'harp',
'123': 'harp', '124': 'harp', '125': 'hat', '126': 'basedrum', '127': 'snare'}

View File

@ -1,92 +0,0 @@
zip_name = {-1: '-1.Acoustic_Kit_打击乐.zip', 0: '0.Acoustic_Grand_Piano_大钢琴.zip', 1: '1.Bright_Acoustic_Piano_亮音大钢琴.zip',
10: '10.Music_Box_八音盒.zip', 100: '100.FX_brightness_合成特效-亮音.zip', 101: '101.FX_goblins_合成特效-小妖.zip',
102: '102.FX_echoes_合成特效-回声.zip', 103: '103.FX_sci-fi_合成特效-科幻.zip', 104: '104.Sitar_锡塔尔.zip',
105: '105.Banjo_班卓.zip', 106: '106.Shamisen_三味线.zip', 107: '107.Koto_筝.zip', 108: '108.Kalimba_卡林巴.zip',
109: '109.Bagpipe_风笛.zip', 11: '11.Vibraphone_电颤琴.zip', 110: '110.Fiddle_古提琴.zip', 111: '111.Shanai_唢呐.zip',
112: '112.Tinkle_Bell_铃铛.zip', 113: '113.Agogo_拉丁打铃.zip', 114: '114.Steel_Drums_钢鼓.zip',
115: '115.Woodblock_木块.zip', 116: '116.Taiko_Drum_太鼓.zip', 117: '117.Melodic_Tom_嗵鼓.zip',
118: '118.Synth_Drum_合成鼓.zip', 119: '119.Reverse_Cymbal_镲波形反转.zip', 12: '12.Marimba_马林巴.zip',
13: '13.Xylophone_木琴.zip', 14: '14.Tubular_Bells_管钟.zip', 15: '15.Dulcimer_扬琴.zip',
16: '16.Drawbar_Organ_击杆风琴.zip', 17: '17.Percussive_Organ_打击型风琴.zip', 18: '18.Rock_Organ_摇滚风琴.zip',
19: '19.Church_Organ_管风琴.zip', 2: '2.Electric_Grand_Piano_电子大钢琴.zip', 20: '20.Reed_Organ_簧风琴.zip',
21: '21.Accordion_手风琴.zip', 22: '22.Harmonica_口琴.zip', 23: '23.Tango_Accordian_探戈手风琴.zip',
24: '24.Acoustic_Guitar_(nylon)_尼龙弦吉他.zip', 25: '25.Acoustic_Guitar(steel)_钢弦吉他.zip',
26: '26.Electric_Guitar_(jazz)_爵士乐电吉他.zip', 27: '27.Electric_Guitar_(clean)_清音电吉他.zip',
28: '28.Electric_Guitar_(muted)_弱音电吉他.zip', 29: '29.Overdriven_Guitar_驱动音效吉他.zip',
3: '3.Honky-Tonk_Piano_酒吧钢琴.zip', 30: '30.Distortion_Guitar_失真音效吉他.zip', 31: '31.Guitar_Harmonics_吉他泛音.zip',
32: '32.Acoustic_Bass_原声贝司.zip', 33: '33.Electric_Bass(finger)_指拨电贝司.zip',
34: '34.Electric_Bass(pick)_拨片拨电贝司.zip', 35: '35.Fretless_Bass_无品贝司.zip', 36: '36.Slap_Bass_A_击弦贝司A.zip',
37: '37.Slap_Bass_B_击弦贝司B.zip', 38: '38.Synth_Bass_A_合成贝司A.zip', 39: '39.Synth_Bass_B_合成贝司B.zip',
4: '4.Electric_Piano_1_电钢琴A.zip', 40: '40.Violin_小提琴.zip', 41: '41.Viola_中提琴.zip', 42: '42.Cello_大提琴.zip',
43: '43.Contrabass_低音提琴.zip', 44: '44.Tremolo_Strings_弦乐震音.zip', 45: '45.Pizzicato_Strings_弦乐拨奏.zip',
46: '46.Orchestral_Harp_竖琴.zip', 47: '47.Timpani_定音鼓.zip', 48: '48.String_Ensemble_A_弦乐合奏A.zip',
49: '49.String_Ensemble_B_弦乐合奏B.zip', 5: '5.Electric_Piano_2_电钢琴B.zip', 50: '50.SynthStrings_A_合成弦乐A.zip',
51: '51.SynthStrings_B_合成弦乐B.zip', 52: '52.Choir_Aahs_合唱“啊”音.zip', 53: '53.Voice_Oohs_人声“哦”音.zip',
54: '54.Synth_Voice_合成人声.zip', 55: '55.Orchestra_Hit_乐队打击乐.zip', 56: '56.Trumpet_小号.zip',
57: '57.Trombone_长号.zip', 58: '58.Tuba_大号.zip', 59: '59.Muted_Trumpet_弱音小号.zip',
6: '6.Harpsichord_拨弦古钢琴.zip', 60: '60.French_Horn_圆号.zip', 61: '61.Brass_Section_铜管组.zip',
62: '62.Synth_Brass_A_合成铜管A.zip', 63: '63.Synth_Brass_A_合成铜管B.zip', 64: '64.Soprano_Sax_高音萨克斯.zip',
65: '65.Alto_Sax_中音萨克斯.zip', 66: '66.Tenor_Sax_次中音萨克斯.zip', 67: '67.Baritone_Sax_上低音萨克斯.zip',
68: '68.Oboe_双簧管.zip', 69: '69.English_Horn_英国管.zip', 7: '7.Clavinet_击弦古钢琴.zip', 70: '70.Bassoon_大管.zip',
71: '71.Clarinet_单簧管.zip', 72: '72.Piccolo_短笛.zip', 73: '73.Flute_长笛.zip', 74: '74.Recorder_竖笛.zip',
75: '75.Pan_Flute_排笛.zip', 76: '76.Bottle_Blow_吹瓶口.zip', 77: '77.Skakuhachi_尺八.zip', 78: '78.Whistle_哨.zip',
79: '79.Ocarina_洋埙.zip', 8: '8.Celesta_钢片琴.zip', 80: '80.Lead_square_合成主音-方波.zip',
81: '81.Lead_sawtooth_合成主音-锯齿波.zip', 82: '82.Lead_calliope_lead_合成主音-汽笛风琴.zip',
83: '83.Lead_chiff_lead_合成主音-吹管.zip', 84: '84.Lead_charang_合成主音5-吉他.zip', 85: '85.Lead_voice_合成主音-人声.zip',
86: '86.Lead_fifths_合成主音-五度.zip', 87: '87.Lead_bass+lead_合成主音-低音加主音.zip', 88: '88.Pad_new_age_合成柔音-新时代.zip',
89: '89.Pad_warm_合成柔音-暖音.zip', 9: '9.Glockenspiel_钟琴.zip', 90: '90.Pad_polysynth_合成柔音-复合成.zip',
91: '91.Pad_choir_合成柔音-合唱.zip', 92: '92.Pad_bowed_合成柔音-弓弦.zip', 93: '93.Pad_metallic_合成柔音-金属.zip',
94: '94.Pad_halo_合成柔音-光环.zip', 95: '95.Pad_sweep_合成柔音-扫弦.zip', 96: '96.FX_rain_合成特效-雨.zip',
97: '97.FX_soundtrack_合成特效-音轨.zip', 98: '98.FX_crystal_合成特效-水晶.zip', 99: '99.FX_atmosphere_合成特效-大气.zip'}
mcpack_name = {-1: '-1.Acoustic_Kit_打击乐.mcpack', 0: '0.Acoustic_Grand_Piano_大钢琴.mcpack',
1: '1.Bright_Acoustic_Piano_亮音大钢琴.mcpack', 10: '10.Music_Box_八音盒.mcpack',
100: '100.FX_brightness_合成特效-亮音.mcpack', 101: '101.FX_goblins_合成特效-小妖.mcpack',
102: '102.FX_echoes_合成特效-回声.mcpack', 103: '103.FX_sci-fi_合成特效-科幻.mcpack', 104: '104.Sitar_锡塔尔.mcpack',
105: '105.Banjo_班卓.mcpack', 106: '106.Shamisen_三味线.mcpack', 107: '107.Koto_筝.mcpack',
108: '108.Kalimba_卡林巴.mcpack', 109: '109.Bagpipe_风笛.mcpack', 11: '11.Vibraphone_电颤琴.mcpack',
110: '110.Fiddle_古提琴.mcpack', 111: '111.Shanai_唢呐.mcpack', 112: '112.Tinkle_Bell_铃铛.mcpack',
113: '113.Agogo_拉丁打铃.mcpack', 114: '114.Steel_Drums_钢鼓.mcpack', 115: '115.Woodblock_木块.mcpack',
116: '116.Taiko_Drum_太鼓.mcpack', 117: '117.Melodic_Tom_嗵鼓.mcpack', 118: '118.Synth_Drum_合成鼓.mcpack',
119: '119.Reverse_Cymbal_镲波形反转.mcpack', 12: '12.Marimba_马林巴.mcpack', 13: '13.Xylophone_木琴.mcpack',
14: '14.Tubular_Bells_管钟.mcpack', 15: '15.Dulcimer_扬琴.mcpack', 16: '16.Drawbar_Organ_击杆风琴.mcpack',
17: '17.Percussive_Organ_打击型风琴.mcpack', 18: '18.Rock_Organ_摇滚风琴.mcpack',
19: '19.Church_Organ_管风琴.mcpack', 2: '2.Electric_Grand_Piano_电子大钢琴.mcpack',
20: '20.Reed_Organ_簧风琴.mcpack', 21: '21.Accordion_手风琴.mcpack', 22: '22.Harmonica_口琴.mcpack',
23: '23.Tango_Accordian_探戈手风琴.mcpack', 24: '24.Acoustic_Guitar_(nylon)_尼龙弦吉他.mcpack',
25: '25.Acoustic_Guitar(steel)_钢弦吉他.mcpack', 26: '26.Electric_Guitar_(jazz)_爵士乐电吉他.mcpack',
27: '27.Electric_Guitar_(clean)_清音电吉他.mcpack', 28: '28.Electric_Guitar_(muted)_弱音电吉他.mcpack',
29: '29.Overdriven_Guitar_驱动音效吉他.mcpack', 3: '3.Honky-Tonk_Piano_酒吧钢琴.mcpack',
30: '30.Distortion_Guitar_失真音效吉他.mcpack', 31: '31.Guitar_Harmonics_吉他泛音.mcpack',
32: '32.Acoustic_Bass_原声贝司.mcpack', 33: '33.Electric_Bass(finger)_指拨电贝司.mcpack',
34: '34.Electric_Bass(pick)_拨片拨电贝司.mcpack', 35: '35.Fretless_Bass_无品贝司.mcpack',
36: '36.Slap_Bass_A_击弦贝司A.mcpack', 37: '37.Slap_Bass_B_击弦贝司B.mcpack', 38: '38.Synth_Bass_A_合成贝司A.mcpack',
39: '39.Synth_Bass_B_合成贝司B.mcpack', 4: '4.Electric_Piano_1_电钢琴A.mcpack', 40: '40.Violin_小提琴.mcpack',
41: '41.Viola_中提琴.mcpack', 42: '42.Cello_大提琴.mcpack', 43: '43.Contrabass_低音提琴.mcpack',
44: '44.Tremolo_Strings_弦乐震音.mcpack', 45: '45.Pizzicato_Strings_弦乐拨奏.mcpack',
46: '46.Orchestral_Harp_竖琴.mcpack', 47: '47.Timpani_定音鼓.mcpack', 48: '48.String_Ensemble_A_弦乐合奏A.mcpack',
49: '49.String_Ensemble_B_弦乐合奏B.mcpack', 5: '5.Electric_Piano_2_电钢琴B.mcpack',
50: '50.SynthStrings_A_合成弦乐A.mcpack', 51: '51.SynthStrings_B_合成弦乐B.mcpack',
52: '52.Choir_Aahs_合唱“啊”音.mcpack', 53: '53.Voice_Oohs_人声“哦”音.mcpack', 54: '54.Synth_Voice_合成人声.mcpack',
55: '55.Orchestra_Hit_乐队打击乐.mcpack', 56: '56.Trumpet_小号.mcpack', 57: '57.Trombone_长号.mcpack',
58: '58.Tuba_大号.mcpack', 59: '59.Muted_Trumpet_弱音小号.mcpack', 6: '6.Harpsichord_拨弦古钢琴.mcpack',
60: '60.French_Horn_圆号.mcpack', 61: '61.Brass_Section_铜管组.mcpack', 62: '62.Synth_Brass_A_合成铜管A.mcpack',
63: '63.Synth_Brass_A_合成铜管B.mcpack', 64: '64.Soprano_Sax_高音萨克斯.mcpack', 65: '65.Alto_Sax_中音萨克斯.mcpack',
66: '66.Tenor_Sax_次中音萨克斯.mcpack', 67: '67.Baritone_Sax_上低音萨克斯.mcpack', 68: '68.Oboe_双簧管.mcpack',
69: '69.English_Horn_英国管.mcpack', 7: '7.Clavinet_击弦古钢琴.mcpack', 70: '70.Bassoon_大管.mcpack',
71: '71.Clarinet_单簧管.mcpack', 72: '72.Piccolo_短笛.mcpack', 73: '73.Flute_长笛.mcpack',
74: '74.Recorder_竖笛.mcpack', 75: '75.Pan_Flute_排笛.mcpack', 76: '76.Bottle_Blow_吹瓶口.mcpack',
77: '77.Skakuhachi_尺八.mcpack', 78: '78.Whistle_哨.mcpack', 79: '79.Ocarina_洋埙.mcpack',
8: '8.Celesta_钢片琴.mcpack', 80: '80.Lead_square_合成主音-方波.mcpack', 81: '81.Lead_sawtooth_合成主音-锯齿波.mcpack',
82: '82.Lead_calliope_lead_合成主音-汽笛风琴.mcpack', 83: '83.Lead_chiff_lead_合成主音-吹管.mcpack',
84: '84.Lead_charang_合成主音5-吉他.mcpack', 85: '85.Lead_voice_合成主音-人声.mcpack',
86: '86.Lead_fifths_合成主音-五度.mcpack', 87: '87.Lead_bass+lead_合成主音-低音加主音.mcpack',
88: '88.Pad_new_age_合成柔音-新时代.mcpack', 89: '89.Pad_warm_合成柔音-暖音.mcpack', 9: '9.Glockenspiel_钟琴.mcpack',
90: '90.Pad_polysynth_合成柔音-复合成.mcpack', 91: '91.Pad_choir_合成柔音-合唱.mcpack',
92: '92.Pad_bowed_合成柔音-弓弦.mcpack', 93: '93.Pad_metallic_合成柔音-金属.mcpack',
94: '94.Pad_halo_合成柔音-光环.mcpack', 95: '95.Pad_sweep_合成柔音-扫弦.mcpack', 96: '96.FX_rain_合成特效-雨.mcpack',
97: '97.FX_soundtrack_合成特效-音轨.mcpack', 98: '98.FX_crystal_合成特效-水晶.mcpack',
99: '99.FX_atmosphere_合成特效-大气.mcpack'}
if __name__ == '__main__':
print(zip_name[0])

View File

@ -1,133 +0,0 @@
pitch = {
'0': '0.0220970869120796',
'1': '0.0234110480761981',
'2': '0.0248031414370031',
'3': '0.0262780129766786',
'4': '0.0278405849418856',
'5': '0.0294960722713029',
'6': '0.03125',
'7': '0.033108221698728',
'8': '0.0350769390096679',
'9': '0.037162722343835',
'10': '0.0393725328092148',
'11': '0.0417137454428136',
'12': '0.0441941738241592',
'13': '0.0468220961523963',
'14': '0.0496062828740062',
'15': '0.0525560259533572',
'16': '0.0556811698837712',
'17': '0.0589921445426059',
'18': '0.0625',
'19': '0.066216443397456',
'20': '0.0701538780193358',
'21': '0.0743254446876701',
'22': '0.0787450656184296',
'23': '0.0834274908856271',
'24': '0.0883883476483184',
'25': '0.0936441923047926',
'26': '0.0992125657480125',
'27': '0.105112051906714',
'28': '0.111362339767542',
'29': '0.117984289085212',
'30': '0.125',
'31': '0.132432886794912',
'32': '0.140307756038672',
'33': '0.14865088937534',
'34': '0.157490131236859',
'35': '0.166854981771254',
'36': '0.176776695296637',
'37': '0.187288384609585',
'38': '0.198425131496025',
'39': '0.210224103813429',
'40': '0.222724679535085',
'41': '0.235968578170423',
'42': '0.25',
'43': '0.264865773589824',
'44': '0.280615512077343',
'45': '0.29730177875068',
'46': '0.314980262473718',
'47': '0.333709963542509',
'48': '0.353553390593274',
'49': '0.37457676921917',
'50': '0.39685026299205',
'51': '0.420448207626857',
'52': '0.44544935907017',
'53': '0.471937156340847',
'54': '0.5',
'55': '0.529731547179648',
'56': '0.561231024154687',
'57': '0.594603557501361',
'58': '0.629960524947437',
'59': '0.667419927085017',
'60': '0.707106781186548',
'61': '0.749153538438341',
'62': '0.7937005259841',
'63': '0.840896415253715',
'64': '0.890898718140339',
'65': '0.943874312681694',
'66': '1',
'67': '1.0594630943593',
'68': '1.12246204830937',
'69': '1.18920711500272',
'70': '1.25992104989487',
'71': '1.33483985417003',
'72': '1.4142135623731',
'73': '1.49830707687668',
'74': '1.5874010519682',
'75': '1.68179283050743',
'76': '1.78179743628068',
'77': '1.88774862536339',
'78': '2',
'79': '2.11892618871859',
'80': '2.24492409661875',
'81': '2.37841423000544',
'82': '2.51984209978975',
'83': '2.66967970834007',
'84': '2.82842712474619',
'85': '2.99661415375336',
'86': '3.1748021039364',
'87': '3.36358566101486',
'88': '3.56359487256136',
'89': '3.77549725072677',
'90': '4',
'91': '4.23785237743718',
'92': '4.48984819323749',
'93': '4.75682846001088',
'94': '5.03968419957949',
'95': '5.33935941668014',
'96': '5.65685424949238',
'97': '5.99322830750673',
'98': '6.3496042078728',
'99': '6.72717132202972',
'100': '7.12718974512272',
'101': '7.55099450145355',
'102': '8',
'103': '8.47570475487436',
'104': '8.97969638647498',
'105': '9.51365692002177',
'106': '10.079368399159',
'107': '10.6787188333603',
'108': '11.3137084989848',
'109': '11.9864566150135',
'110': '12.6992084157456',
'111': '13.4543426440594',
'112': '14.2543794902454',
'113': '15.1019890029071',
'114': '16',
'115': '16.9514095097487',
'116': '17.95939277295',
'117': '19.0273138400435',
'118': '20.158736798318',
'119': '21.3574376667206',
'120': '22.6274169979695',
'121': '23.9729132300269',
'122': '25.3984168314912',
'123': '26.9086852881189',
'124': '28.5087589804909',
'125': '30.2039780058142',
'126': '32',
'127': '33.9028190194974',
'128': '35.9187855458999',
'129': '38.0546276800871',
'130': '40.3174735966359',
'131': '42.7148753334411'}

View File

@ -1,148 +0,0 @@
# -*- coding: utf-8 -*-
from nmcsup.log import log
import pickle
class Note:
def __init__(self, channel, pitch, velocity, time, time_position, instrument):
self.channel = channel
self.pitch = pitch
self.velocity = velocity
self.delay = time
self.time_position = time_position
self.instrument = instrument
self.CD = "d"
def get_CD(self, start, end):
if end - start > 1.00:
self.CD = "c"
else:
self.CD = "d"
def midiNewReader(midfile: str):
import mido
# from msctspt.threadOpera import NewThread
from bgArrayLib.bpm import get
def Time(mt, tpb_a, bpm_a):
return round(mt / tpb_a / bpm_a * 60 * 20)
Notes = []
tracks = []
note_list = []
close = []
on = []
off = []
instruments = []
isPercussion = False
try:
mid = mido.MidiFile(midfile)
except Exception:
log("找不到文件或无法读取文件" + midfile)
return False
tpb = mid.ticks_per_beat
bpm = get(mid)
# 解析
# def loadMidi(track1):
for track in mid.tracks:
overallTime = 0.0
instrument = 0
for i in track:
overallTime += i.time
try:
if i.channel != 9:
# try:
# log("event_type(事件): " + str(i.type) + " channel(音轨): " + str(i.channel) +
# " note/pitch(音高): " +
# str(i[2]) +
# " velocity(力度): " + str(i.velocity) + " time(间隔时间): " + str(i.time) +
# " overallTime/globalTime/timePosition: " + str(overallTime) + " \n")
# except AttributeError:
# log("event_type(事件): " + str(i.type) + " thing(内容)" + str(i) + " \n")
if 'program_change' in str(i):
instrument = i.program
if instrument > 119: # 音色不够
pass
else:
instruments.append(i.program)
if 'note_on' in str(i) and i.velocity > 0:
print(i)
# print(i.note)
# print([Note(i.channel, i.note, i.velocity, i.time, Time(overallTime, tpb, bpm), instrument)])
tracks.append(
[Note(i.channel, i.note, i.velocity, i.time, Time(overallTime, tpb, bpm), instrument)])
note_list.append(
[i.channel, i.note, i.velocity, i.time, Time(overallTime, tpb, bpm), instrument])
on.append([i.note, Time(overallTime, tpb, bpm)])
# return [Note(i.channel, i, i.velocity, i.time, Time(overallTime, tpb, bpm))]
if 'note_off' in str(i) or 'note_on' in str(i) and i.velocity == 0:
# print(i)
# print([Note(i.channel, i.note, i.velocity, i.time, Time(overallTime, tpb, bpm))])
close.append(
[Note(i.channel, i.note, i.velocity, i.time, Time(overallTime, tpb, bpm), instrument)])
off.append([i.note, Time(overallTime, tpb, bpm)])
# return [Note(i.channel, i, i.velocity, i.time, Time(overallTime, tpb, bpm))]
except AttributeError:
pass
if 'note_on' in str(i) and i.channel == 9:
if 'note_on' in str(i) and i.velocity > 0:
print(i)
# print(i.note)
# print([Note(i.channel, i.note, i.velocity, i.time, Time(overallTime, tpb, bpm), -1)])
tracks.append([Note(i.channel, i.note, i.velocity, i.time, Time(overallTime, tpb, bpm), -1)])
note_list.append([i.channel, i.note, i.velocity, i.time, Time(overallTime, tpb, bpm), -1])
on.append([i.note, Time(overallTime, tpb, bpm)])
isPercussion = True
# return [Note(i.channel, i, i.velocity, i.time, Time(overallTime, tpb, bpm))]
Notes.append(tracks)
if instruments is []:
instruments.append(0)
instruments = list(set(instruments))
with open("1.pkl", 'wb') as b:
pickle.dump([instruments, isPercussion], b)
# for j, track in enumerate(mid.tracks):
# th = NewThread(loadMidi, (track,))
# th.start()
# Notes.append(th.getResult())
# print(Notes)
print(Notes.__len__())
# print(note_list)
print(instruments)
return Notes
# return [Notes, note_list]
def midiClassReader(midfile: str):
import mido
from bgArrayLib.bpm import get
def Time(mt, tpb_a, bpm_a):
return round(mt / tpb_a / bpm_a * 60 * 20)
Notes = []
tracks = []
try:
mid = mido.MidiFile(filename=midfile,clip=True)
except Exception:
log("找不到文件或无法读取文件" + midfile)
return False
log("midi已经载入了。")
tpb = mid.ticks_per_beat
bpm = get(mid)
for track in mid.tracks:
overallTime = 0.0
instrument = 0
for i in track:
overallTime += i.time
if 'note_on' in str(i) and i.velocity > 0:
print(i)
tracks.append(
[Note(i.channel, i.note, i.velocity, i.time, Time(overallTime, tpb, bpm), instrument)])
Notes.append(tracks)
print(Notes.__len__())
return Notes

View File

@ -1,131 +0,0 @@
import os
import pickle
# import tkinter.filedialog
# from namesConstant import zip_name
# from namesConstant import mcpack_name
import bgArrayLib.namesConstant
import shutil
zipN = bgArrayLib.namesConstant.zip_name
mpN = bgArrayLib.namesConstant.mcpack_name
manifest = {
"format_version": 1,
"header": {
"name": "羽音缭绕-midiout_25.5--音创使用",
"description": "羽音缭绕-midiout_25.0--音创使用",
"uuid": "c1adbda4-3b3e-4e5b-a57e-cde8ac80ee19",
"version": [25, 5, 0]
},
"modules": [
{
"description": "羽音缭绕-midiout_25.0--音创使用",
"type": "resources",
"uuid": "c13455d5-b9f3-47f2-9706-c05ad86b3180 ",
"version": [25, 5, 0]
}
]
}
def resources_pathSetting(newPath: str = ""):
if not os.path.isfile("./bgArrayLib/resourcesPath.rpposi") and newPath == "":
return [False, 1] # 1:没有路径文件
elif newPath != "": # not os.path.isfile("./bgArrayLib/resourcesPath.rpposi") and
path = newPath
print(path)
with open("./bgArrayLib/resourcesPath.rpposi", 'w') as w:
w.write(path)
if "mcpack(国际版推荐)格式_25.0" in os.listdir(path) and "zip格式_25.0" in os.listdir(path):
return [True, path, 1] # 1:都有
elif "mcpack(国际版推荐)格式_25.0" in os.listdir(path) and "zip格式_25.0" not in os.listdir(path):
return [True, path, 2] # 2:有pack
elif "mcpack(国际版推荐)格式_25.0" not in os.listdir(path) and "zip格式_25.0" in os.listdir(path):
return [True, path, 3] # 3:有zip
else:
return [False, 2] # 2:路径文件指示错误
if os.path.isfile("./bgArrayLib/resourcesPath.rpposi") and newPath == "":
with open("./bgArrayLib/resourcesPath.rpposi", 'r') as f:
path = f.read()
if "mcpack(国际版推荐)格式_25.0" in os.listdir(path) and "zip格式_25.0" in os.listdir(path):
return [True, path, 1] # 1:都有
elif "mcpack(国际版推荐)格式_25.0" in os.listdir(path) and "zip格式_25.0" not in os.listdir(path):
return [True, path, 2] # 2:有pack
elif "mcpack(国际版推荐)格式_25.0" not in os.listdir(path) and "zip格式_25.0" in os.listdir(path):
return [True, path, 3] # 3:有zip
else:
return [False, 2] # 2:路径文件指示错误
def choose_resources():
global zipN
global mpN
back_list = []
try:
with open(r"1.pkl", 'rb') as rb:
instrument = list(pickle.load(rb))
print(instrument)
except FileNotFoundError:
try:
with open(r"./nmcsup/1.pkl", 'rb') as rb:
instrument = list(pickle.load(rb))
print(instrument)
except FileNotFoundError:
return False
path = resources_pathSetting()
if path.__len__() == 2:
return path
else:
dataT = path[2]
pathT = path[1]
if dataT == 1:
if instrument[1] is True:
index = zipN.get(-1)
percussion_instrument = str(pathT) + "\\zip格式_25.0\\" + index
# print(percussion_instrument)
back_list.append(percussion_instrument)
for i in instrument[0]:
ins_p = str(pathT) + "\\zip格式_25.0\\" + str(zipN.get(i))
# print(ins_p)
back_list.append(ins_p)
print(back_list)
return back_list
elif dataT == 2:
if instrument[1] is True:
index = mpN.get(-1)
percussion_instrument = str(pathT) + "\\mcpack(国际版推荐)格式_25.0\\" + index
# print(percussion_instrument)
back_list.append(percussion_instrument)
for i in instrument[0]:
ins_p = str(pathT) + "\\mcpack(国际版推荐)格式_25.0\\" + str(mpN.get(i))
# print(ins_p)
back_list.append(ins_p)
print(back_list)
return back_list
elif dataT == 3:
if instrument[1] is True:
index = zipN.get(-1)
percussion_instrument = str(pathT) + "\\zip格式_25.0\\" + index
# print(percussion_instrument)
back_list.append(percussion_instrument)
for i in instrument[0]:
ins_p = str(pathT) + "\\zip格式_25.0\\" + str(zipN.get(i))
# print(ins_p)
back_list.append(ins_p)
print(back_list)
return back_list
def scatteredPack(path):
pack_list = choose_resources()
print(pack_list)
print(path)
# os.close("L:/0WorldMusicCreater-MFMS new edition")
# shutil.copy("L:\\shenyu\\音源的资源包\\羽音缭绕-midiout_25.0\\mcpack(国际版推荐)格式_25.0\\0.Acoustic_Grand_Piano_大钢琴.mcpack",
# "L:/0WorldMusicCreater-MFMS new edition")
for i in pack_list:
shutil.copy(i, path)
if __name__ == '__main__':
# print(resources_pathSetting(r"L:\shenyu\音源的资源包\羽音缭绕-midiout_25.0"))
choose_resources()

9
example_convert.py Normal file
View File

@ -0,0 +1,9 @@
# THIS PROGRAM IS ONLY A TEST EXAMPLE
from main import *
midiConvert(input('请输入midi文件路径'), input('请输入输出路径:')).tomcpack(1,'mscplay',1.0,1.0)

View File

@ -1,170 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日
# 统计致命三级错误2个---未解决警告二级错误2个语法一级错误17个
__version__ = '0.0.1'
__all__ = []
__author__ = 'Fuckcraft <https://gitee.com/fuckcraft>'
'''
Fuckcraft Websocket Library (FCWSLIB)
A library to develop minecraft websocket server easily.
Copyright (C) 2021 Fuckcraft
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
'''
from main import *
# import os
import json
import uuid
# import logging
import asyncio
import time
import websockets
# 写这段代码的时候,只有我和上帝知道这段代码是干什么的。
# 现在只有上帝知道。
# ----
# 没毛病,我讨厌两种人:一种是要我写注释的人,一种是给我代码看但没有写注释的人。
# 此函数用于向 Minecraft 订阅请求
async def subscribe(websocket, event_name):
"""
参数:
: websocket : websocket 对象 :
: event_name : 需要订阅的请求 :
返回:
None
"""
response = {
'body': {
'eventName': str(event_name) # 示例PlayerMessage
},
'header': {
'requestId': str(uuid.uuid4()),
'messagePurpose': 'subscribe',
'version': 1,
'messageType': 'commandRequest'
}
}
# 增加 json 的可读性
# response = json.dumps(response, sort_keys=True, indent=4, separators=(', ', ': '), ensure_ascii=False)
response = json.dumps(response)
await websocket.send(response)
# 此函数用于向 Minecraft 消除订阅请求
async def unsubscribe(webscket):
"""
参数:
: websocket : websocket 对象 :
: event_name : 需要消除订阅的请求 :
返回:
None
"""
print(webscket)
response = {
"body": {
"eventName": str(event_name) # PlayerMessage
},
"header": {
"requestId": str(uuid.uuid4()),
"messagePurpose": "unsubscribe",
"version": 1,
"messageType": "commandRequest"
}
}
# 增加 json 的可读性
# response = json.dumps(response, sort_keys=True, indent=4, separators=(', ', ': '), ensure_ascii=False)
response = json.dumps(response)
await websocket.send(response)
# 此函数用于向 Minecraft 执行命令
async def send_command(websocket, command):
"""
参数:
: websocket : websocket 对象 :
: command : 执行的命令 :
返回:
None
"""
response = {
'body': {
'origin': {
'type': 'player'
},
'commandLine': str(command),
'version': 1
},
'header': {
'requestId': str(uuid.uuid4()),
'messagePurpose': 'commandRequest',
'version': 1,
'messageType': 'commandRequest'
}
}
# 增加 json 的可读性
# response = json.dumps(response, sort_keys=True, indent=4, separators=(', ', ': '), ensure_ascii=False)
response = json.dumps(response)
await websocket.send(response)
# 此函数用于向 Minecraft 发送消息
async def tellraw(websocket, message):
"""
参数:
: websocket : websocket 对象 :
: message : 发送的消息 :
返回:
None
"""
command = {
'rawtext': [
{
'text': '[{}] {}'.format(time.asctime(), message)
}
]
}
# 增加 json 可读性
# command = json.dumps(command, sort_keys=True, indent=4, separators=(', ', ': '), ensure_ascii=False)
command = json.dumps(command)
command = 'tellraw @a {}'.format(command)
await send_command(websocket, command)
def run_server(function):
# 修改 ip 地址和端口
start_server = websockets.serve(function, 'localhost', 8080)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

View File

@ -1,160 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
__version__ = '0.0.1'
__all__ = ['run_server', 'subscribe', 'unsubscribe', 'send_command', 'tellraw']
__author__ = 'Fuckcraft <https://gitee.com/fuckcraft>'
'''
Fuckcraft Websocket Library (FCWSLIB)
A library to develop minecraft websocket server easily.
Copyright (C) 2021 Fuckcraft
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
'''
import os
import json
import uuid
import logging
import asyncio
import time
import websockets
# 写这段代码的时候,只有我和上帝知道这段代码是干什么的。
# 现在只有上帝知道。
# 此函数用于向 Minecraft 订阅请求
async def subscribe(websocket, event_name):
'''
输入:
: websocket : websocket 对象 :
: event_name : 需要订阅的请求 :
输出:
None
'''
response = {
'body': {
'eventName': str(event_name) # 示例PlayerMessage
},
'header': {
'requestId': str(uuid.uuid4()),
'messagePurpose': 'subscribe',
'version': 1,
'messageType': 'commandRequest'
}
}
# 增加 json 的可读性
# response = json.dumps(response, sort_keys=True, indent=4, separators=(', ', ': '), ensure_ascii=False)
response = json.dumps(response)
await websocket.send(response)
# 此函数用于向 Minecraft 消除订阅请求
async def unsubscribe(webscket):
'''
输入:
: websocket : websocket 对象 :
: event_name : 需要消除订阅的请求 :
输出:
None
'''
response = {
"body": {
"eventName": str(event_name) # 示例PlayerMessage
},
"header": {
"requestId": str(uuid.uuid4()),
"messagePurpose": "unsubscribe",
"version": 1,
"messageType": "commandRequest"
}
}
# 增加 json 的可读性
# response = json.dumps(response, sort_keys=True, indent=4, separators=(', ', ': '), ensure_ascii=False)
response = json.dumps(response)
await websocket.send(response)
# 我个人不负责这块的质量,因为他们逼迫我违心的写了这段代码
# 此函数用于向 Minecraft 执行命令
async def send_command(websocket, command):
'''
输入:
: websocket : websocket 对象 :
: command : 执行的命令 :
输出:
None
'''
response = {
'body': {
'origin': {
'type': 'player'
},
'commandLine': str(command),
'version': 1
},
'header': {
'requestId': str(uuid.uuid4()),
'messagePurpose': 'commandRequest',
'version': 1,
'messageType': 'commandRequest'
}
}
# 增加 json 的可读性
# response = json.dumps(response, sort_keys=True, indent=4, separators=(', ', ': '), ensure_ascii=False)
response = json.dumps(response)
await websocket.send(response)
# 此函数用于向 Minecraft 发送消息
async def tellraw(websocket, message):
'''
输入:
: websocket : websocket 对象 :
: message : 发送的消息 :
输出:
None
'''
command = {
'rawtext':[
{
'text':'[{}] {}'.format(time.asctime(), message)
}
]
}
# 增加 json 可读性
# command = json.dumps(command, sort_keys=True, indent=4, separators=(', ', ': '), ensure_ascii=False)
command = json.dumps(command)
command = 'tellraw @a {}'.format(command)
await send_command(websocket, command)
def run_server(function):
# 修改 ip 地址和端口
start_server = websockets.serve(function, 'localhost', 8080)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

View File

View File

@ -1,13 +0,0 @@
zh-ME
喵喵文 中国大陆
Meow Catsese, China Mainland
喵喵喵~ 祖国喵~
金羿,Email EillesWan@outlook.com,QQ 2647547478
音创创喵~
音·创 Musicreater
音创创喵的主人们
凌天之云创新我的世界开发团队\n×\n凌天之云创新计算机应用软件开发团队
~ 主人们 ~
~ 爸爸妈妈们 ~
好哒~

View File

@ -1,99 +0,0 @@
# -*- coding:utf-8 -*-
'''此功能已废弃'''
# W-YI 金羿
# QQ 2647547478
# 音·创 开发交流群 861684859
# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com
# 版权所有 Team-Ryoun 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray")
# 若需转载或借鉴 请附作者
"""
Copyright 2022 Team-Ryoun 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray")
Licensed under the Apache License, Version 2.0 (the 'License');
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an 'AS IS' BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
# 代码写的并非十分的漂亮还请大佬多多包涵本软件源代码依照Apache软件协议公开
# -----------------------------分割线-----------------------------
# 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日
# 统计致命三级错误0个警告二级错误0个语法一级错误12个
# 目前我的Pycharm并没有显示任何错误有错误可以向
# bgArray 诸葛亮与八卦阵
# QQ 474037765 或最好加入:音·创 开发交流群 861684859
# ------------------------- split line-----------------------------
# Zhuge Liang and Bagua array help to modify the grammar date: -- January 19, 2022
# Statistics: fatal (Level 3) errors: 0; Warning (Level 2) errors: 15; Syntax (Level 1) error: 597
# At present, my Pycham does not display any errors. If there are errors, you can report them to me
# Bgarray Zhuge Liang and Bagua array
# QQ 474037765 or better join: Musicreater development exchange group 861684859
# ------------------------- split line-----------------------------
# 下面为正文
# 将程序中用双引号""括起来的字符串
# 转为字符串列表 list[str, str, ...]
# 方便进行语言翻译支持。
import sys
startWith = 0
def __main__():
textList = []
for fileName in sys.argv[1:]:
print('读取文件: {}'.format(fileName))
fileText = []
for line in open(fileName, 'r', encoding='utf-8'):
while line.count('"') >= 2:
# 只有上帝看得懂我在写什么。
if line[
line.index('"'):2 + line[line.index('"') + 1:].index('"') + len(line[:line.index('"')])] in textList:
thisText = textList.index(
line[line.index('"'):2 + line[line.index('"') + 1:].index('"') + len(line[:line.index('"')])])
else:
thisText = len(textList)
textList.append(
line[line.index('"'):2 + line[line.index('"') + 1:].index('"') + len(line[:line.index('"')])])
line = line.replace(
line[line.index('"'):2 + line[line.index('"') + 1:].index('"') + len(line[:line.index('"')])],
'READABLETEXT[{}]'.format(thisText + startWith)
)
fileText.append(line)
open(fileName + '_C', 'w', encoding='utf-8').writelines(fileText)
outFile = open('lang__.py', 'w', encoding='utf-8')
outFile.write('''# -*- coding:utf-8 -*-
# 由金羿翻译工具生成字符串列表
# 请在所需翻译文件前from 此文件 import READABLETEXT
READABLETEXT = {
''')
for i in range(len(textList)):
outFile.write(" {}:{},\n".format(i + startWith, textList[i]))
outFile.write('}')
outFile.close()
if __name__ == '__main__':
__main__()

View File

@ -1,180 +0,0 @@
# -*- coding:utf-8 -*-
# 由金羿翻译工具生成字符串列表
# 请在所需翻译的文件前from 此文件 import READABLETEXT
READABLETEXT = {
'Translator': (("Eilles Wan (金羿)", True),),
# 此处是语言翻译者列表,其中每个元组第一项为显示文本,第二项为此文本是否为开发者名字
0: "ERROR❌",
1: "TIPS❗",
2: "Clearing log(this wont be in the file)",
3: "Could not clear the temporary files or logs",
4: "saved",
5: "New Musicreater Project",
6: "Select old-type project",
7: "Select Musicreater Project",
8: "Cant open:{}, please check if youve entered the right name",
9: "Musicreat - About",
10: "Musicreater",
11: "Ver. {}",
12: """Team-Ryoun for Minecraft\n×\nTeam-Ryoun for Software Development""",
13: "OK",
14: "Inpute Notes",
15: (("- Developers -", False),
("Eilles Wan (金羿)", True), ("EillesWan@outlook.com", False), ("QQ 2647547478", False),
("bgArray “诸葛亮与八卦阵”", True), ("QQ 474037765", False)),
# 此处是开发者列表,其中每个元组第一项为显示文本,第二项为此文本是否为开发者名字
16: "- Translators -",
# 17:"",
18: "QQ Group: 861684859",
19: "Musicreater - Help",
20: "Select sound file",
21: "Select MIDI file",
22: "Select NoteText file",
23: "Get Note info",
24: "Write in Note info: {}",
25: "Select generating file",
26: "Select generating folder",
27: "Select generating .mcpack file",
28: "Input position info",
29: "Select generating world folder",
30: "Select generating Function Pack",
31: "Select .mcfunction file ",
32: "Select .bdx file ",
33: "DONE✔",
34: "Input playing rate",
35: "Generating",
36: "Select a world folder",
37: "Make sure",
38: "Generate .RyStruct file",
39: "FAILED❌",
40: "Report message inpution",
41: "Musicreater - {}",
42: "ExecutingEntityName: {}",
43: "ScoreboardName: {}",
44: "Instrument: {}",
45: "TrackName: {}",
46: "PackName: {}",
47: "MusicTitle: {}",
48: "IsRepeat?: {}",
49: "Player'sTargetSelector: {}",
50: "Modify Main Option",
51: "Modify Track Option",
52: "Default Instrument: Enter English\n",
53: "Open...",
54: "Open Old Project...",
55: "Save",
56: "Save as...",
57: "Exit",
58: "File",
59: "Load tracks from sound",
60: "Load tracks from Midi",
61: "Load tracks from Text",
62: "Input notes to track",
63: "Edit",
64: "Generate file...",
65: "Generate function pack...",
66: "Generate .mcpack file...",
67: "Functions(Pack)",
68: "Save music as blocks into a map",
69: "Save music as blocks into a exist map...",
70: "Save music as commands into a map",
71: "Save music as commands into a exist map...",
72: "Save music as notebox into a map",
73: "Save music as notebox into a exist map...",
74: "World",
75: "Generate a function that fits current music...",
76: "Export selected track as commands in .bdx...",
77: "Export .bdx file from map...",
78: "Export .RyStruct file from map...",
79: "Load functions into a world...",
80: "Separate long .mcfunction file into small ones and set them into a world as a chain...",
81: "Additional Functions",
82: "Show generating result",
83: "Set a websocket server on localhost:8080 and play the selected track",
84: "Experimental Functions",
85: "Clear log file",
86: "Clear save file(obsolete)",
87: "Help",
88: "About",
89: "Send a bug report",
90: "Q&A",
91: "Main Options",
92: "Export music as .BDX...",
93: "请输入指令链生成最高相对高度(≥5)",
94: "❌You should input a number which is not lower then 4, please reinput again.",
95: "Structure",
96: "Reset Main Options",
97: "Track Options",
# 98:"",
# 99:"",
# 100:"",
# 101:"",
102: "Delete Selected Track",
# 103:"",
# 104:"",
105: "Error with finding or reading file😢{}",
106: "Project is unsaved, save before close?",
107: "Saved in: {}",
108: ("Musicreater 0.0.X Project","Musicreater 0.1+ Project","Musicreater 0.1+ TESTver Project"),
109: "Any Type",
110: "NoteFunCreater Project",
111: "MMFM (V0.0.6) Project",
112: "All Types",
113: ".MP3 file(piano sound)",
114: "Midi file",
115: "Text file",
116: "Position Inpution",
117: "Format Error❌, please Reinput!",
118: ".MCFUNCTION",
119: "The position of the ChainCB for execution:",
# 120: "",
121: "您的函数文件不大于一万条指令,无需进行分割操作。",
122: "请输入执行链生成相对坐标:",
123: "FastBuilder Structure",
124: "Done!\n{}",
125: "一秒,音乐走几拍?",
126: "按下确认后在游戏中使用connect指令连接localhost:8080即可播放",
127: "请输入区域选择的开始坐标:",
128: "请输入区域选择的结束坐标:",
129: "Whether air block remain when export?",
130: "Musicreater Structure",
131: "Done😃\n{}",
132: "Failed❌\n{}\n{}",
133: "Have not developed yet...",
134: "Your name",
135: "Your contact",
136: "Your description of Problem",
137: "Log file will be cleared when you exit.",
138: "Log file will NOT be cleared when you exit.",
139: "修改包名",
140: "修改音乐标题",
141: "修改玩家选择器\n注意!要加上中括号“[]”",
142: "修改本音轨的执行实体名",
143: "修改本音轨所用的积分板",
144: "修改本音轨所用乐器",
145: "您输入的乐器并非游戏内置乐器,是否继续用您输入的字符作为乐器?",
146: "修改本音轨生成的文件名",
# -----2022.1.25更新
147: "生成新文件至...",
148: "从midi导入音轨且用新方法解析",
149: "Open New: Musicreater Project...",
150: "保存为新项目",
151: "另存为新项...",
152: "(开发调试)关闭本次日志记录",
153: "生成新函数包至...",
154: "生成新函数附加包文件至...",
155: "生成新函数附加包文件,并将神羽资源包以散包形式放置至...",
156: "Select [MiraclePlumeResourcePack]...",
157: "没有路径文件(.rpposi文件)请仔细阅读Readme或先试用帮助与疑问->[神羽资源包位置选择]:选择文件夹... 方法添加路径文件吧!",
158: "有路径文件(.rpposi文件)但路径指示错误请仔细阅读Readme或先用帮助与疑问->[神羽资源包位置选择]:选择文件夹... 更改路径!",
159: "更改路径文件(.rpposi文件)成功!!",
160: "从midi导入音轨且用类方法解析",
161: "打开 类方法: 音·创项目...",
162: "保存为类方法项目",
163: "另存为类方法项...",
}

View File

@ -1,206 +0,0 @@
# -*- coding:utf-8 -*-
'''对于音·创的语言支持兼语言文件编辑器'''
"""
Copyright 2022 Team-Ryoun
Licensed under the Apache License, Version 2.0 (the 'License');
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an 'AS IS' BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
DEFAULTLANGUAGE = 'zh-CN'
LANGUAGELIST = {
# 第一个是语言的中文名称和地区
# 第二个是语言的英文名称和地区
# 第三个是语言的本地名称和地区
'zh-CN': (
"简体中文 中国大陆",
"Simplified Chinese - China Mainland",
"简体中文 中国大陆",
),
'zh-TW': (
"繁体中文 中国台湾省",
"Traditional Chinese - Taiwan, China",
"正體中文,中国台灣省",
),
# 'zh-HK': (
# "繁体中文 香港",
# "Traditional Chinese - the Hong Kong Special Administrative Region",
# "繁體中文,香港特別行政區",
# ),
# 'zh-MO': (
# "繁体中文 澳门",
# "Traditional Chinese - the Macao Special Administrative Region",
# "繁體中文,澳門特別行政區",
# ),
'en-GB': (
"英语 英国",
"British English - the United Kingdom",
"British English - the United Kingdom",
),
'zh-ME' : (
"喵喵文 中国大陆",
"Meow Catsese - China Mainland"
"喵喵喵~ 祖国喵~"
)
}
# 对于旧版本音·创的语言支持
# 重构之后将停止使用
try:
from languages.zhCN import READABLETEXT
except:
pass
from msctLib.log import log
def __loadLanguage(languageFilename: str):
with open(languageFilename, 'r', encoding='utf-8') as languageFile:
_text = {}
for line in languageFile:
if line.startswith('#'):
continue
line = line.split(' ', 1)
_text[line[0]] = line[1].replace('\n', '')
langkeys = _text.keys()
with open(languageFilename.replace(languageFilename[-10:-5], 'zh-CN'), 'r', encoding='utf-8') as defaultLangFile:
for line in defaultLangFile:
if line.startswith('#'):
continue
line = line.split(' ', 1)
if not line[0] in langkeys:
_text[line[0]] = line[1].replace('\n', '')
from msctLib.log import log
log(f'丢失对于 {line[0]} 的本地化文本', 'WARRING')
langkeys = _text.keys()
# print(_text)
return _text
if not DEFAULTLANGUAGE == 'zh-CN':
if DEFAULTLANGUAGE in LANGUAGELIST.keys():
_TEXT = __loadLanguage('./languages/' + DEFAULTLANGUAGE + '.lang')
else:
raise KeyError(f'无法打开默认语言{DEFAULTLANGUAGE}')
def wordTranslate(singleWord: str, debug: bool = False):
import requests
try:
return \
requests.post('https://fanyi.baidu.com/sug', data={'kw': f'{singleWord}'}).json()['data'][0]['v'].split(
'; ')[0]
except:
log(f"无法翻译文本{singleWord}", level='WARRING', isPrinted=debug)
return None
def _(text: str, debug: bool = False):
try:
return _TEXT[text]
except:
if debug:
raise KeyError(f'无法找到翻译文本{text}')
else:
log(f'无法找到本地化文本{text}','ERROR')
return ''
if __name__ == '__main__':
# 启动语言编辑器
import tkinter as tk
from tkinter.filedialog import askopenfilename as askfilen
LANGNAME = _('LANGLOCALNAME')
def _changeDefaultLang():
global _TEXT
global DEFAULTLANGUAGE
fileName = askfilen(title='选择所翻译的语言文件', initialdir=r'./',
filetypes=[('音·创语言文件', '.lang'), ('所有文件', '*')],
defaultextension='.lang',
initialfile='.lang')
_TEXT = __loadLanguage(fileName)
DEFAULTLANGUAGE = _('LANGKEY')
LANGNAME = _('LANGLOCALNAME')
orignText = ''
transText = ''
for i, j in _TEXT.items():
orignText += i + '\n'
transText += j + '\n'
Origntextbar.insert('end', orignText)
Translatetextbar.insert('end', transText)
global setlangbutton
setlangbutton['text'] = f'对标语言{LANGNAME}'
def _autoSave(event=None):
with open('autosave.tmp.txt', 'w', encoding='utf-8') as f:
f.write(Translatetextbar.get(1.0, 'end'))
print(str(event))
root = tk.Tk()
root.geometry('600x500')
root.bind("<Motion>", _autoSave)
nowText = ''
Orignrame = tk.Frame(root, bd=2)
Translaterame = tk.Frame(root, bd=2)
Orignscrollbar = tk.Scrollbar(Orignrame)
Origntextbar = tk.Text(Orignrame, width=35, height=40)
Translatetextbar = tk.Text(Translaterame, width=40, height=37, undo=True)
Translatescrollbar = tk.Scrollbar(Translaterame)
def ctrlZ():
Translatetextbar.edit_undo()
Translatetextbar.bind("<Control-z>", ctrlZ)
def ctrlY():
Translatetextbar.edit_redo()
Translatetextbar.bind("<Control-y>", ctrlY)
Translatetextbar.bind("<Control-s>", _autoSave)
tk.Button(Translaterame, text='保存', command=_autoSave).pack(side='bottom', fill='x')
tk.Label(Orignrame, text='中文原文').pack(side='top')
Origntextbar.pack(side='left', fill='y')
Orignscrollbar.pack(side='left', fill='y')
setlangbutton = tk.Button(Translaterame, text=f'对标语言{LANGNAME}', command=_changeDefaultLang)
setlangbutton.pack(side='top')
Translatescrollbar.pack(side='right', fill='y')
Translatetextbar.pack(side='right', fill='y')
Orignscrollbar.config(command=Origntextbar.yview)
Origntextbar.config(yscrollcommand=Orignscrollbar.set)
Translatescrollbar.config(command=Translatetextbar.yview)
Translatetextbar.config(yscrollcommand=Translatescrollbar.set)
Orignrame.pack(side='left')
Translaterame.pack(side='right')
tk.mainloop()

View File

@ -1,16 +0,0 @@
# 音·创 本地化语言文件
# 使用 空格 把键与对应文本隔开
# 使用 井字符 在每一行的开头编写注释
# 注意!井字符请开头放,切勿含有空格
# 也切勿在正文结尾放!
LANGKEY zh-CN
LANGCHINESENAME 简体中文 中国大陆
LANGENGLIFHNAME Simplified Chinese, Chinese Mainland
LANGLOCALNAME 简体中文 中国大陆
MSCT 音·创
F音创 音·创 Musicreater
关于 音·创 - 关于
凌云pairs 凌天之云创新我的世界开发团队\n×\n凌天之云创新计算机应用软件开发团队
开发者 - 开发人员 -
译者 - 翻译人员 -
确定 确定

View File

@ -1,17 +0,0 @@
# 音创创喵的 本地化语言文件
# 使用 空格 把键与对应文本隔开
# 使用 井字符 在每一行的开头编写注释
# 注意!井字符请开头放,切勿含有空格
# 也切勿在正文结尾放!
LANGKEY zh-ME
LANGCHINESENAME 喵喵文 中国大陆
LANGENGLIFHNAME Meow Catsese, China Mainland
LANGLOCALNAME 喵喵喵~ 祖国喵~
TRANSLATERS 金羿,Email EillesWan@outlook.com,QQ 2647547478
MSCT 音创创喵~
F音创 音·创 Musicreater
关于 音创创喵的主人们
凌云pairs 凌天之云创新我的世界开发团队\n×\n凌天之云创新计算机应用软件开发团队
开发者 ~ 主人们 ~
译者 ~ 爸爸妈妈们 ~
确定 好哒~

View File

@ -1,185 +0,0 @@
# -*- coding:utf-8 -*-
# 由金羿翻译工具生成字符串列表
# 请在所需翻译文件前from 此文件 import READABLETEXT
READABLETEXT = {
'Translator': (("金羿 Eilles 原稿", True),),
# 此处是语言翻译者列表,其中每个元组第一项为显示文本,第二项为此文本是否为开发者名字
0: "错误❌",
1: "提示❗",
2: "清除log此句不载入日志",
3: "无法清除日志及临时文件",
4: "已存储",
5: "新建 音·创 项目",
6: "请选择旧类型的项目",
7: "请选择 音·创 项目",
8: "无法打开文件:{},请查看您是否输入正确",
9: "音·创 - 关于",
10: "音·创 Musicreater",
11: "当前版本:{}",
12: """凌云我的世界开发团队\n×\n凌云计算机应用软件开发团队""",
13: "确定",
14: "请输入音符",
15: (("- 开发者 -", False),
("金羿 Eilles", True), ("EillesWan@outlook.com", False), ("QQ 2647547478", False),
("bgArray “诸葛亮与八卦阵”", True), ("QQ 474037765", False),
),
# 此处是开发者列表,其中每个元组第一项为显示文本,第二项为此文本是否为开发者名字
16: "- 翻译者 -",
# 17:"",
18: "讨论群: 861684859",
19: "音·创 - 帮助",
20: "请选择钢琴声音的音乐文件",
21: "请选择 MIDI 文件",
22: "请选择 音符文本 文件",
23: "获取音符信息",
24: "音符数据写入{}",
25: "请选择文件生成的位置",
26: "请选择文件夹生成的位置",
27: "请选择.mcpack文件生成的位置",
28: "坐标信息输入",
29: "请选择世界文件夹生成的位置",
30: "请选择函数包生成的位置",
31: "请选择 .mcfunction 文件",
32: "请选择需要生成的.bdx文件",
33: "完成✔",
34: "输入播放速度",
35: "创建中",
36: "请选择世界文件夹所在的位置",
37: "请确认",
38: "生成.RyStruct文件",
39: "失败❌",
40: "邮件反馈信息输入",
41: "音·创 - {}",
42: "执行实体名:{}",
43: "使用计分板:{}",
44: "所用的乐器:{}",
45: "当前音轨名:{}",
46: "包名:{}",
47: "音乐标题:{}",
48: "是否重复:{}",
49: "玩家选择器:{}",
50: "修改主设置",
51: "修改节设置",
52: "游戏内置乐器如下:请输入英文\n",
53: "打开音·创项目...",
54: "打开旧项目...",
55: "保存项目",
56: "另存为...",
57: "退出",
58: "文件",
59: "从钢琴MP3导入音轨",
60: "从midi导入音轨",
61: "从文本文件导入音轨",
62: "输入音符至音轨",
63: "编辑",
64: "生成文件至...",
65: "生成函数包至...",
66: "生成附加包文件至...",
67: "函数(包)",
68: "将音乐以方块存储生成地图",
69: "将音乐以方块存储载入地图…",
70: "将音乐以指令存储生成地图",
71: "将音乐以指令存储载入地图…",
72: "将音乐以音符盒存储生成地图",
73: "将音乐以音符盒存储载入地图…",
74: "世界",
75: "生成符合当前音乐的函数播放器…",
76: "将选中音轨以指令存储生成.bdx文件…",
77: "由地图导出至.bdx文件…",
78: "由地图导出至.RyStruct文件…",
79: "将函数载入世界…",
80: "将大函数分割并建立执行链…",
81: "辅助功能",
82: "展示生成结果",
83: "建立位于localhost:8080上的websocket服务器播放选中音轨",
84: "实验性功能",
85: "清除日志文件",
86: "清除早期版本的存储文件",
87: "帮助",
88: "关于",
89: "发送错误日志反馈",
90: "帮助与疑问",
91: "音乐总设置(项目设置)",
# =============================================================此处有新增
92: "将音乐导出为BDX",
93: "请输入指令链生成最高相对高度(≥5)",
94: "您输入的数据有误❌相对高度请输入一个不小于4的值请重新输入。",
95: "结构操作",
96: "重置项目设置",
97: "当前音轨设置(段落设置)",
# 98:"",
# 99:"",
# 100:"",
# 101:"",
102: "删除选中音轨",
# 103:"",
# 104:"",
105: "找不到或无法读取文件😢:{}",
106: "您当前的项目已修改但未存储,是否先保存当前项目?",
107: "项目已经存储至:{}",
108: ("音·创0.0.X工程文件", "音·创0.1+工程文件", "音·创0.1+TEST工程文件"),
109: "任意类型",
110: "函数音创工程文件",
111: "MMFM0.0.6版本工程文件",
112: "全部类型",
113: "钢琴声音的音频文件",
114: "Midi文件",
115: "文本文件",
116: "请输入坐标:",
117: "您输入的格式有误❌,请重新输入。",
118: "我的世界指令函数文件",
119: "请输入执行链生成坐标:",
# 120: "",
121: "您的函数文件不大于一万条指令,无需进行分割操作。",
122: "请输入执行链生成相对坐标:",
123: "FastBuilder结构文件",
124: "转换结束!\n{}",
125: "一秒,音乐走几拍?",
126: "按下确认后在游戏中使用connect指令连接localhost:8080即可播放",
127: "请输入区域选择的开始坐标:",
128: "请输入区域选择的结束坐标:",
129: "所选区块导出时是否需要保留空气方块?",
130: "音·创结构文件",
131: "文件已生成\n{}",
132: "文件无法生成\n{}\n{}",
133: "本功能尚未开发。",
134: "您的称呼",
135: "您的联系方式",
136: "您对问题的描述",
137: "在程序结束后将清除日志及临时文件信息。",
138: "在程序结束后将不会清除日志及临时文件信息。",
139: "修改包名",
140: "修改音乐标题",
141: "修改玩家选择器\n注意!要加上中括号“[]”",
142: "修改本音轨的执行实体名",
143: "修改本音轨所用的积分板",
144: "修改本音轨所用乐器",
145: "您输入的乐器并非游戏内置乐器,是否继续用您输入的字符作为乐器?",
146: "修改本音轨生成的文件名",
# -----2022.1.25更新
147: "生成乐器文件至...",
148: "从midi导入音轨且用新方法解析",
# 149: "打开 新: 音·创项目...",
# 150: "保存为新项目",
# 151: "另存为新项...",
152: "(开发调试)关闭本次日志记录",
153: "生成乐器函数包至...",
154: "生成乐器函数附加包文件至...",
155: "生成乐器函数附加包文件,并将神羽资源包以散包形式放置至...",
156: "[神羽资源包位置选择]:选择文件夹...",
157: "没有路径文件(.rpposi文件)请仔细阅读Readme或先试用帮助与疑问->[神羽资源包位置选择]:选择文件夹... 方法添加路径文件吧!",
158: "有路径文件(.rpposi文件)但路径指示错误请仔细阅读Readme或先用帮助与疑问->[神羽资源包位置选择]:选择文件夹... 更改路径!",
159: "更改路径文件(.rpposi文件)成功!!",
160: "从midi导入音轨且用类方法解析",
# 161: "打开 类方法: 音·创项目...",
# 162: "保存为类方法项目",
# 163: "另存为类方法项...",
164: "生成新文件至...",
165: "生成新函数包至...",
166: "生成新函数附加包文件至...",
167: "这个midi文件读取不了mido解析报错"
}

169
main.py Normal file
View File

@ -0,0 +1,169 @@
# -*- coding:utf-8 -*-
import mido
import os
import json
import uuid
import zipfile
import shutil
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
pathfile = os.path.join(parent, filename)
arcname = pathfile[pre_len:].strip(os.path.sep) # 相对路径
zipf.write(pathfile, arcname)
zipf.close()
class midiConvert:
def __init__(self, midiFile: str, outputPath: str):
'''简单的midi转换类将midi文件转换为我的世界结构或者包'''
self.midiFile = midiFile
'''midi文件路径'''
self.midi = mido.MidiFile(self.midiFile)
'''MidiFile对象'''
self.outputPath = outputPath
'''输出路径'''
# 将self.midiFile的文件名不含路径且不含后缀存入self.midiFileName
self.midFileName = os.path.splitext(os.path.basename(self.midiFile))[0]
'''文件名,不含路径且不含后缀'''
def __Inst2SoundID(self,instrumentID, default='note.harp'):
'''返回midi的乐器ID对应的我的世界乐器名
:param instrumentID: midi的乐器ID
:param default: 如果instrumentID不在范围内返回的默认我的世界乐器名称
:return: 我的世界乐器名 str'''
if instrumentID == 105:
return 'note.banjo'
if instrumentID in range(32, 40):
return 'note.bass'
if instrumentID in range(115, 119):
return 'note.basedrum'
if instrumentID == 9 or instrumentID == 14:
return 'note.bell'
if instrumentID == 80 or instrumentID == 81:
return 'note.bit'
if instrumentID == 112:
return 'note.cow_bell'
if instrumentID == -1:
return 'note.didgeridoo' # 这是什么?我看不懂,但我大受震撼
if instrumentID in range(72, 80):
return 'note.flute'
if instrumentID in range(24, 32):
return 'note.guitar'
if instrumentID == -2:
return 'note.hat'
if instrumentID == 14:
return 'note.chime'
if instrumentID == 8 or instrumentID == 11:
return 'iron_xylophone'
if instrumentID == 2:
return 'note.pling'
if instrumentID == 114:
return 'note.snare'
if instrumentID == 13:
return 'note.xylophone'
return default
def _toCmdList_m1(self,scoreboardname : str = 'mscplay',volume:float = 1.0, speed:float = 1.0) -> list:
'''使用Dislink Sforza的转换算法将midi转换为我的世界命令列表
:param scoreboardname: 我的世界的计分板名称
:param volume: 音量注意这里的音量范围为(0,1]如果超出将被处理为正确值其原理为在距离玩家 (1 / volume -1) 的地方播放音频
:param speed: 速度注意这里的速度指的是播放倍率其原理为在播放音频的时候每个音符的播放时间除以 speed
:return: 我的世界命令列表'''
tracks = []
if volume > 1:
volume = 1
if volume <= 0:
volume = 0.001
for i, track in enumerate(self.midi.tracks):
ticks=0
commands=0
instrumentID=0
singleTrack = []
for msg in track:
if msg.is_meta:
if msg.type == 'set_tempo':
tempo=msg.tempo
if msg.type == 'program_change':
instrumentID=msg.program
else:
ticks+=msg.time
if msg.type == 'note_on' and msg.velocity != 0:
singleTrack.append('execute @a[scores={'+scoreboardname+'='+str(round((ticks*tempo)/((self.midi.ticks_per_beat*float(speed))*50000)))+'}'+f'] ~~~ playsound {self.__Inst2SoundID(instrumentID)} @s ~~{1/volume-1}~ {msg.velocity*(0.7 if msg.channel == 0 else 0.9)} {2**((msg.note-66)/12)}')
commands+=1
tracks.append(singleTrack)
return tracks
def tomcpack(self,method:int = 1,scoreboardname : str = 'mscplay',volume:float = 1.0, speed:float = 1.0) -> bool:
'''使用method指定的转换算法将midi转换为我的世界mcpack格式的包
:param method: 转换算法
:param scoreboardname: 我的世界的计分板名称
:param volume: 音量注意这里的音量范围为(0,1]其原理为在距离玩家 (1 / volume -1) 的地方播放音频
:param speed: 速度注意这里的速度指的是播放倍率其原理为在播放音频的时候每个音符的播放时间除以 speed
:return 成功与否成功返回(True,True)失败返回(False,str失败原因)'''
if method == 1:
cmdlist = self._toCmdList_m1(scoreboardname,volume,speed)
else:
return (False,f'无法找到算法ID{method}对应的转换算法')
# 当文件f夹{self.outputPath}/temp/functions存在时清空其下所有项目若其不存在则创建
if os.path.exists(f'{self.outputPath}/temp/functions/'):
shutil.rmtree(f'{self.outputPath}/temp/functions/')
os.makedirs(f'{self.outputPath}/temp/functions/mscplay')
# 写入manifest.json
if not os.path.exists(f'{self.outputPath}/temp/manifest.json'):
with open(f"{self.outputPath}/temp/manifest.json", "w") as f:
f.write("{\n \"format_version\": 1,\n \"header\": {\n \"description\": \"" + self.midFileName + " Pack : behavior pack\",\n \"version\": [ 0, 0, 1 ],\n \"name\": \"" + self.midFileName + "Pack\",\n \"uuid\": \"" + str(uuid.uuid4()) + "\"\n },\n \"modules\": [\n {\n \"description\": \"" + f"the Player of the Music {self.midFileName}" + "\",\n \"type\": \"data\",\n \"version\": [ 0, 0, 1 ],\n \"uuid\": \"" + str(uuid.uuid4()) + "\"\n }\n ]\n}")
else:
with open(f'{self.outputPath}/temp/manifest.json', 'r') as manifest:
data=json.loads(manifest.read())
data['header']['description']=f"the Player of the Music {self.midFileName}"
data['header']['name']=self.midFileName
data['header']['uuid']=str(uuid.uuid4())
data['modules'][0]['description']='None'
data['modules'][0]['uuid']=str(uuid.uuid4())
manifest.close()
open(f'{self.outputPath}/temp/manifest.json','w').write(json.dumps(data))
# 将命令列表写入文件
indexfile = open(f'{self.outputPath}/temp/functions/index.mcfunction', 'w', encoding='utf-8')
for track in cmdlist:
indexfile.write('function mscplay/track'+str(cmdlist.index(track)+1)+'\n')
with open(f'{self.outputPath}/temp/functions/mscplay/track{cmdlist.index(track)+1}.mcfunction','w',encoding='utf-8') as f:
f.write('\n'.join(track))
indexfile.write('scoreboard players add @a[scores={'+scoreboardname+'=1..}] '+scoreboardname+' 1\n')
indexfile.close()
makeZip(f'{self.outputPath}/temp/',self.outputPath+f'/{self.midFileName}.mcpack')
shutil.rmtree(f'{self.outputPath}/temp/')

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

View File

Binary file not shown.

View File

@ -1,50 +0,0 @@
# -*- coding: UTF-8 -*-
"""音·创的核心内置组件功能集合"""
class version:
libraries = (
'mido', 'amulet', 'amulet-core', 'amulet-nbt', 'piano_transcription_inference', 'pypinyin',
'pyinstaller', 'py7zr','websockets', 'torch', 'requests'
)
"""当前所需库"""
version = ('0.2.0', 'Delta',)
"""当前版本"""
def __init__(self) -> None:
self.libraries = version.libraries
"""当前所需库"""
self.version = version.version
"""当前版本"""
def installLibraries(self,index:str = 'https://pypi.tuna.tsinghua.edu.cn/simple'):
"""安装全部开发用库"""
from sys import platform
import os
if platform == 'win32':
import shutil
try:
shutil.rmtree(os.getenv('APPDATA') + '\\Musicreater\\')
except FileNotFoundError:
pass
for i in self.libraries:
print("安装库:" + i)
os.system(f"python -m pip install {i} -i {index}")
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(f"sudo python3 -m pip install {i} -i {index}")
def __call__(self):
'''直接安装库,顺便返回一下当前版本'''
self.installLibraries()
return self.version

View File

@ -1,151 +0,0 @@
# -*- coding:utf-8 -*-
import pickle
import json
from typing import Any, Iterable
class pickleIO:
def __init__(self,fileName:str,data: Any = None) -> None:
'''简单的pickle操作功能'''
self.file = fileName
if data:
self._data = data
else:
with open (self.file, 'rb') as f:
self._data = pickle.load(f)
def __call__(self, *args: Any, **kwds: Any) -> Any:
return self.data
def write(self):
'''将数据写入pickle'''
with open (self.file, 'wb') as f:
pickle.dump(self._data, f)
def load(self) -> Any:
'''从文件读取数据'''
with open (self.file, 'rb') as f:
self._data = pickle.load(f)
return self.data
@property
def data(self):
'''返回数据值'''
if self._data is None:
raise ValueError('无可用值载入或值为None')
else:
return self._data
class jsonIO:
def __init__(self,fileName:str,data: Any = None) -> None:
'''简单的json操作功能'''
self.file = fileName
if data:
self._data = data
else:
with open (self.file, 'r', encoding='utf-8') as f:
self._data = json.load(f)
def __call__(self, *args: Any, **kwds: Any) -> Any:
return self.data
def write(self):
'''将数据写入json'''
with open (self.file, 'w', encoding='utf-8') as f:
json.dump(self._data, f)
def load(self) -> Any:
'''从文件读取数据'''
with open (self.file, 'r', encoding='utf-8') as f:
self._data = json.load(f)
return self.data
@property
def data(self):
'''返回数据值'''
return self._data
class uniteIO:
def __init__(self,fileName:str,fileType = None,data: Any = None) -> None:
'''简单的文件数据IO操作功能'''
self.filename = fileName
if not fileType is None:
self._type = fileType
else:
try:
with open (self.filename, 'r', encoding='utf-8') as f:
self._type = json
except:
with open (self.file, 'rb') as f:
self._type = pickle
if not data is None:
self._data = data
else:
self._data = self.load()
def __call__(self, *args: Any, **kwds: Any) -> Any:
return self.data
def write(self):
'''将数据写入文件'''
if self._type == json:
self._wfile = open(self.filename, 'w', encoding='utf-8')
elif self._type == pickle:
self._wfile = open(self.file, 'wb')
self._type.dump(self._data, self._wfile)
def load(self) -> Any:
'''从文件读取数据'''
if self._type == json:
self._rfile = open(self.filename, 'r', encoding='utf-8')
elif self._type == pickle:
self._rfile = open(self.file, 'rb')
self._data = self._type.load(self._rfile)
return self.data
@property
def data(self):
'''返回数据值'''
return self._data
if __name__ == '__main__':
from sys import argv
if argv[1]:
input(uniteIO(argv[1]).data)

View File

@ -1,326 +0,0 @@
# -*- coding: utf-8 -*-
'''音·创的GUI窗口界面显示库
:若要使用其他界面显示请详见
:开发说明|指南'''
import tkinter as tk
import tkinter.simpledialog as sdialog
import tkinter.filedialog as fdialog
from msctLib.log import log
DEFAULTBLUE = (0, 137, 242)
# 0089F2
WEAKBLUE = (0, 161, 231)
LIGHTBLUE = (38, 226, 255)
# 26E2FF
RED = (255, 52, 50)
PURPLE = (171, 112, 255)
GREEN = (0, 255, 33)
WHITE = (242, 244, 246)
BLACK = (18, 17, 16)
backgroundColor = WHITE
frontgroundColor = BLACK
loadingColor = DEFAULTBLUE
errorColor = RED
okColor = GREEN
tipsColor = PURPLE
# 注UI界面字体、代码字体
fontPattern = ('DengXian Light', 'Fira Code')
class disp:
'''音·创 的基本Tk窗口显示库'''
def __init__(
self,
root: tk.Tk = tk.Tk(),
debug: bool = False,
title: str = '音·创',
geometry: str = '0x0',
iconbitmap: tuple = ('', ''),
menuWidget: dict = {},
wordView: str = '音·创 Musicreater',
buttons: list = [],
settingBox: list = [],
notemap: list = [],
infobar:str = '就绪',
) -> None:
'''使用参数建立基本的 音·创 窗口
:param root 根窗口
:param debug 是否将日志输出到控制台
:param title 窗口标题
wordview: str #言论部分显示的字样
button: list = [ # 操作按钮部分
dict = {
按钮名称 : tuple(按钮图标,执行函数)
},
],
settingbox: list = [ # 设置部分显示的字样及其对应的设置函数
(
设置名称:str,
值类型:tuple,
显示内容:str,
设置操作函数:<function>,
)
],
map: list = [ # 一首曲目的音符数据
音符数据
]
:param infobar 显示信息用
'''
# 载入参量 注意!图标将不被载入参数
self.__root = root
'''窗口根'''
self.title = title
'''窗口标题'''
self.menuWidgets = menuWidget
'''菜单设定项'''
self.wordView = wordView
'''言·论'''
self.buttons = buttons
'''快捷功能按钮'''
self.settingBox = settingBox
'''设置框'''
self.notemap = notemap
'''音符列表'''
self.infoBar = infobar
'''信息显示版'''
self.debug = debug
'''是否打开调试模式'''
self.setTitle()
self.setGeometry(geometry)
self.setIcon(*iconbitmap)
self.setMenu()
self.initWidget()
# =========================================================
# 设定函数部分
# =========================================================
def setTitle(self) -> None:
'''设置窗口标题'''
self.__root.title = self.title
if self.debug:
log(f"设置窗口标题{self.title}")
def setGeometry(self,geometry:str = '0x0') -> None:
'''设置窗口大小'''
self.__root.geometry(geometry)
if self.debug:
log(f"设置窗口大小{geometry}")
def setIcon(
self, bitmap: str = './musicreater.ico', default: str = ''
) -> None:
'''设置窗口图标
注意default参数仅在Windows下有效其意为将所有没有图标的窗口设置默认图标
如果在非Windows环境使用default参数一个Error将被升起'''
if not self.debug:
try:
if default:
self.__root.iconbitmap(bitmap, default)
log(f'设置图标为{bitmap},默认为{default}')
else:
self.__root.iconbitmap(bitmap)
log(f'设置图标为{bitmap}')
return True
except Exception as e:
log(str(e), 'ERROR')
return False
else:
self.__root.iconbitmap(bitmap, default)
return
def setMenu(self) -> None:
'''设置根菜单'''
if not self.menuWidgets:
# 如果传入空参数则返回当前菜单
try:
return self.RootMenu
except Exception as E:
if self.debug:
raise E
else:
log('无法读取菜单信息', 'WARRING')
# 如果不是空参数则新建菜单
self.RootMenu = {}
self.mainMenuBar = tk.Menu(self.__root)
for menuName, menuCmd in self.menuWidgets.items():
# 取得一个菜单名和一堆菜单函数及其显示名称
menu = tk.Menu(self.mainMenuBar, tearoff=0)
for cmdName, cmdFunc in menuCmd.items():
if cmdName:
menu.add_command(label=cmdName, command=cmdFunc)
else:
menu.add_separator()
self.mainMenuBar.add_cascade(label=menuName, menu=menu)
self.RootMenu[menuName] = menu
self.__root.config(menu=self.mainMenuBar)
def addMenu(self, menuRoot: str = '', menuLabel: str = '', menuCommand=None):
'''增加一个菜单项
:param menuRoot : str
菜单的根菜单即所属的菜单上的文字
:param menuLabel : str
所需要增加的项目显示的文字
:param menuCommand : <function>
'''
if menuRoot in self.RootMenu.keys:
# 如果已经有父菜单
if menuLabel:
# 增加菜单指令
self.RootMenu[menuRoot].add_command(
label=menuLabel, command=menuCommand
)
else:
# 增加分隔栏
self.RootMenu[menuRoot].add_separator()
else:
# 没有父菜单则新增一个父菜单
menu = tk.Menu(self.mainMenuBar, tearoff=False)
if menuLabel:
menu.add_command(label=menuLabel, command=menuCommand)
else:
menu.add_separator()
self.mainMenuBar.add_cascade(label=menuRoot, menu=menu)
self.RootMenu[menuRoot] = menu
def initWidget(self,) -> None:
'''设置窗口小部件,分为:
:· WordView
:快捷按钮面板 ButtonBar
:设置框 SettingBar
:音轨框 TrackBar
:各个音轨的显示框 TrackFrame
:信息显示版 InfoBar
'''
self._wordviewBar = tk.Label(
self.__root, bg='white', fg='black', text=self.wordView, font=(fontPattern[0], 30)
)
self.setWordView(self.wordView)
def setWordView(self, text: str) -> None:
self._wordviewBar['text'] = text
# =========================================================
# 预置函数部分
# =========================================================
def authorWindowStarter(
authors: tuple = (
('金羿', 'Email EillesWan@outlook.com', 'QQ 2647547478'),
('诸葛亮与八卦阵', 'QQ 474037765'),
)
):
'''自定义作者界面'''
from languages.lang import _
from languages.lang import DEFAULTLANGUAGE
from msctLib.buildIN import version
authorWindow = tk.Tk()
authorWindow.title(_('关于'))
authorWindow.geometry('550x600') # 像素
tk.Label(authorWindow, text='', font=('', 15)).pack()
tk.Label(authorWindow, text=_('F音创'), font=('', 35)).pack()
tk.Label(
authorWindow,
text='{} {}'.format(version.version[1] + version.version[0]),
font=('', 15),
).pack()
# pack 的side可以赋值为LEFT RTGHT TOP BOTTOM
# grid 的row 是列数、column是行排注意这是针对空间控件本身大小来的即是指向当前控件的第几个。
# place的 x、y是(x,y)坐标
tk.Label(
authorWindow,
image=tk.PhotoImage(file='./resources/RyounLogo.png'),
width=200,
height=200,
).pack()
tk.Label(authorWindow, text=_('凌云pairs'), font=('', 20)).pack()
tk.Label(authorWindow, text='', font=('', 15)).pack()
tk.Label(authorWindow, text=_('开发者'), font=('', 15)).pack()
for i in authors:
for j in i:
tk.Label(
authorWindow,
text=j,
font=(
'',
17 if i.index(j) == 0 else 15,
'bold' if i.index(j) == 0 else '',
),
).pack()
tk.Label(authorWindow, text='', font=('', 5)).pack()
if DEFAULTLANGUAGE != 'zh-CN':
tk.Label(authorWindow, text=_('译者'), font=('', 15)).pack()
for i in _('TRANSLATERS').split(';'):
for j in i.split(','):
tk.Label(
authorWindow,
text=j,
font=(
'',
17 if i.split(',').index(j) == 0 else 15,
'bold' if i.split(',').index(j) == 0 else '',
),
).pack()
def exitAboutWindow():
authorWindow.destroy()
tk.Button(authorWindow, text=_('确定'), command=exitAboutWindow).pack()
authorWindow.mainloop()
class ProgressBar:
def __init__(
self,
root: tk.Tk = tk.Tk(),
style: tuple = (DEFAULTBLUE, BLACK, WHITE),
type: bool = False,
info: str = '',
debug: bool = False,
) -> None:
'''建立一个进度条或者加载等待界面
:param root : tk.Tk
建立进度条的根窗口
:param style : tuple
设置主题颜色第一个参数为进度条或者等待转圈圈的颜色第二个参数为前景色第三个是背景色
:param type : bool
类型 False 时为进度条 True 时为等待板
:param info : str
显示的附加信息
:param debug : bool
是否输出日志到控制台'''
self.root = root
if __name__ == '__mian__':
import os
os.chdir('../')
disp.authorMenu()

View File

@ -1,6 +0,0 @@
# -*- coding: utf-8 -*-
'''音·创的内置功能库
:若要加入其他功能详见
:开发说明|指南'''

View File

@ -1,82 +0,0 @@
"""音·创的日志消息处理"""
# 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日
# 统计致命三级错误0个警告二级错误0个语法一级错误9个
# 对开发者说的话:
#
# 请不要修改这里的日志,日志是给开发者和专业人士看的
# 而不是给普通用户看的,因此,没必要使用开发者自己也
# 不习惯的日志系统,比如说,之前诸葛亮与八卦阵 (bgArray)
# 用了 logging 库来改写我原来的日志支持,但是我反
# 而找不到我想要的信息了,所以,日志系统给我们开发者
# 自己看得好就可以了昂,真的别改了。而且,诸葛八卦改
# 了之后并没有多好,喵喵喵,所以我就换回来了。我知道
# logging 库比较常用,而且功能也好,但是我们毕竟没
# 这个必要,就别用那个库了昂,球球了~
# ——金羿 Eilles
# 2022 03 09
# To ALL the developers who will change this part:
#
# Please do NOT change anything in this file!
# The log file is only for developers or
# someone who knows a lot about our program
# to see, but not the common users. So it
# is NOT NECESSARY to use a logging system
# that we do not familiar or we do not like.
# Take bgAray “诸葛亮与八卦阵” as a example,
# he once change this `log.py` into
# logging-library-based log support system.
# But after the change had done, I could NOT
# find useful infomation according to the
# log file... So use this file but not to
# make changes PLEASE!!! I know some libraries
# like logging is usually better than the
# simple system in this file and it is normal
# to use but, I think it is not necessery,
# so PLEASE DO NOT USE OTHER LIBs TO
# OVERWRITE MY LIBRARY, THANKS.
# ——Eilles 金羿
# 03/09/2022
import datetime,os
#载入日志功能
StrStartTime = str(datetime.datetime.now()).replace(':', '_')[:-7]
'''字符串型的程序开始时间'''
def log(info:str = '',level : str = 'INFO', isPrinted:bool = True):
'''将信息连同当前时间载入日志
:param info : str
日志信息
:param level : str['INFO','WARRING','ERROR','CRASH']
int[ 1, 2, 3, 4 ]
信息等级
:param isPrinted : bool
是否在控制台打印
:return bool
表示是否完成任务'''
if type(level) == type(1):
level = ['INFO','WARRING','ERROR','CRASH'][level-1]
try:
if not os.path.exists('./logs/'):
os.makedirs('./logs/')
outputinfo = f'{str(datetime.datetime.now())[11:19]}-[{level}] {info}'
with open('./logs/'+StrStartTime+'.msct.log', 'a',encoding='UTF-8') as f:
f.write(outputinfo+'\n')
if isPrinted:
print(outputinfo)
return True
except:
return False

View File

@ -1,25 +0,0 @@
# -*- coding:utf-8 -*-
DEFAULTBLUE = (0, 137, 242)
WEAKBLUE = (0, 161, 231)
LIGHTBLUE = (38, 226, 255)
RED = (255, 52, 50)
PURPLE = (171, 112, 255)
GREEN = (0, 255, 33)
WHITE = (242, 244, 246)
BLACK = (18, 17, 16)
settings = {
'language' : 'zh-CN',
'theme' : {
'' : '',
},
}
class msctSetting:
def __init__(self,**settings) -> None:
pass
def __call__(self, **kwds):
pass

View File

@ -1,243 +0,0 @@
开发说明\|指南
==============
此文件旨在使后期欲参与开发之人员减轻其开发负担,同时也为了我们正在开发的人员详细说明功能与用法
掌握开发指南之后,在调用函数等的过程中将会更加方便
文件结构
--------
从主文件调用display.py以实现显示调用functions.py以使用功能
functions.py中会调取./addon/目录下的全部功能文件,这些功能文件必须先由./addon/addons.pkl来预先定义好
详细说明
--------
### msctLib
用于支持主要功能
#### display.py
1. class disp
- 参数
1. `**kwgs`对窗口的基础设定 `{ '组件名称' : 函数自设定 }` 例如:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ python
{
'version': '0.0.1', # version指的是当前配置格式的版本
'title': "音·创",
'geometry': '1200x900',
'iconbitmap': ('./resources/musicreater.ico', './resources/musicreater.ico'),
'menu' : { #对setMenu有特殊说明
'文件': {
'新建': <function>,
'打开': <function>,
},
},
'widget': { #对窗口部件又详细说明
'wordview':{
'text':'言·论',
},
'settingbox':{}, #后文详细说明
'tracklist':{},
'operation':{},
'map':{},
},
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- 变量
1. `infoBar`
信息显示栏,一个字符串,用于显示一些信息。
2. `title`
窗口标题,字符串
3. `menuWidgets`
对于窗口菜单的设定,其格式如下:
```python
menuWidgets: dist = { # 菜单项目
str"菜单名" : dict{
str"选项名"|None : <function>选项函数
},
...
}
```
注:
`菜单名` : `str` 显示在菜单上的字符串
`选项名` : `str` 显示在菜单选项上的字符串
`选项函数` : `function` 菜单调取的函数(无返回值,无入参)
`选项名` 的布尔值判定为 `False` 的时候,无论 `选项函数` 为何,皆插入一段分割线,但 `选项函数` 不得为空
4. `wordView`
显示在言论上的文字,字符串
5. `buttons`
快捷功能按钮的列表列表的元素为字典字典的键是按钮的名称值为一个元组元组中含有两个元素其中元组的第1个元素为按钮图标是一个图片的路径第2个元素为执行的函数其值应当是一个函数对象。
```python
button: list = [ # 操作按钮部分
dict{
str"按钮名称" : tuple(
按钮图标,
执行函数
)
},
...
],
```
6. `settingBox`
设置框,用于设置音乐的基本属性,例如词作者,曲作者等,设置格式如下:
```python
settingbox: list = [ #设置部分显示的字样及其对应的设置函数
tuple(
设置名称:str,
值类型:tuple,
显示内容:str,
设置操作函数:<function>,
),
...
]
```
其中,值类型可以是如下几个项
1. `('str',)` 字符串类型,使用文本框输入数据
2. `('bool',)` 布尔类型,使用复选框输入数据
3. `('num',最小值:float,最大值:float,步长:float = 1)` 数值类型,使用数值滑动条输入数据
4. `('list',列表项:list)` 单选类型,即列表中多选一,使用单选框输入数据
其中,值操作函数需要有一个参数,用于传递用户提供的设置值。
7. `notemap`
音符数据表,用于存储曲谱信息,存储格式如下
```python
notemap: list = [ # 音轨列表
dict{ # 单个音轨
'instrument' : str"乐器",
'velocity' : int 响度,
# 这里理论上需要写一个小节多少个X分音符
# 以及小节里的都是几分音符
# 但是这个留给以后来支持
int 小节编号 : [ # 一个小节
tuple( # 一个音符
时间 : int,
持续 : int,
乐器 : str,
采样 : float,
响度 : int,
),
...
],
...
},
...
]
```
其中,对于每个音符:
1. 时间 单位:帧 当前音符开始时,距离当前小节开始所经过的帧数
2. 持续 单位:帧 当前音符持续的帧数
3. 乐器 当前音符使用的乐器,需要在乐器列表中有所注册
4. 采样 当前音符在MC的采样音高(不含打击乐器)
5. 响度 单位:格的-1次方 音符播放源距离播放者的距离的倒数
- 函数
1. `setMenu`对菜单的基础设定
```python
{
菜单名 : {
选项名 : 选项函数
}
}
```
注:
`菜单名` : `str` 显示在菜单上的字符串
`选项名` : `str` 显示在菜单选项上的字符串
`选项函数` : `function` 菜单调取的函数(无返回值,无入参)
`选项名` 的布尔值判定为 `False` 的时候,无论 `选项函数` 为何,皆插入一段分割线,但 `选项函数` 不得为空
2. `setWidget`对窗口部件的放置
```python
wordview: dict = { #言论部分显示的字样
'text': str = 显示内容,
# ... 即可用 tk.Label 的参数
},
button: list = [
dict = {
按钮名称 : tuple(按钮图标,执行函数)
},
],
settingbox: list = [ #设置部分显示的字样及其对应的设置函数
(
设置名称:str,
值类型:tuple,
显示内容:str,
设置操作函数:<function>,
)
],
map: list = [
音符数据
]
```
注:
上文中,值类型可以是如下几个项
1. `('str',)` 字符串类型,使用文本框输入数据
2. `('bool',)` 布尔类型,使用复选框输入数据
3. `('num',最小值:int,最大值:int,步长:int = 1)` 数值类型,使用数值滑动条输入数据
4. `('list',列表项:list)` 单选类型,即列表中多选一,使用单选框输入数据
值得注意的是在kwgs中修改的部件设置可以在其变量中读取或热修改对应的变量如下
| 参数 | 对应类中的变量 | 变量类型 | 说明 |
|------------|------------------|---------------------------|---------------------|
| wordview | wordview | str | 显示在 言·论 区域的文字 |
| button | button | list[dict{}] | 操作按钮 |
| settingbox | settings | list[ Any ] | 设置项目中的值 |
| tracklist | tracknum | tuple(int,int) | 当前选择到的音轨与音轨总数|
| map | notes | list[ class Note ] | 当前的音符列表 |
####
全曲的设置应该如下:
```python
标题 : str = '无名'
副标题 : str = ''
作曲 : str = '佚名'
作词 : str = ''
歌曲版权信息 : str = ''
# bpm 暂时不需要
```

View File

@ -1,49 +0,0 @@
# -*- coding: utf-8 -*-
'''此文件为音·创的插件加载程序为了满足各平台需求使用的是CLI界面'''
# W-YI 金羿
# QQ 2647547478
# 音·创 开发交流群 861684859
# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com
# 版权所有 Team-Ryoun 金羿
# 若需转载或借鉴 请附作者
"""
Copyright 2022 Eilles Wan (金羿)
Licensed under the Apache License, Version 2.0 (the 'License');
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an 'AS IS' BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
# 代码写的并非十分的漂亮还请大佬多多包涵本软件源代码依照Apache软件协议公开
# 下面为正文
print("""
· 插件管理
Musicreater PLUGINS Management
""")

View File

View File

@ -1,218 +0,0 @@
import os
import brotli
'''感谢由 Charlie_Ping “查理平” 带来的bdx转换代码'''
class BdxConverter:
__header = "BD@"
__bin_header = b"BDX"
__generator_author = b"&Musicreater"
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):
"""
创建一个bdx文件
: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 open(self.file_path,'a+')
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, block):
"""
给定一个方块 返回此方块在这个bdx中的id和方块data
:param block: {block_name: str,particular_value: int}
:return: bytes
"""
block_id = b"\x07" + self.block_type.index(block["block_name"]).to_bytes(2, byteorder="big", signed=False)
particular_value = block["particular_value"].to_bytes(2, byteorder="big", signed=False)
block_header = block_id + particular_value
return block_header
def obtain_command_block(self, block):
"""
给定一个命令方块返回命令方块各种数据
:param block: {
"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(block["block_name"]).to_bytes(2, byteorder="big", signed=False)
particular_value = block["particular_value"].to_bytes(2, byteorder="big", signed=False)
block_header = block_id + particular_value
for i in [
block["impluse"].to_bytes(4, byteorder="big", signed=False),
bytes(block["command"], encoding="utf-8") + b"\x00",
bytes(block["customName"], encoding="utf-8") + b"\x00",
bytes(block["lastOutput"], encoding="utf-8") + b"\x00",
block["tickdelay"].to_bytes(4, byteorder="big", signed=True),
block["executeOnFirstTick"].to_bytes(1, byteorder="big"),
block["trackOutput"].to_bytes(1, byteorder="big"),
block["conditional"].to_bytes(1, byteorder="big"),
block["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)

View File

@ -1,137 +0,0 @@
# -*- coding: UTF-8 -*-
"""提供错误报告的基本操作及方法 顺便提供版本更新、安装库等功能"""
# 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日
# 统计致命三级错误0个警告二级错误1个语法一级错误72个
import os
def makeZip(sourceDir, outFilename, compression=8, exceptFile=None):
import zipfile
"""使用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', 'requests', 'zhdate'
)
"""当前所需库"""
version = ('0.1.6', 'Delta',)
"""当前版本"""
def __init__(self) -> None:
self.libraries = version.libraries
"""当前所需库"""
self.version = version.version
"""当前版本"""
def installLibraries(self,index:str = 'https://pypi.tuna.tsinghua.edu.cn/simple'):
"""安装全部开发用库"""
from sys import platform
import os
if platform == 'win32':
import shutil
try:
shutil.rmtree(os.getenv('APPDATA') + '\\Musicreater\\')
except FileNotFoundError:
pass
for i in self.libraries:
print("安装库:" + i)
os.system(f"python -m pip install {i} -i {index}")
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(f"sudo python3 -m pip install {i} -i {index}")
def __call__(self):
'''直接安装库,顺便返回一下当前版本'''
self.installLibraries()
return self.version

View File

@ -1,422 +0,0 @@
# -*- 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 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("完成============================")
def makeNewFuncFiles(musicset, path='./', isProsess:bool = False):
"""在指定目录下生成函数文件"""
from msctspt.transfer import newList_conversion_SinglePlayer
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) + '个数据')
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(newList_conversion_SinglePlayer(musicset['musics'][i]['notes'],
musicset['musics'][i]['set']['ScoreboardName'],
musicset['musics'][i]['set']['Instrument']))
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 makeClassFuncFiles(musicset, path='./'):
"""在指定目录下生成函数文件"""
from msctspt.transfer import classList_conversion_SinglePlayer
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_SinglePlayer(musicset['musics'][i]['notes'],
musicset['musics'][i]['set']['ScoreboardName'],
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金羿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 makeClassFunDir(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}")
makeClassFuncFiles(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"])
"""

View File

@ -1,27 +0,0 @@
import threading
class NewThread(threading.Thread):
'''新建一个进程来运行函数,函数运行完毕后可以使用.getResult方法获取其返回值'''
def __init__(self, func, args=()):
super(NewThread, self).__init__()
self.func = func
self.args = args
self.result = None
def run(self):
self.result = self.func(*self.args)
def getResult(self):
threading.Thread.join(self) # 等待线程执行完毕
return self.result
#
# ————————————————
# 版权声明上面的类NewThread修改自CSDN博主「星火燎愿」的原创文章中的内容遵循CC 4.0 BY-SA版权协议转载请附上原文出处链接及本声明。
# 原文链接https://blog.csdn.net/xpt211314/article/details/109543014
# ————————————————
#

View File

@ -1,566 +0,0 @@
"""音·创 的转换工具库"""
# 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日
# 统计致命三级错误0个警告二级错误4个--未解决1个语法一级错误302个
# 可序列化对象,即可迭代对象
from typing import Iterable
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 msctLib.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 classList_conversion_SinglePlayer(List: list, ScoreboardName: str, playerSelection: str = '',
isProsess: bool = False) -> list:
from bgArrayLib.compute import round_up
from bgArrayLib.pitchStrConstant import pitch
from bgArrayLib.instrumentConstant import instrument_list
commands = []
length = len(List)
j = 1
for k in range(len(List)):
i = List[k][0]
try:
commands.append(
f"execute @a{playerSelection} ~ ~ ~ execute @s[scores={{{ScoreboardName}="
f"{str(round_up(i.time_position)).replace('.0', '')}}}] ~ ~{127 - i.velocity} "
f"~ playsound note.{instrument_list.get(str(i.instrument))} @s ~ ~ ~ "
f"1000 {pitch.get(str(i.pitch))} 1000\n")
if isProsess:
commands.append(
f"execute @a{playerSelection} ~ ~ ~ execute @s[scores={{{ScoreboardName}="
f"{str(round_up(i.time_position)).replace('.0', '')}}}] ~ ~ ~ "
f"title @s actionbar §e▶ 播放中: §a{j}/{length} || {int(j / length * 1000) / 10}\n")
j += 1
except Exception:
pass
# a += List[i][1]
# commands.append("\n\n# 凌云我的世界开发团队 x 凌云软件开发团队 : W-YI金羿\n")
return commands
def newList_conversion_SinglePlayer(List: list, ScoreboardName: str, playerSelection: str = '',
isProsess: bool = False) -> list:
from bgArrayLib.compute import round_up
commands = []
length = len(List)
j = 1
print(List)
for k in range(len(List)):
i = List[k][0]
print(i)
print(type(i))
try:
if i.instrument > 119:
pass
else:
commands.append(
f"execute @a{playerSelection} ~ ~ ~ execute @s[scores={{{ScoreboardName}="
f"{str(round_up(i.time_position)).replace('.0', '')}}}] ~ ~{127 - i.velocity} "
f"~ playsound {i.instrument}{i.CD}.{i.pitch} @s ~ ~ ~ 1000 1.0 1000\n")
if isProsess:
commands.append(
f"execute @a{playerSelection} ~ ~ ~ execute @s[scores={{{ScoreboardName}="
f"{str(round_up(i.time_position)).replace('.0', '')}}}] ~ ~ ~ "
f"title @s actionbar §e▶ 播放中: §a{j}/{length} || {int(j / length * 1000) / 10}\n")
j += 1
except:
pass
# a += List[i][1]
# commands.append("\n\n# 凌云我的世界开发团队 x 凌云软件开发团队 : W-YI金羿\n")
print(commands)
return commands
def classList_conversion(List: list, ScoreboardName: str, isProsess: bool = False) -> list:
from bgArrayLib.compute import round_up
commands = []
length = len(List)
j = 1
print(List)
for k in range(len(List)):
i = List[k][0]
print(i)
print(type(i))
try:
if i.instrument > 119:
pass
else:
commands.append("execute @e[scores={" +
ScoreboardName + "=" + str(round_up(i.time_position)).replace(".0", "") + "}] ~ ~" +
str(127 - i.velocity) +
" ~ playsound " +
str(i.instrument) +
str(i.CD) + "." +
str(i.pitch)
+ " @a ~ ~ ~ 1000 1.0 1000\n")
if isProsess:
commands.append("execute @a"" ~ ~ ~ execute @s[scores={" + ScoreboardName + "=" +
str(round_up(i.time_position)).replace(".0", "") +
"}] ~ ~ ~ title @s actionbar §e▶ 播放中: §a" +
str(j) + "/" + str(length) + " || " + str(int(j / length * 1000) / 10) + "\n")
j += 1
except AttributeError:
pass
# a += List[i][1]
# commands.append("\n\n# 凌云我的世界开发团队 x 凌云软件开发团队 : W-YI金羿\n")
print(commands)
return commands
def formCmdBlock(direction: Iterable, command: str, particularValue: int, impluse: int = 0, condition: bool = False,
needRedstone: bool = True, tickDelay: int = 0, customName: str = '', lastOutput: str = '',
executeOnFirstTick: bool = False, trackOutput: bool = True):
"""
使用指定项目返回指定的指令方块格式字典
:param direction: `list[x: int, y: int, z: int]`
方块位置
:param command: `str`
指令
:param particularValue:
方块特殊值即朝向
:0 无条件
:1 无条件
:2 z轴负方向 无条件
:3 z轴正方向 无条件
:4 x轴负方向 无条件
:5 x轴正方向 无条件
:6 无条件
:7 无条件
:8 有条件
:9 有条件
:10 z轴负方向 有条件
:11 z轴正方向 有条件
:12 x轴负方向 有条件
:13 x轴正方向 有条件
:14 有条件
:14 有条件
注意此处特殊值中的条件会被下面condition参数覆写
:param impluse: `int 0|1|2`
方块类型
0脉冲 1循环 2连锁
:param condition: `bool`
是否有条件
:param needRedstone: `bool`
是否需要红石
:param tickDelay: `int`
执行延时
:param customName: `str`
悬浮字
:param lastOutput: `str`
上次输出字符串注意此处需要留空
:param executeOnFirstTick: `bool`
执行第一个已选项(循环指令方块是否激活后立即执行若为False则从激活时起延迟后第一次执行)
:param trackOutput: `bool`
是否输出
: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 nmcsup.trans import Note2Cmd
from msctspt.bdxOpera_CP import BdxConverter
cmd = Note2Cmd(Notes, ScoreboardName, Instrument, PlayerSelect, isProsess)
cdl = []
for i in cmd:
if '#' in i:
if (i[:i.index('#')].replace(' ', '') != '\n') and (i[:i.index('#')].replace(' ', '') != ''):
cdl.append(i[:i.index('#')])
else:
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 music2cmdBlocks(direction: Iterable, music: dict, isProsess: bool = False, height: int = 200,
isSquare: bool = False):
"""使用方法同Note2Cmd
:param 参数说明
filePath: 生成.bdx文件的位置
dire: 指令方块在地图中生成的起始位置相对位置
music: 详见 Musicreater.py - dataset[0]
isProsess: 是否显示进度条会很卡
height: 生成结构的最高高度
isSquare: 生成的结构是否需要遵循生成正方形原则
:return 返回一个列表其中包含了音乐生成的所有的指令方块数据"""
from msctspt.threadOpera import NewThread
allblocks = []
'''需要放置的方块'''
baseDire = direction
direction = list(direction)
def trackDealing(direction,track):
blocks = []
cmdList = classList_conversion_SinglePlayer(track['notes'], track['set']['ScoreboardName'],
music['mainset']['PlayerSelect'], isProsess)
if len(cmdList) == 0:
return []
elif cmdList is []:
return []
dire = direction
down = False
'''当前是否为向下的阶段?'''
# 开头的指令方块
blocks.append(formCmdBlock(dire,
f"scoreboard players add @a{music['mainset']['PlayerSelect']} "
f"{track['set']['ScoreboardName']} 1",
1, 1))
dire[1] += 1
blocks.append(formCmdBlock(dire, cmdList.pop(0), 2, needRedstone=False))
dire[1] += 1
# :0 下 无条件
# :1 上 无条件
# :2 z轴负方向 无条件
# :3 z轴正方向 无条件
# :4 x轴负方向 无条件
# :5 x轴正方向 无条件
for cmd in cmdList:
blocks.append(formCmdBlock(dire, cmd, 5 if (down is False and dire[1] == height + direction[1]) or (
down and dire[1] == direction + 1) else 0 if down else 1, 2, needRedstone=False))
if down:
if dire[1] > direction[1] + 1:
dire[1] -= 1
else:
if dire[1] < height + direction[1]:
dire[1] += 1
if (down is False and dire[1] == height + direction[1]) or (down and dire[1] == direction + 1):
down = not down
dire[0] += 1
return blocks
threads = []
for track in music['musics']:
threads.append(NewThread(trackDealing,(direction,track)))
threads[-1].start()
direction[2] += 2
for th in threads:
allblocks += th.getResult()
return allblocks
def music2BDX(filePath: str, direction: Iterable, music: dict, isProsess: bool = False, height: int = 200,
isSquare: bool = False):
"""使用方法同Note2Cmd
:param 参数说明
filePath: 生成.bdx文件的位置
dire: 指令方块在地图中生成的起始位置相对位置
music: 详见 Musicreater.py - dataset[0]
isProsess: 是否显示进度条会很卡
height: 生成结构的最高高度
isSquare: 生成的结构是否需要遵循生成正方形原则
:return 返回一个BdxConverter类同时在指定位置生成.bdx文件"""
from msctspt.bdxOpera_CP import BdxConverter
return BdxConverter(filePath, 'Build by Ryoun Musicreater', music2cmdBlocks(direction,music,isProsess,height,isSquare)
)
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: Iterable = (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', 'notebooks',
{"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'
}
}
"""

View File

@ -1,56 +0,0 @@
# 诸葛亮与八卦阵帮忙修改语法 日期:---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音高:音符盒音调'''

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More