Skip to main content

SDK、GDScript

介绍

GDScript SDK 适用于使用 GDScript 的 Godot 项目。

GDScript SDK 提供了与 ioGame 游戏服务器交互的简单封装,内部使用 Protobuf 数据协议通信。 配合上代码生成能避免编写大量的模板代码, 从而帮助客户端开发者减少巨大的工作量。

安装

通过 AssetLib 搜索 ooGame 并下载 An



点击 Install 按钮,将 sdk 安装到 addons 插件目录中。 An



安装后 addons 目录会多出 sdk 相关文件 An

An

SDK 设置

添加一个 my_net_config.gd 文件,用于配置 sdk 相关内容

class_name MyNetConfig
extends RefCounted

static var _socket: MyNetChannel = MyNetChannel.new()
static var current_time_millis: int = 0

static func start_net():
# --------- IoGameSetting ---------
var setting := IoGame.IoGameSetting
setting.enable_dev_mode = true
setting.set_language(IoGame.IoGameLanguage.Us)
# message callback. cn: 回调监听
setting.listen_message_callback = MyListenMessageCallback.new()
# set socket. cn: 设置网络连接
setting.net_channel = _socket

socket_init()
setting.start_net()


static func poll():
_socket.poll()


static var _heartbeat_message_bytes := IoGame.Proto.ExternalMessage.new().to_bytes()
static var _heartbeat_counter: int = 1

static func send_idle() -> void:
_heartbeat_counter += 1
#print("-------- ..HeartbeatMessage {%s}" % [_heartbeat_counter])
IoGame.IoGameSetting.net_channel.write_and_flush_byte(_heartbeat_message_bytes)


class MyListenMessageCallback extends IoGame.ListenMessageCallback:
func on_idle_callback(message: Proto.ExternalMessage):
var data_bytes := message.get_data()
var long_value := IoGame.Proto.LongValue.new()
long_value.from_bytes(data_bytes)
# Synchronize the time of each heartbeat with that of the server.
# cn: 每次心跳与服务器的时间同步
MyNetConfig.current_time_millis = long_value.get_value()


class MyNetChannel extends IoGame.SimpleNetChannel:
var _last_state: WebSocketPeer.State = WebSocketPeer.State.STATE_CLOSED
var _socket: WebSocketPeer = WebSocketPeer.new()
var _url: String = "ws://127.0.0.1:10100/websocket"

var on_open: Callable = func():
print("on_open")

var on_connecting: Callable = func():
print("on_connecting")

var on_connect_error: Callable = func(error: int):
print("on_connect_error:", error)

var on_closing: Callable = func():
print("on_closing")

var on_closed: Callable = func():
print("on_closed")

func prepare() -> void:
if _url == null or _url.is_empty():
_url = IoGame.IoGameSetting.url

var error: int = _socket.connect_to_url(_url)

if error != 0:
on_connect_error.call(error)
return

_last_state = _socket.get_ready_state()


func write_and_flush_byte(bytes: PackedByteArray) -> void:
_socket.send(bytes)

func poll() -> void:
if _socket.get_ready_state() != WebSocketPeer.State.STATE_CLOSED:
_socket.poll()

while _socket.get_available_packet_count() > 0:
var packet := _socket.get_packet()
var message := IoGame.Proto.ExternalMessage.new()
message.from_bytes(packet)
self.accept_message(message)

var state: WebSocketPeer.State = _socket.get_ready_state()
if _last_state == state:
return

_last_state = state

match state:
WebSocketPeer.State.STATE_OPEN:
on_open.call()
WebSocketPeer.State.STATE_CONNECTING:
on_connecting.call()
WebSocketPeer.State.STATE_CLOSING:
on_closing.call()
WebSocketPeer.State.STATE_CLOSED:
on_closed.call()
_:
printerr("Socket Unknown Status.")

如何生成 .proto

生成 .proto 需要使用 godobuf 库, 下面做一些简单的安装演示,更详细的安装说明可到该库上阅读 README.md 内容。

下载 godobuf 库到本地

git clone https://github.com/oniksan/godobuf.git

将 addons/protobuf 目录复制到项目的 addons 目录中。

An



现在,Godot 工具中目录如下

gds_p2

启用 godobuf 插件 An



现在,会多出 Godobuf tab,通过此 tab 开发者将 .proto 转换为 .gd 文件

gds_p4

Input protobuf file: 选择你想编译的 .proto Output GDScript file: 是 .proto 编译后的输出目录。

注意,编译后 proto 文件一定要放在 gen 目录下。 An



./gen/code 目录中的 action、广播、错误码 ...等交互接口文件由 ioGame 生成。 代码生成可为客户端开发者减少巨大的工作量,代码使用简单,与本地方法调用一般丝滑。

gds_p6

处理错误码

以下分别展示了 callback、async await 两种编码风格对于错误的处理。

SdkAction 由 ioGame 生成。

func int_func():
print("-------- OnIntValue --------")
var value: int = 1

# code style: callback.
SdkAction.of_int_value(value, func(result: IoGame.ResponseResult):
result.log(result.get_int())
).on_error(func(result: IoGame.ResponseResult):
var error_code := result.get_response_status()
print("error_code: ", error_code)
print("error_info: ", result.get_error_info())
)

# code style: async await.
var _result := await SdkAction.of_await_int_value(value)
if _result.success():
_result.log(_result.get_int())
else:
var error_code := _result.get_response_status()
print("error_code: ", error_code)
print("error_info: ", _result.get_error_info())

注意事项

获取网络数据

see https://docs.godotengine.org/en/stable/tutorials/networking/websocket.html#using-websocket-in-godot

需要在 _process(_delta) 方法中调用 MyNetConfig.poll() 方法,接收网络数据

extends Node
...
func _ready():
MyNetConfig.start_net()

func _process(_delta):
# cn: 接收网络数据
# Call this in _process or _physics_process.
# Data transfer, and signals emission will only happen when calling this function.
MyNetConfig.poll()