17TheWord / nonebot-plugin-mcqq

基于NoneBot的与Minecraft Server互通消息的插件
MIT License
94 stars 5 forks source link

【功能建议】原版我的世界服务端支持、其他建议 #2

Closed Todysheep closed 1 year ago

Todysheep commented 2 years ago

原版我的世界服务端无法加载插件,但这不妨碍消息转发,有一办法是检查log文件是否更新,若有更新则向机器人端发送最新消息 向原版服务器发送消息的替代方案是/tellraw(我推荐这个)或者/say指令,通过服务器配置RCON执行命令(py库参考:mcrcon,mctools等)

服务器指令可通过QQ端使用,并可选是否返回指令执行结果

17TheWord commented 2 years ago

很不错的建议,而且感觉不止可以应用于原版端,甚至纯MOD端也可以使用?
但是这一系列操作对我来说已经超纲了,实现起来会很困难。
发送游戏消息到QQ已经有思路了,但QQ到服务器还在构思 。 如果可以的话,可以提供一些代码来帮助我一起实现这个功能。

对于QQ端使用命令,期初只是想实现消息互通的功能,并没有考虑太多,但可以加入日程

Todysheep commented 2 years ago

由QQ到服务器可以使用原版服务端自带的 RCON协议 在python中可以使用 mcron库 tellraw指令如果不了解可以用 https://www.minecraftjson.com 生成 tellraw指令可以使玩家通过点击文本打开外部链接,可以提取图片直链允许玩家查看图片 QQ端使用命令把QQ到服务器消息转发做好顺带地就做上了(

from mcron import MCRcon

mcr = MCRcon("127.0.0.1","1",25575) #(RCON地址,RCON密码,RCON端口)
#或使用 with MCRcon("127.0.0.1","1",25575) as mcr 使执行完毕后断开RCON连接

mcr.connect() #机器人启动时尝试链接,机器人应提供指令以防连接失败
#一些文本处理(若以某字段开头,则认为是执行指令操作)
#username = 用户名
#message = 发送的消息

#普通消息
word = f'/tellraw @a \{"text":"[{username}]{message}","color":"white"\}'  
#含有链接的消息示例
word = '/tellraw @a \{"text":"这是一个链接","clickEvent":\{"action":"open_url","value":"bilibili.com/BV1GJ411x7h7"\}\}' 

mcr.command(word) #执行命令
mcr.disconnect() #需要时时断开连接
17TheWord commented 2 years ago

感谢你的回复。
更换到 mcrcon 需要重写 mcqq,尤其是 QQ 发送到 MC 的每一种消息需要重新构造。
这些更改已经开始做了,距离实用还需要一段时间。

Todysheep commented 2 years ago

也感谢你为开发mcqq插件做出的努力,期待最终成品!

17TheWord commented 2 years ago

Bot 端发送到 MCRcon 端的消息处理(只处理消息,暂不支持处理命令)已基本完成,稍后上传到新的分支 mcrcon_mcqq

Minecraft Server 端发送到 Bot 端,还是没有找到合适的方法。

Todysheep commented 2 years ago

我认为没有新增内容的原因可能是文件被占用没有进行更新 由于没用使用过JAVA,我使用python提供一下思路:

import time

path = r"F:\MinecraftServer\test\server\logs\latest.log"
pos = 0 #最后读取行

while True:
    fd = open(path)

    if pos != 0:
        fd.seek(pos,0)
    while True:
        line = fd.readline()
        if line.strip():
            print (line.strip())
        pos = pos + len(line)
        if not line.strip():
            break

    fd.close() #释放文件占用使服务器写入最新文件
    time.sleep(1) #等待

执行效果: image

17TheWord commented 2 years ago

在今天,我用了你给的代码和网上找到的代码,它们都可以获取到log的信息并打印到控制台
但我在建立websocket通信的时候碰到了困难:

async def hello(): global websocket uri = "ws://localhost:8765" try: async with websockets.connect(uri) as websocket: await listen_log() except Exception: await hello()

if name == "main": asyncio.run(hello())


- Bot 端:
  - 建立 websocket 服务端,获取消息并打印(测试阶段)
  - 但控制台每次只打印一批信息,重启 websocket 客户端之后会再次打印一条批新的信息
  - 代码如下:
```python
# Bot 连接时
@driver.on_bot_connect
async def do_something():
    try:
        await websockets.serve(echo, 'localhost', 8765)
        mcr.connect()
    except ConnectionRefusedError:
        nonebot.logger.error("[MC_QQ]丨连接 MCRcon 失败!")

async def echo(websocket, path):
    try:
        async for message in websocket:
            print(message)
    except websockets.exceptions.ConnectionClosedError:
        async for message in websocket:
            print(message)

很遗憾,我的技术能力有限,无法完成这项功能

Todysheep commented 2 years ago

考虑到只有服务器到QQ的单方向通信,是否可以使用FastAPI构建API使得可以通过GET方式获取最新消息

path = r"F:\MinecraftServer\test\server\logs\latest.log" temp = "temp.log" #缓存文件 pos = 0

while True: fd = open(path)

if pos != 0:
    fd.seek(pos,0)
while True:
    line = fd.readline()
    if line.strip():
        with open(temp,"a") as file:
            file.write(line)
    pos = pos + len(line)
    if not line.strip():
        break

fd.close() #释放文件占用使服务器写入最新文件
time.sleep(1) #等待
```python
#API读取缓存(文件名:main.py)
#在命令行使用 uvicorn main:app --port 12345 --reload 在localhost:12345创建api
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    with open('temp.log','r+') as file:
        result = []
        for i in file.readlines():
            result.append(i.strip())
        file.truncate(0) #清空缓存文件
    return result
#模拟前端
import time
import requests

api = "http://localhost:12345"

while True:
    file = requests.get(url=api)
    data = file.json()
    for i in data:
        print(i)
    time.sleep(0.1)
17TheWord commented 2 years ago

我已经解决了,通过另一段从网上找到的 Java 程序,并成功将消息发送到了 Bot 端

传输的消息:[13:25:50] [Server thread/INFO]: <17TheWord> 1

能成功传输信息是个好的开端,这些内容将在之后进行补充

17TheWord commented 2 years ago

更新完毕了,可以查看文档和不同分支的代码。

17TheWord commented 1 year ago

已在 v0.1.5 更新指令功能