websocket播放支持

This commit is contained in:
EillesWan 2024-05-01 01:16:05 +08:00
parent c17ff0e53a
commit 382b0e1601
10 changed files with 197 additions and 73 deletions

1
.gitignore vendored
View File

@ -23,6 +23,7 @@ RES.txt
/Packer/*.MPK /Packer/*.MPK
/Packer/checksum.txt /Packer/checksum.txt
/bgArrayLib /bgArrayLib
/fcwslib
# Byte-compiled / optimized # Byte-compiled / optimized
__pycache__/ __pycache__/

View File

@ -23,7 +23,6 @@
3. Apache 2.0 License. 3. Apache 2.0 License.
5. A copy of the original Apache Lisence 2.0 can be found below. 5. A copy of the original Apache Lisence 2.0 can be found below.
```text ```text
Apache License Apache License
Version 2.0, January 2004 Version 2.0, January 2004

View File

@ -17,8 +17,8 @@ Terms & Conditions: License.md in the root directory
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md # 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
__version__ = "2.0.0" __version__ = "2.1.0"
__vername__ = "全新组织架构" __vername__ = "Websocket支持"
__author__ = ( __author__ = (
("金羿", "Eilles Wan"), ("金羿", "Eilles Wan"),
("诸葛亮与八卦阵", "bgArray"), ("诸葛亮与八卦阵", "bgArray"),

View File

@ -1,40 +0,0 @@
# -*- coding: utf-8 -*-
"""
存放有关WebSocket服务器操作的内容
"""
"""
版权所有 © 2024 · 开发者
Copyright © 2024 all the developers of Musicreater
开源相关声明请见 仓库根目录下的 License.md
Terms & Conditions: License.md in the root directory
"""
# 睿乐组织 开发交流群 861684859
# Email TriM-Organization@hotmail.com
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
import fcwslib
# 这个库有问题,正在检修
class Plugin(fcwslib.Plugin):
async def on_connect(self) -> None:
print("对象已被连接")
await self.send_command("list", callback=self.list)
await self.subscribe("PlayerMessage", callback=self.player_message)
async def on_disconnect(self) -> None:
print("对象停止连接")
async def on_receive(self, response) -> None:
print("已接收非常规回复 {}".format(response))
async def list(self, response) -> None:
print("已收取指令执行回复 {}".format(response))
async def player_message(self, response) -> None:
print("已收取玩家事件回复 {}".format(response))

View File

@ -11,19 +11,120 @@ Terms & Conditions: License.md in the root directory
# Email TriM-Organization@hotmail.com # Email TriM-Organization@hotmail.com
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md # 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
import fcwslib import fcwslib
import asyncio
import uuid
import time
# from ...main import MidiConvert from ...main import MidiConvert
from ...subclass import ProgressBarStyle
from ...types import Optional, Literal, Tuple, List
# from ..main import ConvertConfig from ...subclass import MineCommand
# from ...subclass import MineCommand
# def open_websocket_server( def to_websocket_server(
# midi_cvt: MidiConvert, midi_cvt_lst: List[MidiConvert],
# data_cfg: ConvertConfig, server_dist: str,
# player: str = "@a", server_port: int,
# server_dist: str = "localhost", progressbar_style: Optional[ProgressBarStyle],
# server_port: int = 8000, ) -> None:
# ): """
# wssever = fcwslib.Server(server=server_dist,port=server_port,debug_mode=False) 将midi以延迟播放器形式转换为mcstructure结构文件后打包成附加包并在附加包中生成相应地导入函数
Parameters
----------
midi_cvt: List[MidiConvert]
一组用于转换的MidiConvert对象
server_dist: str
WebSocket播放服务器开启地址
server_port: str
WebSocket播放服务器开启端口
progressbar_style: ProgressBarStyle 对象
进度条对象
Returns
-------
None
"""
replacement = str(uuid.uuid4())
musics = dict(
[
(k.music_name, k.to_command_list_in_delay(replacement)[:2])
for k in midi_cvt_lst
]
)
class Plugin(fcwslib.Plugin):
async def on_connect(self) -> None:
print("已成功获连接")
await self.send_command("list", callback=self.cmd_feedback)
await self.subscribe("PlayerMessage", callback=self.player_message)
async def on_disconnect(self) -> None:
print("连接已然终止")
await self.disconnect()
async def on_receive(self, response) -> None:
print("已收取非已知列回复 {}".format(response))
async def cmd_feedback(self, response) -> None:
print("已收取指令执行回复 {}".format(response))
async def player_message(self, response) -> None:
print("已收取玩家事件回复 {}".format(response))
if response["body"]["message"].startswith(("。播放", ".play")):
whom_to_play: str = response["body"]["sender"]
music_to_play: str = (
response["body"]["message"]
.replace("。播放", "")
.replace(".play", "")
.strip()
)
if music_to_play in musics.keys():
self.check_play = True
delay_of_now = 0
for cmd in musics[music_to_play][0]:
if not self.check_play:
break
_time = time.time()
if progressbar_style:
await self.send_command(
"title {} actionbar {}".format(
whom_to_play,
progressbar_style.play_output(
played_delays=delay_of_now,
total_delays=musics[music_to_play][1],
music_name=music_to_play,
),
),
callback=self.cmd_feedback,
)
await self.send_command(
cmd.command_text.replace(replacement, whom_to_play),
callback=self.cmd_feedback,
)
delay_of_now += cmd.delay
await asyncio.sleep((time.time() - _time) + cmd.delay / 20)
else:
await self.send_command(
"tellraw {} {}{}{}".format(
whom_to_play,
r'{"rawtext":[{"text":"§c§l所选歌曲',
music_to_play,
'无法播放:播放列表不存在之"}]}',
),
callback=self.cmd_feedback,
)
elif response["body"]["message"].startswith(
("。停止播放", ".stopplay", ".stoplay")
):
self.check_play = False
server = fcwslib.Server(server=server_dist, port=server_port, debug_mode=True)
server.add_plugin(Plugin)
asyncio.run(server.run_forever())

View File

@ -662,9 +662,21 @@ class ProgressBarStyle:
def __init__(self, base_s: str, to_play_s: str, played_s: str): def __init__(self, base_s: str, to_play_s: str, played_s: str):
"""用于存储进度条样式的类 """用于存储进度条样式的类
| 标识符 | 指定的可变量 |
|---------|----------------|
| `%%N` | 乐曲名(即传入的文件名)|
| `%%s` | 当前计分板值 |
| `%^s` | 计分板最大值 |
| `%%t` | 当前播放时间 |
| `%^t` | 曲目总时长 |
| `%%%` | 当前进度比率 |
| `_` | 用以表示进度条占位|
:param base_s 基础样式用以定义进度条整体 :param base_s 基础样式用以定义进度条整体
:param to_play_s 进度条样式尚未播放的样子 :param to_play_s 进度条样式尚未播放的样子
:param played_s 已经播放的样子""" :param played_s 已经播放的样子
"""
self.base_style = base_s self.base_style = base_s
self.to_play_style = to_play_s self.to_play_style = to_play_s
self.played_style = played_s self.played_style = played_s
@ -704,11 +716,47 @@ class ProgressBarStyle:
dst = ProgressBarStyle(self.base_style, self.to_play_style, self.played_style) dst = ProgressBarStyle(self.base_style, self.to_play_style, self.played_style)
return dst return dst
def play_output(
self,
played_delays: int,
total_delays: int,
music_name: str = "无题",
) -> str:
"""
直接依照此格式输出一个进度条
:param played_delays: int 当前播放进度积分值
:param total_delays: int 乐器总延迟数积分数
:param music_name: str 曲名
"""
return (
self.base_style.replace(r"%%N", music_name)
.replace(r"%%s", str(played_delays))
.replace(r"%^s", str(total_delays))
.replace(r"%%t", mctick2timestr(played_delays))
.replace(r"%^t", mctick2timestr(total_delays))
.replace(r"%%%", str(int(10000 * played_delays / total_delays) / 100) + "%")
.replace(
"_",
self.played_style,
(played_delays * self.base_style.count("_") // total_delays) + 1,
)
.replace("_", self.to_play_style)
)
def mctick2timestr(mc_tick: int) -> str:
"""
我的世界的游戏刻计转为表示时间的字符串
"""
return "{:0>2d}:{:0>2d}".format(mc_tick // 1200, (mc_tick // 20) % 60)
DEFAULT_PROGRESSBAR_STYLE = ProgressBarStyle( DEFAULT_PROGRESSBAR_STYLE = ProgressBarStyle(
r"%%N [ %%s/%^s %%% __________ %%t|%^t ]", r"%%N [ %%s/%^s %%% §e__________§r %%t|%^t ]",
r"§e=§r", r"§7=",
r"§7=§r", r"=",
) )
""" """
默认的进度条样式 默认的进度条样式

View File

@ -24,7 +24,7 @@ from .constants import (
MC_PITCHED_INSTRUMENT_LIST, MC_PITCHED_INSTRUMENT_LIST,
MM_INSTRUMENT_RANGE_TABLE, MM_INSTRUMENT_RANGE_TABLE,
) )
from .subclass import SingleNote, MineNote from .subclass import SingleNote, MineNote, mctick2timestr
from .types import ( from .types import (
Any, Any,
@ -38,12 +38,6 @@ from .types import (
) )
def mctick2timestr(mc_tick: int) -> str:
"""
我的世界的游戏刻计转为表示时间的字符串
"""
return str(int(int(mc_tick / 20) / 60)) + ":" + str(int(int(mc_tick / 20) % 60))
def empty_midi_channels(channel_count: int = 17, staff: Any = {}) -> Dict[int, Any]: def empty_midi_channels(channel_count: int = 17, staff: Any = {}) -> Dict[int, Any]:
""" """

View File

@ -52,6 +52,7 @@
``` ```
- 克隆仓库并安装最新版本但**不推荐** - 克隆仓库并安装最新版本但**不推荐**
```bash ```bash
git clone https://gitee.com/TriM-Organization/Musicreater.git git clone https://gitee.com/TriM-Organization/Musicreater.git
cd Musicreater cd Musicreater

View File

@ -7,14 +7,14 @@ console = Console()
def main(): def main():
with console.status("Find the full path of .egg-info folder"): with console.status("寻众迹于 .egg-info 内"):
egg_info: list = [] egg_info: list = []
for file in os.listdir(): for file in os.listdir():
if file.endswith(".egg-info"): if file.endswith(".egg-info"):
egg_info.append(file) egg_info.append(file)
console.print(file) console.print(file)
for file in track( for file in track(
["build", "dist", "logs", *egg_info], description="Deleting files" ["build", "dist", "logs", *egg_info], description="正删档"
): ):
if os.path.isdir(file) and os.access(file, os.W_OK): if os.path.isdir(file) and os.access(file, os.W_OK):
shutil.rmtree(file) shutil.rmtree(file)

20
example_websocket.py Normal file
View File

@ -0,0 +1,20 @@
import Musicreater
import Musicreater.plugin
import Musicreater.plugin.websocket
import os
dire = input("midi目录")
print(
Musicreater.plugin.websocket.to_websocket_server(
[
Musicreater.MidiConvert.from_midi_file(
os.path.join(dire,names), old_exe_format=False
) for names in os.listdir(dire,) if names.endswith((".mid",".midi"))
],
input("服务器地址:"),
int(input("服务器端口:")),
Musicreater.DEFAULT_PROGRESSBAR_STYLE,
)
)