iohao-sdk
v21.0.1
Published
ioGame TypeScript SDK; Protobuf、Netty、WebSocket
Downloads
395
Maintainers
Readme
EN
Introduction
The ioGame TypeScript SDK provides a simple wrapper for interaction between the Netty, WebSocket, Protobuf, TypeScript, and ioGame game servers.
The SDK offers two non-blocking API coding styles for the active request approach. Both can accomplish the same task, and developers can choose to use them according to their own business needs. The interaction APIs provided by the SDK include:
- Request/ResponseCallback
- Request/Void
- Broadcast Callback
- Error Callback
Ts SDK + Code Generation = a variety of advantages
Advantages of SDK Code Generation
- Helps client-side developers reduce significant workload by eliminating the need to write a large amount of template code.
- Clear and semantically precise. The generated interaction code clearly defines parameter types and return types.
- Ensures parameter type safety and clarity in interface methods, effectively avoiding security risks and reducing basic errors during integration.
- Reduces communication costs between the server and client during integration; the code serves as documentation. The generated integration code includes documentation and usage examples, and the examples on the methods will guide you on how to use them, making it zero-learning-cost even for beginners.
- Helps client-side developers abstract away the interaction with the server, allowing them to focus more on the core business logic.
- Reduces the cognitive load during integration. The code is simple to use, similar to local method calls.
- Abandons the traditional protocol-based approach in favor of an interface-method-based integration approach.
About examples
- CocosCreator: https://github.com/iohao/ioGameSdkTsExampleCocos
- Vue: https://github.com/iohao/ioGameSdkTsExampleVue
- (webpack: html + ts): https://github.com/iohao/ioGameSdkTsExampleHtml
Installation
npm i iohao-sdk
Examples
Establish a connection with the ioGame server.
// --------- IoGameSetting ---------
ioGameSetting.enableDevMode = true;
// China or Us
ioGameSetting.language = ioGameLanguage.CHINA;
// connect url
ioGameSetting.url = "ws://127.0.0.1:10100/websocket";
ioGameSetting.startNet();
code style - 1: callback. Advantages: simple, integrated.
This request method is non-blocking. Developers can set up response callbacks and error callbacks.
// code style: callback. Advantages: simple, integrated.
RequestCommand.ofString(cmdMerge, "hello").onCallback(result => {
console.log(`print-1 ${result.getInt()}`)
}).execute();
// code style: callback. Advantages: simple, integrated.
RequestCommand.ofString(cmdMerge, "hello").onCallback(result => {
// ResponseCallback
console.log(`print-1 ${result.getInt()}`)
}).onError(result => {
// Error Callback
console.log(`errorCode:${result.getResponseStatus()} - `, result.getErrorInfo())
}).execute();
code style - 2: async await. Advantages: Avoid callback hell.
This request method is non-blocking and is implemented using the await Promise mechanism.
// code style: async await. Advantages: Avoid callback hell.
const result = await RequestCommand.ofAwaitString(cmdMerge, "hello");
console.log(`ofAwait-1 ${result.getString()}`);
// code style: async await. Advantages: Avoid callback hell.
const result = await RequestCommand.ofAwaitString(cmdMerge, "hello");
if (result.hasError()) {
// Error process
console.log(`ErrorInfo ${result.getErrorInfo()}`);
}
console.log(`ofAwait-1 ${result.getString()}`);
Broadcasting
It is mainly used to listen to the broadcasts from the server. When a broadcast is detected, the corresponding callback method will be triggered.
ListenCommand.of(cmdMerge).onCallback(result => {
// Broadcast Callback
result.log(`Listen ${result.getString()}`);
});
More examples
Request/ResponseCallback:Testing of a single object.
const cmd = 1;
// int value
const intValue = 1234;
RequestCommand.ofInt(CmdKit.merge(cmd, 2), intValue).onCallback(result => {
console.log(`ofInt ${result.getInt()}`);
}).execute();
// long value
const longValue = BigInt("9223372036854775807")
RequestCommand.ofLong(CmdKit.merge(cmd, 3), longValue).onCallback(result => {
console.log(`ofLong ${result.getLong()}`);
}).execute();
// boolean value
const boolValue = true;
RequestCommand.ofBool(CmdKit.merge(cmd, 4), boolValue).onCallback(result => {
console.log(`ofBool ${result.getBool()}`);
}).execute();
// string value
const stringValue = "string-000";
RequestCommand.ofString(CmdKit.merge(cmd, 5), stringValue).onCallback(result => {
console.log(`ofString ${result.getString()}`);
}).execute();
// protobuf object
const loginVerify = create(LoginVerifyMessageSchema, {jwt: "1"});
const data = toBinary(LoginVerifyMessageSchema, loginVerify);
RequestCommand.of(CmdKit.merge(cmd, 6), data).onCallback(result => {
// get protobuf object
const message = result.getValue(UserMessageSchema);
console.log(`of`, message);
}).execute();
Request/ResponseCallback:Testing of a single object list.
// list int value
const intList = [1, 23];
RequestCommand.ofIntList(CmdKit.merge(cmd, 12), intList).onCallback(result => {
console.log(`ofIntList ${result.listInt()}`);
}).execute();
// list long value
const longList = [BigInt("9223372036854775800"), BigInt("9223372036854775800")];
RequestCommand.ofLongList(CmdKit.merge(cmd, 13), longList).onCallback(result => {
console.log(`ofLongList ${result.listLong()}`);
}).execute();
// list boolean value
const boolList = [true, false];
RequestCommand.ofBoolList(CmdKit.merge(cmd, 14), boolList).onCallback(result => {
console.log(`ofBoolList ${result.listBool()}`);
}).execute();
// list string value
const stringList = ["string-000", "string-001"];
RequestCommand.ofStringList(CmdKit.merge(cmd, 15), stringList).onCallback(result => {
console.log(`ofStringList ${result.listString()}`);
}).execute();
// list protobuf object
let valueList: Uint8Array[] = [];
for (let i = 0; i < 2; i++) {
const jwt = 10 + i + "";
const loginVerify = create(LoginVerifyMessageSchema, {jwt: jwt});
const data = toBinary(LoginVerifyMessageSchema, loginVerify);
valueList.push(data);
}
RequestCommand.ofValueList(CmdKit.merge(cmd, 16), valueList).onCallback(result => {
const message = result.listValue(UserMessageSchema);
console.log(`ofValueList`, message);
}).execute();
How to generate code
see https://github.com/bufbuild/protobuf-es/blob/main/MANUAL.md#how-to-generate-code
CN
介绍
ioGame TypeScript SDK 提供了 Netty、WebScoket、Protobuf、TypeScript、ioGame 游戏服务器交互的简单封装。
SDK 为主动请求的方式提供了非阻塞的两种编码风格的 api,两者可以完成同样的工作,开发者可根据自身业务选择使用。SDK 提供的交互 api 有
- 请求/响应
- 请求/无需响应
- 广播监听
- 错误码的处理
SDK 代码生成的几个优势
- 帮助客户端开发者减少巨大的工作量,不需要编写大量的模板代码。
- 语义明确,清晰。生成的交互代码即能明确所需要的参数类型,又能明确服务器是否会有返回值。这些会在生成接口时就提前明确好。
- 由于我们可以做到明确交互接口,进而可以明确参数类型。这使得接口方法参数类型安全、明确,从而有效避免安全隐患,从而减少联调时的低级错误。
- 减少服务器与客户端双方对接时的沟通成本,代码即文档。生成的联调代码中有文档与使用示例,方法上的示例会教你如何使用,即使是新手也能做到零学习成本。
- 帮助客户端开发者屏蔽与服务器交互部分,将更多的精力放在真正的业务上。
- 为双方联调减少心智负担。联调代码使用简单,与本地方法调用一般丝滑。
- 抛弃传统面向协议对接的方式,转而使用面向接口方法的对接方式。
- 当我们的 java 代码编写完成后,我们的文档及交互接口可做到同步更新,不需要额外花时间去维护对接文档及其内容。
相关示例
- CocosCreator: https://github.com/iohao/ioGameSdkTsExampleCocos
- Vue: https://github.com/iohao/ioGameSdkTsExampleVue
- (webpack: html + ts): https://github.com/iohao/ioGameSdkTsExampleHtml
安装
npm i iohao-sdk
示例
与 ioGame 服务器建立连接
// --------- IoGameSetting ---------
ioGameSetting.enableDevMode = true;
// China or Us
ioGameSetting.language = ioGameLanguage.CHINA;
// connect url
ioGameSetting.url = "ws://127.0.0.1:10100/websocket";
ioGameSetting.startNet();
编码风格-1:回调。 优点:简洁,一体化
该请求方式是非阻塞的,开发者可设置响应回调与错误回调。
// 【请求-非阻塞】,可设置响应回调与错误回调;优点:简洁,一体化
RequestCommand.ofString(cmdMerge, "hello").onCallback(result => {
console.log(`print-1 ${result.getInt()}`)
}).execute();
// 【请求-非阻塞】,可设置响应回调与错误回调;优点:简洁,一体化
RequestCommand.ofString(cmdMerge, "hello").onCallback(result => {
// 请求回调
console.log(`print-1 ${result.getInt()}`)
}).onError(result => {
// 错误处理回调
console.log(`errorCode:${result.getResponseStatus()} - `, result.getErrorInfo())
}).execute();
编码风格-2:async await。 优点:可避免回调地狱
该请求方式是非阻塞的,使用 await Promise 机制实现。
// 【请求-非阻塞】,使用 async await 机制;优点:可避免回调地狱
const result = await RequestCommand.ofAwaitString(cmdMerge, "hello");
console.log(`ofAwait-1 ${result.getString()}`);
// 【请求-非阻塞】,使用 async await 机制;优点:可避免回调地狱
const result = await RequestCommand.ofAwaitString(cmdMerge, "hello");
if (result.hasError()) {
// 错误处理
console.log(`ErrorInfo ${result.getErrorInfo()}`);
}
console.log(`ofAwait-1 ${result.getString()}`);
广播监听
主要用于监听服务器的广播,当监听到广播时,会触发对应的回调方法。
ListenCommand.of(cmdMerge).onCallback(result => {
result.log(`Listen ${result.getString()}`);
});
更多示例
请求/响应:单个的协议碎片及对象示例。
const cmd = 1;
// int value
const intValue = 1234;
RequestCommand.ofInt(CmdKit.merge(cmd, 2), intValue).onCallback(result => {
console.log(`ofInt ${result.getInt()}`);
}).execute();
// long value
const longValue = BigInt("9223372036854775807")
RequestCommand.ofLong(CmdKit.merge(cmd, 3), longValue).onCallback(result => {
console.log(`ofLong ${result.getLong()}`);
}).execute();
// boolean value
const boolValue = true;
RequestCommand.ofBool(CmdKit.merge(cmd, 4), boolValue).onCallback(result => {
console.log(`ofBool ${result.getBool()}`);
}).execute();
// string value
const stringValue = "string-000";
RequestCommand.ofString(CmdKit.merge(cmd, 5), stringValue).onCallback(result => {
console.log(`ofString ${result.getString()}`);
}).execute();
// protobuf object
const loginVerify = create(LoginVerifyMessageSchema, {jwt: "1"});
const data = toBinary(LoginVerifyMessageSchema, loginVerify);
RequestCommand.of(CmdKit.merge(cmd, 6), data).onCallback(result => {
// get protobuf object
const message = result.getValue(UserMessageSchema);
console.log(`of`, message);
}).execute();
请求/响应:多个的协议碎片及对象示例。
// list int value
const intList = [1, 23];
RequestCommand.ofIntList(CmdKit.merge(cmd, 12), intList).onCallback(result => {
console.log(`ofIntList ${result.listInt()}`);
}).execute();
// list long value
const longList = [BigInt("9223372036854775800"), BigInt("9223372036854775800")];
RequestCommand.ofLongList(CmdKit.merge(cmd, 13), longList).onCallback(result => {
console.log(`ofLongList ${result.listLong()}`);
}).execute();
// list boolean value
const boolList = [true, false];
RequestCommand.ofBoolList(CmdKit.merge(cmd, 14), boolList).onCallback(result => {
console.log(`ofBoolList ${result.listBool()}`);
}).execute();
// list string value
const stringList = ["string-000", "string-001"];
RequestCommand.ofStringList(CmdKit.merge(cmd, 15), stringList).onCallback(result => {
console.log(`ofStringList ${result.listString()}`);
}).execute();
// list protobuf object
let valueList: Uint8Array[] = [];
for (let i = 0; i < 2; i++) {
const jwt = 10 + i + "";
const loginVerify = create(LoginVerifyMessageSchema, {jwt: jwt});
const data = toBinary(LoginVerifyMessageSchema, loginVerify);
valueList.push(data);
}
RequestCommand.ofValueList(CmdKit.merge(cmd, 16), valueList).onCallback(result => {
const message = result.listValue(UserMessageSchema);
console.log(`ofValueList`, message);
}).execute();
如何生成 .proto
see https://github.com/bufbuild/protobuf-es/blob/main/MANUAL.md#how-to-generate-code