Godot Websocket¶
由 ChrisLR 贡献于 2022 年
此模块允许您将 Godot 客户端直接连接到您的 MUD,并在 Godot 的 RichTextLabel 中使用 BBCode 显示带颜色的常规文本。您可以使用 Godot 提供具有适当 Evennia 支持的高级功能。
安装¶
您需要在 settings.py
中添加以下设置并重启 Evennia。
PORTAL_SERVICES_PLUGIN_MODULES.append('evennia.contrib.base_systems.godotwebsocket.webclient')
GODOT_CLIENT_WEBSOCKET_PORT = 4008
GODOT_CLIENT_WEBSOCKET_CLIENT_INTERFACE = "127.0.0.1"
这将使 Evennia 在端口 4008 上监听 Godot。您可以根据需要更改端口和接口。
用法¶
简而言之,就是使用 Godot Websocket 连接到上面定义的端口。这将允许您从 Evennia 向 Godot 传输数据,使您能够在启用 BBCode 的 RichTextLabel 中获取样式化文本,或根据需要处理来自 Evennia 的额外数据。
本节假设您具备基本的 Godot 使用知识。您可以阅读以下网址以获取有关 Godot Websockets 的更多详细信息,并实现一个最小客户端,或查看此页面底部的完整示例。
https://docs.godotengine.org/en/stable/tutorials/networking/websocket.html
本文档的其余部分将针对 Godot 4。请注意,这里显示的一些代码部分取自官方 Godot 文档。
在 Godot 中进行非常基本的设置需要:
一个 RichTextLabel 节点来显示 Evennia 输出,确保启用了 BBCode。
一个节点用于您的 websocket 客户端代码,并附加一个新脚本。
一个 TextEdit 节点用于输入命令。
一个按钮节点用于按下并发送命令。
布局控件,在本例中我使用了:
Panel
VBoxContainer
RichTextLabel
HBoxContainer
TextEdit
Button
我不会详细介绍布局的工作原理,但 Godot 文档中可以轻松获取相关文档。
打开您的客户端代码脚本。
我们需要定义通向您的 MUD 的 URL,使用您在 Evennia 设置中使用的相同值。接下来,我们编写一些基本代码以建立连接。这将在场景准备好时连接,在接收到数据时轮询并打印数据,并在场景退出时关闭连接。
extends Node
# 我们将连接的 URL。
var websocket_url = "ws://127.0.0.1:4008"
var socket := WebSocketPeer.new()
func _ready():
if socket.connect_to_url(websocket_url) != OK:
print("无法连接。")
set_process(false)
func _process(_delta):
socket.poll()
match socket.get_ready_state():
WebSocketPeer.STATE_OPEN:
while socket.get_available_packet_count():
print(socket.get_packet().get_string_from_ascii())
WebSocketPeer.STATE_CLOSED:
var code = socket.get_close_code()
var reason = socket.get_close_reason()
print("WebSocket 已关闭,代码: %d, 原因 %s. 清理: %s" % [code, reason, code != -1])
set_process(false)
func _exit_tree():
socket.close()
此时,您可以启动您的 Evennia 服务器,运行 Godot,它应该会打印一个默认回复。之后,您需要正确处理 Evennia 发送的数据。为此,我们将添加一个新函数以正确分派消息。
下面是一个示例:
func _handle_data(data):
print(data) # 用于调试的打印
var data_array = JSON.parse_string(data)
# 第一个元素可以用来查看是否是文本
if data_array[0] == 'text':
# 第二个元素包含消息
for msg in data_array[1]:
write_to_rtb(msg)
func write_to_rtb(msg):
output_label.append_text(msg)
第一个元素是类型,如果是消息则为 text
。它可以是您提供给 Evennia msg
函数的任何内容。第二个元素将是与消息类型相关的数据,在这种情况下,它是要显示的文本列表。由于它是解析过的 BBCode,我们可以通过调用 RichTextLabel 的 append_text 方法直接添加到它。
如果您希望在 Godot 中实现比花哨文本更好的功能,您将需要利用 Evennia 的 OOB 发送额外数据。
您可以在这里阅读有关 OOB 的更多信息。
现在要发送数据,我们连接按钮按下信号到一个方法,读取标签输入并通过 websocket 发送,然后清除标签。
func _on_button_pressed():
var msg = text_edit.text
var msg_arr = ['text', [msg], {}]
var msg_str = JSON.stringify(msg_arr)
socket.send_text(msg_str)
text_edit.text = ""
已知问题¶
直接从 Evennia .DB 发送 SaverDicts 和类似对象会导致问题,请在这样做之前将它们转换为 dict() 或 list()。
完整示例脚本¶
extends Node
# 我们将连接的 URL。
var websocket_url = "ws://127.0.0.1:4008"
var socket := WebSocketPeer.new()
@onready var output_label = $"../Panel/VBoxContainer/RichTextLabel"
@onready var text_edit = $"../Panel/VBoxContainer/HBoxContainer/TextEdit"
func _ready():
if socket.connect_to_url(websocket_url) != OK:
print("无法连接。")
set_process(false)
func _process(_delta):
socket.poll()
match socket.get_ready_state():
WebSocketPeer.STATE_OPEN:
while socket.get_available_packet_count():
var data = socket.get_packet().get_string_from_ascii()
_handle_data(data)
WebSocketPeer.STATE_CLOSED:
var code = socket.get_close_code()
var reason = socket.get_close_reason()
print("WebSocket 已关闭,代码: %d, 原因 %s. 清理: %s" % [code, reason, code != -1])
set_process(false)
func _handle_data(data):
print(data) # 用于调试的打印
var data_array = JSON.parse_string(data)
# 第一个元素可以用来查看是否是文本
if data_array[0] == 'text':
# 第二个元素包含消息
for msg in data_array[1]:
write_to_rtb(msg)
func write_to_rtb(msg):
output_label.append_text(msg)
func _on_button_pressed():
var msg = text_edit.text
var msg_arr = ['text', [msg], {}]
var msg_str = JSON.stringify(msg_arr)
socket.send_text(msg_str)
text_edit.text = ""
func _exit_tree():
socket.close()
此文档页面并非由 evennia/contrib/base_systems/godotwebsocket/README.md
自动生成。如想阅读最新文档,请参阅原始README.md文件。