### Call Void Action Method (Example) Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/gdscript/action_method_void_no_param.txt This is an example of how to call a void action method that takes no parameters. It demonstrates the syntax for invoking such methods. ```gdscript ${actionSimpleName}.of_${actionMethodName}(); ``` -------------------------------- ### Example: Handling a Specific Broadcast in GDScript Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/gdscript/broadcast_action.txt An example of how to implement the callback for listening to a specific broadcast action. It shows how to access the result and log relevant information. ```gdscript Listener.listen_${o.methodName}(func(result: IoGame.ResponseResult): # ${o.dataDescription!} ${o.exampleCode!} ) ``` -------------------------------- ### Startup Logic and External Servers with NetServer Source: https://context7.com/iohao/ionet/llms.txt Register and start logic servers and external servers with the NetServer. This step is crucial for the NetServer to manage and coordinate these components. ```java // Logic servers register themselves into the NetServer LogicServerApplication.startup(logicServer, netServer); // External server also registers into the NetServer externalServer.startup(netServer); netServer.onStart(); // fires all registered ServerListeners ``` -------------------------------- ### RunOne - Single-Process Startup Source: https://context7.com/iohao/ionet/llms.txt Starts the External Server, Logic Servers, and an optional Center Server within a single JVM process. Recommended for development and small deployments. ```APIDOC ## `RunOne` — Single-Process All-In-One Startup `RunOne` starts the External Server, one or more Logic Servers, and an optional Center Server all within one JVM process. This is the recommended mode for development and small deployments. ```java public static void main(String[] args) { // 1. Start Aeron media driver (shared memory IPC) var ctx = new Aeron.Context().aeronDirectoryName("/dev/shm/aeron-ionet"); var aeron = Aeron.connect(ctx); // 2. Build the BarSkeleton (business routes) var barSkeleton = BarSkeleton.builder() .addActionController(HallAction.class) .addInOut(new DebugInOut()) .build(); // 3. Build a Logic Server LogicServer logicServer = LogicServer.newBuilder() .setTag("HallServer") .setBarSkeleton(barSkeleton) .build(); // 4. Build an External Server (WebSocket on port 10100) ExternalServer externalServer = ExternalMapper.builder(10100, ExternalJoinEnum.WEBSOCKET) .build(); // 5. Wire everything into RunOne and start new RunOne() .setAeron(aeron) .setExternalServer(externalServer) .setLogicServerList(List.of(logicServer)) .enableCenterServer() // optional built-in center/gateway .startup(); } // Output: ionet banner with startup metrics, then the server accepts WS connections on :10100 ``` ``` -------------------------------- ### Example Usage of Broadcast Listener Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/csharp/broadcast_action.txt Example of how to use the Listen${o.methodName} method to register a callback for a broadcast notification. The callback processes the received result. ```csharp Listener.listen${o.methodName}(result => { // ${o.dataDescription!"broadcast notification"} ${o.exampleCode!} }); ``` -------------------------------- ### RunOne: Single-Process Startup Source: https://context7.com/iohao/ionet/llms.txt Use RunOne to start the External Server, Logic Servers, and an optional Center Server within a single JVM process. This is recommended for development and small deployments. Ensure Aeron is connected and servers are configured before calling startup(). ```java public static void main(String[] args) { // 1. Start Aeron media driver (shared memory IPC) var ctx = new Aeron.Context().aeronDirectoryName("/dev/shm/aeron-ionet"); var aeron = Aeron.connect(ctx); // 2. Build the BarSkeleton (business routes) var barSkeleton = BarSkeleton.builder() .addActionController(HallAction.class) .addInOut(new DebugInOut()) .build(); // 3. Build a Logic Server LogicServer logicServer = LogicServer.newBuilder() .setTag("HallServer") .setBarSkeleton(barSkeleton) .build(); // 4. Build an External Server (WebSocket on port 10100) ExternalServer externalServer = ExternalMapper.builder(10100, ExternalJoinEnum.WEBSOCKET) .build(); // 5. Wire everything into RunOne and start new RunOne() .setAeron(aeron) .setExternalServer(externalServer) .setLogicServerList(List.of(logicServer)) .enableCenterServer() // optional built-in center/gateway .startup(); } // Output: ionet banner with startup metrics, then the server accepts WS connections on :10100 ``` -------------------------------- ### GDScript Action Method Void Example Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/gdscript/action_method_void.txt Example of how to call an action method that returns a void type, typically used for commands. ```gdscript # ${bizDataComment} var ${bizDataName}: ${bizDataType} = ... ${actionSimpleName}.of${actionMethodName}(${bizDataName}); ``` -------------------------------- ### Map Broadcast Command in GDScript Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/gdscript/broadcast_action.txt Maps a broadcast command with its corresponding merge value and method description. This is a setup step for listening to specific broadcast actions. ```gdscript static var _${o.cmdMethodName}_${o.cmd}_${o.subCmd}: int = IoGame.CmdKit.mapping_broadcast(${o.cmdMerge}, "${o.methodDescription}") ``` -------------------------------- ### Handle Fire-and-Forget Actions with @ActionMethod Source: https://context7.com/iohao/ionet/llms.txt Methods with a void return type are treated as fire-and-forget from the server's perspective. This example demonstrates proactively pushing data via broadcast. ```java @ActionMethod(HallCmd.getProfile) void triggerProfilePush(FlowContext flowContext) { // push data proactively via broadcast var cmdInfo = CmdInfo.of(HallCmd.cmd, HallCmd.getProfile); flowContext.broadcastMe(cmdInfo, "your profile data"); } ``` -------------------------------- ### Handle Primitive Return Values with @ActionMethod Source: https://context7.com/iohao/ionet/llms.txt Methods returning primitive types (auto-boxed) are handled without protocol fragmentation. This example returns a String. ```java @ActionMethod(HallCmd.hello) String hello(FlowContext flowContext) { return "hello " + flowContext.getUserId(); } ``` -------------------------------- ### ExternalMapper: Build External Servers Source: https://context7.com/iohao/ionet/llms.txt Factory for creating Netty-backed external servers. Supports TCP, WebSocket, or UDP transports. Multiple transports can be started simultaneously by building separate servers and adding them. ```java // WebSocket external server on port 10100 (default) ExternalServer wsServer = ExternalMapper.builder(10100) .build(); // TCP external server on port 10200 ExternalServer tcpServer = ExternalMapper.builder(10200, ExternalJoinEnum.TCP) .build(); // Multiple transports simultaneously — start both servers ExternalServer wsServer2 = ExternalMapper.builder(10100, ExternalJoinEnum.WEBSOCKET).build(); ExternalServer tcpServer2 = ExternalMapper.builder(10101, ExternalJoinEnum.TCP).build(); new RunOne() .setAeron(aeron) .setExternalServer(wsServer2) // primary external server // additional external servers can be added directly via NetServer.addServer() .setLogicServerList(List.of(logicServer)) .startup(); ``` -------------------------------- ### TypeScript Action Method Void No Param Example Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/ts/action_method_void_no_param.txt Use this method to create a `RequestCommand` that executes an action without requiring parameters and returns void. It's part of a fluent API for command construction. ```typescript static of${actionMethodName}(): RequestCommand { return RequestCommand.of${sdkMethodName!}(this.${memberCmdName}).execute(); } ``` -------------------------------- ### TaskKit: Concurrency and Scheduling Utilities Source: https://context7.com/iohao/ionet/llms.txt Demonstrates submitting tasks to fixed or virtual thread pools, using CompletableFuture, and scheduling one-shot or recurring tasks with delays and intervals. ```java TaskKit.execute(() -> System.out.println("Background task")); ``` ```java TaskKit.executeVirtual(() -> System.out.println("Virtual thread task")); ``` ```java CompletableFuture future = TaskKit.supplyAsync(() -> fetchRemoteData()); ``` ```java TaskKit.runOnce(() -> System.out.println("3s later"), 3, TimeUnit.SECONDS); TaskKit.runOnceMillis(() -> System.out.println("500ms later"), 500); ``` ```java TaskKit.runInterval(() -> System.out.println("Tick every 2s"), 2, TimeUnit.SECONDS); ``` ```java TaskKit.runInterval(new IntervalTaskListener() { int countdown = 5; @Override public void onUpdate() { System.out.println("Countdown: " + countdown--); } @Override public boolean isActive() { return countdown > 0; // removed automatically when countdown reaches 0 } }, 1, TimeUnit.SECONDS); ``` ```java TaskKit.newTimeout(timeout -> System.out.println("Raw timeout"), 1, TimeUnit.SECONDS); ``` -------------------------------- ### Build Minimal NetServer with NetServerBuilder Source: https://context7.com/iohao/ionet/llms.txt Assemble the central NetServer runtime using NetServerBuilder. The minimal configuration requires only the Aeron dependency. ```java // Minimal: Aeron is the only required dependency NetServer netServer = new NetServerBuilder() .setAeron(aeron) .build(); ``` -------------------------------- ### listener_all Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/ts/broadcast_action.txt Sets up listeners for all available broadcast actions. It logs the command merge and title, and optionally executes custom actions based on the broadcast content. ```APIDOC ## listener_all ### Description Sets up listeners for all available broadcast actions. It logs the command merge and title, and optionally executes custom actions based on the broadcast content. ### Method Signature `static listener_all(): void` ### Behavior This method iterates through all defined broadcast actions and registers a listener for each. For each received broadcast, it logs the `mergeTitle` and `title`. If `exampleCodeAction` is defined for a broadcast, it will be executed, and then the `mergeTitle`, `title`, and `value` will be logged. Otherwise, only `mergeTitle` and `title` are logged. ### Example ```typescript Listener.listener_all(); ``` ``` -------------------------------- ### init() Function Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/gdscript/error_code.txt Initializes the error code mapping. ```APIDOC ## Initialization Function The `init()` function is used to trigger the initialization of the error code mapping. ### `GameCode.init()` #### Description Calls the `errorCodeMapping` initialization. This method should be called once to ensure all error codes are properly set up. #### Method `static func init() -> void:` #### Parameters None #### Returns `void` #### Usage Example ```gdscript GameCode.init() ``` ``` -------------------------------- ### Execute Void Action Method with No Parameters Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/gdscript/action_method_void_no_param.txt Use this pattern to execute a void action method that requires no input parameters. Ensure the command is properly initialized before execution. ```gdscript static func of_${actionMethodName}() -> IoGame.RequestCommand: return IoGame.RequestCommand.of_empty(_${memberCmdName}).execute() ``` -------------------------------- ### Generate Void Action Method (List Biz Data) Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/ts/action_method_void.txt Use this snippet when the business data is a list. It maps each item to binary and then executes the command. ```typescript static of${actionMethodName}(${bizDataName}: ${protoPrefix}${bizDataType}): RequestCommand { const dataList = ${bizDataName}.map(o => { return toBinary(${protoPrefix}${actualTypeName}Schema, o); }); return RequestCommand.of${sdkMethodName}(this.${memberCmdName}, dataList).execute(); } ``` -------------------------------- ### Build Custom NetServer with NetServerBuilder Source: https://context7.com/iohao/ionet/llms.txt Customize the NetServer by overriding the load balancer, adding shutdown hooks, and registering server listeners. This allows for fine-grained control over the server's behavior and lifecycle. ```java // Custom: override load balancer, add shutdown hooks, add server listeners NetServer customNetServer = new NetServerBuilder() .setAeron(aeron) .setBalancedManager(new MyCustomBalancedManager()) .addServerListener(new ServerListener() { @Override public void onStart(NetServerSetting setting) { System.out.println("NetServer started, netId=" + setting.netId()); } }) .addServerShutdownHook(() -> { System.out.println("Graceful shutdown..."); myDatabase.close(); }) .build(); ``` -------------------------------- ### Generate Void Action Method (Simple Biz Data) Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/ts/action_method_void.txt Use this snippet for simple business data types. It converts the data to binary and executes the request command. ```typescript static of${actionMethodName}(${bizDataName}: ${protoPrefix}${bizDataType}): RequestCommand { const data = toBinary(${protoPrefix}${bizDataType}Schema, ${bizDataName}); const requestCommand = RequestCommand.of(this.${memberCmdName}, data); requestCommand.dataSource = ${bizDataName}; return requestCommand.execute(); } ``` -------------------------------- ### ionet Action and Message Definitions Source: https://github.com/iohao/ionet/blob/main/README.md Defines an action controller for handling commands, a user message structure, and command routing constants. Requires ionet annotations and Protobuf annotations. ```java // Action @ActionController(HallCmd.cmd) public class HallAction { @ActionMethod(HallCmd.loginVerify) UserMessage loginVerify(String jwt, FlowContext flowContext) { long userId = Math.abs(jwt.hashCode()); flowContext.bindingUserId(userId); UserMessage userMessage = new UserMessage(); userMessage.id = userId; userMessage.nickname = jwt; return userMessage; } @ActionMethod(HallCmd.hello) String hello(FlowContext flowContext) { return "hello " + flowContext.getUserId(); } } // Data Message @ProtobufClass public class UserMessage { public long id; public String nickname; } // Routing public interface HallCmd { int cmd = 1; int loginVerify = 1; int hello = 2; } ``` -------------------------------- ### Build BarSkeleton with Controllers and Interceptors Source: https://context7.com/iohao/ionet/llms.txt Use BarSkeletonBuilder to register action controllers, scan packages, add interceptors for request/response processing, and define startup runners. Register broadcast documentation for API generation. ```java BarSkeletonBuilder builder = BarSkeleton.builder(); // Register controllers explicitly … builder.addActionController(HallAction.class); // … or scan a whole package for @ActionController classes builder.scanActionPackage(HallAction.class); // Add interceptors (plugins) to the processing pipeline builder.addInOut(new DebugInOut()); // prints request/response details builder.addInOut(new StatActionInOut()); // call-count statistics builder.addInOut(new ThreadMonitorInOut()); // thread utilisation monitoring // Add a startup runner builder.addRunner(barSkeleton -> { System.out.println("Logic server is ready. Routes: " + barSkeleton.actionCommandRegions); }); // Register broadcast documentation for auto-generated API docs builder.addBroadcastDocument( BroadcastDocumentBuilder.newBuilder() .setCmdInfo(CmdInfo.of(HallCmd.cmd, HallCmd.hello)) .setDataClass(UserMessage.class) .setDescription("Notify clients about profile updates") ); BarSkeleton skeleton = builder.build(); // skeleton.handle(flowContext) is called internally by the framework ``` -------------------------------- ### Of Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/csharp/action_method_void.txt Executes an action with a single business data object, returning a void RequestCommand. ```APIDOC ## Of ### Description This method is used to execute an action with a specified business data object. It returns a void RequestCommand, indicating the operation completes without returning specific data. ### Method Signature ```csharp public static RequestCommand Of( ) ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters * ** ** - Required - The business data object to be processed by the action. ### Request Example ```csharp // Assuming 'actionMethodName', 'bizDataType', 'bizDataName', and 'memberCmdName' are defined = ...; // Initialize the business data object RequestCommand.Of().Execute(); ``` ### Response #### Success Response (void RequestCommand) This method returns a `RequestCommand` object that signifies the completion of the action. No specific data is returned. #### Response Example ```csharp // The execution of the command is typically handled by calling .Execute() RequestCommand command = RequestCommand.Of(); command.Execute(); // Executes the command ``` ### Remarks This method is part of the C# SDK and is designed for scenarios where an action needs to be performed based on provided data, and the result of the action itself is not directly needed as a return value from this method call. ``` -------------------------------- ### Listen to All Broadcast Actions in GDScript Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/gdscript/broadcast_action.txt Sets up listeners for all defined broadcast actions. Each listener processes the broadcast result and logs a formatted string, either a default format or a custom one if an action code is provided. ```gdscript static func listener_all() -> void: # all listener ``` ```gdscript Listener.listen_${o.methodName}(func(result: IoGame.ResponseResult): var _merge_title := IoGame.CmdKit.to_string_merge(result.get_cmd_merge()) var _title := IoGame.CmdKit.get_broadcast_title(result.get_cmd_merge()) ``` ```gdscript var _format := "[%s], [broadcast_title: %s]" % [_merge_title, _title] IoGame.IoGameSetting.game_console.log(_format) ``` ```gdscript ${o.exampleCodeAction!} var _format := "[%s], [broadcast_title: %s], %s" % [_merge_title, _title, _value] IoGame.IoGameSetting.game_console.log(_format) ``` -------------------------------- ### ActionMethodInOut: Custom Interceptors and Plugin Registration Source: https://context7.com/iohao/ionet/llms.txt Implements custom interceptors for action method pipelines and demonstrates registering built-in and custom plugins with BarSkeletonBuilder. ```java public class RateLimitInOut implements ActionMethodInOut { private final Map lastCallTime = new ConcurrentHashMap<>(); @Override public void fuckIn(FlowContext flowContext) { long userId = flowContext.getUserId(); long now = System.currentTimeMillis(); Long last = lastCallTime.put(userId, now); if (last != null && now - last < 100) { // 100 ms cooldown per user flowContext.setErrorCode(-9001); flowContext.setErrorMessage("Rate limit exceeded"); } } @Override public void fuckOut(FlowContext flowContext) { /* no-op */ } } ``` ```java BarSkeletonBuilder builder = BarSkeleton.builder() .addActionController(HallAction.class); // Built-in: full debug logging (prints request/response/timing/traceId) builder.addInOut(new DebugInOut()); // Built-in: only log requests that take more than 50 ms builder.addInOut(new DebugInOut(50)); // Built-in: call-count statistics per route builder.addInOut(new StatActionInOut()); // Built-in: business thread utilisation monitoring builder.addInOut(new ThreadMonitorInOut()); // Custom rate limiter builder.addInOut(new RateLimitInOut()); BarSkeleton skeleton = builder.build(); ``` -------------------------------- ### of${actionMethodName} Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/ts/action_method_void.txt Executes an action method that returns void. It takes a business data object, serializes it, and returns a RequestCommand. ```APIDOC ## of${actionMethodName} ### Description This method is used to execute an action that does not return a specific value but rather initiates a command. It serializes the provided business data and returns a `RequestCommand` object. ### Method Signature `static of${actionMethodName}(${bizDataName}: ${protoPrefix}${bizDataType}): RequestCommand` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters * **${bizDataName}** (${protoPrefix}${bizDataType}) - Required - The business data object to be processed. ### Request Example ```typescript // ${bizDataComment} const ${bizDataName}: ${protoDataType} = ...; ${actionSimpleName}.of${actionMethodName}(${bizDataName}); ``` ### Response #### Success Response (RequestCommand) Returns a `RequestCommand` object that represents the executed action. #### Response Example ```json { "command": "...", "dataSource": "..." } ``` ``` -------------------------------- ### ofAwait${actionMethodName} Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/ts/action_method.txt Invokes an action method asynchronously and returns a Promise with the response. ```APIDOC ## ofAwait${actionMethodName} ### Description Asynchronously invokes an action method and returns a Promise resolving to the `ResponseResult`. ### Method Signature `static async ofAwait${actionMethodName}(${bizDataName}: ${protoPrefix}${bizDataType}): Promise` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```typescript // ${bizDataComment} const ${bizDataName}: ${bizDataType} = ...; const result = await ${actionSimpleName}.ofAwait${actionMethodName}(${bizDataName}); // your biz code. // ${returnComment} ${exampleCode} result.log(value); ``` ### Response #### Success Response `Promise` - A Promise that resolves with the `ResponseResult` of the operation. #### Response Example (No specific example provided in source) ``` -------------------------------- ### ExternalMapper - External Server Builder Source: https://context7.com/iohao/ionet/llms.txt Factory for creating Netty-backed external servers that accept client connections over TCP, WebSocket, or UDP. ```APIDOC ## `ExternalMapper` — External Server Builder Factory for creating Netty-backed external servers that accept client connections over TCP, WebSocket, or UDP. ```java // WebSocket external server on port 10100 (default) ExternalServer wsServer = ExternalMapper.builder(10100) .build(); // TCP external server on port 10200 ExternalServer tcpServer = ExternalMapper.builder(10200, ExternalJoinEnum.TCP) .build(); // Multiple transports simultaneously — start both servers ExternalServer wsServer2 = ExternalMapper.builder(10100, ExternalJoinEnum.WEBSOCKET).build(); ExternalServer tcpServer2 = ExternalMapper.builder(10101, ExternalJoinEnum.TCP).build(); new RunOne() .setAeron(aeron) .setExternalServer(wsServer2) // primary external server // additional external servers can be added directly via NetServer.addServer() .setLogicServerList(List.of(logicServer)) .startup(); ``` ``` -------------------------------- ### Handling All Broadcast Actions in TypeScript Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/ts/broadcast_action.txt A method to register listeners for all broadcast actions. It iterates through defined broadcast actions and sets up individual listeners, logging command details. ```typescript Listener.listen${o.methodName}(result => { const mergeTitle = CmdKit.toString(result.getCmdMerge()); const title = CmdKit.getBroadcastTitle(result.getCmdMerge()); <% if (o.exampleCodeAction == null) { %> console.log(mergeTitle, title); <% } else { %> ${o.exampleCodeAction!} console.log(mergeTitle, title, value); <%}%> }); ``` -------------------------------- ### Action Method with Async/Await Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/ts/action_method_no_param.txt This method provides an asynchronous way to invoke an action using the async/await pattern. It simplifies handling asynchronous operations by allowing you to write non-blocking code that looks synchronous. ```APIDOC ## ofAwait${actionMethodName}() ### Description Asynchronously invokes an action method and returns a `Promise` that resolves with the `ResponseResult`. This method simplifies asynchronous code by using the `async/await` syntax. ### Method Signature `static async ofAwait${actionMethodName}(): Promise` ### Parameters This method does not accept any parameters. ### Returns * `Promise` - A promise that resolves with the `ResponseResult` of the action. ### Example ```typescript const result = await ${actionSimpleName}.ofAwait${actionMethodName}(); // your biz code. result.log("hello ioGame!"); // ${returnComment} ${exampleCode} result.log(value); ``` ``` -------------------------------- ### listen Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/ts/broadcast_action.txt Subscribes a callback function to a specific broadcast action. The callback receives a ResponseResult object containing broadcast data. ```APIDOC ## listen ### Description Subscribes a callback function to a specific broadcast action. The callback receives a ResponseResult object containing broadcast data. ### Method Signature `static listen(callback: (result: ResponseResult) => void): void` ### Parameters * `callback` (function) - A function that will be executed when the broadcast action is received. It accepts a `ResponseResult` object as an argument. ### Example ```typescript Listener.listen(result => { // Handle the broadcast data // result contains broadcast information }); ``` ``` -------------------------------- ### Handle Request/Response with @ActionMethod Source: https://context7.com/iohao/ionet/llms.txt Register a method as a handler for a specific sub-command using @ActionMethod. Parameters are deserialized, and the return value is serialized and sent back to the client. ```java @ActionMethod(HallCmd.loginVerify) UserMessage loginVerify(String jwt, FlowContext flowContext) { long userId = Math.abs(jwt.hashCode()); flowContext.bindingUserId(userId); // marks the session as authenticated UserMessage user = new UserMessage(); user.id = userId; user.nickname = jwt; return user; // automatically serialized (Protobuf/JSON) and sent to client } ``` -------------------------------- ### of${actionMethodName}() Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/ts/action_method_void_no_param.txt Executes an action command without any parameters. This method is a static factory method that creates and executes a `RequestCommand`. ```APIDOC ## of${actionMethodName}() ### Description Executes an action command without any parameters. This method is a static factory method that creates and executes a `RequestCommand`. ### Method `static of${actionMethodName}()` ### Returns `RequestCommand` - A `RequestCommand` object that has been executed. ### Example ```typescript ${actionSimpleName}.of${actionMethodName}(); ``` ``` -------------------------------- ### GDScript Action Method Void Generation (Default) Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/gdscript/action_method_void.txt Generates a standard GDScript `IoGame.RequestCommand` for business data types. It serializes the data to bytes and then executes the command. ```gdscript static func of_${actionMethodName}(${bizDataName}: ${bizDataType}) -> IoGame.RequestCommand: var _data := ${bizDataName}.to_bytes() var _request = IoGame.RequestCommand.of(_${memberCmdName}, _data) _request.data_source = ${bizDataName} return _request.execute() ``` -------------------------------- ### Action Method with Callback Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/ts/action_method_no_param.txt This method allows you to invoke an action and handle the response using a callback function. It's suitable for scenarios where you need to perform actions asynchronously and process their results when they become available. ```APIDOC ## of${actionMethodName} (callback) ### Description Invokes an action method and provides a callback function to handle the response. This is useful for asynchronous operations where you need to process results upon completion. ### Method Signature `static of${actionMethodName}(callback: (result: ResponseResult) => void): RequestCommand` ### Parameters * **callback** (`(result: ResponseResult) => void`) - A function that will be called with the `ResponseResult` when the action completes. ### Returns * `RequestCommand` - An object representing the request command that can be executed. ### Example ```typescript ${actionSimpleName}.of${actionMethodName}(result => { // your biz code. result.log("hello ioGame!"); // ${returnComment} ${exampleCode} result.log(value); }); ``` ``` -------------------------------- ### Generate C# Synchronous Action Method Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/csharp/action_method.txt Use this for generating synchronous action methods that accept a business data object and a callback delegate. The callback handles the response and any business logic. ```csharp /// /// ${methodComment} /// /// ${bizDataComment} /// ${returnDataIsList?"list of "} ${returnComment} /// RequestCommand /// /// // ${bizDataComment} /// ${codeEscape(bizDataType)} ${bizDataName} = ...; /// ${actionSimpleName}.of${actionMethodName}(${bizDataName}, result => { /// // your biz code. /// // ${returnComment} /// ${exampleCode!} /// result.Log(value); /// }); /// public static RequestCommand Of${actionMethodName}(${bizDataType} ${bizDataName}, CallbackDelegate callback) { <%if (bizDataTypeIsList && !internalBizDataType) {%> var dataList = ${bizDataName}.Cast().ToList(); return RequestCommand.Of${sdkMethodName}(${memberCmdName}, dataList).OnCallback(callback).Execute(); <%} else {%> return RequestCommand.Of${sdkMethodName!}(${memberCmdName}, ${bizDataName}).OnCallback(callback).Execute(); <%}%> } ``` -------------------------------- ### C# Action Method with Callback Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/csharp/action_method_no_param.txt Use this pattern for synchronous operations where a callback function handles the result. Ensure the callback delegate is correctly defined. ```csharp public static RequestCommand Of${actionMethodName}(CallbackDelegate callback) { return RequestCommand.Of${sdkMethodName}(${memberCmdName}).OnCallback(callback).Execute(); } ``` -------------------------------- ### Declare Routing Constants for a Module Source: https://context7.com/iohao/ionet/llms.txt Define unique integer commands for routing network messages within a module. Keep these constants in a single place per module. ```java public interface HallCmd { int cmd = 1; // module ID int loginVerify = 1; int hello = 2; int getProfile = 3; } ``` -------------------------------- ### C# Execute Void Action Method No Param Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/csharp/action_method_void_no_param.txt Use this method to execute a command that returns void and requires no parameters. Ensure the RequestCommand is properly initialized. ```csharp public static RequestCommand Of${actionMethodName}() { return RequestCommand.Of(${memberCmdName}).Execute(); } ``` -------------------------------- ### GDScript Action Method Void Generation (List Biz Data) Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/gdscript/action_method_void.txt Generates a GDScript `IoGame.RequestCommand` for list-based business data types. It serializes each item to bytes before execution. ```gdscript static func of_${actionMethodName}(${bizDataName}: ${bizDataType}) -> IoGame.RequestCommand: var _message := IoGame.Proto.ByteValueList.new() for _value in ${bizDataName}: _message.add_values(_value.to_bytes()) var _request := IoGame.RequestCommand.of_${sdkMethodName}(_${memberCmdName}, _message.to_bytes()) _request.data_source = ${bizDataName} return _request.execute() ``` -------------------------------- ### of${actionMethodName} Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/ts/action_method.txt Invokes an action method with a callback for handling the response. ```APIDOC ## of${actionMethodName} ### Description Invokes an action method with a callback to process the response. ### Method Signature `static of${actionMethodName}(${bizDataName}: ${protoPrefix}${bizDataType}, callback: (result: ResponseResult) => void): RequestCommand` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```typescript // ${bizDataComment} const ${bizDataName}: ${bizDataType} = ...; ${actionSimpleName}.of${actionMethodName}(${bizDataName}, result => { // your biz code. // ${returnComment} ${exampleCode} result.log(value); }); ``` ### Response #### Success Response Returns a `RequestCommand` object that can be executed. #### Response Example (No specific example provided in source) ``` -------------------------------- ### Generate C# Asynchronous Action Method (Awaitable) Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/csharp/action_method.txt Use this for generating asynchronous action methods that return a Task. This pattern is suitable for operations that can be awaited, simplifying asynchronous code flow. ```csharp /// /// ${methodComment} /// /// ${bizDataComment} /// ResponseResult,${returnDataIsList?"list of "} ${returnComment} /// /// // ${bizDataComment} /// ${codeEscape(bizDataType)} ${bizDataName} = ...; /// var result = await ${actionSimpleName}.ofAwait${actionMethodName}(${bizDataName}); /// // your biz code. /// // ${returnComment} /// ${exampleCode!} /// result.Log(value); /// public static async Task OfAwait${actionMethodName}(${bizDataType} ${bizDataName}) { <%if (bizDataTypeIsList && !internalBizDataType) {%> var dataList = ${bizDataName}.Cast().ToList(); return await RequestCommand.OfAwait${sdkMethodName}(${memberCmdName}, dataList); <%} else {%> return await RequestCommand.OfAwait${sdkMethodName}(${memberCmdName}, ${bizDataName}); <%}%> } ``` -------------------------------- ### Listen to all broadcast events Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/gdscript/broadcast_action.txt This method registers a general callback for all broadcast events. It logs the broadcast title and any associated data to the game console. This is useful for debugging or general monitoring of broadcast activity. ```APIDOC ## static func listener_all() -> void ### Description Registers a listener for all broadcast events. When any broadcast event occurs, a formatted string containing the event details is logged to the game console. ### Example Code ```gdscript Listener.listener_all() ``` ``` -------------------------------- ### OfAwait Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/csharp/action_method_no_param.txt This asynchronous method invokes an action without parameters and returns the result directly. ```APIDOC ## OfAwait ### Description Asynchronously invokes an action method without parameters and returns the result. ### Method `public static async Task OfAwait()` ### Returns * `Task` - A task that represents the asynchronous operation, containing the result of the action. ### Code Example ```csharp var result = await .OfAwait(); // your biz code. // result.Log(value); ``` ``` -------------------------------- ### Declare an Action Controller Source: https://context7.com/iohao/ionet/llms.txt Mark a class as a request-handler module using the @ActionController annotation. Each controller is assigned a unique command ID. ```java @ActionController(HallCmd.cmd) public class HallAction { // methods registered with @ActionMethod handle individual sub-commands } ``` -------------------------------- ### Action Method with Async/Await Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/ts/action_method_no_param.txt This method is suitable for modern asynchronous programming using async/await. It returns a Promise that resolves with a ResponseResult object, simplifying asynchronous code flow. ```typescript static async ofAwait${actionMethodName}(): Promise { return await RequestCommand.ofAwait${sdkMethodName!}(this.${memberCmdName}); } ``` -------------------------------- ### GDScript Action Method with Await Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/gdscript/action_method.txt Use this snippet to generate an asynchronous GDScript action method using the `await` keyword for handling responses. It checks for success and provides error details. ```gdscript # ${bizDataComment} var ${bizDataName}: ${bizDataType} = ... var result := await ${actionSimpleName}.of_await_${actionMethodName}(${bizDataName}) if result.success(): # ${returnComment} ${exampleCode} else: var error_code := result.get_response_status() print("error_code: ", error_code) print("error_info: ", result.get_error_info()) [/codeblock] ``` ```gdscript static func of_await_${actionMethodName}(${bizDataName}: ${bizDataType}) -> IoGame.ResponseResult: <% if (internalBizDataType) { %> return await IoGame.RequestCommand.of_await_${sdkMethodName!}(_${memberCmdName}, ${bizDataName}) <% } else if (bizDataTypeIsList) { %> var _message := IoGame.Proto.ByteValueList.new() for _value in ${bizDataName}: _message.add_values(_value.to_bytes()) var _request := IoGame.RequestCommand.of(_${memberCmdName}, _message.to_bytes()) _request.data_source = ${bizDataName} return await IoGame.RequestCommand.of_await_request_command(_request) <% } else { %> var _data := ${bizDataName}.to_bytes() var _request := IoGame.RequestCommand.of(_${memberCmdName}, _data) _request.data_source = ${bizDataName} return await IoGame.RequestCommand.of_await_request_command(_request) <% } %> ``` -------------------------------- ### Async Action Method Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/gdscript/action_method.txt This method executes an action asynchronously and returns a ResponseResult directly, allowing for the use of `await` for cleaner asynchronous code management. ```APIDOC ## of_await_actionMethodName ### Description Executes an action asynchronously with the provided business data and returns the result directly. ### Method `static func of_await_actionMethodName(bizDataName: bizDataType) -> IoGame.ResponseResult` ### Parameters * **bizDataName** (bizDataType) - Description of the business data. ### Request Example ```gdscript # Description of the business data var bizDataName: bizDataType = ... var result := await actionSimpleName.of_await_actionMethodName(bizDataName) if result.success(): # Description of the return comment exampleCode else: var error_code := result.get_response_status() print("error_code: ", error_code) print("error_info: ", result.get_error_info()) ``` ### Response * **IoGame.ResponseResult** - The result of the asynchronous operation. ``` -------------------------------- ### Callback-based Action Method Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/gdscript/action_method_no_param.txt This method executes an action and provides a callback function to handle the result. The callback receives a IoGame.ResponseResult object. ```APIDOC ## Execute Action with Callback ### Description This function executes an action and invokes a provided callback function upon completion. The callback will receive the result of the action. ### Method Signature `static func of_${actionMethodName}(callback: Callable) -> IoGame.RequestCommand` ### Parameters * `callback` (Callable) - A function to be called with the action's result. It should accept a `IoGame.ResponseResult` object. ### Return Value `IoGame.RequestCommand` - An object representing the command that can be used for further manipulation or execution. ### Example Code ```gdscript ${actionSimpleName}.of_${actionMethodName}(func(result: IoGame.ResponseResult): # Handle the result here # For example: print(result.get_response_data()) ${exampleCode} ) ``` ``` -------------------------------- ### Listen to All Broadcast Events Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/csharp/broadcast_action.txt Registers a single callback to receive all broadcast events. Inside the callback, you can inspect the event details to differentiate and handle them. ```APIDOC ## Listener_all Broadcast ### Description Registers a single callback to receive all broadcast events. This is useful for a centralized logging or handling mechanism. ### Method `public static void Listener_all()` ### Usage Example ```csharp Listener.Listener_all(); ``` ### Callback Behavior When `Listener_all()` is called, a default callback is registered for all broadcast events. This callback logs the merge title, title, and potentially other details of the broadcast event to the game console. If `exampleCodeAction` is defined for a specific broadcast type, it will be executed before logging. #### Example of handling within the default callback: ```csharp Listener.Listener_all(); // ... later, when a broadcast occurs ... // The internal callback will execute, for example: // var mergeTitle = CmdKit.ToString(result.GetCmdMerge()); // var title = CmdKit.GetBroadcastTitle(result.GetCmdMerge()); // IoGameSetting.GameGameConsole.Log($"{{mergeTitle}}, {{title}}"); ``` ``` -------------------------------- ### OfAwaitActionMethodName Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/csharp/action_method.txt Asynchronously executes an action and returns the result. This method is suitable for scenarios where you need to await the completion of an action. ```APIDOC ## OfAwaitActionMethodName ### Description Asynchronously executes an action and returns the result. This method is suitable for scenarios where you need to await the completion of an action. ### Method Public static async Task ### Parameters #### Path Parameters - **bizDataName** (bizDataType) - Required - Description of the business data. ### Request Example ```csharp // Description of the business data bizDataName = ...; var result = await OfAwaitActionMethodName(bizDataName); // your biz code. // Description of the return data exampleCode result.Log(value); ``` ### Response #### Success Response (ResponseResult) - Returns a ResponseResult object containing the result of the action. #### Response Example ```csharp ResponseResult result = await OfAwaitActionMethodName(bizDataName); ``` ``` -------------------------------- ### Integrate ActionFactoryBeanForSpring with Spring Source: https://context7.com/iohao/ionet/llms.txt Configure ActionFactoryBeanForSpring in a Spring @Configuration class to integrate ionet action controllers with the Spring ApplicationContext. This allows for full dependency injection support within action controllers. ```java // 1. Declare the Spring bean (e.g., in a @Configuration class) @Configuration public class IonetSpringConfig { @Bean public ActionFactoryBeanForSpring actionFactoryBeanForSpring() { return new ActionFactoryBeanForSpring<>(); } @Bean public BarSkeleton barSkeleton(ActionFactoryBeanForSpring factoryBean) { var builder = BarSkeleton.builder(); builder.setActionFactoryBean(factoryBean); // wire Spring DI into ionet builder.scanActionPackage(HallAction.class); builder.addInOut(new DebugInOut()); return builder.build(); } } // 2. Action controllers become regular Spring beans with full DI support @Component @ActionController(HallCmd.cmd) public class HallAction { @Autowired private UserService userService; // Spring injection works normally @ActionMethod(HallCmd.loginVerify) UserMessage loginVerify(String jwt, FlowContext flowContext) { UserMessage user = userService.authenticate(jwt); // use Spring service flowContext.bindingUserId(user.id); return user; } } ``` -------------------------------- ### Handle Login and Cross-Server Calls in FlowContext Source: https://context7.com/iohao/ionet/llms.txt FlowContext provides per-request context, including user ID binding, metadata retrieval, and capabilities for synchronous/asynchronous cross-server calls and broadcasting messages. Errors can be thrown as typed exceptions. ```java @ActionController(HallCmd.cmd) public class HallAction { @ActionMethod(HallCmd.loginVerify) UserMessage loginVerify(String jwt, FlowContext flowContext) { long userId = Math.abs(jwt.hashCode()); // Bind userId — marks session as authenticated; subsequent requests carry this id boolean ok = flowContext.bindingUserId(userId); if (!ok) { // Throw a typed error — sent back to client with an error code throw new RuntimeException("Login failed"); } // Read metadata long uid = flowContext.getUserId(); // 0 before bindingUserId CmdInfo cmd = flowContext.getCmdInfo(); // e.g., [1-1] long nanoTime = flowContext.getNanoTime(); // creation timestamp // Cross-logic-server synchronous call (returns Response) CmdInfo profileCmd = CmdInfo.of(2, 1); Response profileResp = flowContext.call(profileCmd, userId); UserProfile profile = profileResp.getValue(UserProfile.class); // Cross-logic-server async call with callback (runs on the same user thread) flowContext.callAsync(profileCmd, userId, response -> { UserProfile p = response.getValue(UserProfile.class); System.out.println("Async profile for " + p.name); }); // Broadcast a message back to this specific user only var broadcastCmd = CmdInfo.of(HallCmd.cmd, HallCmd.hello); flowContext.broadcastMe(broadcastCmd, "Welcome back!"); UserMessage user = new UserMessage(); user.id = userId; user.nickname = jwt; return user; } } ``` -------------------------------- ### C# Action Command Mapping Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/csharp/action.txt Defines static readonly integers for action commands, mapping request types and comments using CmdKit.MappingRequest. Ensure CmdKit is properly initialized. ```csharp public static readonly int ${o.memberName} = CmdKit.MappingRequest(${o.cmdMerge}, "${o.comment}"); ``` -------------------------------- ### C# Error Code Definition and Initialization Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/csharp/error_code.txt Defines static error codes and provides an initialization method to trigger their mapping. Use this pattern to define all game-specific error codes. ```csharp using System.Collections.Generic; using IoGame.Sdk; namespace ${namespace} { /// /// GameCode、ErrorCode. 响应错误码 /// /// Author: https://github.com/iohao/ionet public static class GameCode { <%for(o in errorCodeDocumentList) {%> /// /// ${o.description} /// public static readonly int ${o.name} = CmdKit.MappingErrorCode(${o.value}, "${o.description!}"); <%}%> public static void Init() { // trigger errorCodeMapping init. // 调用一次方法,触发错误码的初始化操作。 var ints = new List { <%for(o in errorCodeDocumentList) {%> ${o.name}, <%}%>0 }; } } } ``` -------------------------------- ### Handle Broadcast Notification (With Action) Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/csharp/broadcast_action.txt Executes custom action code and logs the merge title, broadcast title, and a specific value when a notification is received. ```csharp ${originalCode(o.exampleCodeAction)} IoGameSetting.GameGameConsole.Log($"{mergeTitle}, {title}, {value}"); ``` -------------------------------- ### Listen for Specific Broadcast Events Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/csharp/broadcast_action.txt Allows you to register a callback function to receive notifications for specific broadcast events. Each broadcast event is identified by a command and sub-command pair. ```APIDOC ## Listen${o.methodName} Broadcast ### Description Registers a callback to listen for a specific broadcast event. ### Method `public static void Listen${o.methodName}(CallbackDelegate callback)` ### Parameters #### Callback - `callback` (CallbackDelegate) - The function to be executed when the broadcast event occurs. This delegate will receive a result object containing broadcast data. ### Usage Example ```csharp Listener.listen${o.methodName}(result => { // Handle the broadcast notification ${o.exampleCode!} }); ``` ### Data Received - The callback receives a result object containing broadcast data. The type and description of the data depend on the specific broadcast event. - For events where `dataIsList` is true, the data will be a list of `${o.bizDataType}`. - For other events, the data will be a single `${o.bizDataType}`. ``` -------------------------------- ### Of with Callback Source: https://github.com/iohao/ionet/blob/main/extension-codegen/src/main/resources/generate/csharp/action_method_no_param.txt This method invokes an action without parameters and processes the result using a callback delegate. ```APIDOC ## Of with Callback ### Description Invokes an action method without parameters and provides a callback function to handle the result. ### Method `public static RequestCommand Of(CallbackDelegate callback)` ### Parameters * **callback** (`CallbackDelegate`) - A delegate function that accepts the result of the action. ### Returns * `RequestCommand` - An object representing the command to be executed. ### Code Example ```csharp .Of(result => { // your biz code. // result.Log(value); }); ``` ```