Full Code of iohao/iogame for AI

main 917a7964ccf3 cached
906 files
2.4 MB
688.9k tokens
3949 symbols
1 requests
Download .txt
Showing preview only (3,019K chars total). Download the full file or copy to clipboard to get everything.
Repository: iohao/iogame
Branch: main
Commit: 917a7964ccf3
Files: 906
Total size: 2.4 MB

Directory structure:
gitextract_1je6oco0/

├── .github/
│   └── ISSUE_TEMPLATE/
│       ├── ask-question.md
│       ├── bug-report.md
│       ├── empty-issues.md
│       └── enhance-task.md
├── .gitignore
├── BACKERS.md
├── LICENSE
├── README.md
├── README_CN.md
├── changeLog_ioGame.md
├── common/
│   ├── README.md
│   ├── common-core/
│   │   ├── README.md
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── iohao/
│   │       │   │           └── game/
│   │       │   │               └── action/
│   │       │   │                   └── skeleton/
│   │       │   │                       ├── IoGameVersion.java
│   │       │   │                       ├── annotation/
│   │       │   │                       │   ├── ActionController.java
│   │       │   │                       │   ├── ActionMethod.java
│   │       │   │                       │   ├── DocActionSend.java
│   │       │   │                       │   ├── DocActionSends.java
│   │       │   │                       │   ├── ValidatedGroup.java
│   │       │   │                       │   └── package-info.java
│   │       │   │                       ├── core/
│   │       │   │                       │   ├── ActionCommand.java
│   │       │   │                       │   ├── ActionCommandDocParser.java
│   │       │   │                       │   ├── ActionCommandFlowExecute.java
│   │       │   │                       │   ├── ActionCommandHandler.java
│   │       │   │                       │   ├── ActionCommandParser.java
│   │       │   │                       │   ├── ActionCommandRegion.java
│   │       │   │                       │   ├── ActionCommandRegionGlobalCheckKit.java
│   │       │   │                       │   ├── ActionCommandRegions.java
│   │       │   │                       │   ├── ActionFactoryBean.java
│   │       │   │                       │   ├── ActionParserListenerAbout.java
│   │       │   │                       │   ├── ActionSend.java
│   │       │   │                       │   ├── BarMessageKit.java
│   │       │   │                       │   ├── BarSkeleton.java
│   │       │   │                       │   ├── BarSkeletonBuilder.java
│   │       │   │                       │   ├── BarSkeletonBuilderParamConfig.java
│   │       │   │                       │   ├── BarSkeletonSetting.java
│   │       │   │                       │   ├── CmdInfo.java
│   │       │   │                       │   ├── CmdInfoFlyweightFactory.java
│   │       │   │                       │   ├── CmdKit.java
│   │       │   │                       │   ├── DataCodecKit.java
│   │       │   │                       │   ├── DefaultActionCommandFlowExecute.java
│   │       │   │                       │   ├── DefaultActionFactoryBean.java
│   │       │   │                       │   ├── DependencyInjectionPart.java
│   │       │   │                       │   ├── DevConfig.java
│   │       │   │                       │   ├── Handler.java
│   │       │   │                       │   ├── InOutManager.java
│   │       │   │                       │   ├── InOutManagerAbout.java
│   │       │   │                       │   ├── IoGameCommonCoreConfig.java
│   │       │   │                       │   ├── IoGameGlobalSetting.java
│   │       │   │                       │   ├── PrintActionKit.java
│   │       │   │                       │   ├── SkeletonAttr.java
│   │       │   │                       │   ├── ValidatorKit.java
│   │       │   │                       │   ├── action/
│   │       │   │                       │   │   └── parser/
│   │       │   │                       │   │       ├── ActionParserContext.java
│   │       │   │                       │   │       ├── ActionParserListener.java
│   │       │   │                       │   │       └── package-info.java
│   │       │   │                       │   ├── codec/
│   │       │   │                       │   │   ├── DataCodec.java
│   │       │   │                       │   │   ├── DataSelfEncode.java
│   │       │   │                       │   │   ├── JsonDataCodec.java
│   │       │   │                       │   │   ├── ProtoDataCodec.java
│   │       │   │                       │   │   └── package-info.java
│   │       │   │                       │   ├── commumication/
│   │       │   │                       │   │   ├── BroadcastContext.java
│   │       │   │                       │   │   ├── BroadcastOrderContext.java
│   │       │   │                       │   │   ├── BrokerClientContext.java
│   │       │   │                       │   │   ├── ChannelContext.java
│   │       │   │                       │   │   ├── CommunicationAggregationContext.java
│   │       │   │                       │   │   ├── InvokeExternalModuleContext.java
│   │       │   │                       │   │   ├── InvokeModuleContext.java
│   │       │   │                       │   │   ├── ProcessorContext.java
│   │       │   │                       │   │   ├── SimpleServer.java
│   │       │   │                       │   │   └── package-info.java
│   │       │   │                       │   ├── doc/
│   │       │   │                       │   │   ├── ActionCommandDoc.java
│   │       │   │                       │   │   ├── ActionCommandDocKit.java
│   │       │   │                       │   │   ├── ActionDoc.java
│   │       │   │                       │   │   ├── ActionDocs.java
│   │       │   │                       │   │   ├── ActionDocument.java
│   │       │   │                       │   │   ├── ActionMemberCmdDocument.java
│   │       │   │                       │   │   ├── ActionMethodDocument.java
│   │       │   │                       │   │   ├── ActionSendDoc.java
│   │       │   │                       │   │   ├── ActionSendDocs.java
│   │       │   │                       │   │   ├── ActionSendDocsRegion.java
│   │       │   │                       │   │   ├── BarSkeletonDoc.java
│   │       │   │                       │   │   ├── BroadcastDoc.java
│   │       │   │                       │   │   ├── BroadcastDocBuilder.java
│   │       │   │                       │   │   ├── BroadcastDocument.java
│   │       │   │                       │   │   ├── BroadcastDocumentBuilder.java
│   │       │   │                       │   │   ├── DocInfo.java
│   │       │   │                       │   │   ├── DocumentAccessAuthentication.java
│   │       │   │                       │   │   ├── DocumentAnalyseKit.java
│   │       │   │                       │   │   ├── DocumentGenerate.java
│   │       │   │                       │   │   ├── DocumentMethod.java
│   │       │   │                       │   │   ├── ErrorCodeDoc.java
│   │       │   │                       │   │   ├── ErrorCodeDocs.java
│   │       │   │                       │   │   ├── ErrorCodeDocsRegion.java
│   │       │   │                       │   │   ├── ErrorCodeDocument.java
│   │       │   │                       │   │   ├── IoGameDocument.java
│   │       │   │                       │   │   ├── IoGameDocumentHelper.java
│   │       │   │                       │   │   ├── JavaClassDocInfo.java
│   │       │   │                       │   │   ├── TextDocumentGenerate.java
│   │       │   │                       │   │   ├── TypeMappingDocument.java
│   │       │   │                       │   │   ├── TypeMappingRecord.java
│   │       │   │                       │   │   └── package-info.java
│   │       │   │                       │   ├── enhance/
│   │       │   │                       │   │   ├── BarSkeletonBuilderEnhance.java
│   │       │   │                       │   │   └── BarSkeletonBuilderEnhances.java
│   │       │   │                       │   ├── exception/
│   │       │   │                       │   │   ├── ActionErrorEnum.java
│   │       │   │                       │   │   ├── MsgException.java
│   │       │   │                       │   │   ├── MsgExceptionInfo.java
│   │       │   │                       │   │   ├── MsgExceptionKit.java
│   │       │   │                       │   │   └── package-info.java
│   │       │   │                       │   ├── flow/
│   │       │   │                       │   │   ├── ActionAfter.java
│   │       │   │                       │   │   ├── ActionMethodExceptionProcess.java
│   │       │   │                       │   │   ├── ActionMethodInOut.java
│   │       │   │                       │   │   ├── ActionMethodInvoke.java
│   │       │   │                       │   │   ├── ActionMethodParamParser.java
│   │       │   │                       │   │   ├── ActionMethodResultWrap.java
│   │       │   │                       │   │   ├── FlowContext.java
│   │       │   │                       │   │   ├── FlowContextFactory.java
│   │       │   │                       │   │   ├── FlowContextKit.java
│   │       │   │                       │   │   ├── InternalAboutFlowContext.java
│   │       │   │                       │   │   ├── ResponseMessageCreate.java
│   │       │   │                       │   │   ├── UserAttachment.java
│   │       │   │                       │   │   ├── attr/
│   │       │   │                       │   │   │   ├── FlowAttr.java
│   │       │   │                       │   │   │   ├── FlowOption.java
│   │       │   │                       │   │   │   ├── FlowOptionDynamic.java
│   │       │   │                       │   │   │   └── package-info.java
│   │       │   │                       │   │   ├── internal/
│   │       │   │                       │   │   │   ├── DebugInOut.java
│   │       │   │                       │   │   │   ├── DefaultActionAfter.java
│   │       │   │                       │   │   │   ├── DefaultActionMethodExceptionProcess.java
│   │       │   │                       │   │   │   ├── DefaultActionMethodInvoke.java
│   │       │   │                       │   │   │   ├── DefaultActionMethodParamParser.java
│   │       │   │                       │   │   │   ├── DefaultActionMethodResultWrap.java
│   │       │   │                       │   │   │   ├── DefaultResponseMessageCreate.java
│   │       │   │                       │   │   │   ├── StatActionInOut.java
│   │       │   │                       │   │   │   ├── ThreadMonitorInOut.java
│   │       │   │                       │   │   │   ├── TimeRangeInOut.java
│   │       │   │                       │   │   │   ├── TraceIdInOut.java
│   │       │   │                       │   │   │   └── package-info.java
│   │       │   │                       │   │   ├── package-info.java
│   │       │   │                       │   │   └── parser/
│   │       │   │                       │   │       ├── BoolValueMethodParser.java
│   │       │   │                       │   │       ├── DefaultMethodParser.java
│   │       │   │                       │   │       ├── IntValueMethodParser.java
│   │       │   │                       │   │       ├── LongValueMethodParser.java
│   │       │   │                       │   │       ├── MethodParser.java
│   │       │   │                       │   │       ├── MethodParsers.java
│   │       │   │                       │   │       ├── StringValueMethodParser.java
│   │       │   │                       │   │       └── package-info.java
│   │       │   │                       │   ├── package-info.java
│   │       │   │                       │   └── runner/
│   │       │   │                       │       ├── InternalRunner.java
│   │       │   │                       │       ├── Runner.java
│   │       │   │                       │       ├── Runners.java
│   │       │   │                       │       └── package-info.java
│   │       │   │                       ├── eventbus/
│   │       │   │                       │   ├── AbstractEventBusRunner.java
│   │       │   │                       │   ├── EventBrokerClientMessage.java
│   │       │   │                       │   ├── EventBus.java
│   │       │   │                       │   ├── EventBusFireType.java
│   │       │   │                       │   ├── EventBusListener.java
│   │       │   │                       │   ├── EventBusMessage.java
│   │       │   │                       │   ├── EventBusMessageCreator.java
│   │       │   │                       │   ├── EventBusRegion.java
│   │       │   │                       │   ├── EventBusRunner.java
│   │       │   │                       │   ├── EventBusSubscriber.java
│   │       │   │                       │   ├── EventSubscribe.java
│   │       │   │                       │   ├── EventTopicMessage.java
│   │       │   │                       │   ├── ExecutorSelector.java
│   │       │   │                       │   ├── InternalAboutAny.java
│   │       │   │                       │   ├── InternalAboutEventBus.java
│   │       │   │                       │   ├── SubscribeExecutorStrategy.java
│   │       │   │                       │   ├── Subscriber.java
│   │       │   │                       │   ├── SubscriberInvoke.java
│   │       │   │                       │   ├── SubscriberInvokeCreator.java
│   │       │   │                       │   └── package-info.java
│   │       │   │                       ├── ext/
│   │       │   │                       │   └── spring/
│   │       │   │                       │       ├── ActionFactoryBeanForSpring.java
│   │       │   │                       │       └── package-info.java
│   │       │   │                       ├── i18n/
│   │       │   │                       │   ├── Bundle.java
│   │       │   │                       │   └── MessageKey.java
│   │       │   │                       ├── kit/
│   │       │   │                       │   ├── ExecutorSelectEnum.java
│   │       │   │                       │   ├── ExecutorSelectKit.java
│   │       │   │                       │   ├── FixedCmd.java
│   │       │   │                       │   ├── LogicServerCreateKit.java
│   │       │   │                       │   ├── RangeBroadcast.java
│   │       │   │                       │   ├── RangeBroadcaster.java
│   │       │   │                       │   └── package-info.java
│   │       │   │                       ├── package-info.java
│   │       │   │                       ├── protocol/
│   │       │   │                       │   ├── BarMessage.java
│   │       │   │                       │   ├── HeadMetadata.java
│   │       │   │                       │   ├── RequestMessage.java
│   │       │   │                       │   ├── ResponseMessage.java
│   │       │   │                       │   ├── collect/
│   │       │   │                       │   │   ├── RequestCollectMessage.java
│   │       │   │                       │   │   ├── ResponseCollectItemMessage.java
│   │       │   │                       │   │   ├── ResponseCollectMessage.java
│   │       │   │                       │   │   └── package-info.java
│   │       │   │                       │   ├── external/
│   │       │   │                       │   │   ├── RequestCollectExternalMessage.java
│   │       │   │                       │   │   ├── ResponseCollectExternalItemMessage.java
│   │       │   │                       │   │   ├── ResponseCollectExternalMessage.java
│   │       │   │                       │   │   └── package-info.java
│   │       │   │                       │   ├── login/
│   │       │   │                       │   │   ├── SettingUserIdMessage.java
│   │       │   │                       │   │   ├── SettingUserIdMessageResponse.java
│   │       │   │                       │   │   └── SettingUserIdResult.java
│   │       │   │                       │   ├── package-info.java
│   │       │   │                       │   ├── processor/
│   │       │   │                       │   │   ├── EndPointLogicServerMessage.java
│   │       │   │                       │   │   ├── EndPointOperationEnum.java
│   │       │   │                       │   │   ├── SimpleServerInfo.java
│   │       │   │                       │   │   └── package-info.java
│   │       │   │                       │   └── wrapper/
│   │       │   │                       │       ├── BoolValue.java
│   │       │   │                       │       ├── BoolValueList.java
│   │       │   │                       │       ├── ByteValueList.java
│   │       │   │                       │       ├── IntValue.java
│   │       │   │                       │       ├── IntValueList.java
│   │       │   │                       │       ├── LongValue.java
│   │       │   │                       │       ├── LongValueList.java
│   │       │   │                       │       ├── StringValue.java
│   │       │   │                       │       ├── StringValueList.java
│   │       │   │                       │       ├── ValueRecord.java
│   │       │   │                       │       ├── WrapperKit.java
│   │       │   │                       │       └── package-info.java
│   │       │   │                       ├── pulse/
│   │       │   │                       │   ├── Pulses.java
│   │       │   │                       │   ├── core/
│   │       │   │                       │   │   ├── PulseChannel.java
│   │       │   │                       │   │   ├── PulseTransmit.java
│   │       │   │                       │   │   ├── consumer/
│   │       │   │                       │   │   │   ├── DefaultPulseConsumers.java
│   │       │   │                       │   │   │   ├── PulseConsumer.java
│   │       │   │                       │   │   │   ├── PulseConsumers.java
│   │       │   │                       │   │   │   └── PulseSignalRequestAccept.java
│   │       │   │                       │   │   └── producer/
│   │       │   │                       │   │       ├── DefaultPulseProducers.java
│   │       │   │                       │   │       ├── PulseCreatePeriod.java
│   │       │   │                       │   │       ├── PulseCreateRequest.java
│   │       │   │                       │   │       ├── PulseProducer.java
│   │       │   │                       │   │       ├── PulseProducers.java
│   │       │   │                       │   │       └── PulseSignalResponseAccept.java
│   │       │   │                       │   ├── message/
│   │       │   │                       │   │   ├── EmptyMessage.java
│   │       │   │                       │   │   ├── PulseSignalMessage.java
│   │       │   │                       │   │   ├── PulseSignalRequest.java
│   │       │   │                       │   │   ├── PulseSignalResponse.java
│   │       │   │                       │   │   └── SignalType.java
│   │       │   │                       │   ├── package-info.java
│   │       │   │                       │   └── runner/
│   │       │   │                       │       ├── CreatePulsesRunner.java
│   │       │   │                       │       └── PulseRunner.java
│   │       │   │                       └── toy/
│   │       │   │                           ├── BannerColorStrategy.java
│   │       │   │                           ├── BannerData.java
│   │       │   │                           ├── BreakingNewsAbout.java
│   │       │   │                           ├── InternalMemory.java
│   │       │   │                           ├── IoGameBanner.java
│   │       │   │                           ├── ToyLine.java
│   │       │   │                           ├── ToyTable.java
│   │       │   │                           ├── ToyTableRegion.java
│   │       │   │                           └── ToyTableRender.java
│   │       │   └── resources/
│   │       │       ├── iohao.properties
│   │       │       └── iohao_zh_CN.properties
│   │       └── test/
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── iohao/
│   │           │           └── game/
│   │           │               ├── action/
│   │           │               │   └── skeleton/
│   │           │               │       ├── core/
│   │           │               │       │   ├── ActionParserListenerTest.java
│   │           │               │       │   ├── BarSkeletonTest.java
│   │           │               │       │   ├── DataCodecKitTest.java
│   │           │               │       │   ├── InOutManagerTest.java
│   │           │               │       │   ├── JSR380Test.java
│   │           │               │       │   ├── JSR380ValidatedGroupTest.java
│   │           │               │       │   ├── SimpleWrapperActionTest.java
│   │           │               │       │   ├── WrapperIntTest.java
│   │           │               │       │   ├── WrapperLongTest.java
│   │           │               │       │   ├── action/
│   │           │               │       │   │   ├── BeeAction.java
│   │           │               │       │   │   ├── ExampleActionCmd.java
│   │           │               │       │   │   ├── SimpleWrapperAction.java
│   │           │               │       │   │   ├── WrapperIntAction.java
│   │           │               │       │   │   ├── WrapperLongAction.java
│   │           │               │       │   │   ├── group/
│   │           │               │       │   │   │   ├── Create.java
│   │           │               │       │   │   │   └── Update.java
│   │           │               │       │   │   └── pojo/
│   │           │               │       │   │       ├── BeeApple.java
│   │           │               │       │   │       ├── BirdValid.java
│   │           │               │       │   │       ├── DogValid.java
│   │           │               │       │   │       └── Snake.java
│   │           │               │       │   ├── data/
│   │           │               │       │   │   └── TestDataKit.java
│   │           │               │       │   └── flow/
│   │           │               │       │       └── internal/
│   │           │               │       │           ├── StatActionInOutTest.java
│   │           │               │       │           ├── ThreadMonitorInOutTest.java
│   │           │               │       │           └── TimeRangeInOutTest.java
│   │           │               │       ├── eventbus/
│   │           │               │       │   ├── CustomEvent.java
│   │           │               │       │   ├── EventBusTest.java
│   │           │               │       │   ├── MyMessage.java
│   │           │               │       │   └── MyRecord.java
│   │           │               │       ├── i18n/
│   │           │               │       │   └── BundleTest.java
│   │           │               │       ├── protocol/
│   │           │               │       │   ├── ResponseMessageTest.java
│   │           │               │       │   ├── Student.java
│   │           │               │       │   └── wrapper/
│   │           │               │       │       └── WrapperKitTest.java
│   │           │               │       └── toy/
│   │           │               │           └── ToyTableTest.java
│   │           │               └── common/
│   │           │                   └── kit/
│   │           │                       └── ClassScannerTest.java
│   │           └── resources/
│   │               └── logback.xml
│   ├── common-kit/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           └── java/
│   │               └── com/
│   │                   └── iohao/
│   │                       └── game/
│   │                           └── common/
│   │                               └── kit/
│   │                                   ├── ProtoKit.java
│   │                                   ├── asm/
│   │                                   │   ├── ClassRefInfo.java
│   │                                   │   ├── ClassRefInfoBuilder.java
│   │                                   │   ├── ClassRefInfoKit.java
│   │                                   │   ├── FieldRefInfo.java
│   │                                   │   ├── MethodRefInfo.java
│   │                                   │   └── package-info.java
│   │                                   ├── io/
│   │                                   │   ├── FileKit.java
│   │                                   │   ├── ResourceKit.java
│   │                                   │   └── package-info.java
│   │                                   └── system/
│   │                                       ├── InternalSystemPropsKit.java
│   │                                       ├── OsInfo.java
│   │                                       └── package-info.java
│   ├── common-micro-kit/
│   │   ├── README.md
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── com/
│   │       │       │   └── iohao/
│   │       │       │       └── game/
│   │       │       │           └── common/
│   │       │       │               ├── consts/
│   │       │       │               │   ├── CommonConst.java
│   │       │       │               │   └── IoGameLogName.java
│   │       │       │               ├── internal/
│   │       │       │               │   ├── BootConfig.java
│   │       │       │               │   ├── BootItemConfig.java
│   │       │       │               │   └── BootItemConfigKit.java
│   │       │       │               └── kit/
│   │       │       │                   ├── AboutKit.java
│   │       │       │                   ├── ArrayKit.java
│   │       │       │                   ├── BaseTypeKit.java
│   │       │       │                   ├── ByteKit.java
│   │       │       │                   ├── ClassScanner.java
│   │       │       │                   ├── CollKit.java
│   │       │       │                   ├── CompletableFutureKit.java
│   │       │       │                   ├── ExecutorKit.java
│   │       │       │                   ├── HashKit.java
│   │       │       │                   ├── MoreKit.java
│   │       │       │                   ├── MurmurHash3.java
│   │       │       │                   ├── NetworkKit.java
│   │       │       │                   ├── OperationCode.java
│   │       │       │                   ├── PresentKit.java
│   │       │       │                   ├── RandomKit.java
│   │       │       │                   ├── RuntimeKit.java
│   │       │       │                   ├── SafeKit.java
│   │       │       │                   ├── StrKit.java
│   │       │       │                   ├── TimeBetweenKit.java
│   │       │       │                   ├── TimeFormatterKit.java
│   │       │       │                   ├── TimeKit.java
│   │       │       │                   ├── attr/
│   │       │       │                   │   ├── AttrOption.java
│   │       │       │                   │   ├── AttrOptionDynamic.java
│   │       │       │                   │   ├── AttrOptions.java
│   │       │       │                   │   └── package-info.java
│   │       │       │                   ├── beans/
│   │       │       │                   │   └── property/
│   │       │       │                   │       ├── AbstractPropertyValueObservable.java
│   │       │       │                   │       ├── BooleanProperty.java
│   │       │       │                   │       ├── IntegerProperty.java
│   │       │       │                   │       ├── LongProperty.java
│   │       │       │                   │       ├── NumberPropertyValueObservable.java
│   │       │       │                   │       ├── ObjectProperty.java
│   │       │       │                   │       ├── PropertyAbout.java
│   │       │       │                   │       ├── PropertyChangeListener.java
│   │       │       │                   │       ├── PropertyValueObservable.java
│   │       │       │                   │       ├── StringProperty.java
│   │       │       │                   │       └── package-info.java
│   │       │       │                   ├── collect/
│   │       │       │                   │   ├── ListMultiMap.java
│   │       │       │                   │   ├── MultiMap.java
│   │       │       │                   │   ├── NonBlockingListMultiMap.java
│   │       │       │                   │   ├── NonBlockingSetMultiMap.java
│   │       │       │                   │   ├── SetMultiMap.java
│   │       │       │                   │   └── package-info.java
│   │       │       │                   ├── concurrent/
│   │       │       │                   │   ├── CommonTaskListener.java
│   │       │       │                   │   ├── DaemonThreadFactory.java
│   │       │       │                   │   ├── FixedNameThreadFactory.java
│   │       │       │                   │   ├── IntervalTaskListener.java
│   │       │       │                   │   ├── OnceTaskListener.java
│   │       │       │                   │   ├── TaskKit.java
│   │       │       │                   │   ├── TaskListener.java
│   │       │       │                   │   ├── ThreadCreator.java
│   │       │       │                   │   ├── executor/
│   │       │       │                   │   │   ├── AbstractThreadExecutorRegion.java
│   │       │       │                   │   │   ├── ExecutorRegion.java
│   │       │       │                   │   │   ├── ExecutorRegionKit.java
│   │       │       │                   │   │   ├── SimpleThreadExecutorRegion.java
│   │       │       │                   │   │   ├── ThreadExecutor.java
│   │       │       │                   │   │   ├── ThreadExecutorRegion.java
│   │       │       │                   │   │   ├── UserThreadExecutorRegion.java
│   │       │       │                   │   │   ├── UserVirtualThreadExecutorRegion.java
│   │       │       │                   │   │   └── package-info.java
│   │       │       │                   │   ├── package-info.java
│   │       │       │                   │   └── timer/
│   │       │       │                   │       └── delay/
│   │       │       │                   │           ├── DelayTask.java
│   │       │       │                   │           ├── DelayTaskKit.java
│   │       │       │                   │           ├── DelayTaskRegion.java
│   │       │       │                   │           ├── InternalDelayAbout.java
│   │       │       │                   │           └── package-info.java
│   │       │       │                   ├── exception/
│   │       │       │                   │   ├── CommonIllegalArgumentException.java
│   │       │       │                   │   ├── CommonNullPointerException.java
│   │       │       │                   │   ├── CommonRuntimeException.java
│   │       │       │                   │   ├── ThrowKit.java
│   │       │       │                   │   └── package-info.java
│   │       │       │                   ├── id/
│   │       │       │                   │   ├── CacheKeyKit.java
│   │       │       │                   │   ├── IdKit.java
│   │       │       │                   │   ├── StringIdSupplier.java
│   │       │       │                   │   └── package-info.java
│   │       │       │                   ├── micro/
│   │       │       │                   │   └── room/
│   │       │       │                   │       ├── MicroRoom.java
│   │       │       │                   │       ├── MicroRooms.java
│   │       │       │                   │       └── package-info.java
│   │       │       │                   ├── package-info.java
│   │       │       │                   ├── time/
│   │       │       │                   │   ├── CacheTimeKit.java
│   │       │       │                   │   ├── ConfigTimeKit.java
│   │       │       │                   │   ├── ExpireTimeKit.java
│   │       │       │                   │   ├── FormatTimeKit.java
│   │       │       │                   │   ├── ToTimeKit.java
│   │       │       │                   │   └── package-info.java
│   │       │       │                   ├── trace/
│   │       │       │                   │   ├── TraceIdSupplier.java
│   │       │       │                   │   ├── TraceKit.java
│   │       │       │                   │   └── package-info.java
│   │       │       │                   └── weight/
│   │       │       │                       ├── Weight.java
│   │       │       │                       ├── WeightKit.java
│   │       │       │                       └── package-info.java
│   │       │       └── module-info.java.txt
│   │       └── test/
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── iohao/
│   │           │           └── game/
│   │           │               └── common/
│   │           │                   └── kit/
│   │           │                       ├── ByteKitTest.java
│   │           │                       ├── TimeKitTest.java
│   │           │                       ├── attr/
│   │           │                       │   └── AttrOptionDynamicTest.java
│   │           │                       ├── beans/
│   │           │                       │   └── property/
│   │           │                       │       └── PropertyValueObservableTest.java
│   │           │                       ├── collect/
│   │           │                       │   ├── ListMultiMapTest.java
│   │           │                       │   └── SetMultiMapTest.java
│   │           │                       ├── concurrent/
│   │           │                       │   ├── TaskKitTest.java
│   │           │                       │   ├── executor/
│   │           │                       │   │   └── ExecutorRegionKitTest.java
│   │           │                       │   └── timer/
│   │           │                       │       └── delay/
│   │           │                       │           └── DelayTaskTest.java
│   │           │                       ├── time/
│   │           │                       │   ├── CacheTimeKitTest.java
│   │           │                       │   ├── ExpireTimeKitTest.java
│   │           │                       │   └── FormatTimeKitTest.java
│   │           │                       └── trace/
│   │           │                           └── TraceKitTest.java
│   │           └── resources/
│   │               └── logback.xml
│   └── common-validation/
│       ├── README.md
│       ├── pom.xml
│       └── src/
│           └── main/
│               ├── java/
│               │   └── com/
│               │       └── iohao/
│               │           └── game/
│               │               └── common/
│               │                   └── validation/
│               │                       ├── Validation.java
│               │                       ├── Validator.java
│               │                       ├── annotation/
│               │                       │   ├── EnableValidation.java
│               │                       │   └── package-info.java
│               │                       ├── package-info.java
│               │                       ├── processor/
│               │                       │   ├── ValidationProcessor.java
│               │                       │   └── package-info.java
│               │                       └── support/
│               │                           ├── JakartaValidator.java
│               │                           ├── JavaxValidator.java
│               │                           └── package-info.java
│               └── resources/
│                   └── META-INF/
│                       ├── gradle/
│                       │   └── incremental.annotation.processors
│                       └── services/
│                           └── javax.annotation.processing.Processor
├── doc_maven.txt
├── external/
│   ├── README.md
│   ├── external-core/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           └── java/
│   │               └── com/
│   │                   └── iohao/
│   │                       └── game/
│   │                           └── external/
│   │                               └── core/
│   │                                   ├── ExternalCore.java
│   │                                   ├── ExternalCoreSetting.java
│   │                                   ├── ExternalServer.java
│   │                                   ├── aware/
│   │                                   │   ├── ExternalCoreSettingAware.java
│   │                                   │   ├── UserSessionsAware.java
│   │                                   │   └── package-info.java
│   │                                   ├── broker/
│   │                                   │   └── client/
│   │                                   │       ├── ExternalBrokerClientStartup.java
│   │                                   │       ├── enhance/
│   │                                   │       │   ├── ExternalEnhance.java
│   │                                   │       │   └── ExternalEnhances.java
│   │                                   │       ├── ext/
│   │                                   │       │   ├── ExternalBizRegion.java
│   │                                   │       │   ├── ExternalBizRegionContext.java
│   │                                   │       │   ├── ExternalBizRegions.java
│   │                                   │       │   ├── impl/
│   │                                   │       │   │   ├── AttachmentExternalBizRegion.java
│   │                                   │       │   │   ├── ExistUserExternalBizRegion.java
│   │                                   │       │   │   ├── ExternalBizRegionKit.java
│   │                                   │       │   │   ├── ForcedOfflineExternalBizRegion.java
│   │                                   │       │   │   ├── UserHeadMetadataExternalBizRegion.java
│   │                                   │       │   │   └── package-info.java
│   │                                   │       │   └── package-info.java
│   │                                   │       ├── package-info.java
│   │                                   │       └── processor/
│   │                                   │           ├── BroadcastMessageExternalProcessor.java
│   │                                   │           ├── BroadcastOrderMessageExternalProcessor.java
│   │                                   │           ├── BrokerClientOfflineMessageExternalProcessor.java
│   │                                   │           ├── BrokerClientOnlineMessageExternalProcessor.java
│   │                                   │           ├── EndPointLogicServerMessageExternalProcessor.java
│   │                                   │           ├── RequestCollectExternalMessageExternalProcessor.java
│   │                                   │           ├── ResponseMessageExternalProcessor.java
│   │                                   │           ├── SettingUserIdMessageExternalProcessor.java
│   │                                   │           ├── listener/
│   │                                   │           │   ├── CmdRegionBrokerClientListener.java
│   │                                   │           │   └── package-info.java
│   │                                   │           └── package-info.java
│   │                                   ├── config/
│   │                                   │   ├── ExternalGlobalConfig.java
│   │                                   │   ├── ExternalJoinEnum.java
│   │                                   │   └── package-info.java
│   │                                   ├── hook/
│   │                                   │   ├── AccessAuthenticationHook.java
│   │                                   │   ├── BrokerClientExternalAttr.java
│   │                                   │   ├── IdleHook.java
│   │                                   │   ├── UserHook.java
│   │                                   │   ├── cache/
│   │                                   │   │   ├── CmdCacheOption.java
│   │                                   │   │   ├── ExternalCmdCache.java
│   │                                   │   │   ├── ExternalCmdCacheSetting.java
│   │                                   │   │   ├── InternalAboutCache.java
│   │                                   │   │   ├── internal/
│   │                                   │   │   │   └── DefaultExternalCmdCache.java
│   │                                   │   │   └── package-info.java
│   │                                   │   ├── internal/
│   │                                   │   │   ├── DefaultAccessAuthenticationHook.java
│   │                                   │   │   ├── DefaultUserHook.java
│   │                                   │   │   ├── IdleProcessSetting.java
│   │                                   │   │   └── package-info.java
│   │                                   │   └── package-info.java
│   │                                   ├── kit/
│   │                                   │   ├── ExternalKit.java
│   │                                   │   └── package-info.java
│   │                                   ├── message/
│   │                                   │   ├── DefaultExternalCodec.java
│   │                                   │   ├── ExternalCodec.java
│   │                                   │   ├── ExternalCodecKit.java
│   │                                   │   ├── ExternalMessage.java
│   │                                   │   ├── ExternalMessageCmdCode.java
│   │                                   │   └── package-info.java
│   │                                   ├── micro/
│   │                                   │   ├── MicroBootstrap.java
│   │                                   │   ├── MicroBootstrapFlow.java
│   │                                   │   ├── PipelineContext.java
│   │                                   │   ├── join/
│   │                                   │   │   ├── ExternalJoinSelector.java
│   │                                   │   │   ├── ExternalJoinSelectors.java
│   │                                   │   │   └── package-info.java
│   │                                   │   └── package-info.java
│   │                                   ├── package-info.java
│   │                                   └── session/
│   │                                       ├── UserChannelId.java
│   │                                       ├── UserSession.java
│   │                                       ├── UserSessionOption.java
│   │                                       ├── UserSessionState.java
│   │                                       ├── UserSessions.java
│   │                                       └── package-info.java
│   └── external-netty/
│       ├── pom.xml
│       └── src/
│           └── main/
│               ├── java/
│               │   └── com/
│               │       └── iohao/
│               │           └── game/
│               │               └── external/
│               │                   └── core/
│               │                       └── netty/
│               │                           ├── DefaultExternalCore.java
│               │                           ├── DefaultExternalCoreSetting.java
│               │                           ├── DefaultExternalServer.java
│               │                           ├── DefaultExternalServerBuilder.java
│               │                           ├── SettingOption.java
│               │                           ├── handler/
│               │                           │   ├── CmdCacheHandler.java
│               │                           │   ├── CmdCheckHandler.java
│               │                           │   ├── SimpleLoggerHandler.java
│               │                           │   ├── SocketCmdAccessAuthHandler.java
│               │                           │   ├── SocketIdleExcludeHandler.java
│               │                           │   ├── SocketIdleHandler.java
│               │                           │   ├── SocketRequestBrokerHandler.java
│               │                           │   ├── SocketUserSessionHandler.java
│               │                           │   ├── check/
│               │                           │   │   ├── HttpFallbackHandler.java
│               │                           │   │   └── TcpProtocolSanityCheckHandler.java
│               │                           │   ├── codec/
│               │                           │   │   ├── TcpExternalCodec.java
│               │                           │   │   └── WebSocketExternalCodec.java
│               │                           │   └── ws/
│               │                           │       ├── HttpRealIpHandler.java
│               │                           │       └── WebSocketVerifyHandler.java
│               │                           ├── hook/
│               │                           │   ├── DefaultSocketIdleHook.java
│               │                           │   └── SocketIdleHook.java
│               │                           ├── kit/
│               │                           │   └── ExternalServerCreateKit.java
│               │                           ├── micro/
│               │                           │   ├── AbstractMicroBootstrap.java
│               │                           │   ├── AbstractMicroBootstrapFlow.java
│               │                           │   ├── DefaultPipelineContext.java
│               │                           │   ├── SocketMicroBootstrap.java
│               │                           │   ├── SocketMicroBootstrapFlow.java
│               │                           │   ├── TcpMicroBootstrapFlow.java
│               │                           │   ├── WebSocketMicroBootstrapFlow.java
│               │                           │   ├── auto/
│               │                           │   │   ├── EventLoopGroupThreadFactory.java
│               │                           │   │   ├── GroupChannelOption.java
│               │                           │   │   ├── GroupChannelOptionForLinux.java
│               │                           │   │   ├── GroupChannelOptionForMac.java
│               │                           │   │   └── GroupChannelOptionForOther.java
│               │                           │   └── join/
│               │                           │       ├── SocketExternalJoinSelector.java
│               │                           │       ├── TcpExternalJoinSelector.java
│               │                           │       └── WebSocketExternalJoinSelector.java
│               │                           ├── package-info.java
│               │                           └── session/
│               │                               ├── AbstractUserSession.java
│               │                               ├── AbstractUserSessions.java
│               │                               ├── SocketUserSession.java
│               │                               └── SocketUserSessions.java
│               └── resources/
│                   └── META-INF/
│                       └── services/
│                           └── com.iohao.game.external.core.micro.join.ExternalJoinSelector
├── history/
│   └── changeLog_ioGame17.md
├── net-bolt/
│   ├── README.md
│   ├── bolt-broker-server/
│   │   ├── README.md
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       └── com/
│   │       │           └── iohao/
│   │       │               └── game/
│   │       │                   └── bolt/
│   │       │                       └── broker/
│   │       │                           ├── cluster/
│   │       │                           │   ├── Broker.java
│   │       │                           │   ├── BrokerCluster.java
│   │       │                           │   ├── BrokerClusterManager.java
│   │       │                           │   ├── BrokerClusterManagerBuilder.java
│   │       │                           │   ├── BrokerClusterMessageHandler.java
│   │       │                           │   ├── BrokerClusterMetadata.java
│   │       │                           │   ├── BrokerRunModeEnum.java
│   │       │                           │   ├── ClusterMessageListener.java
│   │       │                           │   └── package-info.java
│   │       │                           └── server/
│   │       │                               ├── BrokerServer.java
│   │       │                               ├── BrokerServerBuilder.java
│   │       │                               ├── aware/
│   │       │                               │   ├── BrokerClientModulesAware.java
│   │       │                               │   └── BrokerServerAware.java
│   │       │                               ├── balanced/
│   │       │                               │   ├── BalancedManager.java
│   │       │                               │   ├── BrokerClientLoadBalanced.java
│   │       │                               │   ├── ExternalBrokerClientLoadBalanced.java
│   │       │                               │   ├── LogicBrokerClientLoadBalanced.java
│   │       │                               │   └── region/
│   │       │                               │       ├── BrokerClientProxy.java
│   │       │                               │       ├── BrokerClientRegion.java
│   │       │                               │       ├── BrokerClientRegionFactory.java
│   │       │                               │       ├── DefaultBrokerClientRegion.java
│   │       │                               │       ├── DefaultWithElementSelector.java
│   │       │                               │       ├── StrictBrokerClientRegion.java
│   │       │                               │       └── WithElementSelector.java
│   │       │                               ├── cluster/
│   │       │                               │   └── ClusterMessageListenerImpl.java
│   │       │                               ├── enhance/
│   │       │                               │   ├── BrokerEnhance.java
│   │       │                               │   └── BrokerEnhances.java
│   │       │                               ├── kit/
│   │       │                               │   ├── BrokerPrintKit.java
│   │       │                               │   └── EndPointClientIdKit.java
│   │       │                               ├── processor/
│   │       │                               │   ├── BroadcastMessageBrokerProcessor.java
│   │       │                               │   ├── BroadcastOrderMessageBrokerProcessor.java
│   │       │                               │   ├── BrokerClientItemConnectMessageBrokerProcessor.java
│   │       │                               │   ├── BrokerExternalKit.java
│   │       │                               │   ├── ConnectionCloseEventBrokerProcessor.java
│   │       │                               │   ├── ConnectionEventBrokerProcessor.java
│   │       │                               │   ├── ConnectionExceptionEventBrokerProcessor.java
│   │       │                               │   ├── ConnectionFailedEventBrokerProcessor.java
│   │       │                               │   ├── EndPointLogicServerMessageBrokerProcessor.java
│   │       │                               │   ├── EventBusMessageBrokerProcessor.java
│   │       │                               │   ├── InnerModuleMessageBrokerProcessor.java
│   │       │                               │   ├── InnerModuleRequestCollectExternalMessageBrokerProcessor.java
│   │       │                               │   ├── InnerModuleRequestCollectMessageBrokerProcessor.java
│   │       │                               │   ├── InnerModuleVoidMessageBrokerProcessor.java
│   │       │                               │   ├── LineKit.java
│   │       │                               │   ├── PulseSignalRequestBrokerProcessor.java
│   │       │                               │   ├── PulseSignalResponseBrokerProcessor.java
│   │       │                               │   ├── RegisterBrokerClientModuleMessageBrokerProcessor.java
│   │       │                               │   ├── RequestMessageBrokerProcessor.java
│   │       │                               │   ├── ResponseMessageBrokerProcessor.java
│   │       │                               │   └── SettingUserIdMessageBrokerProcessor.java
│   │       │                               └── service/
│   │       │                                   ├── BrokerClientModules.java
│   │       │                                   └── DefaultBrokerClientModules.java
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── iohao/
│   │                       └── game/
│   │                           └── bolt/
│   │                               └── broker/
│   │                                   ├── cluster/
│   │                                   │   ├── Gossip1Test.java
│   │                                   │   └── Gossip2Test.java
│   │                                   └── server/
│   │                                       └── BrokerServerStandaloneTest.java
│   ├── bolt-client/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           └── java/
│   │               └── com/
│   │                   └── iohao/
│   │                       └── game/
│   │                           └── bolt/
│   │                               └── broker/
│   │                                   └── client/
│   │                                       ├── AbstractBrokerClientStartup.java
│   │                                       ├── BrokerClientApplication.java
│   │                                       ├── BrokerClientStartup.java
│   │                                       ├── RemoteAddress.java
│   │                                       ├── package-info.java
│   │                                       └── processor/
│   │                                           ├── BoltChannelContext.java
│   │                                           ├── BrokerClientLineKit.java
│   │                                           ├── BrokerClientOfflineMessageLogicProcessor.java
│   │                                           ├── BrokerClientOnlineMessageLogicProcessor.java
│   │                                           ├── BrokerClusterMessageClientProcessor.java
│   │                                           ├── EventBusMessageClientProcessor.java
│   │                                           ├── RequestBrokerClientModuleMessageClientProcessor.java
│   │                                           ├── RequestMessageClientProcessor.java
│   │                                           ├── connection/
│   │                                           │   ├── CloseConnectEventClientProcessor.java
│   │                                           │   ├── ConnectEventClientProcessor.java
│   │                                           │   ├── ConnectFailedEventClientProcessor.java
│   │                                           │   ├── ExceptionConnectEventClientProcessor.java
│   │                                           │   └── package-info.java
│   │                                           └── package-info.java
│   └── bolt-core/
│       ├── pom.xml
│       └── src/
│           └── main/
│               └── java/
│                   └── com/
│                       ├── alipay/
│                       │   └── sofa/
│                       │       └── common/
│                       │           └── log/
│                       │               └── factory/
│                       │                   └── LoggerSpaceFactory4LogbackBuilder.java
│                       └── iohao/
│                           └── game/
│                               ├── bolt/
│                               │   └── broker/
│                               │       ├── client/
│                               │       │   └── kit/
│                               │       │       ├── ExternalCommunicationKit.java
│                               │       │       ├── UserIdSettingKit.java
│                               │       │       └── package-info.java
│                               │       └── core/
│                               │           ├── BoltConnection.java
│                               │           ├── GroupWith.java
│                               │           ├── aware/
│                               │           │   ├── AwareInject.java
│                               │           │   ├── AwareKit.java
│                               │           │   ├── BrokerClientAware.java
│                               │           │   ├── BrokerClientItemAware.java
│                               │           │   ├── CmdRegionsAware.java
│                               │           │   ├── PulseConsumerAware.java
│                               │           │   ├── PulseProducerAware.java
│                               │           │   ├── UserProcessorExecutorAware.java
│                               │           │   ├── UserProcessorExecutorSelectorAware.java
│                               │           │   └── UserProcessorInNettyThreadAware.java
│                               │           ├── client/
│                               │           │   ├── Broadcast.java
│                               │           │   ├── BroadcastDebug.java
│                               │           │   ├── BrokerAddress.java
│                               │           │   ├── BrokerClient.java
│                               │           │   ├── BrokerClientAttr.java
│                               │           │   ├── BrokerClientBuilder.java
│                               │           │   ├── BrokerClientHelper.java
│                               │           │   ├── BrokerClientItem.java
│                               │           │   ├── BrokerClientManager.java
│                               │           │   ├── BrokerClientType.java
│                               │           │   ├── BrokerClients.java
│                               │           │   ├── DefaultProcessorContext.java
│                               │           │   ├── EventBusBrokerClientListener.java
│                               │           │   └── config/
│                               │           │       └── BrokerClientStatusConfig.java
│                               │           ├── common/
│                               │           │   ├── AbstractAsyncUserProcessor.java
│                               │           │   ├── DefaultUserProcessorExecutorSelectorStrategy.java
│                               │           │   ├── DefaultUserProcessorExecutorStrategy.java
│                               │           │   ├── IoGameGlobalConfig.java
│                               │           │   ├── ProcessorSelectorThreadExecutorRegion.java
│                               │           │   ├── UserProcessorExecutorSelectorStrategy.java
│                               │           │   ├── UserProcessorExecutorStrategy.java
│                               │           │   ├── VirtualThreadUserProcessorExecutorStrategy.java
│                               │           │   └── processor/
│                               │           │       ├── hook/
│                               │           │       │   ├── ClientProcessorHooks.java
│                               │           │       │   ├── DefaultRequestMessageClientProcessorHook.java
│                               │           │       │   └── RequestMessageClientProcessorHook.java
│                               │           │       ├── listener/
│                               │           │       │   ├── BrokerClientListener.java
│                               │           │       │   ├── BrokerClientListenerRegion.java
│                               │           │       │   ├── ConnectionBeforeListener.java
│                               │           │       │   ├── LineListener.java
│                               │           │       │   └── SimplePrintBrokerClientListener.java
│                               │           │       └── pulse/
│                               │           │           ├── PulseSignalRequestUserProcessor.java
│                               │           │           └── PulseSignalResponseUserProcessor.java
│                               │           ├── kit/
│                               │           │   └── HessianKit.java
│                               │           ├── loadbalance/
│                               │           │   ├── ElementSelector.java
│                               │           │   ├── ElementSelectorFactory.java
│                               │           │   ├── RandomElementSelector.java
│                               │           │   └── RingElementSelector.java
│                               │           └── message/
│                               │               ├── BroadcastMessage.java
│                               │               ├── BroadcastOrderMessage.java
│                               │               ├── BrokerClientItemConnectMessage.java
│                               │               ├── BrokerClientModuleMessage.java
│                               │               ├── BrokerClientOfflineMessage.java
│                               │               ├── BrokerClientOnlineMessage.java
│                               │               ├── BrokerClusterMessage.java
│                               │               ├── BrokerMessage.java
│                               │               ├── InnerModuleMessage.java
│                               │               ├── InnerModuleVoidMessage.java
│                               │               └── RequestBrokerClientModuleMessage.java
│                               └── core/
│                                   └── common/
│                                       ├── NetCommonKit.java
│                                       ├── client/
│                                       │   ├── Attachment.java
│                                       │   └── ExternalBizCodeCont.java
│                                       └── cmd/
│                                           ├── BrokerClientId.java
│                                           ├── CmdRegion.java
│                                           ├── CmdRegions.java
│                                           ├── DefaultCmdRegion.java
│                                           └── DefaultCmdRegions.java
├── pom.xml
├── run-one/
│   └── run-one-netty/
│       ├── pom.xml
│       └── src/
│           └── main/
│               └── java/
│                   └── com/
│                       └── iohao/
│                           └── game/
│                               └── external/
│                                   └── core/
│                                       └── netty/
│                                           └── simple/
│                                               ├── InternalRunOne.java
│                                               ├── NettyClusterSimpleHelper.java
│                                               ├── NettyClusterSimpleRunOne.java
│                                               ├── NettyRunOne.java
│                                               └── NettySimpleHelper.java
└── widget/
    ├── generate-code/
    │   ├── pom.xml
    │   └── src/
    │       └── main/
    │           ├── java/
    │           │   └── com/
    │           │       └── iohao/
    │           │           └── game/
    │           │               └── action/
    │           │                   └── skeleton/
    │           │                       └── core/
    │           │                           └── doc/
    │           │                               ├── CsharpDocumentGenerate.java
    │           │                               ├── DocumentGenerateAbout.java
    │           │                               ├── GDScriptDocumentGenerate.java
    │           │                               └── TypeScriptDocumentGenerate.java
    │           └── resources/
    │               └── generate/
    │                   ├── csharp/
    │                   │   ├── action.txt
    │                   │   ├── action_method.txt
    │                   │   ├── action_method_no_param.txt
    │                   │   ├── action_method_result_example.txt
    │                   │   ├── action_method_void.txt
    │                   │   ├── action_method_void_no_param.txt
    │                   │   ├── broadcast_action.txt
    │                   │   ├── broadcast_action_example.txt
    │                   │   ├── broadcast_action_example_action.txt
    │                   │   └── game_code.txt
    │                   ├── gdscript/
    │                   │   ├── action.txt
    │                   │   ├── action_method.txt
    │                   │   ├── action_method_no_param.txt
    │                   │   ├── action_method_result_example.txt
    │                   │   ├── action_method_void.txt
    │                   │   ├── action_method_void_no_param.txt
    │                   │   ├── broadcast_action.txt
    │                   │   ├── broadcast_action_example.txt
    │                   │   ├── broadcast_action_example_action.txt
    │                   │   └── game_code.txt
    │                   └── ts/
    │                       ├── action.txt
    │                       ├── action_method.txt
    │                       ├── action_method_no_param.txt
    │                       ├── action_method_result_example.txt
    │                       ├── action_method_void.txt
    │                       ├── action_method_void_no_param.txt
    │                       ├── broadcast_action.txt
    │                       ├── broadcast_action_example.txt
    │                       ├── broadcast_action_example_action.txt
    │                       └── game_code.txt
    ├── light-client/
    │   ├── pom.xml
    │   └── src/
    │       └── main/
    │           └── java/
    │               └── com/
    │                   └── iohao/
    │                       └── game/
    │                           └── external/
    │                               └── client/
    │                                   ├── AbstractInputCommandRegion.java
    │                                   ├── ClientConnectOption.java
    │                                   ├── InputCommandCreate.java
    │                                   ├── InputCommandRegion.java
    │                                   ├── command/
    │                                   │   ├── CallbackDelegate.java
    │                                   │   ├── CommandResult.java
    │                                   │   ├── InputCommand.java
    │                                   │   ├── ListenCommand.java
    │                                   │   ├── RequestCommand.java
    │                                   │   └── RequestDataDelegate.java
    │                                   ├── join/
    │                                   │   ├── ClientConnect.java
    │                                   │   ├── ClientConnects.java
    │                                   │   ├── ClientRunOne.java
    │                                   │   ├── ClientTcpExternalCodec.java
    │                                   │   ├── TcpClientStartup.java
    │                                   │   ├── WebSocketClientStartup.java
    │                                   │   └── handler/
    │                                   │       └── ClientMessageHandler.java
    │                                   ├── kit/
    │                                   │   ├── AssertKit.java
    │                                   │   ├── ClientKit.java
    │                                   │   ├── ClientUserConfigs.java
    │                                   │   ├── ScannerKit.java
    │                                   │   └── SplitParam.java
    │                                   ├── package-info.java
    │                                   └── user/
    │                                       ├── ClientChannelRead.java
    │                                       ├── ClientUser.java
    │                                       ├── ClientUserChannel.java
    │                                       ├── ClientUserInputCommands.java
    │                                       ├── ClientUsers.java
    │                                       ├── DefaultClientUser.java
    │                                       └── InternalAboutClient.java
    ├── light-domain-event/
    │   ├── pom.xml
    │   └── src/
    │       ├── main/
    │       │   └── java/
    │       │       └── com/
    │       │           └── iohao/
    │       │               └── game/
    │       │                   └── widget/
    │       │                       └── light/
    │       │                           └── domain/
    │       │                               └── event/
    │       │                                   ├── DisruptorManager.java
    │       │                                   ├── DomainEventContext.java
    │       │                                   ├── DomainEventContextParam.java
    │       │                                   ├── DomainEventPublish.java
    │       │                                   ├── annotation/
    │       │                                   │   └── DomainEvent.java
    │       │                                   ├── disruptor/
    │       │                                   │   ├── ConsumeEventHandler.java
    │       │                                   │   ├── DefaultDisruptorCreate.java
    │       │                                   │   ├── DisruptorCreate.java
    │       │                                   │   ├── DomainEventSource.java
    │       │                                   │   ├── EventDisruptor.java
    │       │                                   │   └── package-info.java
    │       │                                   ├── exception/
    │       │                                   │   ├── DefaultDomainEventExceptionHandler.java
    │       │                                   │   └── package-info.java
    │       │                                   ├── message/
    │       │                                   │   ├── DomainEventHandler.java
    │       │                                   │   ├── Eo.java
    │       │                                   │   ├── Topic.java
    │       │                                   │   └── package-info.java
    │       │                                   └── package-info.java
    │       └── test/
    │           └── java/
    │               └── com/
    │                   └── iohao/
    │                       └── game/
    │                           └── widget/
    │                               └── light/
    │                                   └── domain/
    │                                       └── event/
    │                                           ├── StudentDomainEventTest.java
    │                                           ├── StudentDomainEventTest2.java
    │                                           ├── UserLoginDomainEventTest.java
    │                                           ├── student/
    │                                           │   ├── StudentCountEventHandler.java
    │                                           │   ├── StudentEmailEventHandler1.java
    │                                           │   ├── StudentEo.java
    │                                           │   ├── StudentGoHomeEventHandler2.java
    │                                           │   ├── StudentSleepEventHandler3.java
    │                                           │   └── package-info.java
    │                                           └── user/
    │                                               ├── UserLogin.java
    │                                               ├── UserLoginEmailEventHandler.java
    │                                               └── package-info.java
    ├── light-game-room/
    │   ├── pom.xml
    │   └── src/
    │       └── main/
    │           └── java/
    │               └── com/
    │                   └── iohao/
    │                       └── game/
    │                           └── widget/
    │                               └── light/
    │                                   └── room/
    │                                       ├── GameRoomService.java
    │                                       ├── Player.java
    │                                       ├── Room.java
    │                                       ├── RoomBroadcastEnhance.java
    │                                       ├── RoomKit.java
    │                                       ├── RoomService.java
    │                                       ├── RoomStatusEnum.java
    │                                       ├── SimplePlayer.java
    │                                       ├── SimpleRoom.java
    │                                       ├── SimpleRoomService.java
    │                                       ├── domain/
    │                                       │   ├── GameFlowEo.java
    │                                       │   ├── GameFlowEventHandler.java
    │                                       │   ├── OperationContextEventHandler.java
    │                                       │   └── package-info.java
    │                                       ├── flow/
    │                                       │   ├── GameFixedService.java
    │                                       │   ├── GameFlowContext.java
    │                                       │   ├── GameFlowService.java
    │                                       │   ├── GameStartService.java
    │                                       │   ├── PlayerCreator.java
    │                                       │   ├── RoomCreateContext.java
    │                                       │   ├── RoomCreator.java
    │                                       │   ├── SimpleGameFlowContext.java
    │                                       │   ├── SimpleRoomCreateContext.java
    │                                       │   └── package-info.java
    │                                       ├── operation/
    │                                       │   ├── OperationContext.java
    │                                       │   ├── OperationFactory.java
    │                                       │   ├── OperationHandler.java
    │                                       │   ├── OperationService.java
    │                                       │   ├── PlayerOperationContext.java
    │                                       │   ├── SimpleOperationFactory.java
    │                                       │   ├── SimpleOperationHandler.java
    │                                       │   └── package-info.java
    │                                       └── package-info.java
    ├── light-jprotobuf/
    │   ├── pom.xml
    │   └── src/
    │       ├── main/
    │       │   └── java/
    │       │       └── com/
    │       │           └── iohao/
    │       │               └── game/
    │       │                   └── widget/
    │       │                       └── light/
    │       │                           └── protobuf/
    │       │                               ├── FieldNameGenerate.java
    │       │                               ├── ProtoFieldTypeHolder.java
    │       │                               ├── ProtoFileMerge.java
    │       │                               ├── ProtoFileValue.java
    │       │                               ├── ProtoGenerateFile.java
    │       │                               ├── ProtoGenerateSetting.java
    │       │                               ├── ProtoJava.java
    │       │                               ├── ProtoJavaAnalyse.java
    │       │                               ├── ProtoJavaField.java
    │       │                               ├── ProtoJavaRegion.java
    │       │                               ├── ProtoJavaRegionKey.java
    │       │                               └── kit/
    │       │                                   └── GenerateFileKit.java
    │       └── test/
    │           └── java/
    │               └── com/
    │                   └── iohao/
    │                       └── game/
    │                           └── widget/
    │                               └── light/
    │                                   └── protobuf/
    │                                       ├── ProtoJavaTest.java
    │                                       └── data/
    │                                           ├── AnimalTypeEnum.java
    │                                           ├── Cat.java
    │                                           ├── Food.java
    │                                           ├── ProtoTeacher.java
    │                                           ├── TempProtoFile.java
    │                                           ├── TestEnum.java
    │                                           └── Tiger.java
    ├── light-profile/
    │   ├── pom.xml
    │   └── src/
    │       ├── main/
    │       │   └── java/
    │       │       └── com/
    │       │           └── iohao/
    │       │               └── game/
    │       │                   └── widget/
    │       │                       └── light/
    │       │                           └── profile/
    │       │                               ├── Profile.java
    │       │                               ├── ProfileManager.java
    │       │                               ├── ResourcePatternResolverProfile.java
    │       │                               └── package-info.java
    │       └── test/
    │           ├── java/
    │           │   └── com/
    │           │       └── iohao/
    │           │           └── game/
    │           │               └── widget/
    │           │                   └── light/
    │           │                       └── profile/
    │           │                           ├── ProfileManagerTest.java
    │           │                           └── ResourcePatternResolverProfileTest.java
    │           └── resources/
    │               └── conf/
    │                   ├── common/
    │                   │   ├── db.props
    │                   │   └── other.props
    │                   ├── local/
    │                   │   └── db.props
    │                   └── production/
    │                       ├── db.props
    │                       └── other.props
    └── other-tool/
        ├── README.md
        ├── pom.xml
        └── src/
            └── main/
                └── java/
                    ├── com/
                    │   └── iohao/
                    │       └── game/
                    │           └── common/
                    │               └── kit/
                    │                   └── adapter/
                    │                       ├── AdapterHuUtils.java
                    │                       ├── HuArrayUtil.java
                    │                       ├── HuAssert.java
                    │                       ├── HuBase16Codec.java
                    │                       ├── HuCharFinder.java
                    │                       ├── HuCharUtil.java
                    │                       ├── HuCharsetUtil.java
                    │                       ├── HuClassLoaderUtil.java
                    │                       ├── HuClassPathResource.java
                    │                       ├── HuClassUtil.java
                    │                       ├── HuComputeIter.java
                    │                       ├── HuCopyVisitor.java
                    │                       ├── HuExceptionUtil.java
                    │                       ├── HuFastByteArrayOutputStream.java
                    │                       ├── HuFastByteBuffer.java
                    │                       ├── HuFileResource.java
                    │                       ├── HuFileUtil.java
                    │                       ├── HuFileWriter.java
                    │                       ├── HuFilter.java
                    │                       ├── HuFinder.java
                    │                       ├── HuHexUtil.java
                    │                       ├── HuIoCopier.java
                    │                       ├── HuIoRuntimeException.java
                    │                       ├── HuIoUtil.java
                    │                       ├── HuNoResourceException.java
                    │                       ├── HuObjectUtil.java
                    │                       ├── HuPathUtil.java
                    │                       ├── HuPercentCodec.java
                    │                       ├── HuResource.java
                    │                       ├── HuResourceUtil.java
                    │                       ├── HuRfc3986.java
                    │                       ├── HuSplitIter.java
                    │                       ├── HuStrFinder.java
                    │                       ├── HuStrFormatter.java
                    │                       ├── HuStrUtil.java
                    │                       ├── HuStreamCopier.java
                    │                       ├── HuTextFinder.java
                    │                       ├── HuUrlResource.java
                    │                       ├── HuUrlUtil.java
                    │                       ├── HuUtilException.java
                    │                       └── package-info.java
                    └── module-info.java.txt

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/ISSUE_TEMPLATE/ask-question.md
================================================
---
name: 提问与交流
about: 对框架使用过程中遇到的问题、不清楚或模糊的地方;询问框架能否支持某类需求

---

### 你的问题 | 使用场景

描述你遇到的问题,或使用场景(询问框架能否满足此类需求)



### 预期值

期望的预期值




### 实际值

实际值




### 复现步骤

描述复现步骤,并提供复现 demo




### 版本

- ioGame version: 


================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.md
================================================
---
name: bug
about: 疑似 bug
---

### 你的问题

描述你遇到的问题



### 预期值

期望的预期值




### 实际值

实际值



### 复现步骤

描述复现步骤,并提供复现 demo



### 版本

- ioGame version: 


================================================
FILE: .github/ISSUE_TEMPLATE/empty-issues.md
================================================
---
name: empty issues
about: 自定义 issues 描述
---

### 提问







================================================
FILE: .github/ISSUE_TEMPLATE/enhance-task.md
================================================
---
name: 功能增强建议
about: 对框架功能增强、新增...等相关建议
---

### 新增功能的使用场景

描述功能的使用场景、作用;或描述功能所带来的好处





================================================
FILE: .gitignore
================================================
### other dir ###
classes/
.temp/
logs/
log/
.svn/
svn/
lib/
.act.*
system/

HELP.md
!**/src/main/**
!**/src/test/**

*.class

### jreble config ###
rebel.xml

### Package Files ###
*.jar
*.war
*.ear
*.zip

# tcp 与前端通讯的 api
tcp-api/

# gradle #
build/
.gradle/
out/

### maven ###
target/
!.mvn/wrapper/maven-wrapper.jar
.mvn
mvnw
mvnw.cmd
### intellj file type ###
bin/
.idea
*.iws
*.iml
*.ipr

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/

### VS Code ###
.vscode/

### STS ###
.apt_generated
.factorypath
.settings
.springBeans
.sts4-cache

### eclipse file type ###
.settings/
.classpath
.project

### ---- Mac OS X ###
.DS_Store
Icon?

### ---- Windows ###

### Windows image file caches ###
Thumbs.db

### Folder integration file ###
Desktop.ini

### ---- Javadoc ###
docs.tar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
/target/

doc_game.txt
.claude


================================================
FILE: BACKERS.md
================================================
#### 支持名单

通过 wx、alipay 支付时,不能看见全称,下面使用 '-' 来代替 *。



#### 2025

##### 小星星


| 称号 | 名单                                             |
| ---- | ------------------------------------------------ |
| ⭐⭐   | wuhudsm(admin@playdnf.com)、65714050@qq.com、M-x |



##### 感谢支持

ZhangSir、-鸟

---



#### 2024

##### 小星星


| 称号 | 名单 |
| ------------- | -------------------------------- |
| ⭐⭐ | 刘先生、wells974、404 Not Found(342644552)、山里人(higaojun@qq.com ) |
| ⭐    | 金银花、子在川上(captainl1993@126.com) |



##### 感谢支持

Alan、Y-g、angelhappyboy、黑天小飞侠

---



#### 2023

##### 小星星


| 称号 | 名单 |
| ------------- | -------------------------------- |
| ⭐⭐⭐⭐⭐⭐⭐ | 赵少 |
| ⭐⭐⭐ | Lei Ante |
| ⭐⭐ | 张松林、-辉、北极光 |
| ⭐    | -晖、Bill、明亮北极星        |




##### 感谢支持 

butxx、玩皮猫、v-v、b-e、M-a、j-s、漫步、森、葱花蛋炒饭、小许

---




#### 2022

##### 小星星

| 称号 | 名单 |
| ------------- | -------------------------------- |
| ⭐⭐ | 米斯特姚、WX768925736、猿、Micheal |
| ⭐    | -称                              |




##### 感谢支持 

咖喱、优优、半壁、J-n、华

================================================
FILE: LICENSE
================================================
                    GNU AFFERO GENERAL PUBLIC LICENSE
                       Version 3, 19 November 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.

  A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate.  Many developers of free software are heartened and
encouraged by the resulting cooperation.  However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.

  The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community.  It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server.  Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.

  An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals.  This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU Affero General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Remote Network Interaction; Use with the GNU General Public License.

  Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software.  This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time.  Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source.  For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code.  There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<https://www.gnu.org/licenses/>.


================================================
FILE: README.md
================================================
<h2 align="center" style="text-align:center;">
  ioGame
</h2>
<p align="center">
  <strong>Lock-free, async, event-driven architecture — supports clustering & distribution out of the box, no middleware required</strong>
  <br>
  <strong>Build decentralized, auto-scaling, multi-process distributed game servers with ease</strong>
  <br>
  <strong>Tiny footprint, blazing-fast startup, low memory usage, zero config files, elegant route-level access control</strong>
  <br>
  <strong>Simultaneous support for WebSocket, UDP, TCP and more — with built-in full-link distributed tracing</strong>
  <br>
  <strong>One codebase, multiple protocols — seamlessly switch between Protobuf, JSON, and beyond</strong>
  <br>
  <strong>Near-native performance — 11.52 million business operations per second in a single thread</strong>
  <br>
  <strong>Code-as-documentation, JSR380 validation, assertion + exception patterns — minimal maintenance overhead</strong>
  <br>
  <strong>Smart same-process affinity with IDE-friendly code navigation & jump-to-source</strong>
  <br>
  <strong>Deploy your way — components run independently or fused together</strong>
  <br>
  <strong>Write once, generate client SDKs — interactive code generation for any frontend</strong>
  <br>
  <strong>Cross-process, cross-machine communication between logic servers</strong>
  <br>
  <strong>Dynamic player-to-server binding</strong>
  <br>
  <strong>Plays nicely with any framework</strong>
  <br>
  <strong>Feels natural for web MVC developers</strong>
  <br>
  <strong>No hard dependency on Spring</strong>
  <br>
  <strong>Zero learning curve</strong>
  <br>
  <strong>Pure JavaSE</strong>
</p>
<p align="center">
	<a href="http://game.iohao.com">https://iohao.github.io/game</a>
</p>
<p align="center">
	<a target="_blank" href="https://www.oracle.com/java/technologies/downloads/#java21">
		<img src="https://img.shields.io/badge/JDK-21-success.svg" alt="JDK 21" />
	</a>
	<br>
	<a target="_blank" href="https://www.gnu.org/licenses/agpl-3.0.txt">
		<img src="https://img.shields.io/:license-AGPL3.0-blue.svg" alt="AGPL3.0" />
	</a>
	<br />
	<a target="_blank" href='https://gitee.com/iohao/ioGame'>
		<img src='https://gitee.com/iohao/ioGame/badge/star.svg' alt='gitee star'/>
	</a>
	<a target="_blank" href='https://github.com/iohao/ioGame'>
		<img src="https://img.shields.io/github/stars/iohao/ioGame.svg?logo=github" alt="github star"/>
	</a>
  <br />
	<a target="_blank" href='https://app.codacy.com/gh/iohao/ioGame/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade'>
		<img src="https://app.codacy.com/project/badge/Grade/4981fff112754686baad7442be998b17" alt="code quality"/>
</a>
</p>
<hr />

Documentation: https://iohao.github.io/game/docs/intro

## Vision
Make game server development effortless. We're here to change the industry — lowering the barrier to entry and making game development tools truly accessible to everyone.


## Open, Free & Developer-Friendly License
- There is no commercial edition — never has been, never will be. Every feature is open source.
- We're committed to at least **ten years** of active maintenance, starting from 2022-03-01.
- ioGame is a lightweight networking framework built for **online games, IoT, internal systems**, and any scenario that needs persistent connections. The source code is fully open, documentation is free, and usage costs nothing (subject to license terms).

<hr/>

**Why AGPL 3.0?**

ioGame is released under the [AGPL 3.0](https://www.gnu.org/licenses/agpl-3.0.txt) license. Projects built with ioGame under this license are free of charge.

We chose AGPL 3.0 because it's **fairer to developers**. It ensures that project ownership is shared — meaning that even if a developer leaves a company, they retain legitimate rights to the project they helped build.

Contrast this with permissive licenses like Apache 2.0 or MIT, where developers who leave a company lose all control over the project and get nothing in return. We've all seen it: developers pour their hearts into a project through countless late nights and weekends, only to be let go right before — or just after — launch, watching their hard work become someone else's asset.

Under AGPL 3.0, shared ownership means developers are genuinely motivated to invest in and polish their work.



## Startup Showcase

ioGame is impressively lean:
- **Memory**: Minimal footprint.
- **Startup**: Applications typically boot in under **1 second**.
- **Package size**: ~**15 MB** as a jar.

![](https://iohao.github.io/game/assets/images/start-cc4b7973e832e31c6c5bf50af83aabeb.png)



## What is ioGame?

Looking for a game server framework that's **high-performance, stable, easy to use, with built-in load balancing, clean architecture (no class explosion), cross-process communication, decentralized clustering, auto-scaling, and stateful multi-process distribution**? Meet ioGame — a Java networking framework designed exactly for this.



ioGame is a lightweight networking framework built for **online games, IoT, internal systems**, and any scenario that needs persistent connections.



**Key Features at a Glance:**

> 1. Truly lightweight — lock-free, async, event-driven from the ground up.
> 2. Small package, low memory, fast startup.
> 3. Pure JavaSE — integrates effortlessly with Spring, Vert.x, Quarkus, Solon, and others.
> 4. **Zero learning curve.** If you know basic Java or web MVC, you already know how to use ioGame. No game dev experience required.
> 5. Architecturally eliminates the **N×N scaling problem** that plagues traditional frameworks.
> 6. **No third-party dependencies** for clustering & distribution — just a JVM is all you need.
> 7. Three-part architecture: External Server + Broker (Gateway) + Game Logic Server — each can run **independently or fused together**, adapting to **any game type**.
> 8. Fully **dynamic scaling** — add or remove External Servers, Logic Servers, and Brokers on the fly.
> 9. **Multi-server, single-process** mode for development — debug distributed systems as easily as a monolith.
> 10. Logic Servers can run standalone, **enabling true modularization**.
> 11. Built-in **full-link distributed tracing**.
> 12. Rich communication primitives — logic servers can talk across machines seamlessly.
> 13. MVC-style coding with non-intrusive Java Beans — effectively **prevents class explosion**.
> 14. Built-in **per-player thread safety** — concurrency handled for you.
> 15. **One codebase** supports TCP, WebSocket, UDP simultaneously — no code changes needed. Extensible to KCP, QUIC, and beyond.
> 16. **One codebase** for switching data protocols — Protobuf, JSON, and more. Extensible.
> 17. **Hot-swap protocols** — add or remove protocols without restarting the gateway or External Server. No player disconnections.
> 18. Auto-boxing/unboxing of primitives in actions — solves the [protocol fragment](https://iohao.github.io/game/docs/manual/protocol_fragment) problem.
> 19. Pluggable, extensible **plugin system**.
> 20. Deploy as **single-process** or **multi-process across machines** — switch freely without code changes.
> 21. Logic Servers never expose ports — **immune to port-scanning attacks** by design.
> 22. Built-in **stress testing & simulation module** with real network conditions, continuous interaction, and automation support.
> 23. Sync, async, and async-callback methods for inter-service communication.
> 24. **Distributed event bus** (like MQ / Redis pub-sub — works across machines and processes).
> 25. Elegant **route-level access control**.
> 26. Intelligent **same-process affinity**.
> 27. JSR380 validation + assertions + exceptions = **less boilerplate, fewer bugs**.
> 28. **Write once, generate everywhere** — produce unified interactive SDKs for Godot, UE, Unity, Cocos Creator, Laya, React, Vue, Angular, and more. Massive productivity boost.



Packaging, memory, and startup are all best-in-class: jar size ~**15 MB**, startup typically under **1 second**, low memory footprint.



**Ecosystem integration** is straightforward — [Spring integration](https://iohao.github.io/game/docs/manual/integration_spring) takes just 4 lines of code. Beyond Spring, ioGame plays well with Vert.x, Quarkus, Solon, and any other framework, letting you tap into their ecosystems.



**Zero learning curve.** If you know basic Java or web MVC patterns, you're ready. No game development background needed.



**Clean coding style.** ioGame provides MVC-like conventions with non-intrusive Java Beans, effectively **preventing class explosion**. Sync, async, and callback methods are available for inter-service calls — resulting in elegant code with full-link tracing baked in.



**Write once, connect everywhere.** ioGame generates client interaction code automatically, dramatically cutting client-side workload. Write your Java code once and generate unified SDKs for [Godot](https://godotengine.org/), [UE](https://www.unrealengine.com/), [Unity](https://unity.com/), [Cocos Creator](https://www.cocos.com/), [Laya](https://layaair.layabox.com/#/), [React](https://react.dev/), [Vue](https://vuejs.org/), [Angular](https://angular.dev/), and more. Supports [code generation](https://iohao.github.io/game/docs/examples/code_generate) in C#, TypeScript, GDScript, and C++ — fully extensible.



**No N×N headaches.** Traditional architectures rely on Redis, MQ, ZooKeeper, and other middleware to scale — hardly "lightweight." ioGame solves the [N×N problem](https://iohao.github.io/game/docs/overall/legacy_system) architecturally, without external dependencies.



**Truly lightweight.** No third-party middleware or database is needed for clustering and distribution — just a JVM. This simplifies usage and slashes deployment and maintenance costs. A single dependency gives you the entire framework — no Nginx, Redis, MQ, MySQL, ZooKeeper, or Protobuf compiler to install.



**Flexible architecture.** ioGame's [three-part design](https://iohao.github.io/game/docs/overall/deploy_flexible) — External Server, Broker (Gateway), Game Logic Server — can run independently or merged together, adapting to **any game type** simply by adjusting deployment. These changes are trivial and never break existing code.



**Dynamic scaling.** External Servers, Logic Servers, and Brokers all support live addition and removal. Scale up or down as player counts change. The architecture also enables **zero-downtime updates**: spin up new servers (A-3, A-4) with your latest features, then gracefully retire the old ones (A-1, A-2) — players never notice.



**Decentralized clustering.** The Broker (Gateway) uses a [masterless, self-organizing cluster design](https://iohao.github.io/game/docs/examples/server/example_broker_cluster) — all nodes are equal and autonomous with no single point of failure. The cluster **auto-manages and elastically scales**, maintaining load balance and consistency as nodes join or leave.



**Distributed by design.** Logic servers are organized into distinct layers — [External Servers](https://iohao.github.io/game/docs/overall/external_intro), [Game Logic Servers](https://iohao.github.io/game/docs/overall/logic_intro) — each with clear responsibilities and interfaces. This improves readability, maintainability, and enables effortless **horizontal scaling**.



**Developer-friendly distributed development.** Distributed apps usually mean juggling multiple processes, making debugging painful. Most frameworks can't solve this — **ioGame can.** Multi-server single-process mode lets you develop and debug distributed systems as if they were monoliths.



**Modular ecosystem.** [Game Logic Servers can run standalone](https://iohao.github.io/game/docs/manual_high/your_ecology) — just plug into the Broker to provide services. Build reusable, **componentized logic servers** — Guild, Friends, Login, Lottery, Announcements, Leaderboards, and more. Benefits include:

1. No redundant development.
2. Low coupling between modules.
3. True single-responsibility design — each feature becomes its own **logic server**.
4. Scale any module independently without code changes.
5. Build up your own **ecosystem arsenal** of reusable components for competitive advantage.
6. **Reduced code leak risk.** Monolithic projects put everything in one directory — one leak exposes everything. With modular servers, each developer only accesses their own module.
7. Admins deploy the gateway and External Server on the internal network; developers code and test their own modules locally. Additional perks:
    - Client connections survive logic server restarts.
    - Developers don't need to run each other's modules.
    - Auto-generated docs handle inter-module integration.



**Full-link distributed tracing.** Every request gets a [unique trace ID](https://iohao.github.io/game/docs/manual/trace) recorded across logs — filter by ID to instantly find what you need. ioGame's tracing works **across machines and processes**: from request entry to completion, every logic server touched is precisely recorded.



**Rich communication models.** While most frameworks only offer push/broadcast, ioGame provides a complete set of [communication patterns](https://iohao.github.io/game/docs/manual/communication_model) — all supporting cross-process, cross-machine communication with full-link tracing:

- **Client-facing models:**
    - [request/response](https://iohao.github.io/game/docs/communication/request_response)
    - request/void (fire-and-forget)
    - request/broadcast
    - [broadcast](http://localhost:3000/docs/communication/broadcast) (server push)
- **Internal (server-to-server) models:**
    - [request/response](https://iohao.github.io/game/docs/communication/request_response)
    - request/void
    - [request/multiple_response](https://iohao.github.io/game/docs/communication/request_multiple_response) — fan-out to multiple logic servers of the same type
    - [EventBus](https://iohao.github.io/game/docs/communication/event_bus) — distributed event bus
    - [ExternalRegion](https://iohao.github.io/game/docs/communication/external_biz_region) — access External Servers



Since ioGame 21, **virtual threads** are used for blocking inter-service communication, preventing business thread starvation and significantly boosting throughput.



**Thread safety made easy.** The framework guarantees [per-player thread safety](https://iohao.github.io/game/docs/overall/thread_executor) — even across re-logins, the same thread handles that player's business. For multi-player scenarios (e.g., same room), [Domain Events](https://iohao.github.io/game/docs/extension_module/domain_event) provide a clean solution. ioGame's unique thread executor design makes writing **lock-free concurrent code** straightforward.



**Lock-free concurrency.** ioGame's elegant thread executor design lets developers write high-concurrency code without locks — naturally and safely.



**Protocol-agnostic connections.** Use **one codebase** to support TCP, WebSocket, and UDP simultaneously — no modifications needed. Connection types are extensible: when KCP or QUIC support lands, just switch — your business code stays untouched.



**Flexible data protocols.** [Switch between Protobuf, JSON, and more](https://iohao.github.io/game/docs/manual/data_protocol) with a single line of code. No business method changes required.



**Hot-swap protocols.** Add or remove protocols **without restarting** the External Server or Broker — no player disconnections, no fleet-wide restarts.



**Protocol fragment solution.** Actions auto-box and unbox primitive types, solving the [protocol fragment](https://iohao.github.io/game/docs/manual/protocol_fragment) problem while making business code cleaner and boosting developer productivity.



**[Same-process affinity](https://iohao.github.io/game/docs/manual_high/same_process).** Within a single process, Netty instances communicate via memory — no network overhead, blazing-fast data transfer. The framework intelligently routes requests to same-process logic servers first, falling back to other processes/machines only when needed.



**Great developer experience.** ioGame ships with [JSR380 validation](https://iohao.github.io/game/docs/core/jsr380), [assertions + exception handling](https://iohao.github.io/game/docs/manual/assert_game_code), [code navigation](https://iohao.github.io/game/docs/core_plugin/action_debug), auto-boxing for primitives, and more — all designed to keep your business code clean and concise.



**Extensible [plugin system](https://iohao.github.io/game/docs/manual/plugin_intro).** Built-in plugins include DebugInOut, action call statistics, thread monitoring, time-bucketed call analytics, and more. Combine monitoring plugins to catch **performance issues during development** — find and fix problems before they reach production.



**Flexible deployment.** Run as a **single process** during development, deploy as **multi-process across machines** in production — switch freely without changing a line of code.



**Secure by design.** Logic Servers [never expose ports](https://iohao.github.io/game/docs/overall/legacy_system#Usage-Management) — **port-scanning attacks are impossible.** No need to manage per-service ports or cloud firewall rules. This entire category of ops headaches simply **disappears**.



**Realistic testing.** The [stress test & simulation module](https://iohao.github.io/game/docs/extension_module/simulation_client) goes beyond unit tests. It simulates real network conditions with continuous, interactive server communication and full automation support. Great for complex scenario testing and load validation.



**Cost-effective at every stage.** ioGame reduces costs across learning, development, testing, deployment, scaling, and beyond. With equal resources, ioGame gives your team a competitive edge — and protects you from building value that only benefits others. See the full [cost analysis](https://iohao.github.io/game/services/cost_analysis).



**Well-organized projects.** ioGame's thoughtful **route design** and elegant [access control](https://iohao.github.io/game/docs/external/access_authentication) naturally produce clean, maintainable codebases. Combined with [code organization conventions](https://iohao.github.io/game/docs/manual_high/code_organization), handoffs and long-term maintenance become much smoother. The deeper you go, the more you'll appreciate this.



**Modern Java, modern performance.** ioGame requires **JDK 21+**, giving you access to **Generational ZGC** with **sub-millisecond** pause times and modern syntax. GC pauses become invisible — no stuttering, no crashes — like having a JVM tuning expert on your team.



**In short**, ioGame is purpose-built for online game development. It lets you create high-performance, low-latency, easily scalable game servers while saving time and resources. The framework handles the complex, repetitive infrastructure so you can focus on what matters — your game. It provides **clear structural organization** for modules and development workflows, reducing long-term maintenance costs.



We believe you now have a solid overview of ioGame. There are many more features to discover as you dive deeper. Thank you for reading — we look forward to seeing what you build!

---

## Write Once, Generate Everywhere — A Massive Productivity Boost

ioGame is built around the principle of **code-as-documentation** and **methods-as-interfaces**.



**Write once** means writing your Java business code a single time. **Generate everywhere** means automatically producing client interaction code for any frontend project.



Write your Java code once and generate unified interaction interfaces for [Godot](https://godotengine.org/), [UE](https://www.unrealengine.com/), [Unity](https://unity.com/), [CocosCreator](https://www.cocos.com/), [Laya](https://layaair.layabox.com/#/), [React](https://react.dev/), [Vue](https://vuejs.org/), [Angular](https://angular.dev/), and more.



ioGame generates **action, broadcast, and error code** interfaces for any frontend project. Write your business logic once — it works with all these game engines and modern frontend frameworks simultaneously.



**Why generated client code matters:**

1. **Eliminates boilerplate.** Client developers no longer write mountains of template code.
2. **Crystal-clear semantics.** Generated interfaces explicitly define parameter types and whether to expect a response — no guesswork.
3. **Type-safe parameters.** Precise interface definitions mean type-safe method signatures, fewer security risks, and **fewer integration bugs**.
4. **Code is the documentation.** Generated code includes docs and usage examples — **zero learning cost**, even for newcomers.
5. **Focus on business logic.** Client developers can ignore server communication plumbing and **spend their time on what matters**.
6. **Smooth integration.** Using generated code feels **as natural as calling a local method** — minimal cognitive overhead for both teams.
7. **Interface-oriented, not protocol-oriented.** A modern approach that replaces the traditional protocol-centric integration workflow.
8. **Always in sync.** When your Java code changes, documentation and interfaces update automatically — **no separate docs to maintain**.



## Architecture Overview

> Lock-free, async, event-driven architecture. Truly lightweight — build a clustered, distributed game server with zero middleware.
>
> Decentralized cluster nodes, automated clustering, built-in load balancing, distributed deployment, dynamic machine scaling.

| Component                                                    | Scaling      | Responsibility                   |
| ------------------------------------------------------------ | ------------ | -------------------------------- |
| **ExternalServer** — [External Server](https://iohao.github.io/game/docs/overall/external_intro) | Distributed  | Player connections & interaction |
| **GameLogicServer** — [Game Logic Server](https://iohao.github.io/game/docs/overall/logic_intro) | Distributed  | Business logic processing        |
| **BrokerCluster** — [Broker (Gateway)](https://iohao.github.io/game/docs/overall/broker_intro) | Clustered    | Request scheduling & forwarding  |

![ioGame](https://iohao.github.io/game/assets/images/ioGame-2cd7572c6c81afd341b7d2e9d703bf65.svg)

For details, see the [Architecture Guide](https://iohao.github.io/game/docs/overall/architecture_intro).

------

> The Broker (Gateway) runs as a **cluster** — typically stateless, focused on scheduling and forwarding.
>
> External Servers and Game Logic Servers use a **distributed** model, supporting multiple instances of the same type. When player counts grow, simply spin up more Logic Servers.
>
> **Example:** Two type-A Logic Servers (A-1, A-2) share requests via the gateway's random load-balancing strategy.
>
> Both External Servers and Logic Servers support dynamic addition and removal. **Zero-downtime updates** are built in: launch A-3 and A-4 with new features, then gracefully retire A-1 and A-2 — players won't notice a thing.
>
> The framework also supports [dynamic player-to-server binding](https://iohao.github.io/game/docs/manual/binding_logic_server) — once bound, all subsequent requests from that player route to the same Logic Server.
>
> **Beyond gaming:** ioGame works great for IoT too. Replace "players" with "devices" in the diagram — the architecture handles hundreds of millions of connections. IoT companies have been using ioGame successfully since 2022.



**External Server**

The External Server manages persistent player connections. Say one server supports up to 5,000 connections — when you hit 7,000, just add another External Server to distribute the load.

Scaling External Servers provides natural load balancing and traffic control under high concurrency. Thanks to trivial scaling, supporting **millions** of concurrent players is entirely achievable.

Even with multiple External Servers, developers don't need to track which server a player is connected to — broadcasts and pushes reach every player automatically. From the player's perspective, there's only one server. From the developer's perspective, the same is true.

Wondering about max connections per External Server? That's a Netty question — because under the hood, that's exactly what it is. If you know Netty, extending the External Server will feel second nature.



## Quick Start

Here's a simplified view of how a game engine interacts with the game server:

![Business Interaction Diagram](https://iohao.github.io/game/assets/images/introduction_quick-6b29dfc678257db43afb10939356edb6.jpeg)

> The game frontend and server communicate **bidirectionally**, exchanging business data encoded/decoded via `.proto` files. Protocol Buffers (PB) is currently the best choice for game data serialization, though JSON, XML, or custom formats are also supported since everything is transmitted as binary.
>
> **Game frontends** can be [Godot](https://godotengine.org/), [Unity](https://unity.cn/), [UE](https://www.unrealengine.com/zh-CN/), [Cocos Creator](https://www.cocos.com/), [Laya](https://layaair.layabox.com/#/), [FXGL](https://github.com/AlmasB/FXGL), or any other engine. The engine handles rendering; data exchange happens over TCP, UDP, etc.



**Data Protocol**

Define two simple data protocols for client-server communication. These are jprotobuf objects — a simplified wrapper around Google Protobuf with equivalent performance.

Think of them as DTOs — carriers for business data:

```java
@ProtobufClass
public class LoginVerifyMessage {
    public String jwt;
}

@ProtobufClass
public class UserMessage {
    public String name;
}
```



**Action**

Here's your server-side business logic. This code simultaneously supports TCP, WebSocket, and UDP — no changes needed:

```java
@Slf4j
@ActionController(1)
public class DemoAction {
    @ActionMethod(0)
    public UserMessage here(LoginVerifyMessage message) {
        var userMessage = new UserMessage();
        userMessage.name = "Michael Jackson, " + message.jwt;
        return userMessage;
    }
}
```



Each method (like `here`) is an [Action](https://iohao.github.io/game/docs/manual/action) — a unit of business logic.

Method parameters receive data from the frontend. The return value is automatically sent back to the client. You don't need to understand framework internals.

Notice how this looks just like ordinary Java? That's intentional — and it **prevents class explosion**. If your job is writing game logic, your ioGame learning journey can stop right here.



**Game programming really is this simple.**



**Q: Am I ready to start building a game server?**

> Yes. Yes you are.



**Console Output Example**

When an action is called, the console logs:

```text
┏━━━━━ Debug. [(DemoAction.java:5).here] ━━━━━ [cmd:1-0 65536] ━━━━━ [xxxLogicServer - id:[76526c134cc88232379167be83e4ddfc]
┣ userId: 1
┣ Params: message : LoginVerifyMessage(jwt=hello)
┣ Response: UserMessage(name=Michael Jackson, hello)
┣ Time: 1 ms (total business method execution time)
┗━━━━━ [ioGameVersion] ━━━━━ [Thread:User-8-2] ━━━━━━━ [traceId:956230991452569600] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```

**What each field means:**

- **Debug** `[(DemoAction.java:5).here]` — The action that ran, with line number. Click `DemoAction.java:5` in your IDE to jump straight to the code.
- **userId** — The requesting player's ID.
- **Params** — Input from the frontend.
- **Response** — The return value, automatically pushed to the client.
- **Time** — Execution duration — use this to spot and optimize slow logic.
- **cmd** — The [route](https://iohao.github.io/game/docs/manual/cmd) (unique address) for this action.
- **ioGameVersion** — Current framework version.
- **Thread** — The thread that executed this action.
- **traceId** — Unique per-request ID for distributed tracing.
- **Logic Server** — Which Logic Server handled the request.

This visibility eliminates the most common time sinks in game development:

- "Did the client actually send the data?" *(Parameter issues)*
- "Did the server actually respond?" *(Response issues)*
- "Why is the client not getting responses?" *(Timing issues)*

Code navigation lets developers jump to any business method instantly — invaluable in team settings for understanding and modifying execution flow.



## Who is ioGame For?

1. Web developers curious about game server development.
2. Developers new to the game industry.
3. Anyone interested in game development — no prior experience needed.
4. Learners who want to see design patterns applied in practice.
5. Developers open to modern approaches.
6. Anyone ready to leave legacy codebases behind.



At least one year of hands-on programming experience is recommended.


================================================
FILE: README_CN.md
================================================
<h2 align="center" style="text-align:center;">
  ioGame
</h2>
<p align="center">
  <strong>无锁异步化、事件驱动的架构设计;轻量级,无需依赖任何第三方中间件或数据库就能支持集群、分布式</strong>
  <br>
  <strong>通过 ioGame 可以很容易的搭建出一个集群无中心节点、集群自动化、多进程的分布式游戏服务器</strong>
  <br>
  <strong>包体小、启动快、内存占用少、更加的节约、无需配置文件、提供了优雅的路由访问权限控制</strong>
  <br>
  <strong>可同时支持多种连接方式:WS、UDP、TCP...等;框架已支持全链路调用日志跟踪特性</strong>
  <br>
  <strong>让开发者用一套业务代码,能轻松切换和扩展不同的数据协议:Protobuf、JSON</strong>
  <br>
  <strong>近原生的性能;业务框架在单线程中平均每秒可以执行 1152 万次业务逻辑</strong>
  <br>
  <strong>代码即联调文档、JSR380验证、断言 + 异常机制 = 更少的维护成本</strong>
  <br>
  <strong>框架具备智能的同进程亲和性;开发中,业务代码可定位与跳转</strong>
  <br>
  <strong>架构部署灵活性与多样性:既可相互独立,又可相互融合</strong>
  <br>
  <strong>一次编写到处对接,能为客户端生成可交互的代码</strong>
  <br>
  <strong>逻辑服之间可相互跨进程、跨机器进行通信</strong>
  <br>
  <strong>支持玩家对游戏逻辑服进行动态绑定</strong>
  <br>
  <strong>能与任何其他框架做融合共存</strong>
  <br>
  <strong>对 webMVC 开发者友好</strong>
  <br>
  <strong>无 spring 强依赖</strong>
  <br>
  <strong>零学习成本</strong>
  <br>
  <strong>javaSE</strong>
</p>
<p align="center">
	<a href="http://game.iohao.com">https://iohao.github.io/game</a>
</p>
<p align="center">
	<a target="_blank" href="https://www.oracle.com/java/technologies/downloads/#java21">
		<img src="https://img.shields.io/badge/JDK-21-success.svg" alt="JDK 21" />
	</a>
	<br>
	<a target="_blank" href="https://www.gnu.org/licenses/agpl-3.0.txt">
		<img src="https://img.shields.io/:license-AGPL3.0-blue.svg" alt="AGPL3.0" />
	</a>
	<br />
	<a target="_blank" href='https://gitee.com/iohao/ioGame'>
		<img src='https://gitee.com/iohao/ioGame/badge/star.svg' alt='gitee star'/>
	</a>
	<a target="_blank" href='https://github.com/iohao/ioGame'>
		<img src="https://img.shields.io/github/stars/iohao/ioGame.svg?logo=github" alt="github star"/>
	</a>
  <br />
	<a target="_blank" href='https://app.codacy.com/gh/iohao/ioGame/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade'>
		<img src="https://app.codacy.com/project/badge/Grade/4981fff112754686baad7442be998b17" alt="code quality"/>
</a>
</p>
<hr />

Documentation: https://iohao.github.io/game/docs/intro

## 愿景
让网络游戏服务器的编程变得轻松简单。 改变行业现状,降低使用难度,让游戏开发领域的生产资料公有制!


## 开放、自由、友好的开源协议
- 过去、现在、将来都不会有商业版本,所有功能全部开源。
- 承诺项目的维护周期是十年起步, 2022-03-01 起,至少十年维护期。
- ioGame 是一个轻量级的网络编程框架,适用于**网络游戏服务器、物联网、内部系统**及各种需要长连接的场景。 源码完全开放、最新文档阅读完全开放、提供高质量的使用文档,使用完全自由、免费(遵守开源协议)。

<hr/>

**友好的开源协议**

ioGame 使用 [AGPL3.0](https://www.gnu.org/licenses/agpl-3.0.txt) 开源协议,开发者在使用时需要遵守该协议。 在该协议下开发的项目是免费的,没有任何成本。

同时,该协议对开发者更加友好,它确保了项目所有权在资本家和开发者之间共享。 这意味着,即使开发者带着项目离开公司或自行运营,也依然是合法的。

与 Apache 2.0、MIT 等其他协议不同,那些协议下,一旦开发者离开公司,便会彻底失去对项目的控制权,难以获得任何实质性回报。 尤其是在开发阶段,程序员辛勤付出、996 加班,但当项目即将上线或刚上线时,却可能面临被裁的风险。 最终,他们只能眼睁睁看着自己倾注心血的成果被资本家掌控,而自己却一无所有。

因此,采用 AGPL 3.0 协议的项目,由于开发者能共享所有权,更能激励程序员全身心投入,用心打磨项目。



## 启动展示

ioGame 在内存占用、启动速度、打包等方面也是优秀的。
- 内存方面:内存占用小。
- 启动速度方面:应用通常会在 **0.x 秒**内完成启动。
- 打包方面:打 jar 包后大约 **15MB** 。

![](https://iohao.github.io/game/assets/images/start-cc4b7973e832e31c6c5bf50af83aabeb.png)



## 介绍

你是否想要开发一个**高性能、稳定、易用、自带负载均衡、避免类爆炸设计、可跨进程跨机器通信、集群无中心节点、集群自动化、有状态多进程的分布式的**网络编程服务器呢? 如果是的话,这里向你推荐一个由 java 语言编写的网络编程框架 ioGame。



ioGame 是一个轻量级的网络编程框架,适用于**网络游戏服务器、物联网、内部系统**及各种需要长连接的场景。



**ioGame 有以下特点:**

> 1. 真轻量级、无锁异步化、事件驱动的架构设计。
> 2. 包体小、内存占用少、启动速度快。
> 3. ioGame 是纯 javaSE 的,使得 ioGame 能与其他框架方便的进行集成、融合,如 Spring ...等。
> 4. 在学习成本方面,ioGame 的学习成本非常低,可以说是**零学习成本**,即使没有游戏编程经验,也能轻松上手。开发者只需掌握普通的 java 方法或 webMVC 相关知识,就能用框架开发业务。
> 5. ioGame 在架构上解决了传统框架所产生的 **N\*N 问题**。
> 6. 在轻量级方面,ioGame **不依赖任何第三方**中间件或数据库**就能支持集群、分布式**,只需要 java 环境就可以运行。
> 7. 在架构灵活性方面,ioGame 的架构由三部分组成:1.游戏对外服、2.Broker(游戏网关)、3.游戏逻辑服。三者既可相互独立,又可相互融合,这意味着使用 ioGame 可以**适应任何类型的游戏**。
> 8. 架构是可以动态扩缩的,游戏对外服、游戏逻辑服、Broker(游戏网关)都**支持动态增加和减少**。
> 9. 在分布式开发体验方面,ioGame 支持多服单进程的启动方式,这使得开发者在开发和调试分布式系统时更加简单。
> 10. 在生态规划方面,游戏逻辑服是支持独立运行,**从而实现功能模块化的可能性**。
> 11. 具备全链路调用日志跟踪特性。
> 12. 在通讯方式方面,提供多种通讯方式,且逻辑服之间可以相互跨机器通信。
> 13. 在编码风格上,提供了类 MVC 的编码风格(无入侵的 Java Bean ),这种设计方式很好的**避免了类爆炸**。
> 14. 在线程安全方面,框架为开发者解决了单个玩家的**并发问题**。
> 15. 在连接方式方面,允许开发者**使用一套业务代码**,同时支持 TCP、WebSocket、UDP 等多种连接方式,无需进行任何修改,并且可扩展。
> 16. 在数据协议方面,ioGame 让开发者**用一套业务代码**,就能轻松切换不同的数据协议,如 Protobuf、JSON 等,并且可扩展。
> 17. 在增减协议方面,ioGame 可以让你在**新增或减少协议**时,**无需重启**游戏对外服与 Broker(游戏网关)。这样既能避免玩家断线,又能避免因新增、减少协议而重启所有机器的痛点。
> 18. action 支持自动装箱、拆箱基础类型,用于解决[协议碎片](https://iohao.github.io/game/docs/manual/protocol_fragment)的问题。
> 19. 业务框架提供了插件机制,插件是可插拨、可扩展的。
> 20. 在部署方面,ioGame 支持**多服单进程**的方式部署,也支持**多服多进程**多机器的方式部署,在部署方式上可以随意的切换而不需要更改代码。
> 21. 在安全方面,所有的游戏逻辑服不需要开放端口,**天然地避免了扫描攻击**。
> 22. 在模拟客户端测试方面,ioGame 提供了压测&模拟客户端请求模块。该模块**可以模拟真实的网络环境**,并且在模拟测试的过程中与服务器的交互是可持续的、可互动的,同时也是支持自动化的。
> 23. 框架为开发者提供了同步、异步、异步回调的方法,用于逻辑服之间的相互访问。
> 24. 分布式事件总线支持(类似 MQ、Redis 发布订阅机制,可跨多个机器通信、可跨多个进程通信)。
> 25. 提供优雅的路由访问权限控制。
> 26. 具备智能的同进程亲和性。
> 27. JSR380 验证、断言 + 异常机制 = 更少的维护成本。
> 28. 一次编写到处对接,提升巨大的生产力,能为各客户端生成可交互的代码。你只需要编写一次 java 代码,就能为 Godot、UE、Unity、CocosCreator、Laya、React、Vue、Angular ...等项目生成统一的交互接口。



ioGame 在打包、内存占用、启动速度等方面也是优秀的。 打 jar 包后大约 **15MB**,应用通常会在 **0.x 秒**内完成启动,内存占用小。



在生态融合方面,ioGame 可以很方便的[与 Spring 集成](https://iohao.github.io/game/docs/manual/integration_spring)(4 行代码)。 除了 Spring 外,还能与任何其他的框架做**融合**,如 Vert.x、Quarkus、Solon ...等,从而使用其他框架的相关生态。



在学习成本方面,ioGame 的学习成本非常低,可以说是**零学习成本**,即使没有游戏编程经验也能轻松上手。 开发者只需掌握普通的 java 方法或 webMVC 相关知识,就能使用框架开发业务。



在编码风格上,ioGame 为开发者提供了类 MVC 的编码风格(无入侵的 Java Bean ),这种设计方式很好的**避免了类爆炸**。 同时,框架为开发者提供了同步、异步、异步回调的方法,用于逻辑服之间的相互访问。 这使得开发者所编写的代码会非常的优雅,并且具备全链路调用日志跟踪。



与客户端对接方面,ioGame 具备**一次编写到处对接**的能力,为客户端提供了代码生成的辅助功能,能够帮助客户端开发者减少巨大的工作量。 这将意味着,你只需要编写一次 java 代码,就能为 Godot、UE、Unity、CocosCreator、Laya、React、Vue、Angular ...等项目生成统一的交互接口。 ioGame 提供了多种语言的 SDK 支持及相关语言的[代码生成](https://iohao.github.io/game/docs/examples/code_generate),分别是 C#、TypeScript、GDScript、C++,并支持扩展。



ioGame 在架构上解决了传统框架所产生的 **N\*N 问题**([与传统架构对比](https://iohao.github.io/game/docs/overall/legacy_system))。 传统架构在扩展机器时,需要借助很多第三方中间件,如:Redis、MQ、ZooKeeper ...等,才能满足整体架构的运作。 通常,只要引入了需要安装的中间件才能做到扩展的,那么你的架构或者说框架,基本上与轻量级无缘了。



在轻量级方面,ioGame **不依赖任何第三方**中间件或数据库**就能支持集群、分布式**,只需要 java 环境就可以运行。 这意味着在使用上简单了,在部署上也为企业减少了部署成本、维护难度。使用 ioGame 时,只需一个依赖即可获得整个框架, 而无需安装其他服务,如: Nginx、Redis、MQ、Mysql、ZooKeeper、Protobuf 协议编译工具 ...等。



在[架构灵活性](https://iohao.github.io/game/docs/overall/deploy_flexible)方面,ioGame 的架构由三部分组成:1.游戏对外服、2.Broker(游戏网关)、3.游戏逻辑服。 三者既可相互独立,又可相互融合。 这意味着使用 ioGame 可以**适应任何类型的游戏**,因为只需通过调整部署方式,就可以满足不同类型的游戏需求。 在 ioGame 中进行这些调整工作非常简单,而且不会对现有代码产生不良影响。



架构是可以动态扩缩的,游戏对外服、游戏逻辑服、Broker(游戏网关)都**支持动态增加和减少**。 无论未来玩家数量增加或减少,我们都能够轻松应对。 同时,架构是**支持玩家无感知更新**的,这得益于分布式设计。 举例来说,如果 A 类型的游戏逻辑服需要增加一些新功能,我们可以启动 A-3、A-4 等已经支持了新功能的服务器, 然后逐步将之前的 A-1 和 A-2 下线,从而实现了无感知的更新。



在集群方面,ioGame 的 Broker (游戏网关)采用无中心节点、[自动化的集群设计](https://iohao.github.io/game/docs/examples/server/example_broker_cluster),所有节点平等且自治,不存在单点故障。 集群能够**自动管理和弹性扩缩**,节点加入或退出时,能够自动保证负载均衡和数据一致性,不影响服务可用性。



在分布式方面,ioGame 的逻辑服使用了分布式设计思想,将服务器分为[游戏对外服](https://iohao.github.io/game/docs/overall/external_intro)、[游戏逻辑服](https://iohao.github.io/game/docs/overall/logic_intro)等不同层次, 并且每一层都有明确的职责和接口。这样可以提高代码可读性和可维护性,并且方便进行**水平扩展**。



在分布式开发体验方面,通常在开发分布式应用时是需要启动多个进程的。 这会让调试与排查问题变得非常困难,从而降低开发者的效率、增加工作量等,这也是很多框架都**解决不了的问题**,但 ioGame 做到了! ioGame 支持多服单进程的启动方式,这使得开发者在开发和调试分布式系统时更加简单。



在[生态规划](https://iohao.github.io/game/docs/manual_high/your_ecology)方面,我们的游戏逻辑服是支持独立运行的,只需接入 Broker(游戏网关)上, 就可以为玩家和其他游戏逻辑服提供功能上的扩展与增强。 我们可以将一些**游戏逻辑服组件化**,并制作成相对通用的组件,**从而实现功能模块化的可能性**。这么做有几个优点

1. 避免一些重复开发的工作量。
2. 减少各功能模块的耦合。
3. 更符合单一职责的设计,将相对通用的功能扩展成一个个的**功能逻辑服**。如,公会逻辑服、好友逻辑服、登录逻辑服、抽奖逻辑服、公告逻辑服、排行榜逻辑服...等。
4. 由于模块功能是独立,那么将来可以对任意的功能逻辑服进行扩容,且不需要改动任何代码。
5. 这些组件化后的功能逻辑服就好比一件件武器,积累得足够多时就形成了自己的生态武器库,可以更好的帮助公司与同行竞争。
6. **代码泄漏机率更小**。传统的游戏项目通常采用单机结构,把所有的代码放在一个目录中。这样做有很大的风险,因为如果代码泄漏了,就会泄漏整个项目的内容。当功能模块化后,可以让不同的开发人员只负责自己的游戏逻辑服模块,从而避免代码泄漏的风险和影响。
7. 团队管理员只需要在内网服务器上部署一个游戏网关和游戏对外服,而开发人员就可以在本机上编码和测试自己的游戏逻辑服模块。这样还有以下好处
    - 游戏客户端不会因为游戏逻辑服的变更或重启而断开连接。
    - 开发人员不需要启动其他人的游戏逻辑服模块。
    - 开发人员可以通过 ioGame 自动生成的文档来进行模块间的对接。



ioGame 具备[全链路调用日志跟踪](https://iohao.github.io/game/docs/manual/trace)特性,这在分布式下非常的实用。 该特性为每个请求分配一个唯一标识,并记录在日志中,通过唯一标识可以快速的在日志中过滤出指定请求的信息。 ioGame 提供的全链路调用日志跟踪特性更是强大,**支持跨机器、跨进程**。 简单的说,从玩家的请求进来到结束,无论该请求经过了多少个游戏逻辑服,都能精准记录。



在通讯方式方面,大部分框架只能支持推送(广播)这一类型的通讯方式。 ioGame 则提供了多种[通讯模型](https://iohao.github.io/game/docs/manual/communication_model), 通过对各种通讯方式的组合使用,可以简单完成以往难以完成的工作, 并且这些通讯方式都支持跨进程、跨机器通信,且具备全链路调用日志跟踪。

- 在客户端的角度,提供了如下的通讯模型
    - [request/response](https://iohao.github.io/game/docs/communication/request_response),请求/响应
    - request/void,请求/无响应
    - request/broadcast,请求/广播响应
    - [broadcast](http://localhost:3000/docs/communication/broadcast),广播
- 内部通讯主要用于服务器内部之间的通信,跨服、跨进程通信。提供了如下的通讯模型
    - [request/response](https://iohao.github.io/game/docs/communication/request_response),请求/响应
    - request/void,请求/无响应
    - [request/multiple_response](https://iohao.github.io/game/docs/communication/request_multiple_response),同时请求同类型多个游戏逻辑服
    - [EventBus](https://iohao.github.io/game/docs/communication/event_bus),分布式事件总线
    - [ExternalRegion](https://iohao.github.io/game/docs/communication/external_biz_region),访问游戏对外服



从 ioGame21 开始,框架添加了虚拟线程的相关支持。 各逻辑服之间通信阻塞部分使用虚拟线程,这样可以很好的避免阻塞业务线程,并大幅提高了框架的吞吐量。



在线程安全方面,框架为开发者解决了单个玩家的**并发问题**。 即使玩家重新登录后,也会使用相同的线程来消费业务,并推荐使用[领域事件](https://iohao.github.io/game/docs/extension_module/domain_event)来解决同一房间或业务内多个玩家的并发问题。 [框架在线程的扩展性](https://iohao.github.io/game/docs/overall/thread_executor)上提供了友好的支持,开发者可以很容易的编写出无锁并发代码,这得益于 ioGame 独有的线程执行器设计与扩展。 换句话说,你不会因为并发问题烦恼。



在无锁并发方面,ioGame 提供了优雅、独特的线程执行器设计。通过该特性,开发者能轻易的编写出无锁高并发的代码。



在连接方式方面,ioGame 允许开发者**使用一套业务代码**,**同时支持**多种连接方式,无需进行任何修改。 ioGame 已经支持了 TCP、WebSocket 和 UDP 连接方式,并且也支持在这几种连接方式之间进行灵活切换。 连接方式是可扩展的,并且扩展操作也很简单,这意味着之后如果支持了 KCP、QUIC, 无论你当前项目使用的是 TCP、WebSocket、UDP,都可以切换成 KCP、QUIC。 即使切换到 KCP、QUIC 的连接方式,现有的业务代码也无需改变。



在通信协议方面,ioGame 让开发者**用一套业务代码**,就能轻松[切换和扩展不同的数据协议](https://iohao.github.io/game/docs/manual/data_protocol), 如 Protobuf、JSON 等。只需一行代码,就可以从 Protobuf 切换到 JSON,无需改变业务方法。



在增减协议方面,ioGame 可以让你在**新增或减少协议**时,**无需重启**游戏对外服与 Broker(游戏网关)。 这样既能避免玩家断线,又能避免因新增、减少协议而重启所有机器的痛点。



在协议碎片方面,action 支持自动装箱、拆箱基础类型特性,用于解决[协议碎片](https://iohao.github.io/game/docs/manual/protocol_fragment)的问题。 同时该特性除了能使你的业务代码更加清晰以外,还能大幅提高开发者在该环节的生产力。



在[同进程亲和性](https://iohao.github.io/game/docs/manual_high/same_process)方面,在同一进程内, 不同 Netty 实例之间的通信,是通过内存进行传输的,不需要经过网络传输,数据传输速度极快。 同进程亲和性指的是,优先访问同进程内的游戏逻辑服,当同进程内没有能处理请求的游戏逻辑服时, 才会去其他进程或机器中查找能处理请求的游戏逻辑服。 简单点说,框架对于请求的处理很智能,会优先将请求给同进程内的逻辑服消费。



在开发体验方面,ioGame 非常注重开发者的开发体验。 框架提供了 [JSR380 验证](https://iohao.github.io/game/docs/core/jsr380)、[断言 + 异常机制](https://iohao.github.io/game/docs/manual/assert_game_code)、[业务代码定位](https://iohao.github.io/game/docs/core_plugin/action_debug), action 支持自动装箱、拆箱基础类型,用于解决协议碎片的问题 ...等。 诸多丰富的功能,使得开发者的业务代码更加的清晰、简洁。



业务框架提供了[插件](https://iohao.github.io/game/docs/manual/plugin_intro)机制,插件是可插拨、可扩展的。 框架内置提供了 DebugInOut、action 调用统计、业务线程监控插件、各时间段调用统计插件...等插件。 不同的插件提供了不同的关注点,比如我们可以使用调用、监控等插件相互配合,可以让我们在开发阶段就知道**是否存在性能问题**。 合理利用好各个插件,可以让我们在开发阶段就能知道问题所在,提前发现问题,提前预防问题。



在部署方面,ioGame 支持**多服单进程**的方式部署,也支持**多服多进程**多机器的方式部署,在部署方式上可以随意的切换而不需要更改代码。 日常中我们可以按照单体思维开发,到了生产可以选择性的使用多进程的方式部署。



在安全方面,所有的游戏逻辑服[不需要开放端口,天然地避免了扫描攻击](https://iohao.github.io/game/docs/overall/legacy_system#Usage-Management)。 由于不需要为每个逻辑服分配独立的端口,那么我们在使用诸如云服务器之类的服务时,就不需要担心端口开放权限的问题了。 别小看这一个环节,通常这些小细节最浪费开发者的时间。 由于我们不需要管理这些 IP:Port,**这部分的工作量就自然地消失了**。



在模拟客户端测试方面,ioGame 提供了[压测&模拟客户端请求](https://iohao.github.io/game/docs/extension_module/simulation_client)模块。 此模块是用于模拟客户端,简化模拟工作量,只需要编写对应请求与回调。 除了可以模拟简单的请求外,通常还可以做一些复杂的请求编排,并支持复杂业务的压测。 **与单元测试不同的是,该模块可以模拟真实的网络环境,并且在模拟测试的过程中与服务器的交互是可持续的、可互动的,同时也是支持自动化的**。



使用 ioGame,可以显著的帮助企业减少巨额成本。 文档中,**成本**关键字提到了很多次,各个阶段均有关联,包括了学习、研发、测试、部署、扩展、投入 ...等各阶段。 在同等资源的竞争下,使用 ioGame 能为公司节省更多的资源,从而提高了自身的生存率。 更重要的是避免了为其他公司做嫁衣的可能性,具体可阅读[成本分析案例](https://iohao.github.io/game/services/cost_analysis)。



开发者基于 ioGame 编写的项目模块,通常是条理清晰的,得益于框架对**路由的合理设计**,同时也为路由提供了优雅的[访问权限控制](https://iohao.github.io/game/docs/external/access_authentication)。 当我们整理好这些模块后,对于其他开发者接管项目或后续的维护中,会是一个不错的帮助([代码组织与约定](https://iohao.github.io/game/docs/manual_high/code_organization))。 或许现阶段你感受不到这块的威力,随着你深入地使用实践就能体会到这么设计的诸多好处与优势。



开发者基于 ioGame 编写的项目,通常是语法简洁的、高性能的、低延迟的。 框架最低要求使用 **JDK21**,这样即可以让项目享受到**分代 ZGC** 带来的改进,还能享受语法上的简洁。 分代 ZGC 远低于其**亚毫秒级**暂停时间的目标,可以在不影响游戏速度的情况下,清理掉多余的内存。 这样就不会出现卡顿或者崩溃的问题了,相当于在项目中变相的引入了一位 JVM 调优大师。



综上所述,ioGame 是一个非常适合网络游戏开发的框架。可以让你轻松地创建高性能、低延迟、易扩展的游戏服务器,并且节省时间和资源。 如果你想要快速地开发出令人惊艳的网络游戏,请不要犹豫,立即选择 ioGame 吧! 框架屏蔽了很多复杂且重复性的工作,并可为项目中的功能模块结构、开发流程等进行**清晰的组织定义**,减少了后续的项目维护成本。



框架在开发、部署、压测&模拟测试 ...等,各个阶段都提供了很好的支持。 相信你已经对 ioGame 有了一个初步的了解,虽然还有很多丰富的功能与特性没有介绍到,但你可以通过后续的实践过程中来深入了解。 感谢你的阅读,并期待你使用 ioGame 来打造自己的游戏服务器。

---

## 一次编写到处对接,提升巨大的生产力

ioGame 是非常注重开发体验的,代码注释即文档、方法即交互接口的原则。



ioGame 具备一次编写到处对接的能力,从而让你们团队提升巨大的生产力。 **一次编写**指的是编写一次 java 业务代码,而**到处对接**则是指为不同的前端项目生成与服务器交互的代码。



你只需要编写一次 java 代码,就能为 [Godot](https://godotengine.org/)、 [UE](https://www.unrealengine.com/)、 [Unity](https://unity.com/)、 [CocosCreator](https://www.cocos.com/)、 [Laya](https://layaair.layabox.com/#/)、 [React](https://react.dev/)、 [Vue](https://vuejs.org/)、 [Angular](https://angular.dev/) ...等项目生成统一的交互接口



ioGame 能为各种前端项目生成 **action、广播、错误码** 相关接口代码。 这将意味着,你只需要编写一次业务代码,就可以同时与这些游戏引擎或现代化的前端框架交互。



前端代码生成的几个优势

1. 帮助客户端开发者减少巨大的工作量,**不需要编写大量的模板代码**。
2. **语义明确,清晰**。生成的交互代码即能明确所需要的参数类型,又能明确服务器是否会有返回值。这些会在生成接口时就提前明确好。
3. 由于我们可以做到明确交互接口,进而可以明确参数类型。这使得**接口方法参数类型安全、明确**,从而有效避免安全隐患,从而**减少联调时的低级错误**。
4. 减少服务器与客户端双方对接时的沟通成本,代码即文档。生成的联调代码中有文档与使用示例,方法上的示例会教你如何使用,即使是新手也能做到**零学习成本**。
5. 帮助客户端开发者屏蔽与服务器交互部分,**将更多的精力放在真正的业务上**。
6. 为双方联调减少心智负担。联调代码使用简单,**与本地方法调用一般丝滑**。
7. 抛弃传统面向协议对接的方式,转而**使用面向接口方法的对接方式**。
8. 当我们的 java 代码编写完成后,我们的文档及交互接口可做到同步更新,**不需要额外花时间去维护对接文档及其内容**。



## 架构简图

> 无锁异步化、事件驱动的架构设计;真轻量级,无需依赖任何第三方中间件或数据库就能搭建出一个集群、分布式的网络游戏服务器。
>
> 集群无中心节点、集群自动化、自带负载均衡、分布式支持、可动态增减机器。

| 名称                                                         | 扩展方式 | 职责             |
| ------------------------------------------------------------ | -------- | ---------------- |
| **ExternalServer**,[游戏对外服](https://iohao.github.io/game/docs/overall/external_intro) | 分布式   | 与玩家连接、交互 |
| **GameLogicServer**,[游戏逻辑服](https://iohao.github.io/game/docs/overall/logic_intro) | 分布式   | 处理具体业务逻辑 |
| **BrokerCluster**,[Broker(游戏网关)](https://iohao.github.io/game/docs/overall/broker_intro) | 集群     | 调度和转发任务   |

![ioGame](https://iohao.github.io/game/assets/images/ioGame-2cd7572c6c81afd341b7d2e9d703bf65.svg)

更详细的介绍请阅读[架构介绍](https://iohao.github.io/game/docs/overall/architecture_intro)。

------

> 从图中可以看出,游戏网关支持以集群方式启动多个实例。这个设计选择了集群的方式,因为游戏网关通常是无状态的,主要用于调度和转发任务
>
> 而游戏对外服、游戏逻辑服使用分布式设计,支持启动多个相同类型的服务。这意味着,当玩家数量增加时,我们可以轻松增加相应类型的游戏逻辑服以处理更多请求。
>
> 以游戏逻辑服为例,假设我们启动了两个 A 类型的游戏逻辑服,分别为 A-1 和 A-2。当玩家向 A 类型的游戏逻辑服发起多次请求时,游戏网关会使用默认的随机负载策略将请求分配给 A-1 和 A-2 来处理。
>
> 现在我们明白,游戏对外服和游戏逻辑服都支持动态增加和减少。无论未来玩家数量增加或减少,我们都能够轻松应对。架构是**支持玩家无感知更新**的,这得益于分布式设计。举例来说,如果 A 类型的游戏逻辑服需要增加一些新功能,我们可以启动 A-3、A-4 等已经支持了新功能的服务器,然后逐步将之前的 A-1 和 A-2 下线,从而实现了无感知的更新。
>
> 此外,框架还支持玩家[动态绑定游戏逻辑服](https://iohao.github.io/game/docs/manual/binding_logic_server)。玩家与游戏逻辑服绑定后,之后的请求都由该游戏逻辑服来处理。
>
> 除了游戏之外,ioGame 也适用于物联网相关项目。只需将图中的玩家视为具体的设备,即使存在数亿个设备,ioGame 的架构也可以轻松支持。从 2022 年开始,已经有一些物联网公司开始采用这一解决方案,并得到了很好的体验。



**游戏对外服**

游戏对外服主要负责与用户(玩家)的长连接,先来个假设,假如我们的一台硬件支持我们建立用户连接的上限是 5000 人, 当用户量达到 7000 人时,我们可以多加一个对外服务器来进行分流减压。

通过增加游戏对外服的数量,可以有效地进行连接的负载均衡和流量控制,使得系统能够更好地承受高并发的压力。 由于游戏对外服扩展的简单性,意味着支持同时在线玩家可以轻松的达到百万、千万甚至更多。

即使我们启动了多个游戏对外服,开发者也不需要关心这些玩家连接到了哪个游戏对外服的问题, 这些玩家总是能接收到广播(推送)消息的,因为框架已经把这些事情给做了。 在玩家的角度我们只有“一个”服务器,同样的,在开发者的角度我们只有“一个”游戏对外服。

通常,有些开发者想知道游戏对外服最大支持多少玩家连接。 关于这个问题,只需要搜索 Netty 相关知识即可,因为游戏对外服本质上是 Netty。

同样的,如果开发者已经熟悉了 Netty 相关知识,那么在游戏对外服的扩展上也会变得非常的容易。



## 快速入门

下面是游戏引擎与游戏服务器的业务交互简图。

![业务交互简图](https://iohao.github.io/game/assets/images/introduction_quick-6b29dfc678257db43afb10939356edb6.jpeg)

> 抽象的说,游戏前端与游戏服务器的的交互由上图组成。 游戏前端与游戏服务器可以自由地**双向交互**,即发送和接收业务数据。 业务数据由 .proto 文件作为载体,在前端和后端之间进行编码和解码。 .proto 文件是对业务数据的描述载体,定义了数据类型和消息类型,以及它们的属性和规则。
>
> 通过这种方式,游戏前端和游戏服务端可以建立连接,并开始相互传递业务数据,处理各自的业务。 以上是对游戏前端与游戏服务器之间交互方式的介绍。 接下来,我们将编写一个简单的游戏业务处理示例,并定制一个适合我们需求的业务数据协议。
>
> **协议文件**是对业务数据的描述载体,用于游戏前端与游戏服务器的数据交互。 Protocol Buffers 是 Google 开发的一种数据描述语言,也简称 PB。 协议文件描述还可以是 json、xml 或者任意自定义的,因为最后传输时会转换为二进制,但游戏开发中 PB 是目前的最佳选择。
>
> **游戏前端**的展现可以是 [Godot](https://godotengine.org/)、 [Unity](https://unity.cn/)、 [UE](https://www.unrealengine.com/zh-CN/)、 [Cocos Creator](https://www.cocos.com/)、 [Laya](https://layaair.layabox.com/#/)、 [FXGL](https://github.com/AlmasB/FXGL) 或者其他的游戏引擎。 这些游戏引擎只是展现游戏画面的一种形式,数据交互则由通信来完成(TCP、UDP ...等)。



**数据协议**

现在,我们定义两个数据协议,用于客户端与服务器的数据交互。 这是一个 jprotobuf 的 pb 对象,jprotobuf 是对 google protobuf 的简化使用,性能同等。



可以把这理解成 DTO 业务数据载体等,其主要目的是用于业务数据的传输。

```java
@ProtobufClass
public class LoginVerifyMessage {
    public String jwt;
}

@ProtobufClass
public class UserMessage {
    public String name;
}
```



**Action**

游戏服务器的编程,游戏服务器接收业务数据后,对业务数据进行处理。 下面这段代码可以同时支持 TCP、WebSocket、UDP 通信方式。

```java
@Slf4j
@ActionController(1)
public class DemoAction {
    @ActionMethod(0)
    public UserMessage here(LoginVerifyMessage message) {
        var userMessage = new UserMessage();
        userMessage.name = "Michael Jackson, " + message.jwt;
        return userMessage;
    }
}
```



一个方法(here)在业务框架中表示一个 [Action](https://iohao.github.io/game/docs/manual/action)(业务动作)。

方法声明的参数是用于接收前端传入的业务数据,在方法 return 时,数据就可以被游戏前端接收到。 程序员可以不需要关心业务框架的内部细节。

从上面的示例可以看出,这和普通的 java 类并无区别,同时这种设计方式**避免了类爆炸**。 如果只负责编写游戏业务,那么对于业务框架的学习可以到此为止了。



**游戏编程就是如此简单!**



**问:我可以开始游戏服务器的编程了吗?**

> 是的,你已经可以开始游戏服务器的编程了。



**访问示例(控制台)**

当访问 action 业务方法时,控制台将会打印的日志输出如下

```text
┏━━━━━ Debug. [(DemoAction.java:5).here] ━━━━━ [cmd:1-0 65536] ━━━━━ [xxx逻辑服 - id:[76526c134cc88232379167be83e4ddfc]
┣ userId: 1
┣ 参数: message : LoginVerifyMessage(jwt=hello)
┣ 响应: UserMessage(name=Michael Jackson, hello)
┣ 时间: 1 ms (业务方法总耗时)
┗━━━━━ [ioGameVersion] ━━━━━ [线程:User-8-2] ━━━━━━━ [traceId:956230991452569600] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```

**控制台打印说明**

- **Debug**. [(DemoAction.java:5).here] : 表示执行业务的是 DemoAction 类下的 here 方法,5 表示业务方法所在的代码行数。在工具中点击控制台的 DemoAction.java:5 这条信息,就可以跳转到对应的代码中(快速导航到对应的代码),这是一个开发良好体验的开始!
- **userId** : 当前发起请求的 用户 id。
- **参数** : 通常是游戏前端传入的值。
- **响应** : 通常是业务方法返回的值 ,业务框架会把这个返回值推送到游戏前端。
- **时间** : 执行业务方法总耗时,我们可根据业务方法总耗时的时长来优化业务。
- **路由信息** : [cmd - subCmd][路由](https://iohao.github.io/game/docs/manual/cmd)是唯一的访问地址。
- **ioGameVersion** : 表示当前所使用的 ioGame 版本。
- **线程** : 当前执行 action 所使用的线程。
- **traceId** : 全链路调用日志跟踪 id,每个请求唯一。(该特性在分布式下非常实用)
- **逻辑服** : 当前游戏逻辑服的 id

有了以上信息,游戏开发者可以很快的定位问题。 如果没有可视化的信息,开发中会浪费很多时间在前后端的沟通上。问题包括:

- 是否传参问题 (游戏前端说传了)
- 是否响应问题(游戏后端说返回了)
- 业务执行时长问题 (游戏前端说没收到响应, 游戏后端说早就响应了)

其中代码导航可以让开发者快速的跳转到业务类对应代码中, 在多人合作的项目中可以快速的知道业务经过了哪些方法的执行,使得我们可以快速的进行阅读或修改。



## 适合人群

1. 长期从事 web 内部系统开发人员, 想了解游戏的。
2. 刚从事游戏开发的。
3. 未从事过游戏开发,但却对其感兴趣的。
4. 对设计模式在实践中的应用有兴趣的学习者。
5. 可以接受新鲜事物的。
6. 想放弃祖传代码的。



推荐实际编程经验一年以上的人员。



================================================
FILE: changeLog_ioGame.md
================================================
文档与日志
- [框架版本更新日志](https://iohao.github.io/game/docs/version_log)
- [ioGame 真.轻量级网络编程框架 - 在线使用文档 ](https://game.iohao.com/)


> ioGame 每月会发 1 ~ 2 个版本,通常在大版本内升级总是兼容的,如 21.1 升级到任意 21.x 的高版本。

### 2025-08-11 - v21.30
https://github.com/iohao/ioGame/releases/tag/21.30

**Version update summary**

> 1. fix(generate-code): [#490](https://github.com/iohao/ioGame/issues/490) Fixed the escaping of special characters in the Listener exampleCode for the code generation module. 修复 C# 代码生成时的转义字符


### 2025-07-19 - v21.29
https://github.com/iohao/ioGame/releases/tag/21.29

**Version update summary**

> 1. [#473](https://github.com/iohao/ioGame/issues/473) fix(core): Change the method name from DataSelfEncode getEncodeData to encodeData to avoid JSON serialization.
> 2. fix(doc): [#459](https://github.com/iohao/ioGame/issues/459) Supporting the referencing of classes within a JAR file in a multi-module Gradle environment.
> 3. feat(generate-code): [#452](https://github.com/iohao/ioGame/issues/452)
> 4. fix(generate-code): broadcast_action_example_action.txt、broadcast_action_example.txt
> 5. feat(external): [#469](https://github.com/iohao/ioGame/issues/469) Add HttpFallbackHandler to determine if it's a WebSocket upgrade request.
> 6. perf(doc): Pre-create the Pb for the BroadcastDocument dataClass.

**[other updates]**

Upgrade reactor-netty 1.2.7、commons-io 2.19.0


### 2025-06-17 - v21.28
https://github.com/iohao/ioGame/releases/tag/21.28

**Version update summary**

> 1. feat(room): The room supports convenient operations. 
> 2. Deprecated RoomStatusEnum. 
> 3. feat(room): The room supports convenient broadcastRange. 
> 4. docs(all): Update documentation link (https://iohao.github.io/game). 
> 5. [#451](https://github.com/iohao/ioGame/issues/451) Refactor the usage documentation to use the new access address: https://iohao.github.io/game/ .

------

**[other updates]**

```xml
<netty.version>4.1.122.Final</netty.version>
```

------

### 2025-05-09 - v21.27

https://github.com/iohao/ioGame/releases/tag/21.27


**Version update summary**

> 1. feat(generate-code): #449 Supports GDScript GenerateCode
> 2. #444 Provides GDScript SDK
> 3. #448 Provides GDScript Example with ioGame
> 4. perf(core): ActionCommandDocKit

------



**feat(generate-code)**: #449 Supports GDScript GenerateCode

About examples: https://github.com/iohao/ioGameSdkGDScriptExampleGodot



```java
public final class GenerateTest {
    // setting root path
    static String rootPath = "/Users/join/gitme/ioGame-sdk/";

    public static void main(String[] args) {
        // CHINA or US
        Locale.setDefault(Locale.CHINA);

        // Load the business framework of each gameLogicServer
        // cn: 加载游戏逻辑服的业务框架
        yourListLogic().forEach(BrokerClientStartup::createBarSkeleton);

        /*
         * Generate actions, broadcasts, and error codes.
         * cn: 生成 action、广播、错误码
         */
        
        // ----- About generating GDScript code -----
        generateCodeGDScriptGodot();

        // Added an enumeration error code class to generate error code related information
        IoGameDocumentHelper.addErrorCodeClass(YourGameCodeEnum.class);
        // Generate document
        IoGameDocumentHelper.generateDocument();
    }

    private static void generateCodeGDScriptGodot() {
        var documentGenerate = new GDScriptDocumentGenerate();
        // By default, it will be generated in the target/code directory
        // cn: 设置代码生成所存放的路径,如果不做任何设置,将会生成在 target/code 目录中
        String path = rootPath + "ioGameSdkGDScriptExampleGodot/gen/code";
        documentGenerate.setPath(path);

        IoGameDocumentHelper.addDocumentGenerate(documentGenerate);
    }
}
```






### 2025-04-30 - v21.26

https://github.com/iohao/ioGame/releases/tag/21.26

**Version update summary**

> 1. refactor(Code generation): Code generation supports importing multiple .proto files
> 2. refactor(i18n): #376

------


Supports importing multiple .proto files

```java
public interface SdkProtoFile {
    String fileName = "common.proto";
    String filePackage = "common";

    String fileName2 = "common2.proto";
    String filePackage2 = "common2";
}

@ToString
@ProtobufClass
@FieldDefaults(level = AccessLevel.PUBLIC)
@ProtoFileMerge(fileName = SdkProtoFile.fileName, filePackage = SdkProtoFile.filePackage)
public final class LoginVerifyMessage {
    /** jwt */
    String jwt;
}

@ToString
@ProtobufClass
@FieldDefaults(level = AccessLevel.PUBLIC)
@ProtoFileMerge(fileName = SdkProtoFile.fileName2, filePackage = SdkProtoFile.filePackage2)
public final class BulletMessage {
    /** id */
    int bulletId;
    /** bullet name */
    String name;
}
```


**[other updates]**

```xml
<netty.version>4.1.121.Final</netty.version>
```

 



### 2025-03-20 - v21.25

https://github.com/iohao/ioGame/releases/tag/21.25

**Version update summary**

> 1. fix(broker): DefaultWithElementSelector
> 2. refactor(net): enhance ResponseCollectItemMessage
> 3. refactor(core): FlowContext add the createResponseMessage method

------

**[other updates]**

```xml
<netty.version>4.1.119.Final</netty.version>
```

 

### 2025-02-12 - v21.24

https://github.com/iohao/ioGame/releases/tag/21.24

**Version update summary**

> 1. refactor(client): Client support boxing and unboxing
> 2. refactor(core): FlowContextKit add ofFlowContext method
> 3. refactor(room): room add getPlayerBySeat method
> 4. fix(core): [#425](https://github.com/iohao/ioGame/issues/425) When there is a method with the same name as the action, the `actionMethodIndex` is not obtained correctly.
> 5. refactor(core): MethodParser add parseData method


------



**[client]** Client support boxing and unboxing.

```java
// my client,support:int、long、boolean、String、List
public final class MyInputCommandRegion extends AbstractInputCommandRegion {
    @Override
    public void initInputCommand() {
        this.inputCommandCreate.cmd = 1;
		// Client support boxing and unboxing
        ofCommand(2).setTitle("enterRoom").setRequestData(() -> {
            // enterRoom
            long roomId = 2;
            return roomId;
        });
        
        // or 
        ofCommand(2).setTitle("enterRoom").setRequestData(() -> {
           // enterRoom
           return LongValue.of(2);
        });
    }
}

// my action
@ActionController(1)
public final class MyAction {
    /**
     * enterRoom
     *
     * @param roomId roomId
     */
    @ActionMethod(2)
    public void enterRoom(long roomId) {
    }
}
```



------

**[other updates]**

```xml
<netty.version>4.1.117.Final</netty.version>
```

------





### 2025-01-08 - v21.23

https://github.com/iohao/ioGame/releases/tag/21.23


**Version update summary**

> 1. perf(room): OperationHandler adds the processVerify method to control whether the process method is executed, and deprecates the verify method, which is replaced by processVerify.
> 2. perf(core): Optimize BoolValue and reduce the creation of objects
> 3. perf(net-core): Enhance the invokeModuleMessage and invokeModuleCollectMessage methods of the BrokerClientItem. The return value must not be null, and error information is added.
> 4. fix(generate-code): action_method_void.txt
> 5. perf(doc): GameCode Support single parameter construction method
> 6. perf(kit): [#412](https://github.com/iohao/ioGame/issues/412)
> 7. perf(room): Player adds isRobot method. Room adds methods to distinguish between real players and robot players.
> 8. refactor(proto): [#414](https://github.com/iohao/ioGame/issues/414) Enumeration supports custom value
> 9. perf(room): room add hasSeat、isRealPlayer method
> 10. refactor(kit): RandomKit add randomLong method
> 11. refactor(core): Because the FlowContext method name setUserId is ambiguous, the method name is deprecated.
>
>     1. Deprecated FlowContext setUserId method; see bindingUserId.
>     2. Deprecated FlowContext setUserIdAndGetResult method; see bindingUserIdAndGetResult.
> 12. refactor(core): broadcastMe Added Tip: Please bind UserId before using this method, see FlowContext.bindingUserId.
> 13. perf(proto): Generate .proto files in parallel
> 14. refactor(proto): ProtoGenerateFile supports adding multiple proto packages
> 15. refactor(kit): TaskKit supports setting Timer
> 16. refactor(room): Deprecated OperationHandler verify, see processVerify
> 17. refactor(room): Add OperationCode and enhance Operation


------



About **[core]** 

The name of the FlowContext setUserId method is ambiguous. This method is deprecated and replaced by the bindingUserId method.

```java
flowContext.setUserId(userId); // Deprecated
flowContext.bindingUserId(userId); // now
```



About **[kit]** 

TaskKit supports setting Timer

```java
TaskKit.setTimer(new HashedWheelTimer(17, TimeUnit.MILLISECONDS));
```



About **[room]** 

1. Add hasSeat method to room to check whether there are any empty seats in the room.
2. Room add isRealPlayer method.
3. Add isRobot method to Player, and add method to distinguish real players from robot players to Room.
4. Add OperationCode and enhance Operation
5. Add processVerify method to OperationHandler to control whether to execute process method, and deprecate verify method, replaced by processVerify.

When processVerify returns false, process method will not be executed. There is an assertion mechanism in processVerify, and when there is no seat, an error code will be sent to the client to prompt the player.

```java
public final class EnterRoomOperationHandler implements OperationHandler {
    @Override
    public boolean processVerify(PlayerOperationContext context) {
        
        // assert room spaceSize
        Room room = context.getRoom();
        GameCode.roomSpaceSizeNotEnough.assertTrue(room.hasSeat());

        long userId = context.getUserId();
        long score = AccountKit.getScore(userId);
        
        return score > 500;
    }

    @Override
    public void process(PlayerOperationContext context) {
        Room room = context.getRoom();
        ... enterRoom
    }
}
```



Example of combining OperationCode with enumeration

```java
@ProtobufClass
@ProtoFileMerge(fileName = FileMerge.fileName, filePackage = FileMerge.filePackage)
public enum MyOperation implements OperationCode {
    /** quitRoom */
    quitRoom,
    /** inRoom */
    inRoom
    ;

    final int operationCode;

    FairOperation() {
        this.operationCode = OperationCode.getAndIncrementCode();
    }

    @Override
    public int getOperationCode() {
        return operationCode;
    }
}

// config
public void configOperation() {
    RoomService roomService = ...
    OperationFactory factory = roomService.getOperationFactory();

    // mappingUser operation
    factory.mappingUser(MyOperation.inRoom, new InRoomOperationHandler());
    factory.mappingUser(MyOperation.quitRoom, new QuitRoomOperationHandler());
}
```



About **[proto]** 

1. Optimize .proto generation and process file generation in parallel.

2. ProtoGenerateFile supports adding multiple proto packages

Supports adding multiple proto packages to better support modularization

```java
    private static void generateProtoFile() {

        String generateFolder = "/Users/join/gitme/game/MyGames/proto";
        List<String> protoPackageList = List.of("com.iohao.happy.robot"
                                                ,"com.iohao.happy.email");

        var protoGenerateFile = new ProtoGenerateFile()
                // Generate the directory where the .proto file is stored
                .setGenerateFolder(generateFolder)
                // The package name to be scanned
                .addProtoPackage(protoPackageList)
                .addProtoPackage("com.iohao.happy.common.provide.proto");

        // generate .proto 
        protoGenerateFile.generate();
    }
```



3. Enumeration supports custom values, java code and generated .proto

```java
@ProtobufClass
@ProtoFileMerge(fileName = TempProtoFile.fileName, filePackage = TempProtoFile.filePackage)
public enum AnimalTypeEnum implements EnumReadable {
    /** the cat */
    cat(0),
    /** the tiger */
    tiger(10),
    ;

    final int value;

    AnimalTypeEnum(int value) {
        this.value = value;
    }

    @Override
    public int value() {
        return this.value;
    }
}
```

.proto

```protobuf
// TestAnimalTypeEnum
enum AnimalTypeEnum {
  // the cat
  cat = 0;
  // the tiger
  tiger = 10;
}
```


------

**[other updates]**

```xml
<netty.version>4.1.116.Final</netty.version>
```

------



### 2024-12-02 - v21.22

https://github.com/iohao/ioGame/releases/tag/21.22

**Version update summary**

> 1. perf(core): DefaultActionMethodParamParser
> 1. fix(kit): #407 ClassRefInfoKit invokeSetter
> 1. #376 i18n DefaultUserHook
> 1. feat(GenerateCode): #329 Added TypeScript code generation TypeScriptDocumentGenerate, which can generate interactive code for CocosCreator、Vue、Angular.


------



**feat(GenerateCode)**: #329 Added TypeScript code generation TypeScriptDocumentGenerate, which can generate interactive code for CocosCreator、Vue、Angular.



About examples

1. ioGameServerExample: https://github.com/iohao/ioGameExamples/tree/main/SdkExample
2. CocosCreatorExample: https://github.com/iohao/ioGameSdkTsExampleCocos
3. VueExample: https://github.com/iohao/ioGameSdkTsExampleVue
4. HtmlExample: https://github.com/iohao/ioGameSdkTsExampleHtml
5. AngularExample: https://github.com/iohao/ioGameSdkTsExampleAngular

```java
public final class GenerateTest {
    // setting root path
    static String rootPath = "/Users/join/gitme/ioGame-sdk/";

    public static void main(String[] args) {
        // CHINA or US
        Locale.setDefault(Locale.CHINA);

        // Load the business framework of each gameLogicServer
        // 加载游戏逻辑服的业务框架
        yourListLogic().forEach(BrokerClientStartup::createBarSkeleton);

        /*
         * Generate actions, broadcasts, and error codes.
         * cn: 生成 action、广播、错误码
         */
        
         // About generating TypeScript code
//        generateCodeVue();
//        generateCodeAngular();
//        generateCodeHtml();
        generateCocosCreator();

        // Added an enumeration error code class to generate error code related information
        IoGameDocumentHelper.addErrorCodeClass(YourGameCodeEnum.class);
        // Generate document
        IoGameDocumentHelper.generateDocument();
    }

    private static void generateCodeVue() {
        var documentGenerate = new TypeScriptDocumentGenerate();

        // 设置代码生成所存放的路径,如果不做任何设置,将会生成在 target/code 目录中
        // By default, it will be generated in the target/code directory
        String path = rootPath + "ioGameSdkTsExampleVue/src/assets/gen/code";
        documentGenerate.setPath(path);

        // Your .proto path: Set the import path of common_pb in Vue.
        documentGenerate.setProtoImportPath("../common_pb");

        IoGameDocumentHelper.addDocumentGenerate(documentGenerate);
    }

    private static void generateCodeHtml() {
        var documentGenerate = new TypeScriptDocumentGenerate();

        // 设置代码生成所存放的路径,如果不做任何设置,将会生成在 target/code 目录中
        // By default, it will be generated in the target/code directory
        String path = rootPath + "ioGameSdkTsExampleHtml/src/assets/gen/code";
        documentGenerate.setPath(path);

        // Your .proto path: Set the import path of common_pb in Vue.
        documentGenerate.setProtoImportPath("../common_pb");

        IoGameDocumentHelper.addDocumentGenerate(documentGenerate);
    }

    private static void generateCocosCreator() {
        var documentGenerate = new TypeScriptDocumentGenerate();

        // 设置代码生成所存放的路径,如果不做任何设置,将会生成在 target/code 目录中
        // By default, it will be generated in the target/code directory
        String path = rootPath + "ioGameSdkTsExampleCocos/assets/scripts/gen/code";
        documentGenerate.setPath(path);

        // Your .proto path: Set the import path of common_pb in CocosCreator
        documentGenerate.setProtoImportPath("db://assets/scripts/gen/common_pb");

        IoGameDocumentHelper.addDocumentGenerate(documentGenerate);
    }

    private static void generateCodeAngular() {
        var documentGenerate = new TypeScriptDocumentGenerate();

        // 设置代码生成所存放的路径,如果不做任何设置,将会生成在 target/code 目录中
        // By default, it will be generated in the target/code directory
        String path = rootPath + "ioGameSdkTsExampleAngular/src/assets/gen/code";
        documentGenerate.setPath(path);

        // Your .proto path: Set the import path of common_pb in Vue.
        documentGenerate.setProtoImportPath("../common_pb");

        IoGameDocumentHelper.addDocumentGenerate(documentGenerate);
    }
}
```



Advantages of SDK Code Generation
1. Helps client-side developers reduce significant workload by eliminating the need to write a large amount of template code.
2. Clear and semantically precise. The generated interaction code clearly defines parameter types and return types.
3. Ensures parameter type safety and clarity in interface methods, effectively avoiding security risks and reducing basic errors during integration.
4. 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.
5. Helps client-side developers abstract away the interaction with the server, allowing them to focus more on the core business logic.
6. Reduces the cognitive load during integration. The code is simple to use, similar to local method calls.
7. Abandons the traditional protocol-based approach in favor of an interface-method-based integration approach.

------




### 2024-11-15 - v21.20

https://github.com/iohao/ioGame/releases/tag/21.20

**Version update summary**
> 1. feat(GenerateDoc): Add DocumentMethod annotation : Action supports generating documentation method names through annotations.
> 1. BroadcastDebug enhancements.
> 1. feat(GenerateCode): #328 Added C# code generation CsharpDocumentGenerate, which can generate interactive code for Unity and Godot.


------

**feat(GenerateDoc):** Add DocumentMethod annotation : Action supports generating documentation method names through annotations.

By default, the method names in the generated action interaction code use the method names from the Java action. The action can add the `DocumentMethod` annotation to fix the method name, and when generating the integration code, ioGame will prioritize using the value of the `DocumentMethod` annotation.

```java
@ActionController(SdkCmd.cmd)
public final class SdkAction {    
    @ActionMethod(SdkCmd.noReturn)
    @DocumentMethod("noReturnMethod")
    public void noReturn(String name) {
        ... ...
    }
}
```

---

**feat(GenerateCode):** #328 Added C# code generation CsharpDocumentGenerate, which can generate interactive code for Unity and Godot.



About examples

1. see https://github.com/iohao/ioGameExamples/tree/main/SdkExample
2. UnityExample: https://github.com/iohao/ioGameSdkCsharpExampleUnity
3. GodotExample: https://github.com/iohao/ioGameSdkCsharpExampleGodot

```java
public final class GenerateTest {
    // setting root path
    static String rootPath = "/Users/join/gitme/ioGame-sdk/";

    public static void main(String[] args) {
        // CHINA or US
        Locale.setDefault(Locale.CHINA);

        // Load the business framework of each gameLogicServer
        // 加载游戏逻辑服的业务框架
        yourListLogic().forEach(BrokerClientStartup::createBarSkeleton);

        /*
         * Generate actions, broadcasts, and error codes.
         * cn: 生成 action、广播、错误码
         */
        // About generating C# code
        generateCodeCsharpGodot();
        generateCodeCsharpUnity();

        // Added an enumeration error code class to generate error code related information
        IoGameDocumentHelper.addErrorCodeClass(YourGameCodeEnum.class);
        // Generate document
        IoGameDocumentHelper.generateDocument();
    }

    private static void generateCodeCsharpUnity() {
        var documentGenerate = new CsharpDocumentGenerate();
        // 设置代码生成所存放的路径,如果不做任何设置,将会生成在 target/code 目录中
        // By default, it will be generated in the target/code directory
        String path = rootPath + "ioGameSdkCsharpExampleUnity/Assets/Scripts/Gen/Code";
        documentGenerate.setPath(path);

        IoGameDocumentHelper.addDocumentGenerate(documentGenerate);
    }

    private static void generateCodeCsharpGodot() {
        var documentGenerate = new CsharpDocumentGenerate();
        // 设置代码生成所存放的路径,如果不做任何设置,将会生成在 target/code 目录中
        // By default, it will be generated in the target/code directory
        String path = rootPath + "ioGameSdkCsharpExampleGodot/script/gen/code";
        documentGenerate.setPath(path);

        IoGameDocumentHelper.addDocumentGenerate(documentGenerate);
    }
}
```



Advantages of SDK Code Generation
1. Helps client-side developers reduce significant workload by eliminating the need to write a large amount of template code.
2. Clear and semantically precise. The generated interaction code clearly defines parameter types and return types.
3. Ensures parameter type safety and clarity in interface methods, effectively avoiding security risks and reducing basic errors during integration.
4. 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.
5. Helps client-side developers abstract away the interaction with the server, allowing them to focus more on the core business logic.
6. Reduces the cognitive load during integration. The code is simple to use, similar to local method calls.
7. Abandons the traditional protocol-based approach in favor of an interface-method-based integration approach.

------

**[other updates]**

```xml
<protobuf-java.version>3.25.5</protobuf-java.version>
```

---



### 2024-10-28 - v21.19

https://github.com/iohao/ioGame/releases/tag/21.19



**版本更新汇总**

> 1. [core] FlowContext provides the setUserId method to simplify the login operation.
> 2. [broker] Added RingElementSelector load balancing implementation and set it as default to replace RandomElementSelector
> 3. [core] [#386](https://github.com/iohao/ioGame/issues/386) Action supports constructor injection with parameters in Spring
> 4. Simplify the implementation class of ActionParserListener related to ProtoDataCodec. and #386
> 5. perf(i18n): 🐳 [#376](https://github.com/iohao/ioGame/issues/376) cmd check tips
> 6. refactor(external): simplify and improve externalCache


------

**[core]** FlowContext provides the setUserId method to simplify the login operation.
> FlowContext 提供登录方法以简化登录的使用

```java
@ActionController(LoginCmd.cmd)
public class TheLoginAction {
    ... ...
	@ActionMethod(LoginCmd.login)
    public UserInfo loginVerify(LoginVerify loginVerify, FlowContext flowContext) {
        long userId = ...;
        
        // Deprecated
		boolean success = UserIdSettingKit.settingUserId(flowContext, userId);
        // now
        boolean success = flowContext.setUserId(userId);

        return ...;
    }
}
```

---

**[core]** [#386](https://github.com/iohao/ioGame/issues/386) Action supports constructor injection with parameters in Spring
> 在 Spring 中,Action 支持构造函数注入

```java
// Action supports constructor injection in Spring.
@Component
@AllArgsConstructor
@ActionController(PersonCmd.cmd)
public class PersonAction {    
    final PersonService personService;
    ...
}
```

---

refactor(external): simplify and improve externalCache
> 简化与提升游戏对外服缓存

```java
// create externalCache
private static void extractedExternalCache() {
    // Deprecated
    DefaultExternalCmdCache externalCmdCache = new DefaultExternalCmdCache();
    // now
    var externalCmdCache = ExternalCmdCache.of();
}
```

------

**[其他更新]**

```xml
<netty.version>4.1.114.Final</netty.version>
```

------

### 2024-10-09 - v21.18

https://github.com/iohao/ioGame/releases/tag/21.18



**版本更新汇总**

> - [external] [#375](https://github.com/iohao/ioGame/issues/375) Support for lightweight or embedded Linux distributions. 支持轻量级或嵌入式 Linux 发行版。
> - [core] [#376](https://github.com/iohao/ioGame/issues/376) Support i18n, such as logs and internal messages. 框架内的日志、内部消息支持 i18n。


------

**[core]**

 [#376](https://github.com/iohao/ioGame/issues/376) Support i18n, such as logs and internal messages. 框架内的日志、内部消息支持 i18n。

```java
public class DemoApplication {
    public static void main(String[] args) {
        // setting defaultLocale, such as US or CHINA
        Locale.setDefault(Locale.US);
        Locale.setDefault(Locale.CHINA);

        ... start ioGame
    }
}
```

------

**[其他更新]**

```
<scalecube.version>2.6.17</scalecube.version>
```

------



### 2024-09-25 - v21.17

https://github.com/iohao/ioGame/releases/tag/21.17

**版本更新汇总**

> - [core] 简化 TraceIdSupplier 全链路调用日志跟踪默认实现
> - [core] FlowContext 提供用户(玩家)所关联的用户线程执行器信息及虚拟线程执行器信息方法

---

**[core]**

FlowContext 提供用户(玩家)所关联的用户线程执行器信息及虚拟线程执行器信息方法

```java
void testThreadExecutor(FlowContext flowContext) {
    // 获取 - 用户(玩家)所关联的用户线程执行器信息及虚拟线程执行器信息

    // 用户虚拟线程执行器信息
    ThreadExecutor virtualThreadExecutor = flowContext.getVirtualThreadExecutor();
    // 用户线程执行器信息
    ThreadExecutor threadExecutor = flowContext.getThreadExecutor();

    threadExecutor.execute(() -> {
        log.info("execute");
    });

    threadExecutor.executeTry(() -> {
        log.info("executeTry");
    });

    // get Executor
    Executor executor = threadExecutor.executor();
}
```

------



### 2024-09-09 - v21.16

https://github.com/iohao/ioGame/releases/tag/21.16

**版本更新汇总**

> - [kit] [#291](https://github.com/iohao/ioGame/issues/291) 增加轻量可控的延时任务
> - [kit] 细分时间日期相关工具。
> - [Archive] [#363](https://github.com/iohao/ioGame/issues/363)  light-redis-lock 相关模块
> - [Archive] [#364](https://github.com/iohao/ioGame/issues/364) light-timer-task 相关模块
> - [core] 增加同一个 ActionController 相同的 action 方法名只允许存在一个的检测。
> - [core] Banner 增加启动时的错误数量提示。
> - [core] [#365](https://github.com/iohao/ioGame/issues/365) 支持对接文档生成时,可以根据路由访问权限来控制文档的生成

------

**[kit]**

[#291](https://github.com/iohao/ioGame/issues/291) 增加轻量可控的延时任务


 for example 

```java
@Test
public void example() {
    long timeMillis = System.currentTimeMillis();

    DelayTask delayTask = DelayTaskKit.of(() -> {
                long value = System.currentTimeMillis() - timeMillis;
                log.info("1 - 最终 {} ms 后,执行延时任务", value);
            })
            .plusTime(Duration.ofSeconds(1)) // 增加 1 秒的延时  
            .task(); // 启动任务

    delayTask.plusTimeMillis(500); // 增加 0.5 秒的延时
    delayTask.minusTimeMillis(500);// 减少 0.5 秒的延时时间

    // 因为 taskId 相同,所以会覆盖之前的延时任务
    String taskId = delayTask.getTaskId();
    delayTask = DelayTaskKit.of(taskId, () -> {
                long value = System.currentTimeMillis() - timeMillis;
                log.info("2 - 最终 {} ms 后,执行延时任务", value);
            })
            .plusTime(Duration.ofSeconds(1)) // 增加 1 秒的延时
            .task(); // 启动任务

    // 取消延时任务,下面两个方法是等价的
    delayTask.cancel();
    DelayTaskKit.cancel(taskId);

    // 可以通过 taskId 查找该延时任务
    Optional<DelayTask> optionalDelayTask = DelayTaskKit.optional(taskId);
    if (optionalDelayTask.isPresent()) {
        var delayTask = optionalDelayTask.get();
    }

    // 通过 taskId 查找延时任务,存在则执行给定逻辑
    DelayTaskKit.ifPresent(taskId, delayTask -> {
        delayTask.plusTimeMillis(500); // 增加 0.5 秒的延时时间
    });
}
```

------

细分时间日期相关工具。

see com.iohao.game.common.kit.time

------

**[Archive]**

[#363](https://github.com/iohao/ioGame/issues/363)  light-redis-lock 相关模块

将 light-redis-lock、light-redis-lock-spring-boot-starter 模块做归档。在过去的时间里,由于一直没有改动这些模块的相关内容,现决定将不再上传到 maven 库中,以节约公共资源。如果你使用了该模块的相关内容,请指定最后一个版本即可。如

```xml
<!-- https://mvnrepository.com/artifact/com.iohao.game/light-redis-lock -->
<dependency>
    <groupId>com.iohao.game</groupId>
    <artifactId>light-redis-lock</artifactId>
    <version>21.15</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.iohao.game/light-redis-lock-spring-boot-starter -->
<dependency>
    <groupId>com.iohao.game</groupId>
    <artifactId>light-redis-lock-spring-boot-starter</artifactId>
    <version>21.15</version>
</dependency>
```




------

[#364](https://github.com/iohao/ioGame/issues/364) light-timer-task 相关模块

将 light-timer-task 模块做归档。在过去的时间里,由于一直没有改动这些模块的相关内容;同时,也因为框架内置了类似的功能 #291 。现决定将不再上传到 maven 库中,以节约公共资源。如果你使用了该模块的相关内容,请指定最后一个版本即可。如

```xml
<!-- https://mvnrepository.com/artifact/com.iohao.game/light-timer-task -->
<dependency>
    <groupId>com.iohao.game</groupId>
    <artifactId>light-timer-task</artifactId>
    <version>21.15</version>
</dependency>
```



------

**[core]**

[#365](https://github.com/iohao/ioGame/issues/365) 支持对接文档生成时,可以根据路由访问权限来控制文档的生成



生成相关代码的使用及相关文档

- `ExternalGlobalConfig.accessAuthenticationHook`,相关文档路由访问权限控制
- IoGameDocumentHelper,相关文档游戏对接文档生成

for example 

```java
public class MyExternalServer {
    public static void extractedAccess() {
        // https://iohao.github.io/game/docs/external/access_authentication
        var accessAuthenticationHook = ExternalGlobalConfig.accessAuthenticationHook;
        ... 省略部分代码
        // 添加 - 拒绝玩家访问权限的控制
        accessAuthenticationHook.addRejectionCmd(RankCmd.cmd, RankCmd.internalUpdate);
    }
}

public class TestGenerate {
    ... 省略部分代码
    public static void main(String[] args) {
        // 对外服访问权限控制
        MyExternalServer.extractedAccess();
        // (复用)设置文档路由访问权限控制
      IoGameDocumentHelper.setDocumentAccessAuthentication(ExternalGlobalConfig.accessAuthenticationHook::reject);
        
        // ====== 生成对接文档、生成 proto ======
//        generateCsharp();
//        generateTypeScript();
        // 生成文档
        IoGameDocumentHelper.generateDocument();
        // .proto 文件生成
//        generateProtoFile();
    }
}
```



**预览 - 没有做控制前的生成**

```latex
==================== RankAction  ====================
路由: 4 - 1  --- 【listRank】 --- 【RankAction:48】【listRank】
    方法参数: StringValue 排行类型
    方法返回值: ByteValueList<RankUpdate> 玩家排行名次更新
 
路由: 4 - 10  --- 【玩家排行名次更新】 --- 【RankAction:60】【internalUpdate】
    方法参数: RankUpdate 玩家排行名次更新
    方法返回值: void 
```

**预览 - 加入了访问控制后的生成**

我们可以看见,路由为 4-10 的 action 方法没有生成到对接文档中。

```latex
==================== RankAction  ====================
路由: 4 - 1  --- 【listRank】 --- 【RankAction:48】【listRank】
    方法参数: StringValue 排行类型
    方法返回值: ByteValueList<RankUpdate> 玩家排行名次更新
```



提示:除了文档文档的访问权限控制外,还支持 SDK TypeScript、SDK C# ...等客户端代码生成的访问权限控制。




------

**[其他更新]**

```xml
<netty.version>4.1.113.Final</netty.version>
```

------



### 2024-08-26 - v21.15

https://github.com/iohao/ioGame/releases/tag/21.15



**版本更新汇总**

> - [core] [#351](https://github.com/iohao/ioGame/issues/351)  增加 UserProcessor 线程执行器的选择策略扩展
> - [core] [#350](https://github.com/iohao/ioGame/issues/350) 修复请求消息在 Broker 环节乱序的问题
> - [core] [#353](https://github.com/iohao/ioGame/issues/353) 对接文档支持框架内置错误码的生成
> - [core] [#354](https://github.com/iohao/ioGame/issues/354) 日志打印调整
> - [core] [#359](https://github.com/iohao/ioGame/issues/359) [逻辑服-监听] 增加打印其他进程逻辑服的上线与下线信息
> - [core] 优化 ThreadExecutorRegion 相关实现类。
> - [external] UserSession 接口新增 ofRequestMessage 方法,简化玩家在游戏对外服中创建请求对象。

------

**[external]**

UserSession 接口新增 ofRequestMessage 方法,简化玩家在游戏对外服中创建请求对象。 for example

```java
var cmdInfo = CmdInfo.of(1, 1);
RequestMessage request = userSession.ofRequestMessage(cmdInfo);
```

------

**[core]**

[#359](https://github.com/iohao/ioGame/issues/359) [逻辑服-监听] 增加打印其他进程逻辑服的上线与下线信息

```java
public class MyLogicServer extends AbstractBrokerClientStartup {
    ...

    @Override
    public BrokerClientBuilder createBrokerClientBuilder() {
        BrokerClientBuilder builder = BrokerClient.newBuilder();
        ...
        // 添加监听 - 打印其他进程逻辑服的上线与下线信息
        builder.addListener(SimplePrintBrokerClientListener.me());
        return builder;
    }
}
```

------

[#351](https://github.com/iohao/ioGame/issues/351) 增加 UserProcessor 线程执行器的选择策略扩展

> for example,注意事项:当你的 UserProcessor 做了线程执行器的选择策略扩展,需要重写 CustomSerializer 接口的相关方法。

```java
// 为请求消息开启有序的、多线程处理的优化
IoGameGlobalConfig.enableUserProcessorExecutorSelector();
```



------

### 2024-08-08 - v21.14

https://github.com/iohao/ioGame/releases/tag/21.14



**版本更新汇总**

> - [code quality] 提升代码质量,see [ioGame - Qodana Cloud](https://qodana.cloud/organizations/3k6Pm/teams/zxRGm)
> - [javadoc] 增强相关模块的 javadoc :业务框架、压测与模拟客户端请求、领域事件、Room
> - [core]  [#346](https://github.com/iohao/ioGame/issues/346) 业务框架 InOutManager 提供扩展点
> - [core]  [#344](https://github.com/iohao/ioGame/issues/344) 登录时,如果 FlowContext 存在 userId 就不请求游戏对外服
> - [broker] fixed [#342](https://github.com/iohao/ioGame/issues/342)  非集群环境下,Broker 断开重启后,逻辑服没有将其重新加入到 BrokerClientManager 中所引发的 NPE。

------

**[core]**

 [#346](https://github.com/iohao/ioGame/issues/346) **业务框架 InOutManager 提供扩展点**

在构建器中配置 InOutManager 策略,框架内置了两个实现类,分别是

1. ofAbcAbc :in ABC,out ABC 的顺序,即编排时的顺序。
2. ofPipeline:in ABC,out CBA 的顺序,类似的 netty Pipeline 。(默认策略,如果不做任何设置,将使用该策略)



for example 在构建器中配置 InOutManager 策略

```java
public void config() {
    BarSkeletonBuilder builder = ...;
    builder.setInOutManager(InOutManager.ofAbcAbc());
    builder.setInOutManager(InOutManager.ofPipeline());
}
```



------



### 2024-07-24 - v21.13

https://github.com/iohao/ioGame/releases/tag/21.13



**版本更新汇总**

- [external]  [#334](https://github.com/iohao/ioGame/issues/334) 顶号操作 bug,有概率触发并发问题
- [core]  FlowContext 新增 createRequestCollectExternalMessage 方法
- [javadoc] 源码 javadoc 增强

------



**[core]**

FlowContext 新增 createRequestCollectExternalMessage 方法,request 与游戏对外服交互。

```java
... ... 省略部分代码
@ActionMethod(ExternalBizRegionCmd.listOnlineUserAll)
public List<Long> listOnlineUserAll(FlowContext flowContext) {

    // 创建 RequestCollectExternalMessage
    var request = flowContext
            .createRequestCollectExternalMessage(MyExternalBizCode.onlineUser);

    // 访问多个【游戏对外服】
    var collectExternalMessage = flowContext
            .invokeExternalModuleCollectMessage(request);

    return listUserId(collectExternalMessage);
}
```

------



**[其他更新]**

```xml
<netty.version>4.1.112.Final</netty.version>
<lombok.version>1.18.34</lombok.version>
```

------



### 2024-07-08 - v21.12

https://github.com/iohao/ioGame/releases/tag/21.12



**版本更新汇总**

- [light-game-room]  [#326](https://github.com/iohao/ioGame/issues/326) GameFlowContext getRoom、getPlayer 方法返回值改成泛型
- [对接文档]  [#330](https://github.com/iohao/ioGame/issues/330) 增强,支持对接文档生成与扩展,包括文本文档生成、联调代码生成 ...等



当前版本,为之后生成联调代码做了充分的准备

------



**[light-game-room]**

[#326](https://github.com/iohao/ioGame/issues/326) GameFlowContext getRoom、getPlayer 方法返回值改成泛型

```java
GameFlowContext gameFlowContext = ...;
// FightRoomEntity 是自定义的 Room 对象

// Room、Player 在使用时,不需要强制转换了
FightRoomEntity room =  gameFlowContext.getRoom();
FightPlayerEntity player = gameFlowContext.getPlayer();
```

------



**[对接文档]** 

[#330](https://github.com/iohao/ioGame/issues/330) 增强,支持对接文档生成与扩展,包括文本文档生成、联调代码生成 ...等。开发者做更多个性化的扩展



在该版本中,我们已经新做了对接文档相关模块;该版本功能更加的强大,使用上也更加的简洁。新版本的对接文档模块,除了能提供文本文档的生成外,还能支持生成与客户端联调的代码、并且是可扩展的。通常,客户端联调代码有:

1. 支持生成 C# 客户端的联调代码,通常用在 Unity、Godot 客户端
2. 支持生成 TypeScript 客户端的联调代码,通常用在 cocos、laya 客户端



```java
public static void main(String[] args) {
    // 添加枚举错误码 class,用于生成错误码相关信息
    IoGameDocumentHelper.addErrorCodeClass(GameCode.class);

    // 添加文档生成器,文本文档
    IoGameDocumentHelper.addDocumentGenerate(new TextDocumentGenerate());
    // 添加文档生成器,Ts 联调代码生成
    IoGameDocumentHelper.addDocumentGenerate(new TypeScriptDocumentGenerate());
    // 生成文档
    IoGameDocumentHelper.generateDocument();
}
```

上述代码

- 添加了错误码的生成
- 添加了文本文档的生成
- 添加了 Ts 客户端联调代码的生成(包括 action、广播、错误码...相关代码的生成), [SDK TypeScript 客户端代码生成;方便 CocosCeator、或其他支持 TypeScript 的客户端对接。 #329](https://github.com/iohao/ioGame/issues/329)



addDocumentGenerate 是可扩展的,这将意味着开发者可以扩展出 C#、GodotScript、Js ...等不同客户端的联调代码。默认,我们提供了一个文本文档,即 TextDocumentGenerate,如果默认的实现满足不了当下需求,开发者也可以定制个性化的文档,如 json 格式的。






**新增 DocumentGenerate 接口**

开发者可利用该接口进行定制个性化的对接文档,如代码生成 ...等。

```java
/**
 * 对接文档生成接口,可扩展不同的实现
 */
public interface DocumentGenerate {
    /**
     * 生成文档
     *
     * @param ioGameDocument ioGameDocument
     */
    void generate(IoGameDocument ioGameDocument);
}

/**
 * 文档相关信息,如 action 相关、广播相关、错误码相关。
 */
@Getter
public final class IoGameDocument {
    /** 已经解析好的广播文档 */
    List<BroadcastDocument> broadcastDocumentList;
    /** 已经解析好的错误码文档 */
    List<ErrorCodeDocument> errorCodeDocumentList;
    /** 已经解析好的 action 文档 */
    List<ActionDoc> actionDocList;
}
```



开发者可以通过实现 DocumentGenerate 接口来扩展不同的文档生成,开发者可以扩展此接口来定制更多个性化的扩展,如

- html 版本的文档。
- json 版本的文档。
- 其他语言的联调文档 ...等。



```java
// 使用示例
private static void test() {
    var documentGenerate = new YourDocumentGenerate();
    IoGameDocumentHelper.addDocumentGenerate(documentGenerate);
}
```



------

其他:废弃旧版本对接文档相关类 DocActionSend、DocActionSends、ActionDocs、ActionSendDoc、ActionSendDocs、ActionSendDocsRegion、BarSkeletonDoc、BroadcastDoc、BroadcastDocBuilder、ErrorCodeDocs、ErrorCodeDocsRegion。

------

21.10 及之前版本的使用示例(对接文档)

```java
public static void main(String[] args) {
    ... 省略部分代码

    new NettyRunOne()
            ... ...
            .startup();

    // 生成对接文档
    BarSkeletonDoc.me().buildDoc();
}
```

------



### 2024-06-21 - v21.10

(问题版本)

https://github.com/iohao/ioGame/releases/tag/21.10

------

**版本更新汇总**

- [core] [#315](https://github.com/iohao/ioGame/issues/315) ResponseMessage 增加协议碎片便捷获取,简化跨服调用时的使用
- [core] ActionCommand 增加 containAnnotation、getAnnotation 方法,简化获取 action 相关注解信息的使用。
- [kit] [动态属性]  增加 ifNull 方法,如果动态属性值为 null,则执行给定的操作,否则不执行任何操作。执行给定操作后将得到一个返回值,该返回值会设置到动态属性中。
- [kit]  TimeKit 增加 nowLocalDate 方法,可减少 LocalDate 对象的创建;优化 currentTimeMillis 方法的时间更新策略。同时,优化 nowLocalDate、currentTimeMillis 方法,不使用时将不会占用相关资源。
- [EventBus]  分布式事件总线增加 EventBusRunner 接口。EventBus 接口化,方便开发者自定义扩展。fix 订阅者使用自身所关联的 EventBus 处理相关事件。

------

**[core]** [315](https://github.com/iohao/ioGame/issues/315) ResponseMessage 增加协议碎片便捷获取,简化跨服调用时的使用

框架具备协议碎片特性。某些业务中,我们需要跨服访问其他游戏逻辑服,以获取某些业务数据;一些简单的数据,我们可以通过协议碎片来返回,从而避免定义过多的协议。



现为 ResponseMessage 增加协议碎片支持,简化跨服调用时的使用,新增的方法如下

```java
public void test() {
    ResponseMessage responseMessage = ...;

    // object
    responseMessage.getValue(Student.class);
    List<Student> listValue = responseMessage.listValue(Student.class);

    // int
    int intValue = responseMessage.getInt();
    List<Integer> listInt = responseMessage.listInt();

    // long
    long longValue = responseMessage.getLong();
    List<Long> listLong = responseMessage.listLong();

    // String
    String stringValue = responseMessage.getString();
    List<String> listString = responseMessage.listString();

    // boolean
    boolean boolValue = responseMessage.getBoolean();
    List<Boolean> listBoolean = responseMessage.listBoolean();
}
```



示例说明

- HomeAction 是 【Home 游戏逻辑服】提供的 action
- UserAction 是 【User 游戏逻辑服】提供的 action

两个逻辑服的交互如下,UserAction 使用跨服方式调用了【Home 游戏逻辑服】的几个方法,并通过 responseMessage 的协议碎片支持,简化跨服调用时的使用。



示例中演示了 string、string list、object list 的简化使用(协议碎片获取时的简化使用)。

```java
@ProtobufClass
@FieldDefaults(level = AccessLevel.PUBLIC)
public class Student {
    String name;
}

// home 游戏逻辑服提供的 action
public class HomeAction {
    @ActionMethod(HomeCmd.name)
    public String name() {
        return "a";
    }

    @ActionMethod(HomeCmd.listName)
    public List<String> listName() {
        return List.of("a", "b");
    }

    @ActionMethod(HomeCmd.listStudent)
    public List<Student> listStudent() {
        Student student = new Student();
        student.name = "a";

        Student student2 = new Student();
        student2.name = "b";

        return List.of(student, student2);
    }
}

@ActionController(UserCmd.cmd)
public class UserAction {
    @ActionMethod(UserCmd.userSleep)
    public void userSleep(FlowContext flowContext) {

        flowContext.invokeModuleMessageAsync(HomeCmd.of(HomeCmd.name), responseMessage -> {
            String name = responseMessage.getString();
            log.info("{}", name);
        });

        flowContext.invokeModuleMessageAsync(HomeCmd.of(HomeCmd.listName), responseMessage -> {
            var listName = responseMessage.listString();
            log.info("{}", listName);
        });

        flowContext.invokeModuleMessageAsync(HomeCmd.of(HomeCmd.listStudent), responseMessage -> {
            List<Student> studentList = responseMessage.listValue(Student.class);
            log.info("{}", studentList);
        });
    }
}
```



------

**[core]** ActionCommand 增加 containAnnotation、getAnnotation 方法,简化获取 action 相关注解信息的使用。

```java
ActionCommand actionCommand = flowContext.getActionCommand();

bool contain = actionCommand.containAnnotation(DisableDebugInout.class);
var annotation = actionCommand.getAnnotation(DisableDebugInout.class);
```



------

**[EventBus] 分布式事件总线**

1. [增强扩展] 将抽象类 AbstractEventBusRunner 标记为过时的,由接口 EventBusRunner 代替。
2. [增强扩展] 分布式事件总线 EventBus 接口化,方便开发者自定义扩展。增加[总线相关的 javadoc](https://iohao.github.io/javadoc/com/iohao/game/action/skeleton/eventbus/package-summary.html)。
3. [fix] 订阅者使用自身所关联的 EventBus 处理相关事件。



关于 fix 订阅者使用自身所关联的 EventBus 处理相关事件,在此之前可能引发 bug 的场景如下

1. 【游戏逻辑服 A】 发布事件。
2. 【游戏逻辑服 B】 订阅者接收事件并处理,在处理过程中又调用了【游戏逻辑服 A】 某个 action 方法。



该业务场景,会在多服单进程下会引发调用超时,但在多服多进程下则不会超时。



------

**[kit] TimeKit**

增强 TimeKit 增加 nowLocalDate 方法,可减少 LocalDate 对象的创建;

优化 currentTimeMillis 方法的时间更新策略。

优化 nowLocalDate、currentTimeMillis 不使用时将不会占用相关资源。

```csharp
@Test
public void test() {
    long millis = TimeKit.currentTimeMillis();
    Assert.assertTrue(millis > 0);

    LocalDate localDate = TimeKit.nowLocalDate();
    Assert.assertTrue(localDate.isEqual(LocalDate.now()));
}
```



------

**[kit] 动态属性**

[动态属性] 增加 ifNull 方法,如果动态属性值为 null,则执行给定的操作,否则不执行任何操作。执行给定操作后将得到一个返回值,该返回值会设置到动态属性中。

```csharp
public class AttrOptionDynamicTest {
    // 动态属性 key
    AttrOption<AttrCat> attrCatOption = AttrOption.valueOf("AttrCat");

    @Test
    public void ifNull() {
        var myAttrOptions = new MyAttrOptions();
        Assert.assertNull(myAttrOptions.option(attrCatOption));

        // 如果 catAttrOption 属性为 null,则创建 AttrCat 对象,并赋值到属性中
        myAttrOptions.ifNull(attrCatOption, AttrCat::new);
        Assert.assertNotNull(myAttrOptions.option(attrCatOption));
    }

    private static class AttrCat {
        String name;
    }

    @Getter
    private static class MyAttrOptions implements AttrOptionDynamic {
        final AttrOptions options = new AttrOptions();
    }
}
```



------

**[其他 - 相关库升级]**

<netty.version>4.1.111.Final</netty.version>

<jctools-core.version>4.0.5</jctools-core.version>

<jprotobuf.version>2.4.23</jprotobuf.version>

---



### 2024-06-03 - v21.9

(问题版本)

https://github.com/iohao/ioGame/releases/tag/21.9


---

**版本更新汇总**

- [core]  [#294](https://github.com/iohao/ioGame/issues/294) 增加范围内的广播接口 RangeBroadcaster,业务参数支持基础类型的简化使用
- [core-对接文档]  [#293](https://github.com/iohao/ioGame/issues/293) 广播文档构建器支持对参数的单独描述
- [light-game-room]   [#297](https://github.com/iohao/ioGame/issues/297) 模拟系统创建房间,RoomCreateContext 的使用
- [light-game-room]   [#298](https://github.com/iohao/ioGame/issues/298) 模拟系统创建房间,GameFlowContext 的使用
- [core]   [#301](https://github.com/iohao/ioGame/issues/301) FlowContext 更新元信息后,需要立即生效(跨服调用时)
- [内置 kit] 开放 TaskListener 接口
- 为 SimpleRoom aggregationContext 属性提供默认值,移除 RoomCreateContext 接口的 getAggregationContext 方法,以免产生误导。


---



**[light-game-room]**

为 SimpleRoom aggregationContext 属性提供默认值

<br>

[#297](https://github.com/iohao/ioGame/issues/297),模拟系统创建房间,RoomCreateContext 的使用

>  移除 RoomCreateContext 接口的 getAggregationContext 方法,以免产生误导。
>
> RoomCreateContext 增加默认重载

```java
RoomCreateContext.of(); // 无房间创建者,通常表示系统创建
RoomCreateContext.of(userId); // 房间创建者为 userId
```

<br>

 [#298](https://github.com/iohao/ioGame/issues/298) 模拟系统创建房间,GameFlowContext 的使用

```java
public void test() {
    Room room = ...;
    GameFlowContext context = GameFlowContext.of(room);
    ... 省略部分代码
}
```

---

**[core]**

[#294](https://github.com/iohao/ioGame/issues/294) 增加范围内的广播接口 RangeBroadcaster,业务参数支持基础类型的简化使用

```java
public void testRangeBroadcaster(FlowContext flowContext) {
    // ------------ object ------------
    // 广播 object
    DemoBroadcastMessage message = new DemoBroadcastMessage();
    message.msg = "helloBroadcast --- 1";
    RangeBroadcaster.of(flowContext)
            .setResponseMessage(cmdInfo, message);
    // 广播 object list
    List<DemoBroadcastMessage> messageList = List.of(message);
    RangeBroadcaster.of(flowContext)
            .setResponseMessageList(cmdInfo, messageList);

    // ------------ int ------------
    // 广播 int
    int intValue = 1;
    RangeBroadcaster.of(flowContext)
            .setResponseMessage(cmdInfo, intValue);
    // 广播 int list
    List<Integer> intValueList = List.of(1, 2);
    RangeBroadcaster.of(flowContext)
            .setResponseMessageIntList(cmdInfo, intValueList);

    // ------------ long ------------
    // 广播 long
    long longValue = 1L;
    RangeBroadcaster.of(flowContext)
            .setResponseMessage(cmdInfo, longValue);
    // 广播 long list
    List<Long> longValueList = List.of(1L, 2L);
    RangeBroadcaster.of(flowContext)
            .setResponseMessageLongList(cmdInfo, longValueList);

    // ------------ String ------------
    // 广播 String
    String stringValue = "1";
    RangeBroadcaster.of(flowContext)
            .setResponseMessage(cmdInfo, stringValue);
    // 广播 String list
    List<String> stringValueList = List.of("1L", "2L");
    RangeBroadcaster.of(flowContext)
            .setResponseMessageStringList(cmdInfo, stringValueList);
            
    // ------------ boolean ------------
    // 广播 boolean
    boolean boolValue = true;
    RangeBroadcaster.of(flowContext)
            .setResponseMessage(cmdInfo, boolValue);
    // 广播 boolean list
    List<Boolean> boolValueList = List.of(true, false);
    RangeBroadcaster.of(flowContext)
            .setResponseMessageBoolList(cmdInfo, boolValueList);
}
```

<br>

[#301](https://github.com/iohao/ioGame/issues/301) FlowContext 更新元信息后,需要立即生效(跨服调用时)

> 在此之前,更新元信息后,并不会将元信息同步到 FlowContext 中,只会将元信息同步到游戏对外服中;所以在更新元信息后,紧接着执行跨服调用是不能获取新的元信息内容的。
>
> 当前 issues 会对这部分做增强,也就是在更新元信息后,会将元信息同步到 FlowContext 中;这样,在后续的跨服调用中也能获取到最新的元信息。

```java
void test1(FlowContext flowContext) {
    // 获取元信息
    MyAttachment attachment = flowContext.getAttachment(MyAttachment.class);
    attachment.nickname = "渔民小镇";

    // [同步]更新 - 将元信息同步到玩家所在的游戏对外服中
    flowContext.updateAttachment(attachment);

    // 跨服请求
    CmdInfo helloCmdInfo = CmdInfo.of(1, 1);
    flowContext.invokeModuleMessage(helloCmdInfo);
}

@ActionController(1)
public class DemoFightAction {
    @ActionMethod(1)
    void hello(FlowContext flowContext) {
        // 可以得到最新的元信息
        MyAttachment attachment = flowContext.getAttachment(MyAttachment.class);
        log.info("{}", attachment.nickname);
    }
}
```

<br>

 [#293](https://github.com/iohao/ioGame/issues/293) 广播文档构建器支持对参数的单独描述

```java
  private void extractedDco(BarSkeletonBuilder builder) {
      // UserCmd
      builder.addBroadcastDoc(BroadcastDoc.newBuilder(UserCmd.of(UserCmd.enterSquare))
              .setDataClass(SquarePlayer.class)
              .setDescription("新玩家加入房间,给房间内的其他玩家广播")
      ).addBroadcastDoc(BroadcastDoc.newBuilder(UserCmd.of(UserCmd.offline))
              .setDataClass(LongValue.class, "userId")
              .setDescription("有玩家下线了")
      );
}
```

>  下面是生成后的对接文档预览

```text
==================== FightHallAction 大厅(类似地图) ====================
 
路由: 1 - 2  --- 【进入大厅】 --- 【FightHallAction:94】【enterSquare】
    方法参数: EnterSquare enterSquare 进入大厅
    方法返回值: ByteValueList<SquarePlayer> 所有玩家
    广播推送: SquarePlayer ,(新玩家加入房间,给房间内的其他玩家广播)
 

路由: 1 - 5  --- 【玩家下线】 --- 【FightHallAction:154】【offline】
    方法返回值: void 
    广播推送: LongValue userId,(有玩家下线了)

```



**[内置 kit]** 

开放 TaskListener 接口,TaskListener 是 TaskKit 相关的任务监听接口。



TaskListener 任务监听回调,使用场景有:一次性延时任务、任务调度、轻量可控的延时任务、轻量的定时入库辅助功能 ...等其他扩展场景。这些使用场景都有一个共同特点,即监听回调。接口提供了 4 个方法,如下

1. CommonTaskListener.onUpdate(),监听回调
2. CommonTaskListener.triggerUpdate(),是否触发 CommonTaskListener.onUpdate() 监听回调方法
3. CommonTaskListener.onException(Throwable) ,异常回调。在执行 CommonTaskListener.triggerUpdate() 和 CommonTaskListener.onUpdate() 方法时,如果触发了异常,异常将被该方法捕获。
4. CommonTaskListener.getExecutor(),指定执行器来执行上述方法,目的是不占用业务线程。




---



### 2024-05-19 - v21.8

https://github.com/iohao/ioGame/releases/tag/21.8


---

**版本更新汇总**

- [light-game-room]  [#278](https://github.com/iohao/ioGame/issues/278) 桌游类、房间类游戏的扩展模块,简化与规范化房间管理相关的、开始游戏流程相关的、玩法操作相关的相关扩展
- [core]  [#290](https://github.com/iohao/ioGame/issues/290) 新增广播文档构建器,简化生成广播对接文档
- [示例集合整理] 将 SimpleExample、SpringBootExample、ioGameWeb2Game、fxglSimpleGame FXGL + netty合并成一个示例项目。

---



**[core]**  

[#290](https://github.com/iohao/ioGame/issues/290) 新增广播文档构建器,简化生成广播对接文档

下面是使用示例

```java
public class MyLogicServer extends AbstractBrokerClientStartup {
    @Override
    public BarSkeleton createBarSkeleton() {
        // 业务框架构建器
        BarSkeletonBuilder builder = ...
        
        // 错误码、广播、推送对接文档生成
        extractedDco(builder);

        return builder.build();
    }
    
    private void extractedDco(BarSkeletonBuilder builder) {
        // 错误码
        Arrays.stream(GameCode.values()).forEach(builder::addMsgExceptionInfo);

        // UserCmd
        builder.addBroadcastDoc(BroadcastDoc.newBuilder(UserCmd.of(UserCmd.enterSquare))
                .setDataClass(SquarePlayer.class)
                .setDescription("新玩家加入房间,给房间内的其他玩家广播")
        ).addBroadcastDoc(BroadcastDoc.newBuilder(UserCmd.of(UserCmd.move))
                .setDataClass(SquarePlayerMove.class)
                .setDescription("其他玩家的移动")
        ).addBroadcastDoc(BroadcastDoc.newBuilder(UserCmd.of(UserCmd.offline))
                .setDataClass(LongValue.class)
                .setDescription("有玩家下线了。userId")
        );

        // room
        builder.addBroadcastDoc(BroadcastDoc.newBuilder(RoomCmd.of(RoomCmd.roomUpdateBroadcast))
                .setDataClass(FightRoomNotice.class)
                .setDescription("房间更新通知")
        ).addBroadcastDoc(BroadcastDoc.newBuilder(RoomCmd.of(RoomCmd.playerEnterRoomBroadcast))
                .setDataClass(FightPlayer.class)
                .setDescription("有新玩家加入房间")
        ).addBroadcastDoc(BroadcastDoc.newBuilder(RoomCmd.of(RoomCmd.enterRoom))
                .setDataClass(FightEnterRoom.class)
                .setDescription("玩家自己进入房间")
        ).addBroadcastDoc(BroadcastDoc.newBuilder(RoomCmd.of(RoomCmd.dissolveRoomBroadcast))
                .setDescription("解散房间")
        ).addBroadcastDoc(BroadcastDoc.newBuilder(RoomCmd.of(RoomCmd.quitRoom))
                .setDataClass(LongValue.class)
                .setDescription("有玩家退出房间了。userId")
        ).addBroadcastDoc(BroadcastDoc.newBuilder(RoomCmd.of(RoomCmd.ready))
                .setDataClass(PlayerReady.class)
                .setDescription("有玩家准备或取消准备了")
        ).addBroadcastDoc(BroadcastDoc.newBuilder(RoomCmd.of(RoomCmd.nextRoundBroadcast))
                .setDataClass(IntValue.class)
                .setDescription("对局开始,通知玩家开始选择。round 当前对局数")
        ).addBroadcastDoc(BroadcastDoc.newBuilder(RoomCmd.of(RoomCmd.operationBroadcast))
                .setDataClass(LongValue.class)
                .setDescription("通知其他玩家,有玩家做了选择。userId")
        ).addBroadcastDoc(BroadcastDoc.newBuilder(RoomCmd.of(RoomCmd.littleSettleBroadcast))
                .setDataClassList(FightRoundPlayerScore.class)
                .setDescription("广播玩家对局分数")
        ).addBroadcastDoc(BroadcastDoc.newBuilder(RoomCmd.of(RoomCmd.gameOverBroadcast))
                .setDescription("游戏结束")
        );
    }
}
```

下面是生成后的对接文档预览

```text

==================== FightHallAction 大厅(类似地图) ====================
路由: 1 - 1  --- 【登录】 --- 【FightHallAction:67】【loginVerify】
    方法参数: LoginVerify loginVerify 登录验证
    方法返回值: UserInfo 玩家信息
 
路由: 1 - 2  --- 【进入大厅】 --- 【FightHallAction:95】【enterSquare】
    方法参数: EnterSquare enterSquare 进入大厅
    方法返回值: ByteValueList<SquarePlayer> 所有玩家
    广播推送: SquarePlayer 新玩家加入房间,给房间内的其他玩家广播
 
路由: 1 - 4  --- 【玩家移动】 --- 【FightHallAction:131】【move】
    方法参数: SquarePlayerMove squarePlayerMove 玩家移动
    方法返回值: void 
    广播推送: SquarePlayerMove 其他玩家的移动
 
路由: 1 - 5  --- 【玩家下线】 --- 【FightHallAction:155】【offline】
    方法返回值: void 
    广播推送: LongValue 有玩家下线了。userId
 

==================== FightRoomAction  ====================
路由: 2 - 1  --- 【玩家创建新房间】 --- 【FightRoomAction:63】【createRoom】
    方法返回值: void 
 
路由: 2 - 2  --- 【玩家进入房间】 --- 【FightRoomAction:96】【enterRoom】
    方法参数: LongValue roomId      房间号
    方法返回值: void 房间信息
    广播推送: FightEnterRoom 玩家自己进入房间
 
路由: 2 - 3  --- 【玩家退出房间】 --- 【FightRoomAction:120】【quitRoom】
    方法返回值: void 
    广播推送: LongValue 有玩家退出房间了。userId
 
路由: 2 - 4  --- 【玩家准备】 --- 【FightRoomAction:146】【ready】
    方法参数: BoolValue ready       true 表示准备,false 则是取消准备
    方法返回值: void 
    广播推送: PlayerReady 有玩家准备或取消准备了
 
路由: 2 - 5  --- 【房间列表】 --- 【FightRoomAction:222】【listRoom】
    方法返回值: ByteValueList<FightRoomNotice> 房间列表
 
路由: 2 - 6  --- 【玩家在游戏中的操作】 --- 【FightRoomAction:191】【operation】
    方法参数: FightOperationCommand command     玩家操作数据
    方法返回值: void 
 
路由: 2 - 7  --- 【开始游戏】 --- 【FightRoomAction:162】【startGame】
    方法返回值: void 
 

==================== 其它广播推送 ====================
路由: 2 - 51  --- 广播推送: FightRoomNotice (房间更新通知)
路由: 2 - 50  --- 广播推送: FightPlayer (有新玩家加入房间)
路由: 2 - 52  --- 广播推送: IntValue (对局开始,通知玩家开始选择。round 当前对局数)
路由: 2 - 53  --- 广播推送: LongValue (通知其他玩家,有玩家做了选择。userId)
路由: 2 - 56  --- 广播推送: none (解散房间)
路由: 2 - 54  --- 广播推送: ByteValueList<FightRoundPlayerScore> (广播玩家对局分数)
路由: 2 - 55  --- 广播推送: none (游戏结束)
==================== 错误码 ====================
 -1008 : 绑定的游戏逻辑服不存在 
 -1007 : 强制玩家下线 
 -1006 : 数据不存在 
 -1005 : class 不存在 
 -1004 : 请先登录 
 -1003 : 心跳超时相关 
 -1002 : 路由错误 
 -1001 : 参数验错误 
 -1000 : 系统其它错误 
 1 : 玩家在房间里 
 3 : 房间不存在 
 4 : 非法操作 
 6 : 开始游戏需要的最小人数不足 
 7 : 请等待其他玩家准备 
 8 : 房间空间不足,人数已满 

```

---



**[light-game-room]**


[#278](https://github.com/iohao/ioGame/issues/278) 桌游类、房间类游戏的扩展模块,简化与规范化房间管理相关的、开始游戏流程相关的、玩法操作相关的相关扩展



light-game-room 房间,是 ioGame 提供的一个轻量小部件 - 可按需选择的模块。

> **light-game-room + 领域事件 + 内置 Kit  = 轻松搞定桌游类游戏**



该模块是桌游类、房间类游戏的解决方案。比较适合桌游类、房间类的游戏基础搭建,基于该模型可以做一些如,炉石传说、三国杀、斗地主、麻将 ...等类似的桌游。或者说只要是房间类的游戏,该模型都适用。比如,CS、泡泡堂、飞行棋、坦克大战 ...等。



如果你计划做一些桌游类的游戏,那么推荐你基于该模块做扩展。该模块遵循面向对象的设计原则,没有强耦合,可扩展性强。且帮助开发者屏蔽了很多重复性的工作,并可为项目中的功能模块结构、开发流程等进行清晰的组织定义,减少了后续的项目维护成本。



**主要解决的问题与职责**

桌游、房间类的游戏在功能职责上可以分为 3 大类,分别是

1. **房间管理相关的**
   1. 管理着所有的房间、查询房间列表、房间的添加、房间的删除、房间与玩家之间的关联、房间查找(通过 roomId 查找、通过 userId 查找)。
1. **开始游戏流程相关的**
   1. 通常桌游、房间类的游戏都有一些固定的流程,如创建房间、玩家进入房间、玩家退出房间、解散房间、玩家准备、开始游戏 ...等。
   2. 开始游戏时,需要做开始前的验证,如房间内的玩家是否符足够 ...等,当一切符合业务时,才是真正的开始游戏。
1. **玩法操作相关的**
   1. 游戏开始后,由于不同游戏之间的具体操作是不相同的。如坦克的射击,炉石的战前选牌、出牌,麻将的吃、碰、杠、过、胡,回合制游戏的普攻、防御、技能 ...等。
   2. 由于玩法操作的不同,所以我们的玩法操作需要是可扩展的,并用于处理具体的玩法操作。同时这种扩展方式更符合单一职责,使得我们后续的扩展与维护成本更低。

以上功能职责(房间管理相关、流程相关、玩法操作相关)属于相对通用的功能。如果每款游戏都重复的做这些工作,除了枯燥之外,还将浪费巨大的人力成本。

而当前模块则能很好的帮助开发者屏蔽这些重复性的工作,并可为项目中的功能模块结构、开发流程等进行清晰的组织定义,减少了后续的项目维护成本。更重要的是有相关文档,将来当你的团队有新进成员时,可以快速的上手。

---



**room 实战简介**


文档中,我们基于该 room 模块做一个实战示例,该示例整体比较简单,多名玩家在房间里猜拳(石头、剪刀、布)得分。实战示例包括了前后端,前端使用 [FXGL](https://github.com/almasB/FXGL) 引擎,这样开发者在学习时,只需 JDK 环境就可以了,而不需要安装更多的环境。启动游戏后玩家会将加入大厅(类似地图),多名玩家相互可见,并且玩家可以在大厅内移动。



---



[示例集合整理] 




| github                                                     | gitee                                                     |
| ---------------------------------------------------------- | --------------------------------------------------------- |
| [ioGame 示例集合](https://github.com/iohao/ioGameExamples) | [ioGame 示例集合](https://gitee.com/iohao/ioGameExamples) |

---



### 2024-05-11 - v21.7

https://github.com/iohao/ioGame/releases/tag/21.7



**版本更新汇总**

1. [core]  [#112](https://github.com/iohao/ioGame/issues/112) protobuf 协议类添加检测,通过 action 构建时的监听器实现
2. [core]  [#272](https://github.com/iohao/ioGame/issues/272) 业务框架 - 提供 action 构建时的监听回调
3. [core]  [#274](https://github.com/iohao/ioGame/issues/274) 优化、提速 - 预生成 jprotobuf 协议类的代理,通过 action 构建时的监听器实现
4. [broker] fix [#277](https://github.com/iohao/ioGame/issues/277) 、[#280](https://github.com/iohao/ioGame/issues/280) 偶现 BrokerClientType 为空
5. [external]  [#271](https://github.com/iohao/ioGame/issues/271) 游戏对外服 - 内置与可选 handler - log 相关的打印(触发异常、断开连接时)
6. [room] 简化命名:  AbstractPlayer --> Player、AbstractRoom --> Room
7. 其他优化:预先生成游戏对外服统一协议的代理类及内置的协议碎片相关代理类,优化 action 参数解析



**[external]**

[#271](https://github.com/iohao/ioGame/issues/271) 游戏对外服 - 内置与可选 handler - log 相关的打印(触发异常、断开连接时)




**[core]**

[#272](https://github.com/iohao/ioGame/issues/272) 业务框架 - 提供 action 构建时的监听回调

开发者可以利用 ActionParserListener 接口来观察 action 构建过程,或者做一些额外的扩展。



扩展示例参考

```java
// 简单打印
public final class YourActionParserListener implements ActionParserListener {
    @Override
    public void onActionCommand(ActionParserContext context) {
        ActionCommand actionCommand = context.getActionCommand();
        log.info(actionCommand);
    }
}

void test() {
    BarSkeletonBuilder builder = ...;
    builder.addActionParserListener(new YourActionParserListener());
}
```



[#112](https://github.com/iohao/ioGame/issues/112) protobuf 协议类添加检测,通过 action 构建时的监听器实现

如果当前使用的编解码器为 ProtoDataCodec 时,当 action 的参数或返回值的类没有添加 ProtobufClass 注解时(通常是忘记添加),给予一些警告提示。

```java
// 该协议类没有添加 ProtobufClass 注解
class Bird {
    public String name;
}

@ActionController(1)
public class MyAction {
    @ActionMethod(1)
    public Bird testObject() {
        return new Bird();
    }
}
======== 注意,协议类没有添加 ProtobufClass 注解 ========
class com.iohao.game.action.skeleton.core.action.Bird
```



[#274](https://github.com/iohao/ioGame/issues/274) 优化、提速 - 预生成 jprotobuf 协议类的代理,通过 action 构建时的监听器实现

如果当前使用的编解码器为 ProtoDataCodec 时,会在启动时就预先生成好 jprotobuf 协议类对应的代理类(用于 .proto 相关的 编码、解码),而不必等到用时在创建该代理类。从而达到整体优化提速的效果。

 

在此之前,在没做其他设置的情况下,首次访问 action 时,如果参数使用的 jprotobuf 协议类,那么在解码该参数时,会通过 `ProtobufProxy.create` 来创建对应的代理类(类似 .proto 相关的 编码、解码)。之后再访问时,才会从缓存中取到对应的代理类。

 

该优化默认开启,开发者可以不需要使用与配置跟 jprotobuf-precompile-plugin 插件相关的了。



已经预先生成的代理类有

- 游戏对外服统一协议 ExternalMessage
- 所有开发者定义的 action 的方法参数及返回值
- 解决协议碎片相关,如 int、int list、String、String list、long、long list、ByteValueList ...等



**[room]**
简化命名:  AbstractPlayer --> Player、AbstractRoom --> Room



**其他优化**

优化 action 参数解析

---



### 2024-04-23 - v21.6

https://github.com/iohao/ioGame/releases/tag/21.6



**版本更新汇总**

1. [#264](https://github.com/iohao/ioGame/issues/264) 新增属性值变更监听特性
2. 模拟客户端新增与服务器断开连接的方法。模拟客户端新增是否活跃的状态属性。
3. [#265](https://github.com/iohao/ioGame/issues/265) 从游戏对外服中获取玩家相关数据 - 模拟玩家请求。
4. 任务相关:TaskListener 接口增加异常回调方法,用于接收异常信息;当 triggerUpdate 或 onUpdate 方法抛出异常时,将会传递到该回调方法中。
5. [#266](https://github.com/iohao/ioGame/issues/266) 新增 RangeBroadcast 范围内的广播功能,这个范围指的是,可指定某些用户进行广播。
6. AbstractRoom 增加 ifPlayerExist、ifPlayerNotExist 方法。

------

**属性监听特性**

[#264](https://github.com/iohao/ioGame/issues/264) 新增属性值变更监听特性


属性可添加监听器,当某些属性值的发生变化时,触发监听器。



**使用场景举例**

比如玩家的血量低于一定值时,需要触发无敌状态;此时,我们就可以监听玩家的血量,并在该属性上添加一个对应的监听器来观察血量的变化,当达到预期值时就触发对应的业务。

 

类似的使用场景还有很多,这里就不过多的举例了。属性监听的特点在于属性变化后会触发监听器。



**属性监听特点**

- 可为属性添加监听器,用于观察属性值的变化。
- 属性可以添加多个监听器。
- 属性的监听器可以移除。



**框架已经内置了几个属性实现类,分别是:**

- IntegerProperty
- LongProperty
- StringProperty
- BooleanProperty
- ObjectProperty

------

for example - 添加监听器

BooleanProperty

当 BooleanProperty 对象的值发生改变时,触发监听器。

```java
var property = new BooleanProperty();
// 添加一个监听器。
property.addListener((observable, oldValue, newValue) -> {
   log.info("oldValue:{}, newValue:{}", oldValue, newValue);
});

property.get(); // value is false
property.set(true); // 值变更时,将会触发监听器
property.get(); // value is true
```



IntegerProperty

当 IntegerProperty 对象的值发生改变时,触发监听器。

```java
var property = new IntegerProperty();
// add listener monitor property object
property.addListener((observable, oldValue, newValue) -> {
   log.info("oldValue:{}, newValue:{}", oldValue, newValue);
});

property.get(); // value is 0
property.set(22); // When the value changes,listeners are triggered
property.get(); // value is 22

property.increment(); // value is 23. will trigger listeners
```

------

for example - 移除监听器

下面这个示例,我们将 property 初始值设置为 10,随后添加了一个监听器;当监听器观察到新值为 9 时,就从 observable 中移除自己(这个自己指的是监听器本身),而 observable 则是 IntegerProperty。

```java
@Test
public void remove1() {
    IntegerProperty property = new IntegerProperty(10);
    // 添加一个监听器
    property.addListener(new PropertyChangeListener<>() {
        @Override
        public void changed(PropertyValueObservable<? extends Number> observable, Number oldValue, Number newValue) {
            log.info("1 - newValue : {}", newValue);

            if (newValue.intValue() == 9) {
                // 移除当前监听器
                observable.removeListener(this);
            }
        }
    });

    property.decrement(); // value 是 9,并触发监听器
    property.decrement(); // value 是 8,由于监听器已经移除,所以不会触发任何事件。
}
```



下面的示例中,我们定义了一个监听器类 OnePropertyChangeListener 并实现了 PropertyChangeListener 监听器接口。示例中,我们通过 OnePropertyChangeListener 对象的引用来移除监听器。

```java
@Test
public void remove2() {
    // 监听器
    OnePropertyChangeListener onePropertyChangeListener = new OnePropertyChangeListener();
    
    // 属性
    IntegerProperty property = new IntegerProperty();
    // 添加监听器
    property.addListener(onePropertyChangeListener);

    property.increment(); // value == 1,并触发监听器
    property.removeListener(onePropertyChangeListener); // 移除监听器
    property.increment(); // value == 2,由于监听器已经移除,所以不会触发任何事件。
}

// 自定义的监听器
class OnePropertyChangeListener implements PropertyChangeListener<Number> {
    @Override
    public void changed(PropertyValueObservable<? extends Number> observable, Number oldValue, Number newValue) {
        log.info("oldValue:{}, newValue:{}, observable:{}", oldValue, newValue, observable);
    }
}
```

------

**属性监听 - 小结**

属性监听在使用上是简单的,如果你的业务中**有关于属性变化后需要触发某些事件的**,可以考虑引用该特性。框架为 int、long、boolean、Object、String 等基础类型提供了对应的属性监听。



属性监听特性支持添加多个监听器,支持移除监听器。

------



**模拟客户端相关**

- 模拟客户端新增与服务器断开连接的方法。
- 模拟客户端新增是否活跃的状态属性。

```java
ClientUser clientUser = ...;
// 是否活跃,true 表示玩家活跃
clientUser.isActive();
// 关闭模拟客户端连接
clientUser.getClientUserChannel().closeChannel();
```

------



**访问游戏对外服与扩展相关**


RequestCollectExternalMessage 增加 userId 字段。



[#265](https://github.com/iohao/ioGame/issues/265) 模拟玩家请求时 - 从游戏对外服中获取在线玩家相关数据

新增  UserHeadMetadataExternalBizRegion,从用户(玩家)所在游戏对外服中获取用户自身的数据,如用户所绑定的游戏逻辑服、元信息 ...等

```java
@Slf4j
@RestController
@RequestMapping("other")
public class OtherController {
    static final AtomicLong msgId = GameManagerController.msgId;
    /** 为了方便测试,这里指定一个 userId 来模拟玩家 */
    static final long userId = GameManagerController.userId;

    @GetMapping("/notice")
    public String notice() {
        log.info("other notice");
        // 使用协议碎片特性 https://iohao.github.io/game/docs/manual/protocol_fragment
        StringValue data = StringValue.of("other GM web msg " + msgId.incrementAndGet());
        // 模拟请求 : 路由 - 业务数据
        RequestMessage requestMessage = BarMessageKit.createRequestMessage(ExchangeCmd.of(ExchangeCmd.notice), data);

        // 设置需要模拟的玩家
        HeadMetadata headMetadata = requestMessage.getHeadMetadata();
        headMetadata.setUserId(userId);

        // 从游戏对外服中获取一些用户(玩家的)自身的数据,如元信息、所绑定的游戏逻辑服 ...等
        Optional<HeadMetadata> headMetadataOptional = ExternalCommunicationKit.employHeadMetadata(requestMessage);

        if (headMetadataOptional.isPresent()) {
            // 发起模拟请求
            extractedRequestLogic(requestMessage);

            // 打印从游戏对外服获取的元信息
            byte[] attachmentData = headMetadata.getAttachmentData();
            ExchangeAttachment attachment = DataCodecKit.decode(attachmentData, ExchangeAttachment.class);
            return "other notice 玩家的元信息: %s - %s".formatted(attachment, msgId.get());
        } else {
            return "other notice 玩家 %s 不在线,无法获取玩家的元信息 - %s".formatted(userId, msgId.get());
        }
    }

    private void extractedRequestLogic(RequestMessage requestMessage) {
        // 向逻辑服发送请求,该模拟请求具备了玩家的元信息。
        BrokerClient brokerClient = MyKit.brokerClient;
        InvokeModuleContext invokeModuleContext = brokerClient.getInvokeModuleContext();
        invokeModuleContext.invokeModuleVoidMessage(requestMessage);
    }
}
```

------



**任务工具相关**

TaskListener 接口增加异常回调方法 `void onException(Throwable e)`,用于接收异常信息;当 triggerUpdate 或 onUpdate 方法抛出异常时,将会传递到该回调方法中。

```java
@Test
public void testException() throws InterruptedException {
    AtomicBoolean hasEx = new AtomicBoolean(false);
    TaskKit.runOnce(new OnceTaskListener() {
        @Override
        public void onUpdate() {
            // 模拟一个业务异常
            throw new RuntimeException("hello exception");
        }

        @Override
        public void onException(Throwable e) {
            hasEx.set(true);
            // 触发异常后,将来到这里
            log.error(e.getMessage(), e);
        }
    }, 10, TimeUnit.MILLISECONDS);

    TimeUnit.MILLISECONDS.sleep(200);
    Assert.assertTrue(hasEx.get()); // true
}
```

------



**业务框架相关 - [common-core]**

[#266](https://github.com/iohao/ioGame/issues/266) 新增 RangeBroadcast 范围内的广播功能,这个范围指的是,可指定某些用户进行广播。



在执行广播前,开发者可以自定义业务逻辑,如

- 添加一些需要广播的用户
- 删除一些不需要接收广播的用户
- 可通过重写 logic、trick 方法来做一些额外扩展

```java
// example - 1
new RangeBroadcast(flowContext)
        // 需要广播的数据
        .setResponseMessage(responseMessage)
        // 添加需要接收广播的用户
        .addUserId(1)
        .addUserId(2)
        .addUserId(List.of(3L, 4L, 5L))
        // 排除一些用户,被排除的用户将不会接收到广播
        .removeUserId(1)
        // 执行广播
        .execute();

// example - 2
new RangeBroadcast(flowContext)
        // 需要广播的数据
        .setResponseMessage(cmdInfo, playerReady)
        // 添加需要接收广播的用户
        .addUserId(1)
        // 执行广播
        .execute();
```

------

**[light-game-room] 房间模块**

- 移除 AbstractRoom broadcast 系列方法,开发者可使用 RoomBroadcastFlowContext 接口实现旧的兼容。
- 移除 AbstractRoom createSend 方法,开发者可使用 ofRangeBroadcast 系列来代替。AbstractRoom 新增 RoomBroadcastEnhance,实现房间内的广播增强,该系列在语义上更清晰。



```java
final RoomService roomService = ...;

@ActionMethod(RoomCmd.ready)
public void ready(boolean ready, FlowContext flowContext) {
    long userId = flowContext.getUserId();
    // 得到玩家所在的房间
    AbstractRoom room = this.roomService.getRoomByUserId(userId);
    
    // 准备
    PlayerReady playerReady = new PlayerReady();
    playerReady.userId = userId;
    playerReady.ready = ready;
  
    // 通知房间内的所有玩家,有玩家准备或取消准备了
    room.ofRangeBroadcast(flowContext)
            // 响应数据(路由、业务数据)
            .setResponseMessage(flowContext.getCmdInfo(), playerReady)
            .execute();
}

// 准备或取消准备
@ProtobufClass
@FieldDefaults(level = AccessLevel.PUBLIC)
public class PlayerReady {
    /** 当前操作的玩家 userId */
    long userId;
    /** true 表示准备 */
    boolean ready;
}
```

------



**AbstractRoom 增加 ifPlayerExist、ifPlayerNotExist 方法。**

**ifPlayerExist 方法**

如果玩家在房间内,就执行给定的操作,否则不执行任何操作。

```java
RoomService roomService = ...;
AbstractRoom room = ...;
// 如果玩家不在房间内,就创建一个玩家,并让玩家加入房间
room.ifPlayerNotExist(userId, () -> {
    // 玩家加入房间
    FightPlayerEntity newPlayer = new FightPlayerEntity();
    newPlayer.setId(userId);
    
    this.roomService.addPlayer(room, newPlayer);
});
```



**ifPlayerNotExist 方法**

如果玩家不在房间内,就执行给定的操作,否则不执行任何操作。

```java
AbstractRoom room = ...;
// 有新玩家加入房间,通知其他玩家
room.ifPlayerExist(userId, (FightPlayerEntity playerEntity) -> {
    FightPlayer fightPlayer = FightMapstruct.ME.convert(playerEntity);
    room.ofRangeBroadcast(flowContext)
            .setResponseMessage(RoomCmd.of(RoomCmd.playerEnterRoomBroadcast), fightPlayer)
            // 排除不需要通知的玩家(当前 userId 是自己)
            .removeUserId(userId)
            .execute();
});
```

---



### 2024-04-16 - v21.5

https://github.com/iohao/ioGame/releases/tag/21.5



1.  增强 ClassScanner 类 
2.  优化模拟客户端 
3.  [#258](about:blank) 文档生成,兼容 gradle 编译路径 
4.  enhance jprotobuf,临时解决打包后不能在 linux java21 环境运行的问题,see [java21,springBoot3.2 打 jar 后使用异常 · Issue #211 · jhunters/jprotobuf (github.com)](https://github.com/jhunters/jprotobuf/issues/211) 
5.  生成 .proto 时,在最后打印文件路径 

1. [#255](https://github.com/iohao/ioGame/issues/255) 关于 Proto 生成排除属性问题

```java
/**
 * 动物
 */
@ProtobufClass
@FieldDefaults(level = AccessLevel.PUBLIC)
public class Animal {
    /** id */
    int id;
    /** 动物类型 - 枚举测试 */
    AnimalType animalType;
  	/** 年龄 - 忽略的属性*/
    @Ignore
    String age;
}
```



生成后的 .proto

```protobuf
// 动物
message Animal {
  // id
  int32 id = 1;
  // 动物类型 - 枚举测试
  AnimalType animalType = 2;
}
```

---



### 2024-03-28 - v21.4

https://github.com/iohao/ioGame/releases/tag/21.4




[ #253](https://github.com/iohao/ioGame/issues/253)

> CreateRoomInfo.createUserId int --> long



ExecutorRegion

> 1. 优化默认创建策略
> 2. 优化 ExecutorRegionKit,SimpleThreadExecutorRegion 默认使用全局单例,减少对象的创建。



proto 文档生成时,默认指定为 StandardCharsets.UTF_8

>  javaProjectBuilder.setEncoding(StandardCharsets.UTF_8.name());



玩家下线时,使用自身所关联的线程处理。

>  SocketUserSessions removeUserSession

```java
public void removeUserSession(SocketUserSession userSession) {

    if (Objects.isNull(userSession)) {
        return;
    }

    long userId = userSession.getUserId();
    ExecutorRegionKit.getSimpleThreadExecutor(userId)
            .executeTry(() -> internalRemoveUserSession(userSession));
}
```

---



### 2024-03-11 - v21.3

https://github.com/game-town/ioGame/releases/tag/21.3



[#250](https://github.com/game-town/ioGame/issues/250) 游戏对外服 - 自定义编解码 - WebSocketMicroBootstrapFlow




重写 WebSocketMicroBootstrapFlow createExternalCodec 方法,用于创建开发者自定义的编解码,其他配置则使用 pipelineCodec 中的默认配置。

```java
DefaultExternalServerBuilder builder = ...;

builder.setting().setMicroBootstrapFlow(new WebSocketMicroBootstrapFlow() {
    @Override
    protected MessageToMessageCodec<BinaryWebSocketFrame, BarMessage> createExternalCodec() {
        // 开发者自定义的编解码实现类。
        return new YourWsExternalCodec();
    }
});
```



以下展示的是 WebSocketMicroBootstrapFlow pipelineCodec 相关代码

```java
public class WebSocketMicroBootstrapFlow extends SocketMicroBootstrapFlow {
    ... 省略部分代码
    @Override
    public void pipelineCodec(PipelineContext context) {
        // 添加 http 相关 handler
        this.httpHandler(context);

        // 建立连接前的验证 handler
        this.verifyHandler(context);

        // 添加 websocket 相关 handler
        this.websocketHandler(context);

        // websocket 编解码
        var externalCodec = this.createExternalCodec();
        context.addLast("codec", externalCodec);
    }

    @Override
    protected MessageToMessageCodec<BinaryWebSocketFrame, BarMessage> createExternalCodec() {
        // createExternalCodec 相当于一个钩子方法。
        return new WebSocketExternalCodec();
    }
};
```



[#249](https://github.com/game-town/ioGame/issues/249)
将集群启动顺序放到 Broker(游戏网关)之后。

集群增减和逻辑服 Connect 增减使用同一线程处理。

IoGameGlobalConfig brokerClusterLog 集群相关日志不开启。

---



### 2024-02-22 - v21.2

修复版本号显示错误问题(该版本没有功能上的更新与修改,不升级也不影响)



###  2024-02-21 - v21.1

https://github.com/game-town/ioGame/releases/tag/21.1



ioGame21 首发计划

| 功能支持                                                                                                                                                                                           | 完成 | 描述        | issu                                                   |
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----|-----------|--------------------------------------------------------|
| 游戏对外服开放自定义协议                                                                                                                                                                                   | ✅  | 功能增强      | [#213](https://github.com/game-town/ioGame/issues/213) |
| 游戏对外服缓存                                                                                                                                                                                        | ✅  | 功能增强、性能提升 | [#76](https://github.com/game-town/ioGame/issues/76)   |
| FlowContext 增加通信能力,提供同步、异步、异步回调的便捷使用                                                                                                                                                           | ✅  | 功能增强      | [#235](https://github.com/game-town/ioGame/issues/235) |
| 虚拟线程支持;  各逻辑服之间通信阻塞部分,改为使用虚拟线程,避免阻塞业务线程                                                                                                                                                        | ✅  | 功能增强、性能提升 |                                                        |
| 默认不使用 bolt 线程池,减少上下文切换。  ioGame17:netty --> bolt 线程池 --> ioGame 线程池。  ioGame21: 1. netty --> ioGame 线程池。 2. 部分业务将直接在 netty 线程中消费业务。 | ✅  | 性能提升      |                                                        |
| 全链路调用日志跟踪;日志增强 traceId                                                                                                                                                                         | ✅  | 功能增强      | [#230](https://github.com/game-town/ioGame/issues/230) |
| 移除过期代码                                                                                                                                                                                         | ✅  | 整理        | [#237](https://github.com/game-town/ioGame/issues/239) |
| 分布式事件总线可以代替 redis pub sub 、 MQ ,并且具备全链路调用日志跟踪,这点是中间件产品做不到的。                                                                                                                                    | ✅  | 功能增强      | [#228](https://github.com/game-town/ioGame/issues/228) |
| 日志库使用新版本 slf4j 2.0                                                                                                                                                                             | ✅  |           |                                                        |
| 心跳响应前的回调                                                                                                                                                                                       | ✅  | 功能增强      | [#234](https://github.com/game-town/ioGame/issues/234) |
| FlowContext 增加更新、获取元信息的便捷使用                                                                                                                                                                    | ✅  | 功能增强      | [#236](https://github.com/game-town/ioGame/issues/236) |



### 2024

#### ioGame21 首发内容简介

在 ioGame21 中,该版本做了数百项优化及史诗级增强。

- 文档方面
- 线程管理域方面的开放与统一、减少线程池上下文切换
- FlowContext 得到了**史诗级**的增强。
- 新增通讯方式 - 分布式事件总线
- 游戏对外服方面增强
- 全链路调用日志跟踪
- 各逻辑服之间通信阻塞部分,改为使用虚拟线程, 避免阻塞业务线程,从而使得框架的吞吐量得到了巨大的提升。



##### 游戏对外服相关

[#76](https://github.com/game-town/ioGame/issues/76) 游戏对外服缓存 




游戏对外服缓存,可以将一些热点的业务数据缓存在游戏对外服中,玩家每次访问相关路由时,会直接从游戏对外服的内存中取数据。这样可以避免反复请求游戏逻辑服,从而达到性能的超级提升;

```java
private static void extractedExternalCache() {
    // 框架内置的缓存实现类
    DefaultExternalCmdCache externalCmdCache = new DefaultExternalCmdCache();
    // 添加到配置中
    ExternalGlobalConfig.externalCmdCache = externalCmdCache;
    // 配置缓存 3-1
    externalCmdCache.addCmd(3, 1);
}
```



[#213](https://github.com/game-town/ioGame/issues/213) 游戏对外服开放自定义协议 


开发者可自定义游戏对外服协议,用于代替框架默认的 ExternalMessage 公共对外协议。



[#234](https://github.com/game-town/ioGame/issues/234) 心跳响应前的回调 


在部分场景下,在响应心跳前可添加当前时间,使得客户端与服务器时间同步。

```java
@Slf4j
public class DemoIdleHook implements SocketIdleHook {
    ... ... 省略部分代码
    volatile byte[] timeBytes;

    public DemoIdleHook() {
        updateTime();
        // 每秒更新当前时间
        TaskKit.runInterval(this::updateTime, 1, TimeUnit.SECONDS);
    }

    private void updateTime() {
        LongValue data = LongValue.of(TimeKit.currentTimeMillis());
        // 避免重复序列化,这里提前序列化好时间数据
        timeBytes = DataCodecKit.encode(data);
    }

    @Override
    public void pongBefore(BarMessage idleMessage) {
        // 把当前时间戳给到心跳接收端
        idleMessage.setData(timeBytes);
    }
}
```



##### FlowContext - 跨服通信

[#235](https://github.com/game-town/ioGame/issues/235) FlowContext 增加通信能力,提供同步、异步、异步回调的便捷使用 


```java
// 跨服请求 - 同步、异步回调演示
void invokeModuleMessage() {
    // 路由、请求参数
    ResponseMessage responseMessage = flowContext.invokeModuleMessage(cmdInfo, yourData);
    RoomNumMsg roomNumMsg = responseMessage.getData(RoomNumMsg.class);
    log.info("同步调用 : {}", roomNumMsg.roomCount);

    // --- 此回调写法,具备全链路调用日志跟踪 ---
    // 路由、请求参数、回调
    flowContext.invokeModuleMessageAsync(cmdInfo, yourData, responseMessage -> {
        RoomNumMsg roomNumMsg = responseMessage.getData(RoomNumMsg.class);
        log.info("异步回调 : {}", roomNumMsg.roomCount);
    });
}

// 广播
public void broadcast(FlowContext flowContext) {
    // 全服广播 - 路由、业务数据
    flowContext.broadcast(cmdInfo, yourData);

    // 广播消息给单个用户 - 路由、业务数据、userId
    long userId = 100;
    flowContext.broadcast(cmdInfo, yourData, userId);

    // 广播消息给指定用户列表 - 路由、业务数据、userIdList
    List<Long> userIdList = new ArrayList<>();
    userIdList.add(100L);
    userIdList.add(200L);
    flowContext.broadcast(cmdInfo, yourData, userIdList);

    // 给自己发送消息 - 路由、业务数据
    flowContext.broadcastMe(cmdInfo, yourData);

    // 给自己发送消息 - 业务数据
    // 路由则使用当前 action 的路由。
    flowContext.broadcastMe(yourData);
}
```



[#236](https://github.com/game-town/ioGame/issues/236) FlowContext 增加更新、获取元信息的便捷使用 


```java
void test(MyFlowContext flowContext) {
    // 获取元信息
    MyAttachment attachment = flowContext.getAttachment();
    attachment.nickname = "渔民小镇";

    // [同步]更新 - 将元信息同步到玩家所在的游戏对外服中
    flowContext.updateAttachment();

    // [异步无阻塞]更新 - 将元信息同步到玩家所在的游戏对外服中
	flowContext.updateAttachmentAsync();
}

public class MyFlowContext extends FlowContext {
    MyAttachment attachment;

    @Override
    @SuppressWarnings("unchecked")
    public MyAttachment getAttachment() {
        if (Objects.isNull(attachment)) {
            this.attachment = this.getAttachment(MyAttachment.class);
        }

        return this.attachment;
    }
}
```



##### 线程相关 - 无锁高并发




虚拟线程支持,各逻辑服之间通信阻塞部分使用虚拟线程来处理,避免阻塞业务线程。



默认不使用 bolt 线程池,减少上下文切换。ioGame21 业务消费的线程相关内容如下:

1. netty --> ioGame 线程池。
2. 部分业务将直接在 netty 线程中消费业务。



在 ioGame21 中,框架内置了 3 个线程执行器管理域,分别是

1. UserThreadExecutorRegion ,用户线程执行器管理域。
2. UserVirtualThreadExecutorRegion ,用户虚拟线程执行器管理域。
3. SimpleThreadExecutorRegion ,简单的线程执行器管理域。



**从工具类中得到与用户(玩家)所关联的线程执行器**

```java
@Test
public void userThreadExecutor() {
    long userId = 1;

    ThreadExecutor userThreadExecutor = ExecutorRegionKit.getUserThreadExecutor(userId);

    userThreadExecutor.execute(() -> {
        // print 1
        log.info("userThreadExecutor : 1");
    });

    userThreadExecutor.execute(() -> {
        // print 2
        log.info("userThreadExecutor : 2");
    });
}

@Test
public void getUserVirtualThreadExecutor() {
    long userId = 1;

    ThreadExecutor userVirtualThreadExecutor = ExecutorRegionKit.getUserVirtualThreadExecutor(userId);

    userVirtualThreadExecutor.execute(() -> {
        // print 1
        log.info("userVirtualThreadExecutor : 1");
    });

    userVirtualThreadExecutor.execute(() -> {
        // print 2
        log.info("userVirtualThreadExecutor : 2");
    });
}

@Test
public void getSimpleThreadExecutor() {
    long userId = 1;

    ThreadExecutor simpleThreadExecutor = ExecutorRegionKit.getSimpleThreadExecutor(userId);

    simpleThreadExecutor.execute(() -> {
        // print 1
        log.info("simpleThreadExecutor : 1");
    });

    simpleThreadExecutor.execute(() -> {
        // print 2
        log.info("simpleThreadExecutor : 2");
    });
}
```



**从 FlowContext 中得到与用户(玩家)所关联的线程执行器**

```java
void executor() {
    // 该方法具备全链路调用日志跟踪
    flowContext.execute(() -> {
        log.info("用户线程执行器");
    });

    // 正常提交任务到用户线程执行器中
    // getExecutor() 用户线程执行器
    flowContext.getExecutor().execute(() -> {
        log.info("用户线程执行器");
    });
}

void executeVirtual() {
    // 该方法具备全链路调用日志跟踪
    flowContext.executeVirtual(() -> {
        log.info("用户虚拟线程执行器");
    });

    // 正常提交任务到用户虚拟线程执行器中
    // getVirtualExecutor() 用户虚拟线程执行器
    flowContext.getVirtualExecutor().execute(() -> {
        log.info("用户虚拟线程执行器");
    });

    // 示例演示 - 更新元信息(可以使用虚拟线程执行完成一些耗时的操作)
    flowContext.executeVirtual(() -> {
        log.info("用户虚拟线程执行器");
        
        // 更新元信息
        flowContext.updateAttachment();
        
        // ... ... 其他业务逻辑
    });
}
```



##### 日志相关

日志库使用新版本 slf4j 2.x



[#230](https://github.com/game-town/ioGame/issues/230) 支持全链路调用日志跟踪;




**开启 traceId 特性**

该配置需要在游戏对外服中设置,因为游戏对外服是玩家请求的入口。

```java
// true 表示开启 traceId 特性
IoGameGlobalConfig.openTraceId = true;
```



将全链路调用日志跟踪插件 TraceIdInOut 添加到业务框架中,表示该游戏逻辑服需要支持全链路调用日志跟踪。如果游戏逻辑服没有添加该插件的,表示不需要记录日志跟踪。

```java
BarSkeletonBuilder builder = ...;
// traceId
TraceIdInOut traceIdInOut = new TraceIdInOut();
builder.addInOut(traceIdInOut);
```



##### 分布式事件总线 - 跨服解耦

[#228](https://github.com/game-town/ioGame/issues/228) 分布式事件总线是新增的通讯方式,可以代替 redis pub sub 、 MQ ...等中间件产品;分布式事件总线具备全链路调用日志跟踪,这点是中间件产品所做不到的。



**ioGame 分布式事件总线,特点**

- 使用方式与 Guava EventBus 类似
- 具备**全链路调用日志跟踪**。(这点是中间件产品做不到的)
- 支持跨多个机器、多个进程通信
- 支持与多种不同类型的多个逻辑服通信
- 纯 javaSE,不依赖其他服务,耦合性低。(不需要安装任何中间件)
- 事件源和事件监听器之间通过事件进行通信,从而实现了模块之间的解耦
- 当没有任何远程订阅者时,**将不会触发网络请求**。(这点是中间件产品做不到的)



下面两个订阅者是分别在**不同的进程中**的,当事件发布后,这两个订阅者都能接收到 UserLoginEventMessage 消息。

```java
@ActionController(UserCmd.cmd)
public class UserAction {
	... 省略部分代码
    @ActionMethod(UserCmd.fireEvent)
    public String fireEventUser(FlowContext flowContext) {
        long userId = flowContext.getUserId();

        log.info("fire : {} ", userId);
        
        // 事件源
        var userLoginEventMessage = new UserLoginEventMessage(userId);
        // 发布事件
        flowContext.fire(userLoginEventMessage);

        return "fireEventUser";
    }
}

// 该订阅者在 【UserLogicStartup 逻辑服】进程中,与 UserAction 同在一个进程
@EventBusSubscriber
public class UserEventBusSubscriber {
    @EventSubscribe(ExecutorSelector.userExecutor)
    public void userLogin(UserLoginEventMessage message) {
        log.info("event - 玩家[{}]登录,记录登录时间", message.getUserId());
    }
}

// 该订阅者在 【EmailLogicStartup 逻辑服】进程中。
@EventBusSubscriber
public class EmailEventBusSubscriber {
    @EventSubscribe
    public void mail(UserLoginEventMessage message) {
        long userId = message.getUserId();
        log.info("event - 玩家[{}]登录,发放 email 奖励", userId);
    }
}
```



##### 小结

在 ioGame21 中,该版本做了数百项优化及史诗级增强。

- 在线文档方面
- 线程管理域方面的开放与统一、减少线程池上下文切换
- FlowContext 增强
- 新增通讯方式 - 分布式事件总线
- 游戏对外服方面增强
- 全链路调用日志跟踪



#### ioGame17 迁移到 ioGame21

文档:[17 迁移到 ioGame21](https://www.yuque.com/iohao/game/hcgsfobyoph9r74r) 



#### ioGame17 - 更新日志

see online [ioGame17 - 更新日志](https://iohao.github.io/game/docs/archive/version_log_17) 

================================================
FILE: common/README.md
================================================
```text
.
├── common-core 业务框架
└── common-kit 工具相关

```

================================================
FILE: common/common-core/README.md
================================================
## 业务框架

如果说  [sofa-bolt](https://www.sofastack.tech/projects/sofa-bolt/overview/) 是为了让 Java 程序员能将更多的精力放在基于网络通信的业务逻辑实现上。而业务框架正是解决业务逻辑如何方便实现这一问题上。业务框架是游戏框架的一部分,职责是简化程序员的业务逻辑实现,业务框架使程序员能够快速的开始编写游戏业务。



业务框架对于每个 action (即业务的处理类) 都是通过 [asm](https://www.oschina.net/p/reflectasm) 与 Singleton、Flyweight 、Command 等设计模式结合,对 action 的获取上通过 array 来得到,是一种近原生的方式。



业务框架平均每秒可以执行 1152 万次业务逻辑。



================================================
FILE: common/common-core/pom.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>ioGame</artifactId>
        <groupId>com.iohao.game</groupId>
        <version>21.34</version>
        <relativePath>../../pom.xml</relativePath>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>common-core</artifactId>
    <name>common-core for ioGame</name>

    <dependencies>
        <dependency>
            <groupId>com.iohao.game</groupId>
            <artifactId>common-kit</artifactId>
            <version>${project.parent.version}</version>
        </dependency>

        <dependency>
            <groupId>com.iohao.game</groupId>
            <artifactId>common-validation</artifactId>
            <version>${project.parent.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 -->
        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2</artifactId>
            <version>${fastjson.version}</version>
            <scope>provided</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.fusesource.jansi/jansi -->
        <dependency>
            <groupId>org.fusesource.jansi</groupId>
            <artifactId>jansi</artifactId>
            <version>${jansi.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.thoughtworks.qdox/qdox -->
        <dependency>
            <groupId>com.thoughtworks.qdox</groupId>
            <artifactId>qdox</artifactId>
            <version>${qdox.version}</version>
        </dependency>

        <dependency>
            <groupId>jakarta.validation</groupId>
            <artifactId>jakarta.validation-api</artifactId>
            <version>${jakarta.validation-api.version}</version>
            <scope>provided</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.iohao.game</groupId>
            <artifactId>light-jprotobuf</artifactId>
            <version>${project.parent.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
        <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>${hibernate-validator.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.glassfish/jakarta.el -->
        <!-- EL实现。在 Java SE 环境中,您必须将实现作为依赖项添加到 POM 文件中 -->
        <dependency>
            <groupId>org.glassfish</groupId>
            <artifactId>jakarta.el</artifactId>
            <version>${jakarta.el.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>


</project>

================================================
FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/IoGameVersion.java
================================================
/*
 * ioGame
 * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.
 * # iohao.com . 渔民小镇
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
package com.iohao.game.action.skeleton;

/**
 * @author 渔民小镇
 * @date 2022-12-23
 */
public final class IoGameVersion {
    public static final String VERSION;

    static {
        String internalVersion = "<version>21.34</version>";

        VERSION = internalVersion
                .replace("<version>", "")
                .replace("</version>", "")
        ;
    }
}


================================================
FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/annotation/ActionController.java
================================================
/*
 * ioGame
 * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.
 * # iohao.com . 渔民小镇
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
package com.iohao.game.action.skeleton.annotation;

import java.lang.annotation.*;

/**
 * 控制器注解, 一般用作类的路由
 * <pre>
 *     类 cmd 注解
 *     一般用作类的路由
 * </pre>
 *
 * @author 渔民小镇
 * @date 2021-12-12
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ActionController {
    /**
     * @return 路由
     */
    int value();
}

================================================
FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/annotation/ActionMethod.java
================================================
/*
 * ioGame
 * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.
 * # iohao.com . 渔民小镇
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
package com.iohao.game.action.skeleton.annotation;

import java.lang.annotation.*;

/**
 * 方法注解, 一般用作类方法的路由
 * <pre>
 *     方法 subCmd 注解
 *     一般用作类方法的路由
 * </pre>
 *
 * @author 渔民小镇
 * @date 2021-12-12
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ActionMethod {
    /**
     * subCmd int
     *
     * @return subCmd
     */
    int value();
}


================================================
FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/annotation/DocActionSend.java
================================================
/*
 * ioGame
 * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.
 * # iohao.com . 渔民小镇
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
package com.iohao.game.action.skeleton.annotation;

import com.iohao.game.action.skeleton.core.doc.BroadcastDocument;

import java.lang.annotation.*;

/**
 * 文档相关
 * <pre>
 *     仅用于推送文档生成
 * </pre>
 *
 * @author 渔民小镇
 * @date 2022-01-31
 * @deprecated 请使用 {@link BroadcastDocument} 代替
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(DocActionSends.class)
@Deprecated
public @interface DocActionSend {
    /** 主路由 */
    int cmd();

    /** 子路由 */
    int subCmd();

    /** 业务对象class */
    Class<?> dataClass();

    /** 推送描述 */
    String description() default "";
}


================================================
FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/annotation/DocActionSends.java
================================================
/*
 * ioGame
 * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.
 * # iohao.com . 渔民小镇
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
package com.iohao.game.action.skeleton.annotation;

import com.iohao.game.action.skeleton.core.doc.BroadcastDocument;

import java.lang.annotation.*;

/**
 * 文档相关
 * <pre>
 *     仅用于推送文档生成
 * </pre>
 *
 * @author 渔民小镇
 * @date 2022-01-31
 * @deprecated 请使用 {@link BroadcastDocument} 代替
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Deprecated
public @interface DocActionSends {
    DocActionSend[] value();
}


================================================
FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/annotation/ValidatedGroup.java
================================================
/*
 * ioGame
 * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.
 * # iohao.com . 渔民小镇
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
package com.iohao.game.action.skeleton.annotation;

import java.lang.annotation.*;

/**
 * 验证组
 *
 * @author fangwei
 * @date 2022-09-20
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
public @interface ValidatedGroup {
    /**
     * 确定验证组,校验组对象的 Class
     *
     * @return 校验组对象的 Class 数组
     */
    Class<?>[] value() default {};
}


================================================
FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/annotation/package-info.java
================================================
/*
 * ioGame
 * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.
 * # iohao.com . 渔民小镇
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
/**
 * 业务框架 - 注解相关
 *
 * @author 渔民小镇
 * @date 2024-08-05
 */
package com.iohao.game.action.skeleton.annotation;

================================================
FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionCommand.java
================================================
/*
 * ioGame
 * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.
 * # iohao.com . 渔民小镇
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
package com.iohao.game.action.skeleton.core;

import com.esotericsoftware.reflectasm.ConstructorAccess;
import com.esotericsoftware.reflectasm.MethodAccess;
import com.iohao.game.action.skeleton.annotation.ValidatedGroup;
import com.iohao.game.action.skeleton.core.doc.ActionCommandDoc;
import com.iohao.game.action.skeleton.core.flow.FlowContext;
import com.iohao.game.action.skeleton.core.flow.parser.MethodParser;
import com.iohao.game.action.skeleton.core.flow.parser.MethodParsers;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import lombok.experimental.FieldDefaults;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;

/**
 * ActionCommand 命令对象,也称为 action。
 * <pre>
 *     在业务框架构建时阶段创建的, ActionCommand 中保存了 action 相关信息,如:
 *     路由信息
 *     类信息
 *     类访问器
 *     方法对象
 *     方法名
 *     方法访问器
 *     方法信息下标
 *     方法返回值类型
 *     类是否托管于容器管理(是否交付给容器来管理 如 spring 等)
 * </pre>
 *
 * <pre>
 *     作用:
 *     业务框架处理业务流程时,也就是处理时阶段。会通过 action 来得到想要的各种信息。
 * </pre>
 *
 * @author 渔民小镇
 * @date 2021-12-12
 */
@Getter
public final class ActionCommand {
    /** cmdInfo */
    final CmdInfo cmdInfo;

    /** 一个single控制器对象 */
    final Object actionController;
    /** 方法所在 class */
    final Class<?> actionControllerClazz;
    /** 默认:true ,action 对象是 single. 如果设置为 false, 每次创建新的 action 类的对象. */
    final boolean createSingleActionCommandController;

    /** 方法对象 */
    final Method actionMethod;
    /** 方法名 */
    final String actionMethodName;
    /** 方法下标 */
    final int actionMethodIndex;
    /** 方法访问器 */
    final MethodAccess actionMethodAccess;

    /** 方法参数信息 数组 */
    final ParamInfo[] paramInfos;
    /** 方法是否有参数: true 有参数 */
    final boolean methodHasParam;
    /** 方法是否有异常抛出, 一般是错误码: true 有异常 */
    final boolean throwException;
    /** 返回类型 */
    final ActionMethodReturnInfo actionMethodReturnInfo;

    final ActionCommandDoc actionCommandDoc;

    /** true 表示交付给容器来管理 如 spring 等 */
    boolean deliveryContainer;
    /** 构造方法访问器 */
    ConstructorAccess<?> actionControllerConstructorAccess;

    private ActionCommand(Builder builder) {
        // -------------- 路由相关 --------------
        this.cmdInfo = CmdInfo.of(builder.cmd, builder.subCmd);

        // -------------- 控制器相关 --------------
        this.actionControllerClazz = builder.actionControllerClazz;
        this.actionController = builder.actionController;
        this.createSingleActionCommandController = builder.createSingleActionCommandController;

        // -------------- 控制器-方法相关 --------------
        this.actionMethod = builder.actionMethod;
        this.actionMethodName = builder.actionMethodName;
        this.actionMethodIndex = builder.actionMethodIndex;
        this.actionMethodAccess = builder.actionMethodAccess;

        // -------------- 控制器-方法参数相关 --------------
        this.paramInfos = builder.paramInfos;
        this.methodHasParam = builder.paramInfos != null;
        this.throwException = builder.actionMethod.getExceptionTypes().length != 0;
        this.actionMethodReturnInfo = new ActionMethodReturnInfo(builder);

        this.actionCommandDoc = builder.actionCommandDoc;

        this.deliveryContainer = builder.deliveryContainer;
    }

    public Stream<ParamInfo> streamParamInfo() {
        return this.methodHasParam ? Arrays.stream(this.paramInfos) : Stream.empty();
    }

    /**
     * action method 是否包含相关注解
     *
     * @param annotationClass 相关注解
     * @return true 是的
     * @since 21.10
     */
    public boolean containAnnotation(Class<? extends Annotation> annotationClass) {
        return this.getAnnotation(annotationClass) != null;
    }

    /**
     * 获取 action method 相关注解
     *
     * @param annotationClass 相关注解
     * @param <T>             t
     * @return 相关注解
     * @since 21.10
     */
    public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
        return actionMethod.getAnnotation(annotationClass);
    }

    /**
     * {@link ActionCommand} 命令的构建器
     * <p>
     * 因为 {@link ActionCommand} 的参数较复杂, 所以这里考虑用构建器。
     */
    @Accessors(chain = true)
    @Setter
    @FieldDefaults(level = AccessLevel.PUBLIC)
    static final class Builder {
        /** 目标路由 */
        int cmd;
        /** 目标子路由 */
        int subCmd;
        /** 方法访问器 */
        MethodAccess actionMethodAccess;
        /** 方法名 */
        String actionMethodName;
        /** tcp controller类 */
        Class<?> actionControllerClazz;
        /** 方法对象 */
        Method actionMethod;
        /** 参数列表信息 */
        ActionCommand.ParamInfo[] paramInfos;
        /** 方法下标 (配合 MethodAccess 使用) */
        int actionMethodIndex;
        /** 返回值信息 */
        Class<?> returnTypeClazz;
        /** action command 文档 */
        ActionCommandDoc actionCommandDoc;
        /** true 表示交付给容器来管理 如 spring 等 */
        boolean deliveryContainer;
        /** 默认:true ,action 对象是 single. 如果设置为 false, 每次创建新的 action 类的对象. */
        boolean createSingleActionCommandController;
        /** 一个single控制器对象 */
        Object actionController;

        ActionCommand build() {
            return new ActionCommand(this);
        }
    }

    /**
     * action 方法中的参数与返回值信息
     */
    public interface MethodParamResultInfo {
        /**
         * 是否是 List 类型
         *
         * @return true 是 List 类型
         */
        default boolean isList() {
            return false;
        }

        /**
         * List 泛型的类型,也称为方法返回值类型
         * <pre>
         *     如果不是方法的返回值不是 List 类型,这个值会取自 paramClazz 成员属性
         *     原计划想用 Collection ,这样可以兼容 Set 之类的;但似乎这样有一点争议,先暂支持 List 把
         * </pre>
         *
         * @return List 泛型的类型
         */
        Class<?> getActualTypeArgumentClazz();
    }

    /**
     * 方法参数信息
     */
    @Getter
    public static final class ParamInfo implements MethodParamResultInfo {
        /** JSR380 空验证组 */
        static final Class<?>[] EMPTY_GROUPS = new Class<?>[0];
        /** 参数名 */
        final String name;
        /** 参数下标 */
        final int index;
        /** 保存 Parameter 对象 */
        final Parameter parameter;
        /** 参数类型 */
        final Class<?> paramClazz;
        /**
         * List 泛型的类型,也称为方法返回值类型
         * <pre>
         *     如果方法的返回值不是 List 类型,这个值会取自 paramClazz 成员属性
         *     原计划想用 Collection ,这样可以兼容 Set 之类的;但似乎这样有一点争议,先暂支持 List
         * </pre>
         */
        final Class<?> actualTypeArgumentClazz;
        /** true 是 list 类型 */
        final boolean list;

        /**
         * 实际的内置包装类型
         * <pre>
         *     常规的 java class 是指本身,如:
         *     开发者自定义了一个 StudentPb,在 action 方法上参数声明为 xxx(StudentPb studentPb)
         *     那么这个值就是 StudentPb
         * </pre>
         *
         * <pre>
         *     但由于框架现在内置了一些包装类型,如:
         *     int --> IntValue
         *     List&lt;Integer&gt; --> IntValueList
         *
         *     long --> LongValue
         *     List&lt;Long&gt; --> LongValueList
         *
         *     所以当开发者在 action 方法上参数声明为基础类型时;
         *     如声明为 int 那么这个值将会是 IntValue
         *     如声明为 long 那么这个值将会是 LongValue
         *
         *     如声明为 List&lt;Integer&gt; 那么这个值将会是 IntValueList
         *     包装类型相关的以此类推;
         *
         *     这么做的目的是为了生成文档时,不与前端产生争议,
         *     如果提供给前端的文档显示 int ,或许前端同学会懵B,
         *     当然如果提前与前端同学沟通好这些约定,也不是那么麻烦。
         *     但实际上如果前端是新来接手项目的,碰见这种情况也会小懵,
         *     所以为了避免这些小尬,框架在生成文档时,用基础类型的内置包装类型来表示。
         * </pre>
         */
        final Class<?> actualClazz;
        final boolean customMethodParser;
        /** JSR380 验证组 */
        final Class<?>[] validatorGroups;
        /** true 表示参数类型是 {@link FlowContext} */
        final boolean flowContext;
        /** true : 开启 JSR380 验证规范 */
        boolean validator;

        ParamInfo(int index, Parameter p) {
            // 保存Parameter对象
            this.parameter = p;
            // 方法的参数下标
            this.index = index;
            // 方法的参数名
            this.name = p.getName();
            // 方法的参数类型 class
            this.paramClazz = p.getType();

            /*
             * 关于方法参数支持 list 这个特性也纠结了很久
             * 因为这可能会给开发者造成一些困惑,现在方法支持 list 但只是为了支持基础类型相关的 list
             * 开发者会不会把这个 list 的泛型类型用在协议上,如: List<StudentPb> 这种;
             */
            if (List.class.isAssignableFrom(this.paramClazz)) {
                ParameterizedType genericReturnType = (ParameterizedType) p.getParameterizedType();
                this.actualTypeArgumentClazz = (Class<?>) genericReturnType.getActualTypeArguments()[0];
                this.list = true;
            } else {
                this.actualTypeArgumentClazz = this.paramClazz;
                this.list = false;
            }

            MethodParser methodParser = MethodParsers.getMethodParser(this);
            this.actualClazz = methodParser.getActualClazz(this);
            this.customMethodParser = methodParser.isCustomMethodParser();

            // JSR380 相关,确定验证组,校验组对象的 Class 数组
            var validatedAnn = this.parameter.getAnnotation(ValidatedGroup.class);
            this.validatorGroups = Objects.isNull(validatedAnn) ? EMPTY_GROUPS : validatedAnn.value();

            this.flowContext = FlowContext.class.isAssignableFrom(actualTypeArgumentClazz);
        }

        /**
         * 是否业务参数
         *
         * @return true 业务参数
         * @since 21.7
         */
        public boolean isBizData() {
            return !this.flowContext;
        }

        @Override
        public String toString() {
            return this.toString(false);
        }

        public String toString(boolean fullName) {
            boolean isCustomList = this.list && !MethodParsers.containsKey(this.actualClazz);

            if (isCustomList) {
                String simpleNameParamClazz = this.paramClazz.getSimpleName();
                String simpleNameActualClazz = fullName
                        ? this.actualClazz.getName()
                        : this.actualClazz.getSimpleName();

                return String.format("%s<%s> %s", simpleNameParamClazz, simpleNameActualClazz, this.name);
            }

            String simpleNameActualClazz = fullName
                    ? this.actualClazz.getName()
                    : this.actualClazz.getSimpleName();

            return String.format("%s %s", simpleNameActualClazz, this.name);
        }
    }

    /**
     * action 方法参数返回值信息
     */
    @Getter
    @FieldDefaults(level = AccessLevel.PRIVATE)
    public static final class ActionMethodReturnInfo implements MethodParamResultInfo {
        /** 返回类型 */
        final Class<?> returnTypeClazz;
        /**
         * List 泛型的类型,也称为方法返回值类型
         * <pre>
         *     如果不是方法的返回值不是 List 类型,这个值会取自 returnTypeClazz 成员属性
         *     原计划想用 Collection ,这样可以兼容 Set 之类的;但似乎这样有一点争议,先暂支持 List 把
         * </pre>
         */
        final Class<?> actualTypeArgumentClazz;
        /** true 是 list 类型 */
        final boolean list;
        /**
         * 实际的内置包装类型
         * <pre>
         *     常规的 java class 是指本身,如:
         *     开发者自定义了一个 StudentPb,在 action 方法上参数声明为 xxx(StudentPb studentPb)
         *     那么这个值就是 StudentPb
         * </pre>
         *
         * <pre>
         *     但由于框架现在内置了一些包装类型,如:
         *     int --> IntValue
         *     List&lt;Integer&gt; --> IntValueList
         *
         *     long --> LongValue
         *     List&lt;Long&gt; --> LongValueList
         *
         *     所以当开发者在 action 方法上参数声明为基础类型时;
         *     如声明为 int 那么这个值将会是 IntValue
         *     如声明为 long 那么这个值将会是 LongValue
         *
         *     如声明为 List&lt;Integer&gt; 那么这个值将会是 IntValueList
         *     包装类型相关的以此类推;
         *
         *     这么做的目的是为了生成文档时,不与前端产生争议,
         *     如果提供给前端的文档显示 int ,或许前端同学会懵B,
         *     当然如果提前与前端同学沟通好这些约定,也不是那么麻烦。
         *     但实际上如果前端是新来接手项目的,碰见这种情况也会小懵,
         *     所以为了避免这些小尬,框架在生成文档时,用基础类型的内置包装类型来表示。
         * </pre>
         */
        final Class<?> actualClazz;
        final boolean customMethodParser;

        private ActionMethodReturnInfo(ActionCommand.Builder builder) {

            this.returnTypeClazz = builder.returnTypeClazz;

            if (List.class.isAssignableFrom(returnTypeClazz)) {
                ParameterizedType genericReturnType = (ParameterizedType) builder.actionMethod.getGenericReturnType();
                this.actualTypeArgumentClazz = (Class<?>) genericReturnType.getActualTypeArguments()[0];
                this.list = true;
            } else {
                this.actualTypeArgumentClazz = returnTypeClazz;
                this.list = false;
            }

            MethodParser methodParser = MethodParsers.getMethodParser(this);
            this.actualClazz = methodParser.getActualClazz(this);
            this.customMethodParser = methodParser.isCustomMethodParser();
        }

        /**
         * 方法返回值类型是否 void
         *
         * @return true 是 void
         */
        public boolean isVoid() {
            return Void.TYPE == this.returnTypeClazz;
        }

        @Override
        public String toString() {
            return toString(false);
        }

        public String toString(boolean fullName) {
            boolean isCustomList = this.list && !MethodParsers.containsKey(this.actualClazz);

            if (isCustomList) {
                String simpleNameReturnTypeClazz = this.returnTypeClazz.getSimpleName();
                String simpleNameActualClazz = fullName
                        ? this.actualClazz.getName()
                        : this.actualClazz.getSimpleName();

                return String.format("%s<%s>", simpleNameReturnTypeClazz, simpleNameActualClazz);
            }

            return fullName
                    ? this.actualClazz.getName()
                    : this.actualClazz.getSimpleName();
        }
    }
}


================================================
FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionCommandDocParser.java
================================================
/*
 * ioGame
 * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.
 * # iohao.com . 渔民小镇
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
package com.iohao.game.action.skeleton.core;

import com.iohao.game.action.skeleton.annotation.ActionController;
import com.iohao.game.action.skeleton.annotation.ActionMethod;
import com.iohao.game.action.skeleton.core.doc.*;
import lombok.AccessLevel;
import lombok.experimental.FieldDefaults;
import org.jctools.maps.NonBlockingHashMap;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

/**
 * source doc 解析类
 *
 * @author 渔民小镇
 * @date 2022-12-09
 */
@FieldDefaults(level = AccessLevel.PRIVATE)
final class ActionCommandDocParser {
    final ActionCommandParser actionCommandParser;

    final Map<Integer, ActionCommandDoc> actionCommandDocMap = new NonBlockingHashMap<>();

    final ActionCommandDoc emptyActionCommandDoc = new ActionCommandDoc();

    ActionCommandDocParser(ActionCommandParser actionCommandParser, List<Class<?>> controllerList, boolean parseDoc) {
        this.actionCommandParser = actionCommandParser;
        if (parseDoc) {
            this.buildSourceDoc(controllerList);
        }
    }

    private void buildSourceDoc(List<Class<?>> controllerList) {

        var actionCommandRegions = this.actionCommandParser.getActionCommandRegions();

        // java source
        Map<String, JavaClassDocInfo> javaClassDocInfoMap = ActionCommandDocKit.getJavaClassDocInfoMap(controllerList);

        this.actionCommandParser.getActionControllerStream(controllerList).parallel().forEach
Download .txt
gitextract_1je6oco0/

├── .github/
│   └── ISSUE_TEMPLATE/
│       ├── ask-question.md
│       ├── bug-report.md
│       ├── empty-issues.md
│       └── enhance-task.md
├── .gitignore
├── BACKERS.md
├── LICENSE
├── README.md
├── README_CN.md
├── changeLog_ioGame.md
├── common/
│   ├── README.md
│   ├── common-core/
│   │   ├── README.md
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── iohao/
│   │       │   │           └── game/
│   │       │   │               └── action/
│   │       │   │                   └── skeleton/
│   │       │   │                       ├── IoGameVersion.java
│   │       │   │                       ├── annotation/
│   │       │   │                       │   ├── ActionController.java
│   │       │   │                       │   ├── ActionMethod.java
│   │       │   │                       │   ├── DocActionSend.java
│   │       │   │                       │   ├── DocActionSends.java
│   │       │   │                       │   ├── ValidatedGroup.java
│   │       │   │                       │   └── package-info.java
│   │       │   │                       ├── core/
│   │       │   │                       │   ├── ActionCommand.java
│   │       │   │                       │   ├── ActionCommandDocParser.java
│   │       │   │                       │   ├── ActionCommandFlowExecute.java
│   │       │   │                       │   ├── ActionCommandHandler.java
│   │       │   │                       │   ├── ActionCommandParser.java
│   │       │   │                       │   ├── ActionCommandRegion.java
│   │       │   │                       │   ├── ActionCommandRegionGlobalCheckKit.java
│   │       │   │                       │   ├── ActionCommandRegions.java
│   │       │   │                       │   ├── ActionFactoryBean.java
│   │       │   │                       │   ├── ActionParserListenerAbout.java
│   │       │   │                       │   ├── ActionSend.java
│   │       │   │                       │   ├── BarMessageKit.java
│   │       │   │                       │   ├── BarSkeleton.java
│   │       │   │                       │   ├── BarSkeletonBuilder.java
│   │       │   │                       │   ├── BarSkeletonBuilderParamConfig.java
│   │       │   │                       │   ├── BarSkeletonSetting.java
│   │       │   │                       │   ├── CmdInfo.java
│   │       │   │                       │   ├── CmdInfoFlyweightFactory.java
│   │       │   │                       │   ├── CmdKit.java
│   │       │   │                       │   ├── DataCodecKit.java
│   │       │   │                       │   ├── DefaultActionCommandFlowExecute.java
│   │       │   │                       │   ├── DefaultActionFactoryBean.java
│   │       │   │                       │   ├── DependencyInjectionPart.java
│   │       │   │                       │   ├── DevConfig.java
│   │       │   │                       │   ├── Handler.java
│   │       │   │                       │   ├── InOutManager.java
│   │       │   │                       │   ├── InOutManagerAbout.java
│   │       │   │                       │   ├── IoGameCommonCoreConfig.java
│   │       │   │                       │   ├── IoGameGlobalSetting.java
│   │       │   │                       │   ├── PrintActionKit.java
│   │       │   │                       │   ├── SkeletonAttr.java
│   │       │   │                       │   ├── ValidatorKit.java
│   │       │   │                       │   ├── action/
│   │       │   │                       │   │   └── parser/
│   │       │   │                       │   │       ├── ActionParserContext.java
│   │       │   │                       │   │       ├── ActionParserListener.java
│   │       │   │                       │   │       └── package-info.java
│   │       │   │                       │   ├── codec/
│   │       │   │                       │   │   ├── DataCodec.java
│   │       │   │                       │   │   ├── DataSelfEncode.java
│   │       │   │                       │   │   ├── JsonDataCodec.java
│   │       │   │                       │   │   ├── ProtoDataCodec.java
│   │       │   │                       │   │   └── package-info.java
│   │       │   │                       │   ├── commumication/
│   │       │   │                       │   │   ├── BroadcastContext.java
│   │       │   │                       │   │   ├── BroadcastOrderContext.java
│   │       │   │                       │   │   ├── BrokerClientContext.java
│   │       │   │                       │   │   ├── ChannelContext.java
│   │       │   │                       │   │   ├── CommunicationAggregationContext.java
│   │       │   │                       │   │   ├── InvokeExternalModuleContext.java
│   │       │   │                       │   │   ├── InvokeModuleContext.java
│   │       │   │                       │   │   ├── ProcessorContext.java
│   │       │   │                       │   │   ├── SimpleServer.java
│   │       │   │                       │   │   └── package-info.java
│   │       │   │                       │   ├── doc/
│   │       │   │                       │   │   ├── ActionCommandDoc.java
│   │       │   │                       │   │   ├── ActionCommandDocKit.java
│   │       │   │                       │   │   ├── ActionDoc.java
│   │       │   │                       │   │   ├── ActionDocs.java
│   │       │   │                       │   │   ├── ActionDocument.java
│   │       │   │                       │   │   ├── ActionMemberCmdDocument.java
│   │       │   │                       │   │   ├── ActionMethodDocument.java
│   │       │   │                       │   │   ├── ActionSendDoc.java
│   │       │   │                       │   │   ├── ActionSendDocs.java
│   │       │   │                       │   │   ├── ActionSendDocsRegion.java
│   │       │   │                       │   │   ├── BarSkeletonDoc.java
│   │       │   │                       │   │   ├── BroadcastDoc.java
│   │       │   │                       │   │   ├── BroadcastDocBuilder.java
│   │       │   │                       │   │   ├── BroadcastDocument.java
│   │       │   │                       │   │   ├── BroadcastDocumentBuilder.java
│   │       │   │                       │   │   ├── DocInfo.java
│   │       │   │                       │   │   ├── DocumentAccessAuthentication.java
│   │       │   │                       │   │   ├── DocumentAnalyseKit.java
│   │       │   │                       │   │   ├── DocumentGenerate.java
│   │       │   │                       │   │   ├── DocumentMethod.java
│   │       │   │                       │   │   ├── ErrorCodeDoc.java
│   │       │   │                       │   │   ├── ErrorCodeDocs.java
│   │       │   │                       │   │   ├── ErrorCodeDocsRegion.java
│   │       │   │                       │   │   ├── ErrorCodeDocument.java
│   │       │   │                       │   │   ├── IoGameDocument.java
│   │       │   │                       │   │   ├── IoGameDocumentHelper.java
│   │       │   │                       │   │   ├── JavaClassDocInfo.java
│   │       │   │                       │   │   ├── TextDocumentGenerate.java
│   │       │   │                       │   │   ├── TypeMappingDocument.java
│   │       │   │                       │   │   ├── TypeMappingRecord.java
│   │       │   │                       │   │   └── package-info.java
│   │       │   │                       │   ├── enhance/
│   │       │   │                       │   │   ├── BarSkeletonBuilderEnhance.java
│   │       │   │                       │   │   └── BarSkeletonBuilderEnhances.java
│   │       │   │                       │   ├── exception/
│   │       │   │                       │   │   ├── ActionErrorEnum.java
│   │       │   │                       │   │   ├── MsgException.java
│   │       │   │                       │   │   ├── MsgExceptionInfo.java
│   │       │   │                       │   │   ├── MsgExceptionKit.java
│   │       │   │                       │   │   └── package-info.java
│   │       │   │                       │   ├── flow/
│   │       │   │                       │   │   ├── ActionAfter.java
│   │       │   │                       │   │   ├── ActionMethodExceptionProcess.java
│   │       │   │                       │   │   ├── ActionMethodInOut.java
│   │       │   │                       │   │   ├── ActionMethodInvoke.java
│   │       │   │                       │   │   ├── ActionMethodParamParser.java
│   │       │   │                       │   │   ├── ActionMethodResultWrap.java
│   │       │   │                       │   │   ├── FlowContext.java
│   │       │   │                       │   │   ├── FlowContextFactory.java
│   │       │   │                       │   │   ├── FlowContextKit.java
│   │       │   │                       │   │   ├── InternalAboutFlowContext.java
│   │       │   │                       │   │   ├── ResponseMessageCreate.java
│   │       │   │                       │   │   ├── UserAttachment.java
│   │       │   │                       │   │   ├── attr/
│   │       │   │                       │   │   │   ├── FlowAttr.java
│   │       │   │                       │   │   │   ├── FlowOption.java
│   │       │   │                       │   │   │   ├── FlowOptionDynamic.java
│   │       │   │                       │   │   │   └── package-info.java
│   │       │   │                       │   │   ├── internal/
│   │       │   │                       │   │   │   ├── DebugInOut.java
│   │       │   │                       │   │   │   ├── DefaultActionAfter.java
│   │       │   │                       │   │   │   ├── DefaultActionMethodExceptionProcess.java
│   │       │   │                       │   │   │   ├── DefaultActionMethodInvoke.java
│   │       │   │                       │   │   │   ├── DefaultActionMethodParamParser.java
│   │       │   │                       │   │   │   ├── DefaultActionMethodResultWrap.java
│   │       │   │                       │   │   │   ├── DefaultResponseMessageCreate.java
│   │       │   │                       │   │   │   ├── StatActionInOut.java
│   │       │   │                       │   │   │   ├── ThreadMonitorInOut.java
│   │       │   │                       │   │   │   ├── TimeRangeInOut.java
│   │       │   │                       │   │   │   ├── TraceIdInOut.java
│   │       │   │                       │   │   │   └── package-info.java
│   │       │   │                       │   │   ├── package-info.java
│   │       │   │                       │   │   └── parser/
│   │       │   │                       │   │       ├── BoolValueMethodParser.java
│   │       │   │                       │   │       ├── DefaultMethodParser.java
│   │       │   │                       │   │       ├── IntValueMethodParser.java
│   │       │   │                       │   │       ├── LongValueMethodParser.java
│   │       │   │                       │   │       ├── MethodParser.java
│   │       │   │                       │   │       ├── MethodParsers.java
│   │       │   │                       │   │       ├── StringValueMethodParser.java
│   │       │   │                       │   │       └── package-info.java
│   │       │   │                       │   ├── package-info.java
│   │       │   │                       │   └── runner/
│   │       │   │                       │       ├── InternalRunner.java
│   │       │   │                       │       ├── Runner.java
│   │       │   │                       │       ├── Runners.java
│   │       │   │                       │       └── package-info.java
│   │       │   │                       ├── eventbus/
│   │       │   │                       │   ├── AbstractEventBusRunner.java
│   │       │   │                       │   ├── EventBrokerClientMessage.java
│   │       │   │                       │   ├── EventBus.java
│   │       │   │                       │   ├── EventBusFireType.java
│   │       │   │                       │   ├── EventBusListener.java
│   │       │   │                       │   ├── EventBusMessage.java
│   │       │   │                       │   ├── EventBusMessageCreator.java
│   │       │   │                       │   ├── EventBusRegion.java
│   │       │   │                       │   ├── EventBusRunner.java
│   │       │   │                       │   ├── EventBusSubscriber.java
│   │       │   │                       │   ├── EventSubscribe.java
│   │       │   │                       │   ├── EventTopicMessage.java
│   │       │   │                       │   ├── ExecutorSelector.java
│   │       │   │                       │   ├── InternalAboutAny.java
│   │       │   │                       │   ├── InternalAboutEventBus.java
│   │       │   │                       │   ├── SubscribeExecutorStrategy.java
│   │       │   │                       │   ├── Subscriber.java
│   │       │   │                       │   ├── SubscriberInvoke.java
│   │       │   │                       │   ├── SubscriberInvokeCreator.java
│   │       │   │                       │   └── package-info.java
│   │       │   │                       ├── ext/
│   │       │   │                       │   └── spring/
│   │       │   │                       │       ├── ActionFactoryBeanForSpring.java
│   │       │   │                       │       └── package-info.java
│   │       │   │                       ├── i18n/
│   │       │   │                       │   ├── Bundle.java
│   │       │   │                       │   └── MessageKey.java
│   │       │   │                       ├── kit/
│   │       │   │                       │   ├── ExecutorSelectEnum.java
│   │       │   │                       │   ├── ExecutorSelectKit.java
│   │       │   │                       │   ├── FixedCmd.java
│   │       │   │                       │   ├── LogicServerCreateKit.java
│   │       │   │                       │   ├── RangeBroadcast.java
│   │       │   │                       │   ├── RangeBroadcaster.java
│   │       │   │                       │   └── package-info.java
│   │       │   │                       ├── package-info.java
│   │       │   │                       ├── protocol/
│   │       │   │                       │   ├── BarMessage.java
│   │       │   │                       │   ├── HeadMetadata.java
│   │       │   │                       │   ├── RequestMessage.java
│   │       │   │                       │   ├── ResponseMessage.java
│   │       │   │                       │   ├── collect/
│   │       │   │                       │   │   ├── RequestCollectMessage.java
│   │       │   │                       │   │   ├── ResponseCollectItemMessage.java
│   │       │   │                       │   │   ├── ResponseCollectMessage.java
│   │       │   │                       │   │   └── package-info.java
│   │       │   │                       │   ├── external/
│   │       │   │                       │   │   ├── RequestCollectExternalMessage.java
│   │       │   │                       │   │   ├── ResponseCollectExternalItemMessage.java
│   │       │   │                       │   │   ├── ResponseCollectExternalMessage.java
│   │       │   │                       │   │   └── package-info.java
│   │       │   │                       │   ├── login/
│   │       │   │                       │   │   ├── SettingUserIdMessage.java
│   │       │   │                       │   │   ├── SettingUserIdMessageResponse.java
│   │       │   │                       │   │   └── SettingUserIdResult.java
│   │       │   │                       │   ├── package-info.java
│   │       │   │                       │   ├── processor/
│   │       │   │                       │   │   ├── EndPointLogicServerMessage.java
│   │       │   │                       │   │   ├── EndPointOperationEnum.java
│   │       │   │                       │   │   ├── SimpleServerInfo.java
│   │       │   │                       │   │   └── package-info.java
│   │       │   │                       │   └── wrapper/
│   │       │   │                       │       ├── BoolValue.java
│   │       │   │                       │       ├── BoolValueList.java
│   │       │   │                       │       ├── ByteValueList.java
│   │       │   │                       │       ├── IntValue.java
│   │       │   │                       │       ├── IntValueList.java
│   │       │   │                       │       ├── LongValue.java
│   │       │   │                       │       ├── LongValueList.java
│   │       │   │                       │       ├── StringValue.java
│   │       │   │                       │       ├── StringValueList.java
│   │       │   │                       │       ├── ValueRecord.java
│   │       │   │                       │       ├── WrapperKit.java
│   │       │   │                       │       └── package-info.java
│   │       │   │                       ├── pulse/
│   │       │   │                       │   ├── Pulses.java
│   │       │   │                       │   ├── core/
│   │       │   │                       │   │   ├── PulseChannel.java
│   │       │   │                       │   │   ├── PulseTransmit.java
│   │       │   │                       │   │   ├── consumer/
│   │       │   │                       │   │   │   ├── DefaultPulseConsumers.java
│   │       │   │                       │   │   │   ├── PulseConsumer.java
│   │       │   │                       │   │   │   ├── PulseConsumers.java
│   │       │   │                       │   │   │   └── PulseSignalRequestAccept.java
│   │       │   │                       │   │   └── producer/
│   │       │   │                       │   │       ├── DefaultPulseProducers.java
│   │       │   │                       │   │       ├── PulseCreatePeriod.java
│   │       │   │                       │   │       ├── PulseCreateRequest.java
│   │       │   │                       │   │       ├── PulseProducer.java
│   │       │   │                       │   │       ├── PulseProducers.java
│   │       │   │                       │   │       └── PulseSignalResponseAccept.java
│   │       │   │                       │   ├── message/
│   │       │   │                       │   │   ├── EmptyMessage.java
│   │       │   │                       │   │   ├── PulseSignalMessage.java
│   │       │   │                       │   │   ├── PulseSignalRequest.java
│   │       │   │                       │   │   ├── PulseSignalResponse.java
│   │       │   │                       │   │   └── SignalType.java
│   │       │   │                       │   ├── package-info.java
│   │       │   │                       │   └── runner/
│   │       │   │                       │       ├── CreatePulsesRunner.java
│   │       │   │                       │       └── PulseRunner.java
│   │       │   │                       └── toy/
│   │       │   │                           ├── BannerColorStrategy.java
│   │       │   │                           ├── BannerData.java
│   │       │   │                           ├── BreakingNewsAbout.java
│   │       │   │                           ├── InternalMemory.java
│   │       │   │                           ├── IoGameBanner.java
│   │       │   │                           ├── ToyLine.java
│   │       │   │                           ├── ToyTable.java
│   │       │   │                           ├── ToyTableRegion.java
│   │       │   │                           └── ToyTableRender.java
│   │       │   └── resources/
│   │       │       ├── iohao.properties
│   │       │       └── iohao_zh_CN.properties
│   │       └── test/
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── iohao/
│   │           │           └── game/
│   │           │               ├── action/
│   │           │               │   └── skeleton/
│   │           │               │       ├── core/
│   │           │               │       │   ├── ActionParserListenerTest.java
│   │           │               │       │   ├── BarSkeletonTest.java
│   │           │               │       │   ├── DataCodecKitTest.java
│   │           │               │       │   ├── InOutManagerTest.java
│   │           │               │       │   ├── JSR380Test.java
│   │           │               │       │   ├── JSR380ValidatedGroupTest.java
│   │           │               │       │   ├── SimpleWrapperActionTest.java
│   │           │               │       │   ├── WrapperIntTest.java
│   │           │               │       │   ├── WrapperLongTest.java
│   │           │               │       │   ├── action/
│   │           │               │       │   │   ├── BeeAction.java
│   │           │               │       │   │   ├── ExampleActionCmd.java
│   │           │               │       │   │   ├── SimpleWrapperAction.java
│   │           │               │       │   │   ├── WrapperIntAction.java
│   │           │               │       │   │   ├── WrapperLongAction.java
│   │           │               │       │   │   ├── group/
│   │           │               │       │   │   │   ├── Create.java
│   │           │               │       │   │   │   └── Update.java
│   │           │               │       │   │   └── pojo/
│   │           │               │       │   │       ├── BeeApple.java
│   │           │               │       │   │       ├── BirdValid.java
│   │           │               │       │   │       ├── DogValid.java
│   │           │               │       │   │       └── Snake.java
│   │           │               │       │   ├── data/
│   │           │               │       │   │   └── TestDataKit.java
│   │           │               │       │   └── flow/
│   │           │               │       │       └── internal/
│   │           │               │       │           ├── StatActionInOutTest.java
│   │           │               │       │           ├── ThreadMonitorInOutTest.java
│   │           │               │       │           └── TimeRangeInOutTest.java
│   │           │               │       ├── eventbus/
│   │           │               │       │   ├── CustomEvent.java
│   │           │               │       │   ├── EventBusTest.java
│   │           │               │       │   ├── MyMessage.java
│   │           │               │       │   └── MyRecord.java
│   │           │               │       ├── i18n/
│   │           │               │       │   └── BundleTest.java
│   │           │               │       ├── protocol/
│   │           │               │       │   ├── ResponseMessageTest.java
│   │           │               │       │   ├── Student.java
│   │           │               │       │   └── wrapper/
│   │           │               │       │       └── WrapperKitTest.java
│   │           │               │       └── toy/
│   │           │               │           └── ToyTableTest.java
│   │           │               └── common/
│   │           │                   └── kit/
│   │           │                       └── ClassScannerTest.java
│   │           └── resources/
│   │               └── logback.xml
│   ├── common-kit/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           └── java/
│   │               └── com/
│   │                   └── iohao/
│   │                       └── game/
│   │                           └── common/
│   │                               └── kit/
│   │                                   ├── ProtoKit.java
│   │                                   ├── asm/
│   │                                   │   ├── ClassRefInfo.java
│   │                                   │   ├── ClassRefInfoBuilder.java
│   │                                   │   ├── ClassRefInfoKit.java
│   │                                   │   ├── FieldRefInfo.java
│   │                                   │   ├── MethodRefInfo.java
│   │                                   │   └── package-info.java
│   │                                   ├── io/
│   │                                   │   ├── FileKit.java
│   │                                   │   ├── ResourceKit.java
│   │                                   │   └── package-info.java
│   │                                   └── system/
│   │                                       ├── InternalSystemPropsKit.java
│   │                                       ├── OsInfo.java
│   │                                       └── package-info.java
│   ├── common-micro-kit/
│   │   ├── README.md
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── com/
│   │       │       │   └── iohao/
│   │       │       │       └── game/
│   │       │       │           └── common/
│   │       │       │               ├── consts/
│   │       │       │               │   ├── CommonConst.java
│   │       │       │               │   └── IoGameLogName.java
│   │       │       │               ├── internal/
│   │       │       │               │   ├── BootConfig.java
│   │       │       │               │   ├── BootItemConfig.java
│   │       │       │               │   └── BootItemConfigKit.java
│   │       │       │               └── kit/
│   │       │       │                   ├── AboutKit.java
│   │       │       │                   ├── ArrayKit.java
│   │       │       │                   ├── BaseTypeKit.java
│   │       │       │                   ├── ByteKit.java
│   │       │       │                   ├── ClassScanner.java
│   │       │       │                   ├── CollKit.java
│   │       │       │                   ├── CompletableFutureKit.java
│   │       │       │                   ├── ExecutorKit.java
│   │       │       │                   ├── HashKit.java
│   │       │       │                   ├── MoreKit.java
│   │       │       │                   ├── MurmurHash3.java
│   │       │       │                   ├── NetworkKit.java
│   │       │       │                   ├── OperationCode.java
│   │       │       │                   ├── PresentKit.java
│   │       │       │                   ├── RandomKit.java
│   │       │       │                   ├── RuntimeKit.java
│   │       │       │                   ├── SafeKit.java
│   │       │       │                   ├── StrKit.java
│   │       │       │                   ├── TimeBetweenKit.java
│   │       │       │                   ├── TimeFormatterKit.java
│   │       │       │                   ├── TimeKit.java
│   │       │       │                   ├── attr/
│   │       │       │                   │   ├── AttrOption.java
│   │       │       │                   │   ├── AttrOptionDynamic.java
│   │       │       │                   │   ├── AttrOptions.java
│   │       │       │                   │   └── package-info.java
│   │       │       │                   ├── beans/
│   │       │       │                   │   └── property/
│   │       │       │                   │       ├── AbstractPropertyValueObservable.java
│   │       │       │                   │       ├── BooleanProperty.java
│   │       │       │                   │       ├── IntegerProperty.java
│   │       │       │                   │       ├── LongProperty.java
│   │       │       │                   │       ├── NumberPropertyValueObservable.java
│   │       │       │                   │       ├── ObjectProperty.java
│   │       │       │                   │       ├── PropertyAbout.java
│   │       │       │                   │       ├── PropertyChangeListener.java
│   │       │       │                   │       ├── PropertyValueObservable.java
│   │       │       │                   │       ├── StringProperty.java
│   │       │       │                   │       └── package-info.java
│   │       │       │                   ├── collect/
│   │       │       │                   │   ├── ListMultiMap.java
│   │       │       │                   │   ├── MultiMap.java
│   │       │       │                   │   ├── NonBlockingListMultiMap.java
│   │       │       │                   │   ├── NonBlockingSetMultiMap.java
│   │       │       │                   │   ├── SetMultiMap.java
│   │       │       │                   │   └── package-info.java
│   │       │       │                   ├── concurrent/
│   │       │       │                   │   ├── CommonTaskListener.java
│   │       │       │                   │   ├── DaemonThreadFactory.java
│   │       │       │                   │   ├── FixedNameThreadFactory.java
│   │       │       │                   │   ├── IntervalTaskListener.java
│   │       │       │                   │   ├── OnceTaskListener.java
│   │       │       │                   │   ├── TaskKit.java
│   │       │       │                   │   ├── TaskListener.java
│   │       │       │                   │   ├── ThreadCreator.java
│   │       │       │                   │   ├── executor/
│   │       │       │                   │   │   ├── AbstractThreadExecutorRegion.java
│   │       │       │                   │   │   ├── ExecutorRegion.java
│   │       │       │                   │   │   ├── ExecutorRegionKit.java
│   │       │       │                   │   │   ├── SimpleThreadExecutorRegion.java
│   │       │       │                   │   │   ├── ThreadExecutor.java
│   │       │       │                   │   │   ├── ThreadExecutorRegion.java
│   │       │       │                   │   │   ├── UserThreadExecutorRegion.java
│   │       │       │                   │   │   ├── UserVirtualThreadExecutorRegion.java
│   │       │       │                   │   │   └── package-info.java
│   │       │       │                   │   ├── package-info.java
│   │       │       │                   │   └── timer/
│   │       │       │                   │       └── delay/
│   │       │       │                   │           ├── DelayTask.java
│   │       │       │                   │           ├── DelayTaskKit.java
│   │       │       │                   │           ├── DelayTaskRegion.java
│   │       │       │                   │           ├── InternalDelayAbout.java
│   │       │       │                   │           └── package-info.java
│   │       │       │                   ├── exception/
│   │       │       │                   │   ├── CommonIllegalArgumentException.java
│   │       │       │                   │   ├── CommonNullPointerException.java
│   │       │       │                   │   ├── CommonRuntimeException.java
│   │       │       │                   │   ├── ThrowKit.java
│   │       │       │                   │   └── package-info.java
│   │       │       │                   ├── id/
│   │       │       │                   │   ├── CacheKeyKit.java
│   │       │       │                   │   ├── IdKit.java
│   │       │       │                   │   ├── StringIdSupplier.java
│   │       │       │                   │   └── package-info.java
│   │       │       │                   ├── micro/
│   │       │       │                   │   └── room/
│   │       │       │                   │       ├── MicroRoom.java
│   │       │       │                   │       ├── MicroRooms.java
│   │       │       │                   │       └── package-info.java
│   │       │       │                   ├── package-info.java
│   │       │       │                   ├── time/
│   │       │       │                   │   ├── CacheTimeKit.java
│   │       │       │                   │   ├── ConfigTimeKit.java
│   │       │       │                   │   ├── ExpireTimeKit.java
│   │       │       │                   │   ├── FormatTimeKit.java
│   │       │       │                   │   ├── ToTimeKit.java
│   │       │       │                   │   └── package-info.java
│   │       │       │                   ├── trace/
│   │       │       │                   │   ├── TraceIdSupplier.java
│   │       │       │                   │   ├── TraceKit.java
│   │       │       │                   │   └── package-info.java
│   │       │       │                   └── weight/
│   │       │       │                       ├── Weight.java
│   │       │       │                       ├── WeightKit.java
│   │       │       │                       └── package-info.java
│   │       │       └── module-info.java.txt
│   │       └── test/
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── iohao/
│   │           │           └── game/
│   │           │               └── common/
│   │           │                   └── kit/
│   │           │                       ├── ByteKitTest.java
│   │           │                       ├── TimeKitTest.java
│   │           │                       ├── attr/
│   │           │                       │   └── AttrOptionDynamicTest.java
│   │           │                       ├── beans/
│   │           │                       │   └── property/
│   │           │                       │       └── PropertyValueObservableTest.java
│   │           │                       ├── collect/
│   │           │                       │   ├── ListMultiMapTest.java
│   │           │                       │   └── SetMultiMapTest.java
│   │           │                       ├── concurrent/
│   │           │                       │   ├── TaskKitTest.java
│   │           │                       │   ├── executor/
│   │           │                       │   │   └── ExecutorRegionKitTest.java
│   │           │                       │   └── timer/
│   │           │                       │       └── delay/
│   │           │                       │           └── DelayTaskTest.java
│   │           │                       ├── time/
│   │           │                       │   ├── CacheTimeKitTest.java
│   │           │                       │   ├── ExpireTimeKitTest.java
│   │           │                       │   └── FormatTimeKitTest.java
│   │           │                       └── trace/
│   │           │                           └── TraceKitTest.java
│   │           └── resources/
│   │               └── logback.xml
│   └── common-validation/
│       ├── README.md
│       ├── pom.xml
│       └── src/
│           └── main/
│               ├── java/
│               │   └── com/
│               │       └── iohao/
│               │           └── game/
│               │               └── common/
│               │                   └── validation/
│               │                       ├── Validation.java
│               │                       ├── Validator.java
│               │                       ├── annotation/
│               │                       │   ├── EnableValidation.java
│               │                       │   └── package-info.java
│               │                       ├── package-info.java
│               │                       ├── processor/
│               │                       │   ├── ValidationProcessor.java
│               │                       │   └── package-info.java
│               │                       └── support/
│               │                           ├── JakartaValidator.java
│               │                           ├── JavaxValidator.java
│               │                           └── package-info.java
│               └── resources/
│                   └── META-INF/
│                       ├── gradle/
│                       │   └── incremental.annotation.processors
│                       └── services/
│                           └── javax.annotation.processing.Processor
├── doc_maven.txt
├── external/
│   ├── README.md
│   ├── external-core/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           └── java/
│   │               └── com/
│   │                   └── iohao/
│   │                       └── game/
│   │                           └── external/
│   │                               └── core/
│   │                                   ├── ExternalCore.java
│   │                                   ├── ExternalCoreSetting.java
│   │                                   ├── ExternalServer.java
│   │                                   ├── aware/
│   │                                   │   ├── ExternalCoreSettingAware.java
│   │                                   │   ├── UserSessionsAware.java
│   │                                   │   └── package-info.java
│   │                                   ├── broker/
│   │                                   │   └── client/
│   │                                   │       ├── ExternalBrokerClientStartup.java
│   │                                   │       ├── enhance/
│   │                                   │       │   ├── ExternalEnhance.java
│   │                                   │       │   └── ExternalEnhances.java
│   │                                   │       ├── ext/
│   │                                   │       │   ├── ExternalBizRegion.java
│   │                                   │       │   ├── ExternalBizRegionContext.java
│   │                                   │       │   ├── ExternalBizRegions.java
│   │                                   │       │   ├── impl/
│   │                                   │       │   │   ├── AttachmentExternalBizRegion.java
│   │                                   │       │   │   ├── ExistUserExternalBizRegion.java
│   │                                   │       │   │   ├── ExternalBizRegionKit.java
│   │                                   │       │   │   ├── ForcedOfflineExternalBizRegion.java
│   │                                   │       │   │   ├── UserHeadMetadataExternalBizRegion.java
│   │                                   │       │   │   └── package-info.java
│   │                                   │       │   └── package-info.java
│   │                                   │       ├── package-info.java
│   │                                   │       └── processor/
│   │                                   │           ├── BroadcastMessageExternalProcessor.java
│   │                                   │           ├── BroadcastOrderMessageExternalProcessor.java
│   │                                   │           ├── BrokerClientOfflineMessageExternalProcessor.java
│   │                                   │           ├── BrokerClientOnlineMessageExternalProcessor.java
│   │                                   │           ├── EndPointLogicServerMessageExternalProcessor.java
│   │                                   │           ├── RequestCollectExternalMessageExternalProcessor.java
│   │                                   │           ├── ResponseMessageExternalProcessor.java
│   │                                   │           ├── SettingUserIdMessageExternalProcessor.java
│   │                                   │           ├── listener/
│   │                                   │           │   ├── CmdRegionBrokerClientListener.java
│   │                                   │           │   └── package-info.java
│   │                                   │           └── package-info.java
│   │                                   ├── config/
│   │                                   │   ├── ExternalGlobalConfig.java
│   │                                   │   ├── ExternalJoinEnum.java
│   │                                   │   └── package-info.java
│   │                                   ├── hook/
│   │                                   │   ├── AccessAuthenticationHook.java
│   │                                   │   ├── BrokerClientExternalAttr.java
│   │                                   │   ├── IdleHook.java
│   │                                   │   ├── UserHook.java
│   │                                   │   ├── cache/
│   │                                   │   │   ├── CmdCacheOption.java
│   │                                   │   │   ├── ExternalCmdCache.java
│   │                                   │   │   ├── ExternalCmdCacheSetting.java
│   │                                   │   │   ├── InternalAboutCache.java
│   │                                   │   │   ├── internal/
│   │                                   │   │   │   └── DefaultExternalCmdCache.java
│   │                                   │   │   └── package-info.java
│   │                                   │   ├── internal/
│   │                                   │   │   ├── DefaultAccessAuthenticationHook.java
│   │                                   │   │   ├── DefaultUserHook.java
│   │                                   │   │   ├── IdleProcessSetting.java
│   │                                   │   │   └── package-info.java
│   │                                   │   └── package-info.java
│   │                                   ├── kit/
│   │                                   │   ├── ExternalKit.java
│   │                                   │   └── package-info.java
│   │                                   ├── message/
│   │                                   │   ├── DefaultExternalCodec.java
│   │                                   │   ├── ExternalCodec.java
│   │                                   │   ├── ExternalCodecKit.java
│   │                                   │   ├── ExternalMessage.java
│   │                                   │   ├── ExternalMessageCmdCode.java
│   │                                   │   └── package-info.java
│   │                                   ├── micro/
│   │                                   │   ├── MicroBootstrap.java
│   │                                   │   ├── MicroBootstrapFlow.java
│   │                                   │   ├── PipelineContext.java
│   │                                   │   ├── join/
│   │                                   │   │   ├── ExternalJoinSelector.java
│   │                                   │   │   ├── ExternalJoinSelectors.java
│   │                                   │   │   └── package-info.java
│   │                                   │   └── package-info.java
│   │                                   ├── package-info.java
│   │                                   └── session/
│   │                                       ├── UserChannelId.java
│   │                                       ├── UserSession.java
│   │                                       ├── UserSessionOption.java
│   │                                       ├── UserSessionState.java
│   │                                       ├── UserSessions.java
│   │                                       └── package-info.java
│   └── external-netty/
│       ├── pom.xml
│       └── src/
│           └── main/
│               ├── java/
│               │   └── com/
│               │       └── iohao/
│               │           └── game/
│               │               └── external/
│               │                   └── core/
│               │                       └── netty/
│               │                           ├── DefaultExternalCore.java
│               │                           ├── DefaultExternalCoreSetting.java
│               │                           ├── DefaultExternalServer.java
│               │                           ├── DefaultExternalServerBuilder.java
│               │                           ├── SettingOption.java
│               │                           ├── handler/
│               │                           │   ├── CmdCacheHandler.java
│               │                           │   ├── CmdCheckHandler.java
│               │                           │   ├── SimpleLoggerHandler.java
│               │                           │   ├── SocketCmdAccessAuthHandler.java
│               │                           │   ├── SocketIdleExcludeHandler.java
│               │                           │   ├── SocketIdleHandler.java
│               │                           │   ├── SocketRequestBrokerHandler.java
│               │                           │   ├── SocketUserSessionHandler.java
│               │                           │   ├── check/
│               │                           │   │   ├── HttpFallbackHandler.java
│               │                           │   │   └── TcpProtocolSanityCheckHandler.java
│               │                           │   ├── codec/
│               │                           │   │   ├── TcpExternalCodec.java
│               │                           │   │   └── WebSocketExternalCodec.java
│               │                           │   └── ws/
│               │                           │       ├── HttpRealIpHandler.java
│               │                           │       └── WebSocketVerifyHandler.java
│               │                           ├── hook/
│               │                           │   ├── DefaultSocketIdleHook.java
│               │                           │   └── SocketIdleHook.java
│               │                           ├── kit/
│               │                           │   └── ExternalServerCreateKit.java
│               │                           ├── micro/
│               │                           │   ├── AbstractMicroBootstrap.java
│               │                           │   ├── AbstractMicroBootstrapFlow.java
│               │                           │   ├── DefaultPipelineContext.java
│               │                           │   ├── SocketMicroBootstrap.java
│               │                           │   ├── SocketMicroBootstrapFlow.java
│               │                           │   ├── TcpMicroBootstrapFlow.java
│               │                           │   ├── WebSocketMicroBootstrapFlow.java
│               │                           │   ├── auto/
│               │                           │   │   ├── EventLoopGroupThreadFactory.java
│               │                           │   │   ├── GroupChannelOption.java
│               │                           │   │   ├── GroupChannelOptionForLinux.java
│               │                           │   │   ├── GroupChannelOptionForMac.java
│               │                           │   │   └── GroupChannelOptionForOther.java
│               │                           │   └── join/
│               │                           │       ├── SocketExternalJoinSelector.java
│               │                           │       ├── TcpExternalJoinSelector.java
│               │                           │       └── WebSocketExternalJoinSelector.java
│               │                           ├── package-info.java
│               │                           └── session/
│               │                               ├── AbstractUserSession.java
│               │                               ├── AbstractUserSessions.java
│               │                               ├── SocketUserSession.java
│               │                               └── SocketUserSessions.java
│               └── resources/
│                   └── META-INF/
│                       └── services/
│                           └── com.iohao.game.external.core.micro.join.ExternalJoinSelector
├── history/
│   └── changeLog_ioGame17.md
├── net-bolt/
│   ├── README.md
│   ├── bolt-broker-server/
│   │   ├── README.md
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       └── com/
│   │       │           └── iohao/
│   │       │               └── game/
│   │       │                   └── bolt/
│   │       │                       └── broker/
│   │       │                           ├── cluster/
│   │       │                           │   ├── Broker.java
│   │       │                           │   ├── BrokerCluster.java
│   │       │                           │   ├── BrokerClusterManager.java
│   │       │                           │   ├── BrokerClusterManagerBuilder.java
│   │       │                           │   ├── BrokerClusterMessageHandler.java
│   │       │                           │   ├── BrokerClusterMetadata.java
│   │       │                           │   ├── BrokerRunModeEnum.java
│   │       │                           │   ├── ClusterMessageListener.java
│   │       │                           │   └── package-info.java
│   │       │                           └── server/
│   │       │                               ├── BrokerServer.java
│   │       │                               ├── BrokerServerBuilder.java
│   │       │                               ├── aware/
│   │       │                               │   ├── BrokerClientModulesAware.java
│   │       │                               │   └── BrokerServerAware.java
│   │       │                               ├── balanced/
│   │       │                               │   ├── BalancedManager.java
│   │       │                               │   ├── BrokerClientLoadBalanced.java
│   │       │                               │   ├── ExternalBrokerClientLoadBalanced.java
│   │       │                               │   ├── LogicBrokerClientLoadBalanced.java
│   │       │                               │   └── region/
│   │       │                               │       ├── BrokerClientProxy.java
│   │       │                               │       ├── BrokerClientRegion.java
│   │       │                               │       ├── BrokerClientRegionFactory.java
│   │       │                               │       ├── DefaultBrokerClientRegion.java
│   │       │                               │       ├── DefaultWithElementSelector.java
│   │       │                               │       ├── StrictBrokerClientRegion.java
│   │       │                               │       └── WithElementSelector.java
│   │       │                               ├── cluster/
│   │       │                               │   └── ClusterMessageListenerImpl.java
│   │       │                               ├── enhance/
│   │       │                               │   ├── BrokerEnhance.java
│   │       │                               │   └── BrokerEnhances.java
│   │       │                               ├── kit/
│   │       │                               │   ├── BrokerPrintKit.java
│   │       │                               │   └── EndPointClientIdKit.java
│   │       │                               ├── processor/
│   │       │                               │   ├── BroadcastMessageBrokerProcessor.java
│   │       │                               │   ├── BroadcastOrderMessageBrokerProcessor.java
│   │       │                               │   ├── BrokerClientItemConnectMessageBrokerProcessor.java
│   │       │                               │   ├── BrokerExternalKit.java
│   │       │                               │   ├── ConnectionCloseEventBrokerProcessor.java
│   │       │                               │   ├── ConnectionEventBrokerProcessor.java
│   │       │                               │   ├── ConnectionExceptionEventBrokerProcessor.java
│   │       │                               │   ├── ConnectionFailedEventBrokerProcessor.java
│   │       │                               │   ├── EndPointLogicServerMessageBrokerProcessor.java
│   │       │                               │   ├── EventBusMessageBrokerProcessor.java
│   │       │                               │   ├── InnerModuleMessageBrokerProcessor.java
│   │       │                               │   ├── InnerModuleRequestCollectExternalMessageBrokerProcessor.java
│   │       │                               │   ├── InnerModuleRequestCollectMessageBrokerProcessor.java
│   │       │                               │   ├── InnerModuleVoidMessageBrokerProcessor.java
│   │       │                               │   ├── LineKit.java
│   │       │                               │   ├── PulseSignalRequestBrokerProcessor.java
│   │       │                               │   ├── PulseSignalResponseBrokerProcessor.java
│   │       │                               │   ├── RegisterBrokerClientModuleMessageBrokerProcessor.java
│   │       │                               │   ├── RequestMessageBrokerProcessor.java
│   │       │                               │   ├── ResponseMessageBrokerProcessor.java
│   │       │                               │   └── SettingUserIdMessageBrokerProcessor.java
│   │       │                               └── service/
│   │       │                                   ├── BrokerClientModules.java
│   │       │                                   └── DefaultBrokerClientModules.java
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── iohao/
│   │                       └── game/
│   │                           └── bolt/
│   │                               └── broker/
│   │                                   ├── cluster/
│   │                                   │   ├── Gossip1Test.java
│   │                                   │   └── Gossip2Test.java
│   │                                   └── server/
│   │                                       └── BrokerServerStandaloneTest.java
│   ├── bolt-client/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           └── java/
│   │               └── com/
│   │                   └── iohao/
│   │                       └── game/
│   │                           └── bolt/
│   │                               └── broker/
│   │                                   └── client/
│   │                                       ├── AbstractBrokerClientStartup.java
│   │                                       ├── BrokerClientApplication.java
│   │                                       ├── BrokerClientStartup.java
│   │                                       ├── RemoteAddress.java
│   │                                       ├── package-info.java
│   │                                       └── processor/
│   │                                           ├── BoltChannelContext.java
│   │                                           ├── BrokerClientLineKit.java
│   │                                           ├── BrokerClientOfflineMessageLogicProcessor.java
│   │                                           ├── BrokerClientOnlineMessageLogicProcessor.java
│   │                                           ├── BrokerClusterMessageClientProcessor.java
│   │                                           ├── EventBusMessageClientProcessor.java
│   │                                           ├── RequestBrokerClientModuleMessageClientProcessor.java
│   │                                           ├── RequestMessageClientProcessor.java
│   │                                           ├── connection/
│   │                                           │   ├── CloseConnectEventClientProcessor.java
│   │                                           │   ├── ConnectEventClientProcessor.java
│   │                                           │   ├── ConnectFailedEventClientProcessor.java
│   │                                           │   ├── ExceptionConnectEventClientProcessor.java
│   │                                           │   └── package-info.java
│   │                                           └── package-info.java
│   └── bolt-core/
│       ├── pom.xml
│       └── src/
│           └── main/
│               └── java/
│                   └── com/
│                       ├── alipay/
│                       │   └── sofa/
│                       │       └── common/
│                       │           └── log/
│                       │               └── factory/
│                       │                   └── LoggerSpaceFactory4LogbackBuilder.java
│                       └── iohao/
│                           └── game/
│                               ├── bolt/
│                               │   └── broker/
│                               │       ├── client/
│                               │       │   └── kit/
│                               │       │       ├── ExternalCommunicationKit.java
│                               │       │       ├── UserIdSettingKit.java
│                               │       │       └── package-info.java
│                               │       └── core/
│                               │           ├── BoltConnection.java
│                               │           ├── GroupWith.java
│                               │           ├── aware/
│                               │           │   ├── AwareInject.java
│                               │           │   ├── AwareKit.java
│                               │           │   ├── BrokerClientAware.java
│                               │           │   ├── BrokerClientItemAware.java
│                               │           │   ├── CmdRegionsAware.java
│                               │           │   ├── PulseConsumerAware.java
│                               │           │   ├── PulseProducerAware.java
│                               │           │   ├── UserProcessorExecutorAware.java
│                               │           │   ├── UserProcessorExecutorSelectorAware.java
│                               │           │   └── UserProcessorInNettyThreadAware.java
│                               │           ├── client/
│                               │           │   ├── Broadcast.java
│                               │           │   ├── BroadcastDebug.java
│                               │           │   ├── BrokerAddress.java
│                               │           │   ├── BrokerClient.java
│                               │           │   ├── BrokerClientAttr.java
│                               │           │   ├── BrokerClientBuilder.java
│                               │           │   ├── BrokerClientHelper.java
│                               │           │   ├── BrokerClientItem.java
│                               │           │   ├── BrokerClientManager.java
│                               │           │   ├── BrokerClientType.java
│                               │           │   ├── BrokerClients.java
│                               │           │   ├── DefaultProcessorContext.java
│                               │           │   ├── EventBusBrokerClientListener.java
│                               │           │   └── config/
│                               │           │       └── BrokerClientStatusConfig.java
│                               │           ├── common/
│                               │           │   ├── AbstractAsyncUserProcessor.java
│                               │           │   ├── DefaultUserProcessorExecutorSelectorStrategy.java
│                               │           │   ├── DefaultUserProcessorExecutorStrategy.java
│                               │           │   ├── IoGameGlobalConfig.java
│                               │           │   ├── ProcessorSelectorThreadExecutorRegion.java
│                               │           │   ├── UserProcessorExecutorSelectorStrategy.java
│                               │           │   ├── UserProcessorExecutorStrategy.java
│                               │           │   ├── VirtualThreadUserProcessorExecutorStrategy.java
│                               │           │   └── processor/
│                               │           │       ├── hook/
│                               │           │       │   ├── ClientProcessorHooks.java
│                               │           │       │   ├── DefaultRequestMessageClientProcessorHook.java
│                               │           │       │   └── RequestMessageClientProcessorHook.java
│                               │           │       ├── listener/
│                               │           │       │   ├── BrokerClientListener.java
│                               │           │       │   ├── BrokerClientListenerRegion.java
│                               │           │       │   ├── ConnectionBeforeListener.java
│                               │           │       │   ├── LineListener.java
│                               │           │       │   └── SimplePrintBrokerClientListener.java
│                               │           │       └── pulse/
│                               │           │           ├── PulseSignalRequestUserProcessor.java
│                               │           │           └── PulseSignalResponseUserProcessor.java
│                               │           ├── kit/
│                               │           │   └── HessianKit.java
│                               │           ├── loadbalance/
│                               │           │   ├── ElementSelector.java
│                               │           │   ├── ElementSelectorFactory.java
│                               │           │   ├── RandomElementSelector.java
│                               │           │   └── RingElementSelector.java
│                               │           └── message/
│                               │               ├── BroadcastMessage.java
│                               │               ├── BroadcastOrderMessage.java
│                               │               ├── BrokerClientItemConnectMessage.java
│                               │               ├── BrokerClientModuleMessage.java
│                               │               ├── BrokerClientOfflineMessage.java
│                               │               ├── BrokerClientOnlineMessage.java
│                               │               ├── BrokerClusterMessage.java
│                               │               ├── BrokerMessage.java
│                               │               ├── InnerModuleMessage.java
│                               │               ├── InnerModuleVoidMessage.java
│                               │               └── RequestBrokerClientModuleMessage.java
│                               └── core/
│                                   └── common/
│                                       ├── NetCommonKit.java
│                                       ├── client/
│                                       │   ├── Attachment.java
│                                       │   └── ExternalBizCodeCont.java
│                                       └── cmd/
│                                           ├── BrokerClientId.java
│                                           ├── CmdRegion.java
│                                           ├── CmdRegions.java
│                                           ├── DefaultCmdRegion.java
│                                           └── DefaultCmdRegions.java
├── pom.xml
├── run-one/
│   └── run-one-netty/
│       ├── pom.xml
│       └── src/
│           └── main/
│               └── java/
│                   └── com/
│                       └── iohao/
│                           └── game/
│                               └── external/
│                                   └── core/
│                                       └── netty/
│                                           └── simple/
│                                               ├── InternalRunOne.java
│                                               ├── NettyClusterSimpleHelper.java
│                                               ├── NettyClusterSimpleRunOne.java
│                                               ├── NettyRunOne.java
│                                               └── NettySimpleHelper.java
└── widget/
    ├── generate-code/
    │   ├── pom.xml
    │   └── src/
    │       └── main/
    │           ├── java/
    │           │   └── com/
    │           │       └── iohao/
    │           │           └── game/
    │           │               └── action/
    │           │                   └── skeleton/
    │           │                       └── core/
    │           │                           └── doc/
    │           │                               ├── CsharpDocumentGenerate.java
    │           │                               ├── DocumentGenerateAbout.java
    │           │                               ├── GDScriptDocumentGenerate.java
    │           │                               └── TypeScriptDocumentGenerate.java
    │           └── resources/
    │               └── generate/
    │                   ├── csharp/
    │                   │   ├── action.txt
    │                   │   ├── action_method.txt
    │                   │   ├── action_method_no_param.txt
    │                   │   ├── action_method_result_example.txt
    │                   │   ├── action_method_void.txt
    │                   │   ├── action_method_void_no_param.txt
    │                   │   ├── broadcast_action.txt
    │                   │   ├── broadcast_action_example.txt
    │                   │   ├── broadcast_action_example_action.txt
    │                   │   └── game_code.txt
    │                   ├── gdscript/
    │                   │   ├── action.txt
    │                   │   ├── action_method.txt
    │                   │   ├── action_method_no_param.txt
    │                   │   ├── action_method_result_example.txt
    │                   │   ├── action_method_void.txt
    │                   │   ├── action_method_void_no_param.txt
    │                   │   ├── broadcast_action.txt
    │                   │   ├── broadcast_action_example.txt
    │                   │   ├── broadcast_action_example_action.txt
    │                   │   └── game_code.txt
    │                   └── ts/
    │                       ├── action.txt
    │                       ├── action_method.txt
    │                       ├── action_method_no_param.txt
    │                       ├── action_method_result_example.txt
    │                       ├── action_method_void.txt
    │                       ├── action_method_void_no_param.txt
    │                       ├── broadcast_action.txt
    │                       ├── broadcast_action_example.txt
    │                       ├── broadcast_action_example_action.txt
    │                       └── game_code.txt
    ├── light-client/
    │   ├── pom.xml
    │   └── src/
    │       └── main/
    │           └── java/
    │               └── com/
    │                   └── iohao/
    │                       └── game/
    │                           └── external/
    │                               └── client/
    │                                   ├── AbstractInputCommandRegion.java
    │                                   ├── ClientConnectOption.java
    │                                   ├── InputCommandCreate.java
    │                                   ├── InputCommandRegion.java
    │                                   ├── command/
    │                                   │   ├── CallbackDelegate.java
    │                                   │   ├── CommandResult.java
    │                                   │   ├── InputCommand.java
    │                                   │   ├── ListenCommand.java
    │                                   │   ├── RequestCommand.java
    │                                   │   └── RequestDataDelegate.java
    │                                   ├── join/
    │                                   │   ├── ClientConnect.java
    │                                   │   ├── ClientConnects.java
    │                                   │   ├── ClientRunOne.java
    │                                   │   ├── ClientTcpExternalCodec.java
    │                                   │   ├── TcpClientStartup.java
    │                                   │   ├── WebSocketClientStartup.java
    │                                   │   └── handler/
    │                                   │       └── ClientMessageHandler.java
    │                                   ├── kit/
    │                                   │   ├── AssertKit.java
    │                                   │   ├── ClientKit.java
    │                                   │   ├── ClientUserConfigs.java
    │                                   │   ├── ScannerKit.java
    │                                   │   └── SplitParam.java
    │                                   ├── package-info.java
    │                                   └── user/
    │                                       ├── ClientChannelRead.java
    │                                       ├── ClientUser.java
    │                                       ├── ClientUserChannel.java
    │                                       ├── ClientUserInputCommands.java
    │                                       ├── ClientUsers.java
    │                                       ├── DefaultClientUser.java
    │                                       └── InternalAboutClient.java
    ├── light-domain-event/
    │   ├── pom.xml
    │   └── src/
    │       ├── main/
    │       │   └── java/
    │       │       └── com/
    │       │           └── iohao/
    │       │               └── game/
    │       │                   └── widget/
    │       │                       └── light/
    │       │                           └── domain/
    │       │                               └── event/
    │       │                                   ├── DisruptorManager.java
    │       │                                   ├── DomainEventContext.java
    │       │                                   ├── DomainEventContextParam.java
    │       │                                   ├── DomainEventPublish.java
    │       │                                   ├── annotation/
    │       │                                   │   └── DomainEvent.java
    │       │                                   ├── disruptor/
    │       │                                   │   ├── ConsumeEventHandler.java
    │       │                                   │   ├── DefaultDisruptorCreate.java
    │       │                                   │   ├── DisruptorCreate.java
    │       │                                   │   ├── DomainEventSource.java
    │       │                                   │   ├── EventDisruptor.java
    │       │                                   │   └── package-info.java
    │       │                                   ├── exception/
    │       │                                   │   ├── DefaultDomainEventExceptionHandler.java
    │       │                                   │   └── package-info.java
    │       │                                   ├── message/
    │       │                                   │   ├── DomainEventHandler.java
    │       │                                   │   ├── Eo.java
    │       │                                   │   ├── Topic.java
    │       │                                   │   └── package-info.java
    │       │                                   └── package-info.java
    │       └── test/
    │           └── java/
    │               └── com/
    │                   └── iohao/
    │                       └── game/
    │                           └── widget/
    │                               └── light/
    │                                   └── domain/
    │                                       └── event/
    │                                           ├── StudentDomainEventTest.java
    │                                           ├── StudentDomainEventTest2.java
    │                                           ├── UserLoginDomainEventTest.java
    │                                           ├── student/
    │                                           │   ├── StudentCountEventHandler.java
    │                                           │   ├── StudentEmailEventHandler1.java
    │                                           │   ├── StudentEo.java
    │                                           │   ├── StudentGoHomeEventHandler2.java
    │                                           │   ├── StudentSleepEventHandler3.java
    │                                           │   └── package-info.java
    │                                           └── user/
    │                                               ├── UserLogin.java
    │                                               ├── UserLoginEmailEventHandler.java
    │                                               └── package-info.java
    ├── light-game-room/
    │   ├── pom.xml
    │   └── src/
    │       └── main/
    │           └── java/
    │               └── com/
    │                   └── iohao/
    │                       └── game/
    │                           └── widget/
    │                               └── light/
    │                                   └── room/
    │                                       ├── GameRoomService.java
    │                                       ├── Player.java
    │                                       ├── Room.java
    │                                       ├── RoomBroadcastEnhance.java
    │                                       ├── RoomKit.java
    │                                       ├── RoomService.java
    │                                       ├── RoomStatusEnum.java
    │                                       ├── SimplePlayer.java
    │                                       ├── SimpleRoom.java
    │                                       ├── SimpleRoomService.java
    │                                       ├── domain/
    │                                       │   ├── GameFlowEo.java
    │                                       │   ├── GameFlowEventHandler.java
    │                                       │   ├── OperationContextEventHandler.java
    │                                       │   └── package-info.java
    │                                       ├── flow/
    │                                       │   ├── GameFixedService.java
    │                                       │   ├── GameFlowContext.java
    │                                       │   ├── GameFlowService.java
    │                                       │   ├── GameStartService.java
    │                                       │   ├── PlayerCreator.java
    │                                       │   ├── RoomCreateContext.java
    │                                       │   ├── RoomCreator.java
    │                                       │   ├── SimpleGameFlowContext.java
    │                                       │   ├── SimpleRoomCreateContext.java
    │                                       │   └── package-info.java
    │                                       ├── operation/
    │                                       │   ├── OperationContext.java
    │                                       │   ├── OperationFactory.java
    │                                       │   ├── OperationHandler.java
    │                                       │   ├── OperationService.java
    │                                       │   ├── PlayerOperationContext.java
    │                                       │   ├── SimpleOperationFactory.java
    │                                       │   ├── SimpleOperationHandler.java
    │                                       │   └── package-info.java
    │                                       └── package-info.java
    ├── light-jprotobuf/
    │   ├── pom.xml
    │   └── src/
    │       ├── main/
    │       │   └── java/
    │       │       └── com/
    │       │           └── iohao/
    │       │               └── game/
    │       │                   └── widget/
    │       │                       └── light/
    │       │                           └── protobuf/
    │       │                               ├── FieldNameGenerate.java
    │       │                               ├── ProtoFieldTypeHolder.java
    │       │                               ├── ProtoFileMerge.java
    │       │                               ├── ProtoFileValue.java
    │       │                               ├── ProtoGenerateFile.java
    │       │                               ├── ProtoGenerateSetting.java
    │       │                               ├── ProtoJava.java
    │       │                               ├── ProtoJavaAnalyse.java
    │       │                               ├── ProtoJavaField.java
    │       │                               ├── ProtoJavaRegion.java
    │       │                               ├── ProtoJavaRegionKey.java
    │       │                               └── kit/
    │       │                                   └── GenerateFileKit.java
    │       └── test/
    │           └── java/
    │               └── com/
    │                   └── iohao/
    │                       └── game/
    │                           └── widget/
    │                               └── light/
    │                                   └── protobuf/
    │                                       ├── ProtoJavaTest.java
    │                                       └── data/
    │                                           ├── AnimalTypeEnum.java
    │                                           ├── Cat.java
    │                                           ├── Food.java
    │                                           ├── ProtoTeacher.java
    │                                           ├── TempProtoFile.java
    │                                           ├── TestEnum.java
    │                                           └── Tiger.java
    ├── light-profile/
    │   ├── pom.xml
    │   └── src/
    │       ├── main/
    │       │   └── java/
    │       │       └── com/
    │       │           └── iohao/
    │       │               └── game/
    │       │                   └── widget/
    │       │                       └── light/
    │       │                           └── profile/
    │       │                               ├── Profile.java
    │       │                               ├── ProfileManager.java
    │       │                               ├── ResourcePatternResolverProfile.java
    │       │                               └── package-info.java
    │       └── test/
    │           ├── java/
    │           │   └── com/
    │           │       └── iohao/
    │           │           └── game/
    │           │               └── widget/
    │           │                   └── light/
    │           │                       └── profile/
    │           │                           ├── ProfileManagerTest.java
    │           │                           └── ResourcePatternResolverProfileTest.java
    │           └── resources/
    │               └── conf/
    │                   ├── common/
    │                   │   ├── db.props
    │                   │   └── other.props
    │                   ├── local/
    │                   │   └── db.props
    │                   └── production/
    │                       ├── db.props
    │                       └── other.props
    └── other-tool/
        ├── README.md
        ├── pom.xml
        └── src/
            └── main/
                └── java/
                    ├── com/
                    │   └── iohao/
                    │       └── game/
                    │           └── common/
                    │               └── kit/
                    │                   └── adapter/
                    │                       ├── AdapterHuUtils.java
                    │                       ├── HuArrayUtil.java
                    │                       ├── HuAssert.java
                    │                       ├── HuBase16Codec.java
                    │                       ├── HuCharFinder.java
                    │                       ├── HuCharUtil.java
                    │                       ├── HuCharsetUtil.java
                    │                       ├── HuClassLoaderUtil.java
                    │                       ├── HuClassPathResource.java
                    │                       ├── HuClassUtil.java
                    │                       ├── HuComputeIter.java
                    │                       ├── HuCopyVisitor.java
                    │                       ├── HuExceptionUtil.java
                    │                       ├── HuFastByteArrayOutputStream.java
                    │                       ├── HuFastByteBuffer.java
                    │                       ├── HuFileResource.java
                    │                       ├── HuFileUtil.java
                    │                       ├── HuFileWriter.java
                    │                       ├── HuFilter.java
                    │                       ├── HuFinder.java
                    │                       ├── HuHexUtil.java
                    │                       ├── HuIoCopier.java
                    │                       ├── HuIoRuntimeException.java
                    │                       ├── HuIoUtil.java
                    │                       ├── HuNoResourceException.java
                    │                       ├── HuObjectUtil.java
                    │                       ├── HuPathUtil.java
                    │                       ├── HuPercentCodec.java
                    │                       ├── HuResource.java
                    │                       ├── HuResourceUtil.java
                    │                       ├── HuRfc3986.java
                    │                       ├── HuSplitIter.java
                    │                       ├── HuStrFinder.java
                    │                       ├── HuStrFormatter.java
                    │                       ├── HuStrUtil.java
                    │                       ├── HuStreamCopier.java
                    │                       ├── HuTextFinder.java
                    │                       ├── HuUrlResource.java
                    │                       ├── HuUrlUtil.java
                    │                       ├── HuUtilException.java
                    │                       └── package-info.java
                    └── module-info.java.txt
Download .txt
Showing preview only (375K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (3949 symbols across 729 files)

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/IoGameVersion.java
  class IoGameVersion (line 25) | public final class IoGameVersion {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionCommand.java
  class ActionCommand (line 66) | @Getter
    method ActionCommand (line 103) | private ActionCommand(Builder builder) {
    method streamParamInfo (line 129) | public Stream<ParamInfo> streamParamInfo() {
    method containAnnotation (line 140) | public boolean containAnnotation(Class<? extends Annotation> annotatio...
    method getAnnotation (line 152) | public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
    class Builder (line 161) | @Accessors(chain = true)
      method build (line 192) | ActionCommand build() {
    type MethodParamResultInfo (line 200) | public interface MethodParamResultInfo {
      method isList (line 206) | default boolean isList() {
      method getActualTypeArgumentClazz (line 219) | Class<?> getActualTypeArgumentClazz();
    class ParamInfo (line 225) | @Getter
      method ParamInfo (line 287) | ParamInfo(int index, Parameter p) {
      method isBizData (line 328) | public boolean isBizData() {
      method toString (line 332) | @Override
      method toString (line 337) | public String toString(boolean fullName) {
    class ActionMethodReturnInfo (line 360) | @Getter
      method ActionMethodReturnInfo (line 408) | private ActionMethodReturnInfo(ActionCommand.Builder builder) {
      method isVoid (line 431) | public boolean isVoid() {
      method toString (line 435) | @Override
      method toString (line 440) | public String toString(boolean fullName) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionCommandDocParser.java
  class ActionCommandDocParser (line 38) | @FieldDefaults(level = AccessLevel.PRIVATE)
    method ActionCommandDocParser (line 46) | ActionCommandDocParser(ActionCommandParser actionCommandParser, List<C...
    method buildSourceDoc (line 53) | private void buildSourceDoc(List<Class<?>> controllerList) {
    method extractedDeprecate (line 87) | private static void extractedDeprecate(ActionCommandRegions actionComm...
    method getActionCommandDoc (line 93) | ActionCommandDoc getActionCommandDoc(int cmd, int subCmd) {
    method getActionCommandDoc (line 98) | private ActionCommandDoc getActionCommandDoc(JavaClassDocInfo javaClas...

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionCommandFlowExecute.java
  type ActionCommandFlowExecute (line 29) | public interface ActionCommandFlowExecute {
    method execute (line 56) | void execute(FlowContext flowContext);
    method defaultInstance (line 58) | static ActionCommandFlowExecute defaultInstance() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionCommandHandler.java
  class ActionCommandHandler (line 31) | @Slf4j
    method handler (line 34) | @Override
    method settingFlowContext (line 50) | protected void settingFlowContext(FlowContext flowContext) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionCommandParser.java
  class ActionCommandParser (line 56) | @Setter
    method ActionCommandParser (line 68) | ActionCommandParser(BarSkeletonBuilder builder) {
    method buildAction (line 83) | ActionCommandParser buildAction(List<Class<?>> controllerList) {
    method getActionControllerStream (line 163) | Stream<Class<?>> getActionControllerStream(List<Class<?>> controllerLi...
    method getMethodStream (line 196) | Stream<Method> getMethodStream(Class<?> actionControllerClass) {
    method deliveryContainer (line 208) | private boolean deliveryContainer(Class<?> controllerClazz) {
    method paramInfo (line 217) | private void paramInfo(Method method, ActionCommand.Builder builder) {
    method checkExistSubCmd (line 249) | private void checkExistSubCmd(Class<?> controllerClass, int subCmd, Ac...
    method checkSoleActionName (line 262) | private void checkSoleActionName(Method method,
    method ofActionInstance (line 295) | private Object ofActionInstance(Class<?> controllerClazz) {
    method executeActionListeners (line 309) | private void executeActionListeners() {
  class ActionParserListeners (line 327) | @FieldDefaults(level = AccessLevel.PRIVATE)
    method addActionParserListener (line 331) | void addActionParserListener(ActionParserListener listener) {
    method onActionCommand (line 336) | void onActionCommand(ActionParserContext context) {
    method onAfter (line 340) | void onAfter(BarSkeleton barSkeleton) {
    method ActionParserListeners (line 344) | ActionParserListeners() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionCommandRegion.java
  class ActionCommandRegion (line 42) | @Getter
    method ActionCommandRegion (line 59) | public ActionCommandRegion(int cmd) {
    method containsKey (line 63) | public boolean containsKey(int subCmd) {
    method add (line 67) | public void add(ActionCommand subActionCommand) {
    method getMaxSubCmd (line 80) | public int getMaxSubCmd() {
    method values (line 89) | public Collection<ActionCommand> values() {
    method arrayActionCommand (line 98) | public ActionCommand[] arrayActionCommand() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionCommandRegionGlobalCheckKit.java
  class ActionCommandRegionGlobalCheckKit (line 38) | @UtilityClass
    method putActionCommandRegions (line 43) | public void putActionCommandRegions(String key, ActionCommandRegions a...
    method checkGlobalExistSubCmd (line 55) | public void checkGlobalExistSubCmd() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionCommandRegions.java
  class ActionCommandRegions (line 48) | @Getter
    method getActionCommand (line 82) | public ActionCommand getActionCommand(int cmd, int subCmd) {
    method getActionCommand (line 103) | public ActionCommand getActionCommand(int cmdMerge) {
    method listCmdMerge (line 114) | public List<Integer> listCmdMerge() {
    method streamActionCommandRegion (line 128) | Stream<ActionCommandRegion> streamActionCommandRegion() {
    method getActionCommandRegion (line 132) | ActionCommandRegion getActionCommandRegion(int cmd) {
    method initActionCommandArray (line 145) | void initActionCommandArray(BarSkeletonSetting barSkeletonSetting) {
    method convertArray (line 159) | private ActionCommand[][] convertArray(BarSkeletonSetting barSkeletonS...
    method getMaxCmd (line 179) | private int getMaxCmd(BarSkeletonSetting barSkeletonSetting) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionFactoryBean.java
  type ActionFactoryBean (line 30) | public interface ActionFactoryBean<T> {
    method getBean (line 40) | T getBean(ActionCommand actionCommand);
    method getBean (line 48) | default T getBean(Class<?> actionControllerClazz) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionParserListenerAbout.java
  class ProtobufActionParserListener (line 45) | @FieldDefaults(level = AccessLevel.PRIVATE)
    method onActionCommand (line 66) | @Override
    method collect (line 73) | static void collect(ActionParserContext context, Predicate<Class<?>> p...
    method onAfter (line 101) | @Override
  class ProtobufCheckActionParserListener (line 114) | @Slf4j
    method onActionCommand (line 118) | @Override
    method onAfter (line 125) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionSend.java
  type ActionSend (line 25) | @Deprecated
    method getCmdMerge (line 34) | int getCmdMerge();

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/BarMessageKit.java
  class BarMessageKit (line 36) | @UtilityClass
    method createRequestMessage (line 38) | public RequestMessage createRequestMessage(CmdInfo cmdInfo) {
    method createRequestMessage (line 49) | public RequestMessage createRequestMessage(CmdInfo cmdInfo, Object dat...
    method employ (line 65) | public void employ(RequestMessage requestMessage, CmdInfo cmdInfo, Obj...
    method createResponseMessage (line 85) | public ResponseMessage createResponseMessage(CmdInfo cmdInfo) {
    method createResponseMessage (line 101) | public ResponseMessage createResponseMessage(CmdInfo cmdInfo, Object b...

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/BarSkeleton.java
  class BarSkeleton (line 46) | @Getter
    method BarSkeleton (line 77) | BarSkeleton(Handler[] handlers) {
    method newBuilder (line 81) | public static BarSkeletonBuilder newBuilder() {
    method handle (line 90) | public void handle(final FlowContext flowContext) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/BarSkeletonBuilder.java
  class BarSkeletonBuilder (line 48) | @Setter
    method BarSkeletonBuilder (line 86) | BarSkeletonBuilder() {
    method build (line 92) | public BarSkeleton build() {
    method addActionController (line 146) | public BarSkeletonBuilder addActionController(Class<?> controller) {
    method addBroadcastDocument (line 158) | public BarSkeletonBuilder addBroadcastDocument(BroadcastDocumentBuilde...
    method addHandler (line 163) | public BarSkeletonBuilder addHandler(Handler handler) {
    method addInOut (line 179) | public BarSkeletonBuilder addInOut(ActionMethodInOut inOut) {
    method addRunner (line 191) | public BarSkeletonBuilder addRunner(Runner runner) {
    method addActionParserListener (line 196) | public BarSkeletonBuilder addActionParserListener(ActionParserListener...
    method extractedActionCommand (line 201) | private void extractedActionCommand(BarSkeleton barSkeleton) {
    method defaultSetting (line 214) | private void defaultSetting() {
    method addMsgExceptionInfo (line 233) | @Deprecated
    method addActionSend (line 247) | @Deprecated
    method addActionSendDoc (line 261) | @Deprecated
    method addBroadcastDoc (line 274) | @Deprecated

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/BarSkeletonBuilderParamConfig.java
  class BarSkeletonBuilderParamConfig (line 52) | @Setter
    method createBuilder (line 77) | public BarSkeletonBuilder createBuilder() {
    method scanActionPackage (line 106) | public BarSkeletonBuilderParamConfig scanActionPackage(Class<?> action...
    method scanActionSendPackage (line 121) | public BarSkeletonBuilderParamConfig scanActionSendPackage(Class<?> ac...
    method addErrorCode (line 133) | @Deprecated
    method enhance (line 139) | private void enhance(BarSkeletonBuilder builder) {
    method scanClassActionController (line 150) | private void scanClassActionController(Consumer<Class<?>> actionConsum...
    method scanClassActionSend (line 161) | @Deprecated
    method scanClass (line 167) | private void scanClass(final List<Class<?>> actionList
    method extracted2 (line 182) | private static void extracted2() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/BarSkeletonSetting.java
  class BarSkeletonSetting (line 30) | @Getter
    method BarSkeletonSetting (line 107) | BarSkeletonSetting() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/CmdInfo.java
  class CmdInfo (line 40) | @Getter
    method CmdInfo (line 59) | CmdInfo(int cmdMerge) {
    method getCmdInfo (line 78) | public static CmdInfo getCmdInfo(int cmd, int subCmd) {
    method getCmdInfo (line 93) | public static CmdInfo getCmdInfo(int cmdMerge) {
    method of (line 107) | public static CmdInfo of(int cmd, int subCmd) {
    method of (line 120) | public static CmdInfo of(int cmdMerge) {
    method toString (line 124) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/CmdInfoFlyweightFactory.java
  class CmdInfoFlyweightFactory (line 33) | public final class CmdInfoFlyweightFactory {
    method of (line 52) | public static CmdInfo of(int cmd, int subCmd) {
    method of (line 66) | public static CmdInfo of(int cmdMerge) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/CmdKit.java
  class CmdKit (line 29) | @UtilityClass
    method getCmd (line 38) | public int getCmd(int cmdMerge) {
    method getSubCmd (line 49) | public int getSubCmd(int cmdMerge) {
    method merge (line 67) | public int merge(int cmd, int subCmd) {
    method mergeToString (line 71) | public String mergeToString(int cmdMerge) {
    method mergeToShort (line 78) | public String mergeToShort(int cmdMerge) {
    method toString (line 84) | public String toString(int cmdMerge) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/DataCodecKit.java
  class DataCodecKit (line 37) | @UtilityClass
    method encode (line 51) | public byte[] encode(Object data) {
    method decode (line 63) | public <T> T decode(byte[] data, Class<T> paramClazz) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/DefaultActionCommandFlowExecute.java
  class DefaultActionCommandFlowExecute (line 33) | final class DefaultActionCommandFlowExecute implements ActionCommandFlow...
    method execute (line 35) | @Override
    method me (line 79) | static DefaultActionCommandFlowExecute me() {
    class Holder (line 84) | private static class Holder {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/DefaultActionFactoryBean.java
  class DefaultActionFactoryBean (line 27) | final class DefaultActionFactoryBean<T> implements ActionFactoryBean<T> {
    method getBean (line 28) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/DependencyInjectionPart.java
  class DependencyInjectionPart (line 38) | @Getter
    method deliveryContainer (line 61) | public boolean deliveryContainer(Class<?> controllerClazz) {
    method getBean (line 65) | @SuppressWarnings("unchecked")
    method getBean (line 70) | @SuppressWarnings("unchecked")
    method DependencyInjectionPart (line 75) | private DependencyInjectionPart() {
    method me (line 79) | public static DependencyInjectionPart me() {
    class Holder (line 84) | private static class Holder {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/DevConfig.java
  class DevConfig (line 32) | @Deprecated
    method getCmdDataClass (line 61) | public static Class<?> getCmdDataClass(int cmdMerge) {
    method put (line 65) | public static void put(Integer cmdMerge, Class<?> dataClass) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/Handler.java
  type Handler (line 29) | public interface Handler {
    method handler (line 36) | boolean handler(FlowContext flowContext);

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/InOutManager.java
  type InOutManager (line 34) | public interface InOutManager {
    method fuckIn (line 40) | void fuckIn(FlowContext flowContext);
    method fuckOut (line 47) | void fuckOut(FlowContext flowContext);
    method addInOut (line 54) | void addInOut(ActionMethodInOut inOut);
    method listInOut (line 61) | List<ActionMethodInOut> listInOut();
    method getOptional (line 71) | @SuppressWarnings("unchecked")
    method ofAbcAbc (line 87) | static InOutManager ofAbcAbc() {
    method ofPipeline (line 96) | static InOutManager ofPipeline() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/InOutManagerAbout.java
  class AbcAbcInOutManager (line 29) | @FieldDefaults(level = AccessLevel.PRIVATE)
    method fuckIn (line 33) | public void fuckIn(FlowContext flowContext) {
    method fuckOut (line 48) | public void fuckOut(FlowContext flowContext) {
    method addInOut (line 63) | @Override
    method listInOut (line 68) | public List<ActionMethodInOut> listInOut() {
  class PipelineInOutManager (line 73) | final class PipelineInOutManager implements InOutManager {
    method fuckIn (line 77) | @Override
    method fuckOut (line 95) | @Override
    method addInOut (line 113) | @Override
    method listInOut (line 119) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/IoGameCommonCoreConfig.java
  class IoGameCommonCoreConfig (line 29) | @UtilityClass
    type ExternalBizCode (line 39) | public interface ExternalBizCode {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/IoGameGlobalSetting.java
  class IoGameGlobalSetting (line 30) | @UtilityClass
    method setDataCodec (line 37) | public void setDataCodec(DataCodec dataCodec) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/PrintActionKit.java
  class PrintActionKit (line 44) | @UtilityClass
    method print (line 47) | void print(BarSkeleton barSkeleton, BarSkeletonSetting setting) {
    method extractedRunners (line 78) | private static void extractedRunners(BarSkeleton barSkeleton) {
    method printInout (line 98) | void printInout(List<ActionMethodInOut> inOuts) {
    method printTitle (line 111) | private void printTitle(String title) {
    method printHandler (line 116) | void printHandler(List<Handler> handlers) {
    method printActionCommand (line 137) | void printActionCommand(ActionCommand[][] behaviors, boolean shortName) {
    method printDataCodec (line 224) | void printDataCodec() {
    method shortName (line 237) | private void shortName(Map<String, Object> params, boolean shortName) {
    method checkReturnType (line 248) | private void checkReturnType(final Class<?> returnTypeClazz) {
    class Color (line 257) | private static class Color {
      method Color (line 266) | public Color(String start) {
      method wrap (line 270) | String wrap(String str) {
      method format (line 274) | String format(String template, Map<String, Object> params) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/SkeletonAttr.java
  type SkeletonAttr (line 34) | public interface SkeletonAttr {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ValidatorKit.java
  class ValidatorKit (line 42) | @UtilityClass
    method getValidator (line 47) | public Validator getValidator() throws RuntimeException {
    method validate (line 62) | public String validate(Object data, Class<?>... groups) {
    method isValidator (line 73) | boolean isValidator(Class<?> paramClazz) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/action/parser/ActionParserContext.java
  class ActionParserContext (line 36) | @Getter

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/action/parser/ActionParserListener.java
  type ActionParserListener (line 30) | public interface ActionParserListener {
    method onActionCommand (line 39) | void onActionCommand(ActionParserContext context);
    method onAfter (line 46) | default void onAfter(BarSkeleton barSkeleton) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/codec/DataCodec.java
  type DataCodec (line 32) | public interface DataCodec {
    method encode (line 39) | byte[] encode(Object data);
    method decode (line 49) | <T> T decode(byte[] data, Class<?> dataClass);
    method codecName (line 56) | default String codecName() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/codec/DataSelfEncode.java
  type DataSelfEncode (line 28) | public interface DataSelfEncode {
    method encodeData (line 35) | byte[] encodeData();

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/codec/JsonDataCodec.java
  class JsonDataCodec (line 33) | public final class JsonDataCodec implements DataCodec {
    method encode (line 34) | @Override
    method decode (line 39) | @Override
    method codecName (line 45) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/codec/ProtoDataCodec.java
  class ProtoDataCodec (line 32) | @SuppressWarnings("unchecked")
    method encode (line 34) | @Override
    method decode (line 39) | @Override
    method codecName (line 49) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/commumication/BroadcastContext.java
  type BroadcastContext (line 33) | public interface BroadcastContext {
    method broadcast (line 40) | void broadcast(ResponseMessage responseMessage, Collection<Long> userI...
    method broadcast (line 48) | void broadcast(ResponseMessage responseMessage, long userId);
    method broadcast (line 55) | void broadcast(ResponseMessage responseMessage);
    method broadcast (line 63) | default void broadcast(CmdInfo cmdInfo, Object bizData) {
    method broadcast (line 75) | default void broadcast(CmdInfo cmdInfo, Object bizData, Collection<Lon...
    method broadcast (line 87) | default void broadcast(CmdInfo cmdInfo, Object bizData, long userId) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/commumication/BroadcastOrderContext.java
  type BroadcastOrderContext (line 37) | public interface BroadcastOrderContext {
    method broadcastOrder (line 44) | void broadcastOrder(ResponseMessage responseMessage, Collection<Long> ...
    method broadcastOrder (line 52) | void broadcastOrder(ResponseMessage responseMessage, long userId);
    method broadcastOrder (line 59) | void broadcastOrder(ResponseMessage responseMessage);
    method broadcastOrder (line 67) | default void broadcastOrder(CmdInfo cmdInfo, Object bizData) {
    method broadcastOrder (line 79) | default void broadcastOrder(CmdInfo cmdInfo, Object bizData, Collectio...
    method broadcastOrder (line 91) | default void broadcastOrder(CmdInfo cmdInfo, Object bizData, long user...

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/commumication/BrokerClientContext.java
  type BrokerClientContext (line 33) | public interface BrokerClientContext extends ChannelContext, SimpleServer {
    method getId (line 39) | String getId();
    method oneway (line 47) | void oneway(final Object request) throws Exception;
    method invokeSync (line 58) | <T> T invokeSync(final Object request) throws Exception;
    method getCommunicationAggregationContext (line 65) | CommunicationAggregationContext getCommunicationAggregationContext();
    method getBroadcastContext (line 72) | default BroadcastContext getBroadcastContext() {
    method getBroadcastOrderContext (line 81) | default BroadcastOrderContext getBroadcastOrderContext() {
    method getProcessorContext (line 90) | default ProcessorContext getProcessorContext() {
    method getInvokeModuleContext (line 99) | default InvokeModuleContext getInvokeModuleContext() {
    method getInvokeExternalModuleContext (line 108) | default InvokeExternalModuleContext getInvokeExternalModuleContext() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/commumication/ChannelContext.java
  type ChannelContext (line 31) | public interface ChannelContext {
    method sendResponse (line 37) | void sendResponse(Object responseObject);

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/commumication/CommunicationAggregationContext.java
  type CommunicationAggregationContext (line 27) | public interface CommunicationAggregationContext extends

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/commumication/InvokeExternalModuleContext.java
  type InvokeExternalModuleContext (line 40) | public interface InvokeExternalModuleContext {
    method invokeExternalModuleCollectMessage (line 53) | ResponseCollectExternalMessage invokeExternalModuleCollectMessage(int ...
    method invokeExternalModuleCollectMessage (line 65) | default ResponseCollectExternalMessage invokeExternalModuleCollectMess...
    method invokeExternalModuleCollectMessage (line 79) | ResponseCollectExternalMessage invokeExternalModuleCollectMessage(Requ...

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/commumication/InvokeModuleContext.java
  type InvokeModuleContext (line 82) | public interface InvokeModuleContext {
    method invokeModuleVoidMessage (line 99) | default void invokeModuleVoidMessage(CmdInfo cmdInfo, Object data) {
    method invokeModuleVoidMessage (line 118) | default void invokeModuleVoidMessage(CmdInfo cmdInfo) {
    method invokeModuleVoidMessage (line 136) | void invokeModuleVoidMessage(RequestMessage requestMessage);
    method invokeModuleMessageData (line 161) | default <T> T invokeModuleMessageData(CmdInfo cmdInfo, Object data, Cl...
    method invokeModuleMessageData (line 189) | default <T> T invokeModuleMessageData(CmdInfo cmdInfo, Class<T> clazz) {
    method invokeModuleMessageData (line 213) | default <T> T invokeModuleMessageData(RequestMessage requestMessage, C...
    method invokeModuleMessage (line 244) | default ResponseMessage invokeModuleMessage(CmdInfo cmdInfo, Object da...
    method invokeModuleMessage (line 271) | default ResponseMessage invokeModuleMessage(CmdInfo cmdInfo) {
    method invokeModuleMessage (line 295) | ResponseMessage invokeModuleMessage(RequestMessage requestMessage);
    method invokeModuleCollectMessage (line 327) | default ResponseCollectMessage invokeModuleCollectMessage(CmdInfo cmdI...
    method invokeModuleCollectMessage (line 364) | default ResponseCollectMessage invokeModuleCollectMessage(CmdInfo cmdI...
    method invokeModuleCollectMessage (line 400) | ResponseCollectMessage invokeModuleCollectMessage(RequestMessage reque...

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/commumication/ProcessorContext.java
  type ProcessorContext (line 36) | public interface ProcessorContext {
    method invokeOneway (line 42) | void invokeOneway(Object message);

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/commumication/SimpleServer.java
  type SimpleServer (line 27) | public interface SimpleServer {
    method getSimpleServerInfo (line 33) | SimpleServerInfo getSimpleServerInfo();

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ActionCommandDoc.java
  class ActionCommandDoc (line 36) | @Getter

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ActionCommandDocKit.java
  class ActionCommandDocKit (line 43) | @UtilityClass
    method getJavaClassDocInfoMap (line 82) | public Map<String, JavaClassDocInfo> getJavaClassDocInfoMap(List<Class...

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ActionDoc.java
  class ActionDoc (line 40) | @Getter
    method ActionDoc (line 57) | public ActionDoc(int cmd, Class<?> controllerClazz) {
    method addActionCommandDoc (line 62) | public void addActionCommandDoc(ActionCommandDoc actionCommandDoc) {
    method addActionCommand (line 67) | public void addActionCommand(ActionCommand actionCommand) {
    method stream (line 76) | public Stream<ActionCommandDoc> stream() {
    method equals (line 83) | @Override
    method hashCode (line 96) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ActionDocs.java
  class ActionDocs (line 28) | @Deprecated
    method ofActionDoc (line 37) | public static ActionDoc ofActionDoc(int cmd, Class<?> controllerClazz) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ActionDocument.java
  class ActionDocument (line 38) | @Getter
    method ActionDocument (line 48) | ActionDocument(ActionDoc actionDoc, TypeMappingDocument typeMappingDoc...
    method analyse (line 53) | void analyse() {
    method generateMemberCmdCode (line 72) | private ActionMemberCmdDocument generateMemberCmdCode(ActionCommandDoc...

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ActionMemberCmdDocument.java
  class ActionMemberCmdDocument (line 32) | @Getter
    method ActionMemberCmdDocument (line 41) | ActionMemberCmdDocument(int cmd, int subCmd, String memberName, String...

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ActionMethodDocument.java
  class ActionMethodDocument (line 35) | @Getter
    method ActionMethodDocument (line 87) | public ActionMethodDocument(ActionCommandDoc actionCommandDoc, TypeMap...
    method extractedReturnInfo (line 119) | private void extractedReturnInfo(ActionCommand actionCommand) {
    method extractedParamInfo (line 137) | private void extractedParamInfo(ActionCommand.ParamInfo paramInfo, Act...

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ActionSendDoc.java
  class ActionSendDoc (line 33) | @Data
    method ActionSendDoc (line 54) | public ActionSendDoc(DocActionSend docActionSend) {
    method ActionSendDoc (line 58) | public ActionSendDoc(CmdInfo cmdInfo, Class<?> dataClass, String descr...
    method ActionSendDoc (line 62) | public ActionSendDoc(int cmd, int subCmd, Class<?> dataClass, String d...
    method ActionSendDoc (line 69) | public ActionSendDoc(CmdInfo cmdInfo) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ActionSendDocs.java
  class ActionSendDocs (line 36) | @Getter
    method add (line 42) | public void add(ActionSendDoc actionSendDoc) {
    method put (line 46) | private void put(ActionSendDoc actionSendDoc) {
    method buildActionSendDoc (line 51) | public void buildActionSendDoc(List<Class<?>> actionSendClassList) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ActionSendDocsRegion.java
  class ActionSendDocsRegion (line 31) | @Getter
    method addActionSendDocs (line 36) | public void addActionSendDocs(ActionSendDocs actionSendDocs) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/BarSkeletonDoc.java
  class BarSkeletonDoc (line 33) | @Deprecated
    method setGenerateDoc (line 49) | public void setGenerateDoc(boolean generateDoc) {
    method addSkeleton (line 53) | public void addSkeleton(BarSkeleton barSkeleton) {
    method buildDoc (line 57) | public void buildDoc() {
    method buildDoc (line 61) | @Deprecated
    method BarSkeletonDoc (line 66) | private BarSkeletonDoc() {
    method me (line 69) | public static BarSkeletonDoc me() {
    class Holder (line 74) | private static class Holder {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/BroadcastDoc.java
  type BroadcastDoc (line 29) | @Deprecated
    method newBuilder (line 38) | static BroadcastDocBuilder newBuilder(CmdInfo cmdInfo) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/BroadcastDocBuilder.java
  class BroadcastDocBuilder (line 34) | @Accessors(chain = true)
    method BroadcastDocBuilder (line 40) | BroadcastDocBuilder(CmdInfo cmdInfo) {
    method setMethodDescription (line 44) | public BroadcastDocBuilder setMethodDescription(String methodDescripti...
    method setDataDescription (line 50) | public BroadcastDocBuilder setDataDescription(String dataDescription) {
    method setList (line 55) | public BroadcastDocBuilder setList(boolean list) {
    method setMethodName (line 60) | public BroadcastDocBuilder setMethodName(String methodName) {
    method setDescription (line 71) | public BroadcastDocBuilder setDescription(String description) {
    method setDataClassList (line 82) | public BroadcastDocBuilder setDataClassList(Class<?> dataClass) {
    method setDataClassList (line 86) | public BroadcastDocBuilder setDataClassList(Class<?> dataClass, String...
    method setDataClass (line 97) | public BroadcastDocBuilder setDataClass(Class<?> dataClass) {
    method setDataClass (line 108) | public BroadcastDocBuilder setDataClass(Class<?> dataClass, String dat...
    method build (line 121) | @Deprecated
    method buildDocument (line 131) | public BroadcastDocument buildDocument() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/BroadcastDocument.java
  class BroadcastDocument (line 34) | @Getter
    method getCmdMerge (line 71) | public int getCmdMerge() {
    method getCmd (line 75) | public int getCmd() {
    method getSubCmd (line 79) | public int getSubCmd() {
    method BroadcastDocument (line 83) | BroadcastDocument(CmdInfo cmdInfo) {
    method newBuilder (line 87) | public static BroadcastDocumentBuilder newBuilder(CmdInfo cmdInfo) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/BroadcastDocumentBuilder.java
  class BroadcastDocumentBuilder (line 44) | @Setter
    method BroadcastDocumentBuilder (line 66) | BroadcastDocumentBuilder(CmdInfo cmdInfo) {
    method setDataClassList (line 76) | public BroadcastDocumentBuilder setDataClassList(Class<?> dataClass) {
    method setDataClassList (line 80) | public BroadcastDocumentBuilder setDataClassList(Class<?> dataClass, S...
    method setDataClass (line 106) | public BroadcastDocumentBuilder setDataClass(Class<?> dataClass) {
    method setDataClass (line 117) | public BroadcastDocumentBuilder setDataClass(Class<?> dataClass, Strin...
    method getMethodName (line 133) | private String getMethodName() {
    method build (line 145) | public BroadcastDocument build() {
    method extractedPreparedProto (line 162) | private void extractedPreparedProto() {
    method buildToDocument (line 173) | public void buildToDocument() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/DocInfo.java
  class DocInfo (line 34) | @Getter
    method setHead (line 42) | void setHead(ActionCommand subBehavior) {
    method add (line 48) | void add(ActionCommand subBehavior) {
    method paramInfoToString (line 81) | private String paramInfoToString(ActionCommand.ParamInfo paramInfo) {
    method returnToString (line 87) | private String returnToString(ActionCommand.ActionMethodReturnInfo act...
    method paramResultInfoToString (line 93) | private String paramResultInfoToString(Class<?> actualClazz, boolean i...
    method render (line 107) | String render() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/DocumentAccessAuthentication.java
  type DocumentAccessAuthentication (line 28) | public interface DocumentAccessAuthentication {
    method reject (line 35) | boolean reject(int cmdMerge);

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/DocumentAnalyseKit.java
  class DocumentAnalyseKit (line 40) | @Slf4j
    method analyseActionDocument (line 43) | List<ActionDocument> analyseActionDocument(IoGameDocument ioGameDocume...
    method analyseErrorCodeDocument (line 57) | List<ErrorCodeDocument> analyseErrorCodeDocument(Class<? extends MsgEx...
    method analyseActionErrorEnumDocument (line 68) | private List<ErrorCodeDocument> analyseActionErrorEnumDocument(Class<?...
    method analyseJavaClass (line 89) | AnalyseJavaClassRecord analyseJavaClass(Class<?> clazz) {
    method analyseErrorCodeDocument (line 118) | private List<ErrorCodeDocument> analyseErrorCodeDocument(JavaClass jav...
    method getBizParam (line 147) | ActionCommand.ParamInfo getBizParam(ActionCommand actionCommand) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/DocumentGenerate.java
  type DocumentGenerate (line 28) | public interface DocumentGenerate {
    method generate (line 34) | void generate(IoGameDocument ioGameDocument);

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ErrorCodeDoc.java
  class ErrorCodeDoc (line 30) | @Data

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ErrorCodeDocs.java
  class ErrorCodeDocs (line 34) | @Getter
    method addMsgExceptionInfo (line 39) | public void addMsgExceptionInfo(MsgExceptionInfo msgExceptionInfo) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ErrorCodeDocsRegion.java
  class ErrorCodeDocsRegion (line 30) | @Deprecated
    method addErrorCodeDocs (line 35) | public void addErrorCodeDocs(ErrorCodeDocs errorCodeDocs) {
    method listErrorCodeDoc (line 40) | public List<ErrorCodeDoc> listErrorCodeDoc() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ErrorCodeDocument.java
  class ErrorCodeDocument (line 33) | @Getter

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/IoGameDocument.java
  class IoGameDocument (line 32) | @Getter

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/IoGameDocumentHelper.java
  class IoGameDocumentHelper (line 52) | @UtilityClass
    method setGenerateDoc (line 80) | public void setGenerateDoc(boolean generateDoc) {
    method generateDocument (line 90) | public void generateDocument() {
    method analyse (line 105) | private IoGameDocument analyse() {
    method addDocumentGenerate (line 156) | public void addDocumentGenerate(DocumentGenerate documentGenerate) {
    method addErrorCodeClass (line 168) | public void addErrorCodeClass(Class<? extends MsgExceptionInfo> clazz) {
    method addBroadcastDocument (line 177) | public void addBroadcastDocument(BroadcastDocument broadcastDocument) {
    method addBroadcastDocument (line 186) | public void addBroadcastDocument(BroadcastDocumentBuilder broadcastDoc...
    method ofActionDoc (line 197) | public ActionDoc ofActionDoc(int cmd, Class<?> controllerClazz) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/JavaClassDocInfo.java
  class JavaClassDocInfo (line 37) | public final class JavaClassDocInfo {
    method JavaClassDocInfo (line 41) | public JavaClassDocInfo(JavaClass javaClass) {
    method createActionCommandDoc (line 50) | public ActionCommandDoc createActionCommandDoc(Method method) {
    method methodParamReturnComment (line 74) | private void methodParamReturnComment(ActionCommandDoc actionCommandDo...
    method getComment (line 98) | public String getComment() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/TextDocumentGenerate.java
  class TextDocumentGenerate (line 37) | public final class TextDocumentGenerate implements DocumentGenerate {
    method generate (line 43) | @Override
    method gameDocURLDescription (line 92) | private void gameDocURLDescription() {
    method extractedBroadcastDoc (line 105) | private void extractedBroadcastDoc(Map<Integer, BroadcastDocument> bro...
    method toMap (line 133) | private HashMap<Object, Object> toMap(BroadcastDocument broadcastDocum...
    method extractedErrorCode (line 149) | private void extractedErrorCode(IoGameDocument ioGameDocument) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/TypeMappingDocument.java
  type TypeMappingDocument (line 35) | public interface TypeMappingDocument {
    method getMap (line 41) | Map<Class<?>, TypeMappingRecord> getMap();
    method getTypeMappingRecord (line 43) | TypeMappingRecord getTypeMappingRecord(Class<?> protoTypeClazz);
    method mapping (line 45) | default void mapping(TypeMappingRecord record, List<Class<?>> clazzLis...

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/TypeMappingRecord.java
  class TypeMappingRecord (line 33) | @Setter
    method getParamTypeName (line 57) | public String getParamTypeName(boolean isList) {
    method getOfMethodTypeName (line 61) | public String getOfMethodTypeName(boolean isList) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/enhance/BarSkeletonBuilderEnhance.java
  type BarSkeletonBuilderEnhance (line 27) | public interface BarSkeletonBuilderEnhance {
    method enhance (line 28) | void enhance(BarSkeletonBuilder builder);

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/enhance/BarSkeletonBuilderEnhances.java
  class BarSkeletonBuilderEnhances (line 32) | @UtilityClass
    method add (line 41) | void add(BarSkeletonBuilderEnhance enhance) {
    method enhance (line 45) | public void enhance(BarSkeletonBuilder builder) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/exception/ActionErrorEnum.java
  type ActionErrorEnum (line 33) | @Getter
    method ActionErrorEnum (line 71) | ActionErrorEnum(int code, String msg) {
    method getMsg (line 76) | public String getMsg() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/exception/MsgException.java
  class MsgException (line 32) | public class MsgException extends RuntimeException {
    method MsgException (line 41) | public MsgException(int msgCode, String message) {
    method MsgException (line 46) | public MsgException(MsgExceptionInfo msgExceptionInfo) {
    method getMsgExceptionInfo (line 51) | public MsgExceptionInfo getMsgExceptionInfo() {
    method getMsg (line 58) | @Override
    method getCode (line 63) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/exception/MsgExceptionInfo.java
  type MsgExceptionInfo (line 29) | public interface MsgExceptionInfo {
    method getMsg (line 35) | String getMsg();
    method getCode (line 42) | int getCode();
    method assertTrueThrows (line 50) | default void assertTrueThrows(boolean v1) throws MsgException {
    method assertTrueThrows (line 63) | default void assertTrueThrows(boolean v1, String msg) throws MsgExcept...
    method assertNonNull (line 77) | default void assertNonNull(Object value, String msg) throws MsgExcepti...
    method assertNonNull (line 87) | default void assertNonNull(Object value) throws MsgException {
    method assertNullThrows (line 97) | default void assertNullThrows(Object value) throws MsgException {
    method assertNullThrows (line 108) | default void assertNullThrows(Object value, String msg) throws MsgExce...
    method assertTrue (line 118) | default void assertTrue(boolean v1) throws MsgException {
    method assertFalse (line 133) | default void assertFalse(boolean v1) throws MsgException {
    method assertFalse (line 144) | default void assertFalse(boolean v1, String msg) throws MsgException {
    method assertTrue (line 156) | default void assertTrue(boolean v1, String msg) throws MsgException {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/exception/MsgExceptionKit.java
  class MsgExceptionKit (line 35) | @Slf4j
    method onException (line 44) | public void onException(Throwable e, FlowContext flowContext) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/ActionAfter.java
  type ActionAfter (line 27) | public interface ActionAfter {
    method execute (line 37) | void execute(FlowContext flowContext);

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/ActionMethodExceptionProcess.java
  type ActionMethodExceptionProcess (line 29) | public interface ActionMethodExceptionProcess {
    method processException (line 36) | MsgException processException(Throwable e);

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/ActionMethodInOut.java
  type ActionMethodInOut (line 43) | public interface ActionMethodInOut {
    method fuckIn (line 54) | void fuckIn(FlowContext flowContext);
    method fuckOut (line 64) | void fuckOut(FlowContext flowContext);

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/ActionMethodInvoke.java
  type ActionMethodInvoke (line 33) | public interface ActionMethodInvoke {
    method invoke (line 45) | Object invoke(FlowContext flowContext);

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/ActionMethodParamParser.java
  type ActionMethodParamParser (line 29) | public interface ActionMethodParamParser {
    method listParam (line 39) | Object[] listParam(final FlowContext flowContext);

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/ActionMethodResultWrap.java
  type ActionMethodResultWrap (line 30) | public interface ActionMethodResultWrap {
    method wrap (line 39) | void wrap(FlowContext flowContext);

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/FlowContext.java
  class FlowContext (line 54) | @Setter
    method setMethodResult (line 107) | public FlowContext setMethodResult(Object methodResult) {
    method getHeadMetadata (line 116) | @Override
    method inOutStartTime (line 129) | public void inOutStartTime() {
    method getInOutTime (line 143) | public long getInOutTime() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/FlowContextFactory.java
  type FlowContextFactory (line 32) | public interface FlowContextFactory {
    method createFlowContext (line 38) | FlowContext createFlowContext();

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/FlowContextKit.java
  class FlowContextKit (line 37) | @UtilityClass
    method employ (line 48) | public void employ(FlowContext flowContext) {
    method getChannelContext (line 79) | public ChannelContext getChannelContext(FlowContext flowContext) {
    method ofFlowContext (line 92) | public FlowContext ofFlowContext(long userId) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/InternalAboutFlowContext.java
  type SimpleContext (line 83) | interface SimpleContext extends SimpleAttachment
  type SimpleAttachment (line 104) | interface SimpleAttachment extends SimpleCommunicationInvokeExternalModu...
    method updateAttachment (line 115) | default void updateAttachment(final UserAttachment attachment) {
    method updateAttachmentAsync (line 143) | default void updateAttachmentAsync(UserAttachment attachment) {
    method updateAttachment (line 155) | default void updateAttachment() {
    method updateAttachmentAsync (line 168) | default void updateAttachmentAsync() {
    method getAttachment (line 183) | default <T extends UserAttachment> T getAttachment(final Class<T> claz...
    method getAttachment (line 221) | default <T extends UserAttachment> T getAttachment() {
  type SimpleCommunication (line 245) | interface SimpleCommunication extends SimpleExecutor
    method getBrokerClientContext (line 257) | default BrokerClientContext getBrokerClientContext() {
    method aggregationContext (line 266) | private CommunicationAggregationContext aggregationContext() {
    method getBroadcastContext (line 275) | default BroadcastContext getBroadcastContext() {
    method getBroadcastOrderContext (line 284) | default BroadcastOrderContext getBroadcastOrderContext() {
    method getInvokeModuleContext (line 293) | default InvokeModuleContext getInvokeModuleContext() {
    method getInvokeExternalModuleContext (line 302) | default InvokeExternalModuleContext getInvokeExternalModuleContext() {
    method supplyAsync (line 306) | default <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
  type SimpleCommunicationInvokeModuleCollect (line 314) | interface SimpleCommunicationInvokeModuleCollect extends SimpleCommunica...
    method invokeModuleCollectMessage (line 327) | default ResponseCollectMessage invokeModuleCollectMessage(CmdInfo cmdI...
    method invokeModuleCollectMessage (line 343) | default ResponseCollectMessage invokeModuleCollectMessage(CmdInfo cmdI...
    method invokeModuleCollectMessage (line 359) | default ResponseCollectMessage invokeModuleCollectMessage(RequestMessa...
    method invokeModuleCollectMessageFuture (line 375) | default CompletableFuture<ResponseCollectMessage> invokeModuleCollectM...
    method invokeModuleCollectMessageFuture (line 391) | default CompletableFuture<ResponseCollectMessage> invokeModuleCollectM...
    method invokeModuleCollectMessageFuture (line 407) | default CompletableFuture<ResponseCollectMessage> invokeModuleCollectM...
    method invokeModuleCollectMessageAsync (line 422) | default void invokeModuleCollectMessageAsync(CmdInfo cmdInfo, Consumer...
    method invokeModuleCollectMessageAsync (line 438) | default void invokeModuleCollectMessageAsync(CmdInfo cmdInfo, Object d...
    method invokeModuleCollectMessageAsync (line 454) | default void invokeModuleCollectMessageAsync(RequestMessage requestMes...
    method invokeModuleCollectMessageAsync (line 470) | default void invokeModuleCollectMessageAsync(final RequestMessage requ...
  type SimpleCommunicationBroadcast (line 491) | interface SimpleCommunicationBroadcast extends SimpleCommunication {
    method employTraceId (line 492) | private void employTraceId(ResponseMessage responseMessage) {
    method extractedSourceClientId (line 501) | private void extractedSourceClientId(ResponseMessage responseMessage, ...
    method broadcastMe (line 528) | default void broadcastMe(Object bizData) {
    method broadcastMe (line 539) | default void broadcastMe(CmdInfo cmdInfo, Object bizData) {
    method broadcastMe (line 549) | default void broadcastMe(ResponseMessage responseMessage) {
    method broadcast (line 564) | default void broadcast(CmdInfo cmdInfo, Object bizData) {
    method broadcast (line 574) | default void broadcast(ResponseMessage responseMessage) {
    method broadcast (line 588) | default void broadcast(CmdInfo cmdInfo, Object bizData, long userId) {
    method broadcast (line 599) | default void broadcast(final ResponseMessage responseMessage, final lo...
    method broadcast (line 616) | default void broadcast(CmdInfo cmdInfo, Object bizData, Collection<Lon...
    method broadcast (line 627) | default void broadcast(final ResponseMessage responseMessage, final Co...
    method broadcastOrderMe (line 643) | default void broadcastOrderMe(Object bizData) {
    method broadcastOrderMe (line 654) | default void broadcastOrderMe(CmdInfo cmdInfo, Object bizData) {
    method broadcastOrderMe (line 664) | default void broadcastOrderMe(ResponseMessage responseMessage) {
    method broadcastOrder (line 675) | default void broadcastOrder(CmdInfo cmdInfo, Object bizData) {
    method broadcastOrder (line 685) | default void broadcastOrder(final ResponseMessage responseMessage) {
    method broadcastOrder (line 699) | default void broadcastOrder(CmdInfo cmdInfo, Object bizData, Collectio...
    method broadcastOrder (line 710) | default void broadcastOrder(ResponseMessage responseMessage, Collectio...
    method broadcastOrder (line 724) | default void broadcastOrder(CmdInfo cmdInfo, Object bizData, long user...
    method broadcastOrder (line 735) | default void broadcastOrder(final ResponseMessage responseMessage, fin...
  type SimpleCommunicationInvokeExternalModule (line 749) | interface SimpleCommunicationInvokeExternalModule extends SimpleCommunic...
    method invokeExternalModuleCollectMessage (line 757) | default ResponseCollectExternalMessage invokeExternalModuleCollectMess...
    method invokeExternalModuleCollectMessage (line 768) | default ResponseCollectExternalMessage invokeExternalModuleCollectMess...
    method extractedSourceClientId (line 776) | private void extractedSourceClientId(RequestCollectExternalMessage req...
    method createRequestCollectExternalMessage (line 788) | default RequestCollectExternalMessage createRequestCollectExternalMess...
    method createRequestCollectExternalMessage (line 799) | default RequestCollectExternalMessage createRequestCollectExternalMess...
    method invokeExternalModuleCollectMessage (line 821) | default ResponseCollectExternalMessage invokeExternalModuleCollectMess...
    method invokeExternalModuleCollectMessageFuture (line 844) | default CompletableFuture<ResponseCollectExternalMessage> invokeExtern...
    method invokeExternalModuleCollectMessageFuture (line 855) | default CompletableFuture<ResponseCollectExternalMessage> invokeExtern...
    method invokeExternalModuleCollectMessageFuture (line 872) | default CompletableFuture<ResponseCollectExternalMessage> invokeExtern...
    method invokeExternalModuleCollectMessageAsync (line 884) | default void invokeExternalModuleCollectMessageAsync(int bizCode
    method invokeExternalModuleCollectMessageAsync (line 897) | default void invokeExternalModuleCollectMessageAsync(int bizCode
    method invokeExternalModuleCollectMessageAsync (line 913) | default void invokeExternalModuleCollectMessageAsync(RequestCollectExt...
    method invokeExternalModuleCollectMessageAsync (line 927) | default void invokeExternalModuleCollectMessageAsync(final RequestColl...
  type SimpleCommunicationInvokeModuleVoid (line 947) | interface SimpleCommunicationInvokeModuleVoid extends SimpleCommunication {
    method invokeModuleVoidMessage (line 963) | default void invokeModuleVoidMessage(CmdInfo cmdInfo) {
    method invokeModuleVoidMessage (line 982) | default void invokeModuleVoidMessage(CmdInfo cmdInfo, Object data) {
    method invokeModuleVoidMessage (line 1001) | default void invokeModuleVoidMessage(RequestMessage requestMessage) {
  type SimpleCommunicationInvokeModule (line 1010) | interface SimpleCommunicationInvokeModule extends SimpleCommunication {
    method invokeModuleMessage (line 1018) | default ResponseMessage invokeModuleMessage(CmdInfo cmdInfo) {
    method invokeModuleMessage (line 1029) | default ResponseMessage invokeModuleMessage(CmdInfo cmdInfo, Object da...
    method invokeModuleMessage (line 1040) | default ResponseMessage invokeModuleMessage(RequestMessage requestMess...
    method invokeModuleMessageFuture (line 1051) | default CompletableFuture<ResponseMessage> invokeModuleMessageFuture(C...
    method invokeModuleMessageFuture (line 1062) | default CompletableFuture<ResponseMessage> invokeModuleMessageFuture(C...
    method invokeModuleMessageFuture (line 1073) | default CompletableFuture<ResponseMessage> invokeModuleMessageFuture(R...
    method invokeModuleMessageAsync (line 1083) | default void invokeModuleMessageAsync(CmdInfo cmdInfo, Consumer<Respon...
    method invokeModuleMessageAsync (line 1094) | default void invokeModuleMessageAsync(CmdInfo cmdInfo, Object data, Co...
    method invokeModuleMessageAsync (line 1105) | default void invokeModuleMessageAsync(RequestMessage requestMessage, C...
    method invokeModuleMessageAsync (line 1116) | default void invokeModuleMessageAsync(final RequestMessage requestMessage
  type SimpleCommunicationEventBus (line 1137) | interface SimpleCommunicationEventBus extends SimpleCommunication {
    method getEventBus (line 1143) | default EventBus getEventBus() {
    method fire (line 1156) | default void fire(Object eventSource) {
    method fireSync (line 1174) | default void fireSync(Object eventSource) {
    method fireAny (line 1195) | default void fireAny(Object eventSource) {
    method fireAnySync (line 1220) | default void fireAnySync(Object eventSource) {
    method fireLocal (line 1232) | default void fireLocal(Object eventSource) {
    method fireLocalSync (line 1244) | default void fireLocalSync(Object eventSource) {
    method fireMe (line 1256) | default void fireMe(Object eventSource) {
    method fireMeSync (line 1268) | default void fireMeSync(Object eventSource) {
    method createEventBusMessage (line 1281) | default EventBusMessage createEventBusMessage(Object eventSource) {
  type SimpleExecutor (line 1298) | interface SimpleExecutor extends SimpleCommon {
    method getExecutorRegion (line 1299) | default ExecutorRegion getExecutorRegion() {
    method getVirtualExecutor (line 1308) | default Executor getVirtualExecutor() {
    method getVirtualThreadExecutor (line 1318) | default ThreadExecutor getVirtualThreadExecutor() {
    method getExecutor (line 1332) | default Executor getExecutor() {
    method getThreadExecutor (line 1342) | default ThreadExecutor getThreadExecutor() {
    method execute (line 1356) | default void execute(Runnable command) {
    method executeVirtual (line 1373) | default void executeVirtual(Runnable command) {
  type SimpleBarMessageCreator (line 1389) | interface SimpleBarMessageCreator extends SimpleCommon {
    method createRequestMessage (line 1397) | default RequestMessage createRequestMessage(CmdInfo cmdInfo) {
    method createRequestMessage (line 1415) | default RequestMessage createRequestMessage(final CmdInfo cmdInfo, fin...
    method createResponseMessage (line 1441) | default ResponseMessage createResponseMessage(CmdInfo cmdInfo, Object ...
    method createResponseMessage (line 1457) | default ResponseMessage createResponseMessage(CmdInfo cmdInfo) {
  type SimpleCommon (line 1478) | interface SimpleCommon extends FlowOptionDynamic {
    method getHeadMetadata (line 1485) | HeadMetadata getHeadMetadata();
    method getBarSkeleton (line 1492) | BarSkeleton getBarSkeleton();
    method getCmdInfo (line 1499) | default CmdInfo getCmdInfo() {
    method getUserId (line 1508) | default long getUserId() {
  type UserIdSetting (line 1513) | interface UserIdSetting extends SimpleCommunication {
    method bindingUserId (line 1522) | default boolean bindingUserId(long userId) {
    method bindingUserIdAndGetResult (line 1533) | default SettingUserIdResult bindingUserIdAndGetResult(final long userI...
    method setUserId (line 1570) | @Deprecated
    method setUserIdAndGetResult (line 1583) | @Deprecated
  class InternalFlowContextKit (line 1589) | @UtilityClass
    method decorate (line 1591) | <T> void decorate(String traceId, Consumer<T> callback, T response) {
    method decorator (line 1600) | Runnable decorator(String traceId, Runnable command) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/ResponseMessageCreate.java
  type ResponseMessageCreate (line 29) | public interface ResponseMessageCreate {
    method createResponseMessage (line 35) | ResponseMessage createResponseMessage();

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/UserAttachment.java
  type UserAttachment (line 32) | public interface UserAttachment extends Serializable {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/attr/FlowAttr.java
  type FlowAttr (line 36) | public interface FlowAttr {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/attr/FlowOption.java
  method valueOf (line 28) | public static <T> FlowOption<T> valueOf(String name) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/attr/FlowOptionDynamic.java
  type FlowOptionDynamic (line 30) | public interface FlowOptionDynamic {
    method getOptions (line 36) | Map<FlowOption<?>, Object> getOptions();
    method hasOption (line 44) | default boolean hasOption(FlowOption<?> option) {
    method option (line 54) | @SuppressWarnings("unchecked")
    method option (line 67) | @SuppressWarnings("unchecked")

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/DebugInOut.java
  class DebugInOut (line 102) | public final class DebugInOut implements ActionMethodInOut {
    method DebugInOut (line 121) | public DebugInOut() {
    method DebugInOut (line 128) | public DebugInOut(long time) {
    method fuckIn (line 132) | @Override
    method fuckOut (line 138) | @Override
    method extractedI18n (line 187) | private static void extractedI18n(Map<String, Object> paramMap) {
    method extractedTraceId (line 207) | private static void extractedTraceId(FlowContext flowContext, Map<Stri...
    method extractedJoin (line 220) | private static void extractedJoin(FlowContext flowContext, Map<String,...
    method printValidate (line 236) | private void printValidate(FlowContext flowContext, Map<String, Object...
    method printNormal (line 260) | private void printNormal(FlowContext flowContext, Map<String, Object> ...
    method methodResponseData (line 282) | private void methodResponseData(FlowContext flowContext, Map<String, O...
    method methodRequestParam (line 303) | private void methodRequestParam(FlowContext flowContext, Map<String, O...

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/DefaultActionAfter.java
  class DefaultActionAfter (line 34) | public final class DefaultActionAfter implements ActionAfter {
    method execute (line 35) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/DefaultActionMethodExceptionProcess.java
  class DefaultActionMethodExceptionProcess (line 32) | @Slf4j
    method processException (line 34) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/DefaultActionMethodInvoke.java
  class DefaultActionMethodInvoke (line 31) | public final class DefaultActionMethodInvoke implements ActionMethodInvo...
    method invoke (line 33) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/DefaultActionMethodParamParser.java
  class DefaultActionMethodParamParser (line 37) | public final class DefaultActionMethodParamParser implements ActionMetho...
    method listParam (line 39) | @Override
    method extractedValidator (line 79) | private void extractedValidator(FlowContext flowContext, ActionCommand...

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/DefaultActionMethodResultWrap.java
  class DefaultActionMethodResultWrap (line 36) | public final class DefaultActionMethodResultWrap implements ActionMethod...
    method wrap (line 38) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/DefaultResponseMessageCreate.java
  class DefaultResponseMessageCreate (line 30) | public final class DefaultResponseMessageCreate implements ResponseMessa...
    method createResponseMessage (line 31) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/StatActionInOut.java
  class StatActionInOut (line 85) | public final class StatActionInOut implements ActionMethodInOut {
    method fuckIn (line 93) | @Override
    method fuckOut (line 99) | @Override
    class StatActionRegion (line 108) | public final class StatActionRegion {
      method update (line 111) | void update(long time, FlowContext flowContext) {
      method getStatAction (line 122) | public StatAction getStatAction(CmdInfo cmdInfo) {
      method forEach (line 134) | public void forEach(BiConsumer<CmdInfo, StatAction> action) {
      method stream (line 138) | public Stream<StatAction> stream() {
      method toString (line 142) | @Override
    class StatAction (line 151) | @Getter
      method StatAction (line 169) | private StatAction(CmdInfo cmdInfo) {
      method update (line 183) | private void update(FlowContext flowContext, long time) {
      method getTimeRange (line 213) | public TimeRange getTimeRange(long time) {
      method getAvgTime (line 225) | public long getAvgTime() {
      method toString (line 232) | @Override
    type StatActionChangeListener (line 263) | public interface StatActionChangeListener {
      method changed (line 271) | void changed(StatAction statAction, long time, FlowContext flowConte...
      method createTimeRangeList (line 288) | default List<TimeRange> createTimeRangeList() {
      method triggerUpdateTimeRange (line 309) | default boolean triggerUpdateTimeRange(StatAction statAction, long t...
      method updateTimeRange (line 320) | default void updateTimeRange(StatAction statAction, long time, FlowC...
      method flow (line 337) | default void flow(StatAction statAction, long time, FlowContext flow...
    method create (line 362) | public static TimeRange create(long start, long end) {
    method create (line 374) | public static TimeRange create(long start, long end, String name) {
    method inRange (line 378) | boolean inRange(long time) {
    method increment (line 385) | void increment() {
    method toString (line 392) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/ThreadMonitorInOut.java
  class ThreadMonitorInOut (line 65) | @Getter
    method fuckIn (line 69) | @Override
    method fuckOut (line 74) | @Override
    class ThreadMonitorRegion (line 85) | @Getter
      method getStatThread (line 89) | private ThreadMonitor getStatThread(ThreadExecutor threadExecutor) {
      method update (line 102) | void update(long time, ThreadExecutor threadExecutor) {
      method forEach (line 106) | public void forEach(Consumer<ThreadMonitor> action) {
      method toString (line 113) | @Override
    method create (line 133) | public static ThreadMonitor create(String name, ThreadExecutor executo...
    method increment (line 137) | void increment(long time) {
    method notEmpty (line 142) | boolean notEmpty() {
    method getAvgTime (line 151) | public long getAvgTime() {
    method countRemaining (line 160) | public int countRemaining() {
    method toString (line 169) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/TimeRangeInOut.java
  class TimeRangeInOut (line 100) | @Getter
    method setListener (line 112) | public void setListener(ChangeListener listener) {
    method fuckIn (line 116) | @Override
    method fuckOut (line 120) | @Override
    class TimeRangeDayRegion (line 131) | @Getter
      method forEach (line 135) | public void forEach(BiConsumer<LocalDate, TimeRangeDay> action) {
      method update (line 139) | void update(LocalDate localDate, LocalTime localTime, FlowContext fl...
      method getTimeRangeDay (line 148) | public TimeRangeDay getTimeRangeDay(LocalDate localDate) {
    method create (line 186) | public static TimeRangeDay create(LocalDate localDate, List<TimeRangeH...
    method stream (line 198) | public Stream<TimeRangeHour> stream() {
    method getTimeRangeHour (line 203) | public TimeRangeHour getTimeRangeHour(LocalTime localTime) {
    method increment (line 208) | public void increment(LocalTime localTime) {
    method toString (line 222) | @Override
    method create (line 256) | public static TimeRangeHour create(int hour, List<TimeRangeMinute> min...
    method increment (line 261) | void increment(LocalTime localTime) {
    method getHour (line 276) | public int getHour() {
    method toString (line 283) | @Override
    method create (line 317) | public static TimeRangeMinute create(int start, int end) {
    method inRange (line 321) | boolean inRange(int minute) {
    method increment (line 325) | void increment() {
    method toString (line 332) | @Override
    type ChangeListener (line 341) | public interface ChangeListener {
      method changed (line 343) | default void changed(TimeRangeDay timeRangeDay, LocalTime localTime,...
      method callbackYesterday (line 351) | default void callbackYesterday(TimeRangeDay timeRangeYesterday) {
      method nowLocalDate (line 359) | default LocalDate nowLocalDate() {
      method nowLocalTime (line 368) | default LocalTime nowLocalTime() {
      method createTimeRangeDay (line 378) | default TimeRangeDay createTimeRangeDay(LocalDate localDate) {
      method createListenerTimeRangeHourList (line 388) | default List<TimeRangeHour> createListenerTimeRangeHourList() {
      method createListenerTimeRangeHour (line 401) | default TimeRangeHour createListenerTimeRangeHour(int hour) {
      method createListenerTimeRangeMinuteList (line 411) | default List<TimeRangeMinute> createListenerTimeRangeMinuteList() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/TraceIdInOut.java
  class TraceIdInOut (line 35) | public final class TraceIdInOut implements ActionMethodInOut {
    method fuckIn (line 36) | @Override
    method fuckOut (line 47) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/parser/BoolValueMethodParser.java
  class BoolValueMethodParser (line 36) | final class BoolValueMethodParser implements MethodParser {
    method getActualClazz (line 37) | @Override
    method parseParam (line 42) | @Override
    method parseData (line 63) | @Override
    method BoolValueMethodParser (line 80) | private BoolValueMethodParser() {
    method me (line 83) | public static BoolValueMethodParser me() {
    class Holder (line 88) | private static class Holder {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/parser/DefaultMethodParser.java
  class DefaultMethodParser (line 37) | class DefaultMethodParser implements MethodParser {
    method getActualClazz (line 38) | @Override
    method parseParam (line 43) | @Override
    method parseResult (line 74) | @Override
    method parseData (line 79) | @Override
    method isCustomMethodParser (line 97) | @Override
    method DefaultMethodParser (line 102) | private DefaultMethodParser() {
    method me (line 105) | public static DefaultMethodParser me() {
    class Holder (line 110) | private static class Holder {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/parser/IntValueMethodParser.java
  class IntValueMethodParser (line 36) | final class IntValueMethodParser implements MethodParser {
    method getActualClazz (line 38) | @Override
    method parseParam (line 43) | @Override
    method parseData (line 64) | @Override
    method IntValueMethodParser (line 83) | private IntValueMethodParser() {
    method me (line 86) | public static IntValueMethodParser me() {
    class Holder (line 91) | private static class Holder {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/parser/LongValueMethodParser.java
  class LongValueMethodParser (line 36) | final class LongValueMethodParser implements MethodParser {
    method getActualClazz (line 38) | @Override
    method parseParam (line 43) | @Override
    method parseData (line 63) | @Override
    method LongValueMethodParser (line 82) | private LongValueMethodParser() {
    method me (line 85) | public static LongValueMethodParser me() {
    class Holder (line 90) | private static class Holder {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/parser/MethodParser.java
  type MethodParser (line 29) | public interface MethodParser {
    method getActualClazz (line 64) | Class<?> getActualClazz(ActionCommand.MethodParamResultInfo methodPara...
    method parseParam (line 73) | Object parseParam(byte[] data, ActionCommand.ParamInfo paramInfo);
    method parseResult (line 82) | default Object parseResult(ActionCommand.ActionMethodReturnInfo action...
    method isCustomMethodParser (line 91) | default boolean isCustomMethodParser() {
    method parseData (line 103) | default Object parseData(boolean isList, Object data) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/parser/MethodParsers.java
  class MethodParsers (line 37) | @UtilityClass
    method mappingParamSupplier (line 59) | public void mappingParamSupplier(Class<?> paramClass, Supplier<?> supp...
    method mapping (line 63) | public void mapping(Class<?> paramClass, MethodParser methodParamParse...
    method getMethodParser (line 67) | public MethodParser getMethodParser(ActionCommand.ActionMethodReturnIn...
    method getMethodParser (line 72) | public MethodParser getMethodParser(ActionCommand.ParamInfo paramInfo) {
    method getMethodParser (line 77) | public MethodParser getMethodParser(Class<?> paramClazz) {
    method clear (line 81) | public void clear() {
    method containsKey (line 86) | public boolean containsKey(Class<?> clazz) {
    method keySet (line 90) | public Set<Class<?>> keySet() {
    method init (line 94) | private void init() {
    method newObject (line 127) | Object newObject(Class<?> paramClass) {
    method mapping (line 135) | private void mapping(Class<?> paramClass, MethodParser methodParamPars...

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/parser/StringValueMethodParser.java
  class StringValueMethodParser (line 34) | final class StringValueMethodParser implements MethodParser {
    method getActualClazz (line 35) | @Override
    method parseParam (line 40) | @Override
    method parseData (line 61) | @SuppressWarnings("unchecked")
    method StringValueMethodParser (line 74) | private StringValueMethodParser() {
    method me (line 77) | public static StringValueMethodParser me() {
    class Holder (line 82) | private static class Holder {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/runner/InternalRunner.java
  class InternalRunner (line 32) | final class InternalRunner {
    method InternalRunner (line 35) | InternalRunner() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/runner/Runner.java
  type Runner (line 88) | public interface Runner {
    method onStart (line 97) | void onStart(BarSkeleton skeleton);
    method onStartAfter (line 108) | default void onStartAfter(BarSkeleton skeleton) {
    method name (line 116) | default String name() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/core/runner/Runners.java
  class Runners (line 41) | @FieldDefaults(level = AccessLevel.PRIVATE)
    method Runners (line 50) | public Runners() {
    method addRunner (line 56) | public void addRunner(Runner runner) {
    method onStart (line 69) | public void onStart() {
    method onStartAfter (line 80) | public void onStartAfter() {
    method listRunnerName (line 98) | public List<String> listRunnerName() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/AbstractEventBusRunner.java
  class AbstractEventBusRunner (line 29) | @Deprecated

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/EventBrokerClientMessage.java
  class EventBrokerClientMessage (line 34) | @Data
    method EventBrokerClientMessage (line 44) | public EventBrokerClientMessage(String appName, String tag, String bro...
    method getTopics (line 51) | public Collection<String> getTopics() {
    method equals (line 55) | @Override
    method hashCode (line 68) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/EventBus.java
  type EventBus (line 105) | public interface EventBus {
    method getId (line 111) | String getId();
    method register (line 118) | void register(Object eventBusSubscriber);
    method listSubscriber (line 126) | Collection<Subscriber> listSubscriber(EventBusMessage eventBusMessage);
    method listTopic (line 133) | Set<String> listTopic();
    method fire (line 144) | void fire(EventBusMessage eventBusMessage);
    method fireSync (line 157) | void fireSync(EventBusMessage eventBusMessage);
    method fire (line 168) | default void fire(Object eventSource) {
    method fireSync (line 184) | default void fireSync(Object eventSource) {
    method fireLocal (line 194) | default void fireLocal(Object eventSource) {
    method fireLocal (line 204) | void fireLocal(EventBusMessage eventBusMessage);
    method fireLocalSync (line 211) | default void fireLocalSync(Object eventSource) {
    method fireLocalSync (line 221) | void fireLocalSync(EventBusMessage eventBusMessage);
    method fireMe (line 231) | default void fireMe(Object eventSource) {
    method fireMe (line 244) | void fireMe(EventBusMessage eventBusMessage);
    method fireMeSync (line 254) | default void fireMeSync(Object eventSource) {
    method fireMeSync (line 267) | void fireMeSync(EventBusMessage eventBusMessage);
    method fireAny (line 278) | default void fireAny(Object eventSource) {
    method fireAny (line 292) | void fireAny(EventBusMessage eventBusMessage);
    method fireAnySync (line 303) | default void fireAnySync(Object eventSource) {
    method fireAnySync (line 317) | void fireAnySync(EventBusMessage eventBusMessage);
    method fireLocalNeighbor (line 324) | default void fireLocalNeighbor(Object eventSource) {
    method fireLocalNeighbor (line 334) | void fireLocalNeighbor(EventBusMessage eventBusMessage);
    method fireLocalNeighborSync (line 341) | default void fireLocalNeighborSync(Object eventSource) {
    method fireLocalNeighborSync (line 351) | void fireLocalNeighborSync(EventBusMessage eventBusMessage);
    method setSubscribeExecutorStrategy (line 358) | void setSubscribeExecutorStrategy(SubscribeExecutorStrategy subscribeE...
    method getSubscribeExecutorStrategy (line 365) | SubscribeExecutorStrategy getSubscribeExecutorStrategy();
    method setSubscriberInvokeCreator (line 372) | void setSubscriberInvokeCreator(SubscriberInvokeCreator subscriberInvo...
    method setEventBusMessageCreator (line 379) | void setEventBusMessageCreator(EventBusMessageCreator eventBusMessageC...
    method setEventBusListener (line 386) | void setEventBusListener(EventBusListener eventBusListener);
    method getEventBusListener (line 393) | EventBusListener getEventBusListener();
    method setEventBrokerClientMessage (line 400) | void setEventBrokerClientMessage(EventBrokerClientMessage eventBrokerC...
    method setBrokerClientContext (line 407) | void setBrokerClientContext(BrokerClientContext brokerClientContext);
    method setExecutorRegion (line 414) | void setExecutorRegion(ExecutorRegion executorRegion);
    method getExecutorRegion (line 421) | ExecutorRegion getExecutorRegion();
    method getEventBusMessageCreator (line 428) | EventBusMessageCreator getEventBusMessageCreator();
    method getEventBrokerClientMessage (line 435) | EventBrokerClientMessage getEventBrokerClientMessage();
    method createEventBusMessage (line 443) | default EventBusMessage createEventBusMessage(Object eventSource) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/EventBusFireType.java
  type EventBusFireType (line 29) | public interface EventBusFireType {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/EventBusListener.java
  type EventBusListener (line 28) | public interface EventBusListener {
    method invokeException (line 36) | void invokeException(Throwable e, Object eventSource, EventBusMessage ...
    method emptySubscribe (line 47) | void emptySubscribe(EventBusMessage eventBusMessage, EventBus eventBus);
    method defaultInstance (line 49) | static EventBusListener defaultInstance() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/EventBusMessage.java
  class EventBusMessage (line 37) | @Getter
    method containsFireType (line 65) | public boolean containsFireType(int fireType) {
    method addFireType (line 75) | void addFireType(int fireType) {
    method emptyFireType (line 79) | boolean emptyFireType() {
    method getTopic (line 83) | String getTopic() {
    method getTopicClass (line 87) | Class<?> getTopicClass() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/EventBusMessageCreator.java
  type EventBusMessageCreator (line 28) | public interface EventBusMessageCreator {
    method create (line 29) | EventBusMessage create(Object eventSource);
    method defaultInstance (line 31) | static EventBusMessageCreator defaultInstance() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/EventBusRegion.java
  class EventBusRegion (line 40) | @UtilityClass
    method getEventBus (line 42) | public EventBus getEventBus(String brokerClientId) {
    method addLocal (line 46) | void addLocal(EventBus eventBus) {
    method streamLocalEventBus (line 52) | Stream<EventBus> streamLocalEventBus() {
    method hasLocalNeighbor (line 56) | boolean hasLocalNeighbor() {
    method listLocalSubscriber (line 66) | List<Subscriber> listLocalSubscriber(EventBusMessage eventBusMessage) {
    method loadRemoteEventTopic (line 70) | public void loadRemoteEventTopic(EventBrokerClientMessage eventBrokerC...
    method unloadRemoteTopic (line 76) | public void unloadRemoteTopic(EventBrokerClientMessage eventBrokerClie...
    method listRemoteEventBrokerClientMessage (line 82) | Set<EventBrokerClientMessage> listRemoteEventBrokerClientMessage(Event...

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/EventBusRunner.java
  type EventBusRunner (line 63) | public interface EventBusRunner extends Runner {
    method onStart (line 64) | @Override
    method ofEventBus (line 105) | default EventBus ofEventBus(String id) {
    method getEventBrokerClientMessage (line 109) | private EventBrokerClientMessage getEventBrokerClientMessage(BrokerCli...
    method registerEventBus (line 130) | void registerEventBus(EventBus eventBus, BarSkeleton skeleton);

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/ExecutorSelector.java
  type ExecutorSelector (line 51) | public enum ExecutorSelector {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/InternalAboutAny.java
  class AnyTagBrokerClient (line 44) | @FieldDefaults(level = AccessLevel.PRIVATE)
    method isEmpty (line 52) | boolean isEmpty() {
    method streamEventBrokerClientMessage (line 56) | Stream<EventBrokerClientMessage> streamEventBrokerClientMessage() {
    method add (line 60) | void add(EventBrokerClientMessage eventBrokerClientMessage) {
    method remove (line 69) | void remove(EventBrokerClientMessage eventBrokerClientMessage) {
    method anyEventBrokerClientMessage (line 77) | EventBrokerClientMessage anyEventBrokerClientMessage() {
    method getIndex (line 98) | private int getIndex(long index, EventBrokerClientMessage[] clientMess...
    method reload (line 104) | private void reload() {
  class AnyTagViewData (line 130) | @Getter
    method add (line 137) | void add(EventBrokerClientMessage eventBrokerClientMessage) {
    method initLocalMessages (line 147) | private void initLocalMessages() {
    method initRemoteMessages (line 153) | private void initRemoteMessages() {
  class AnyTagView (line 160) | @FieldDefaults(level = AccessLevel.PRIVATE)
    method getAnyTagData (line 164) | AnyTagViewData getAnyTagData(EventBusMessage message) {
    method reload (line 181) | void reload(Collection<AnyTagBrokerClient> values) {
  method of (line 199) | static BrokerClientTag of(String tag) {
  method equals (line 210) | @Override
  method hashCode (line 223) | @Override
  method of (line 232) | static BrokerClientId of(String id) {
  method equals (line 243) | @Override
  method hashCode (line 256) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/InternalAboutEventBus.java
  class DefaultEventBusListener (line 52) | @Slf4j
    method invokeException (line 54) | @Override
    method emptySubscribe (line 59) | @Override
    method me (line 66) | static DefaultEventBusListener me() {
    class Holder (line 71) | private static class Holder {
  class DefaultEventBusMessageCreator (line 76) | final class DefaultEventBusMessageCreator implements EventBusMessageCrea...
    method create (line 77) | @Override
    method me (line 90) | static DefaultEventBusMessageCreator me() {
    class Holder (line 95) | private static class Holder {
  class DefaultSubscribeExecutorStrategy (line 100) | final class DefaultSubscribeExecutorStrategy implements SubscribeExecuto...
    method select (line 103) | @Override
    method getThreadIndex (line 130) | long getThreadIndex(EventBusMessage eventBusMessage) {
    method me (line 140) | static DefaultSubscribeExecutorStrategy me() {
    class Holder (line 145) | private static class Holder {
  method invoke (line 151) | @Override
  method invoke (line 171) | void invoke(Object param) {
  class DefaultSubscriberInvokeCreator (line 180) | final class DefaultSubscriberInvokeCreator implements SubscriberInvokeCr...
    method create (line 182) | @Override
    method me (line 187) | static DefaultSubscriberInvokeCreator me() {
    class Holder (line 192) | private static class Holder {
  class EventBusKit (line 197) | @UtilityClass
    method executeSafe (line 199) | void executeSafe(Runnable runnable) {
    method sort (line 203) | void sort(List<Subscriber> subscribers) {
  class EventBusLocalRegion (line 209) | @UtilityClass
    method getEventBus (line 227) | public EventBus getEventBus(String brokerClientId) {
    method hasLocalNeighbor (line 231) | boolean hasLocalNeighbor() {
    method listLocalSubscriber (line 242) | List<Subscriber> listLocalSubscriber(EventBusMessage eventBusMessage) {
    method streamEventBus (line 247) | Stream<EventBus> streamEventBus() {
    method addLocal (line 251) | void addLocal(EventBus eventBus) {
    method resetLocalSubscriber (line 257) | private void resetLocalSubscriber() {
  class EventBusAnyTagRegion (line 288) | @UtilityClass
    method getAnyTagData (line 297) | AnyTagViewData getAnyTagData(EventBusMessage message) {
    method add (line 301) | void add(EventBrokerClientMessage eventBrokerClientMessage) {
    method remove (line 311) | void remove(EventBrokerClientMessage eventBrokerClientMessage) {
    method getAnyTagBrokerClient (line 325) | private AnyTagBrokerClient getAnyTagBrokerClient(BrokerClientTag tag) {
    method reload (line 336) | private void reload() {
  class EventBusRemoteRegion (line 342) | @UtilityClass
    method loadRemoteEventTopic (line 366) | public void loadRemoteEventTopic(EventBrokerClientMessage eventBrokerC...
    method unloadRemoteTopic (line 372) | public void unloadRemoteTopic(EventBrokerClientMessage eventBrokerClie...
    method listRemoteEventBrokerClientMessage (line 382) | Set<EventBrokerClientMessage> listRemoteEventBrokerClientMessage(Event...
  class SubscriberRegistry (line 394) | @Slf4j
    method register (line 403) | void register(Object eventBusSubscriber, SubscriberInvokeCreator subsc...
    method listEventSourceClass (line 452) | Collection<Class<?>> listEventSourceClass() {
    method listSubscriber (line 456) | Collection<Subscriber> listSubscriber(EventBusMessage eventBusMessage) {
    method streamMethod (line 465) | private Stream<Method> streamMethod(Class<?> clazz) {
  type EventBusStatus (line 495) | enum EventBusStatus {
  class DefaultEventBus (line 500) | @Slf4j
    method DefaultEventBus (line 523) | DefaultEventBus(String id) {
    method setBrokerClientContext (line 527) | public void setBrokerClientContext(BrokerClientContext brokerClientCon...
    method register (line 531) | @Override
    method createEventBusMessage (line 544) | @Override
    method listTopic (line 549) | @Override
    method fire (line 559) | @Override
    method fireSync (line 571) | @Override
    method fire (line 583) | @Override
    method fireSync (line 589) | @Override
    method fireLocal (line 595) | @Override
    method fireLocal (line 601) | @Override
    method fireLocalSync (line 606) | @Override
    method fireLocalSync (line 612) | @Override
    method fireLocal (line 617) | private void fireLocal(EventBusMessage eventBusMessage, boolean async) {
    method fireRemote (line 629) | void fireRemote(EventBusMessage eventBusMessage) {
    method fireRemote (line 635) | void fireRemote(EventBusMessage eventBusMessage, Collection<EventBroke...
    method fireMe (line 653) | @Override
    method fireMe (line 659) | @Override
    method fireMeSync (line 664) | @Override
    method fireMeSync (line 670) | @Override
    method fireMe (line 675) | private void fireMe(EventBusMessage eventBusMessage, boolean async) {
    method fireAny (line 687) | @Override
    method fireAny (line 693) | @Override
    method fireAnySync (line 708) | @Override
    method fireAnySync (line 714) | @Override
    method fireAny (line 729) | void fireAny(EventBusMessage eventBusMessage, List<EventBrokerClientMe...
    method fireLocalNeighbor (line 743) | @Override
    method fireLocalNeighborSync (line 748) | @Override
    method fireLocalNeighbor (line 759) | private void fireLocalNeighbor(EventBusMessage eventBusMessage, boolea...
    method extractedPrint (line 782) | private void extractedPrint(EventBusMessage eventBusMessage) {
    method invokeSubscriber (line 793) | private void invokeSubscriber(EventBusMessage eventBusMessage, boolean...
    method invoke (line 813) | private void invoke(Subscriber subscriber, EventBusMessage eventBusMes...
    method listSubscriber (line 824) | @Override
    method equals (line 829) | @Override
    method hashCode (line 842) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/SubscribeExecutorStrategy.java
  type SubscribeExecutorStrategy (line 31) | public interface SubscribeExecutorStrategy {
    method select (line 40) | ThreadExecutor select(Subscriber subscriber, EventBusMessage eventBusM...
    method defaultInstance (line 42) | static SubscribeExecutorStrategy defaultInstance() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/Subscriber.java
  class Subscriber (line 41) | @Accessors(chain = true)
    method Subscriber (line 85) | Subscriber(long id) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/SubscriberInvoke.java
  type SubscriberInvoke (line 28) | public interface SubscriberInvoke {
    method invoke (line 35) | void invoke(EventBusMessage eventBusMessage);

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/SubscriberInvokeCreator.java
  type SubscriberInvokeCreator (line 28) | public interface SubscriberInvokeCreator {
    method create (line 36) | SubscriberInvoke create(Subscriber subscriber);
    method defaultInstance (line 38) | static SubscriberInvokeCreator defaultInstance() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/ext/spring/ActionFactoryBeanForSpring.java
  class ActionFactoryBeanForSpring (line 41) | @SuppressWarnings("unchecked")
    method getBean (line 48) | @Override
    method getBean (line 54) | @Override
    method setApplicationContext (line 59) | @Override
    method initDependencyInjectionPart (line 70) | private void initDependencyInjectionPart() {
    method ActionFactoryBeanForSpring (line 80) | private ActionFactoryBeanForSpring() {
    method me (line 83) | public static ActionFactoryBeanForSpring me() {
    class Holder (line 88) | private static class Holder {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/i18n/Bundle.java
  class Bundle (line 32) | @UtilityClass
    method getBundle (line 37) | ResourceBundle getBundle() {
    method getMessage (line 45) | public String getMessage(String key) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/i18n/MessageKey.java
  type MessageKey (line 28) | public interface MessageKey {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/kit/ExecutorSelectEnum.java
  type ExecutorSelectEnum (line 50) | public enum ExecutorSelectEnum implements Serializable {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/kit/ExecutorSelectKit.java
  class ExecutorSelectKit (line 38) | @UtilityClass
    method processLogic (line 47) | public boolean processLogic(BarSkeleton barSkeleton, FlowContext flowC...
    method getThreadExecutor (line 66) | private ThreadExecutor getThreadExecutor(BarSkeleton barSkeleton, Head...
    method getExecutorIndex (line 80) | public long getExecutorIndex(HeadMetadata headMetadata) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/kit/FixedCmd.java
  type FixedCmd (line 28) | public interface FixedCmd<V extends FixedCmd.CmdNode> {
    method get (line 30) | V get(int cmdMerge);
    method ifPresent (line 32) | void ifPresent(int cmdMerge, Consumer<V> consumer);
    method stream (line 34) | Stream<V> stream();
    type CmdNode (line 36) | interface CmdNode {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/kit/LogicServerCreateKit.java
  class LogicServerCreateKit (line 35) | @UtilityClass
    method createBuilder (line 43) | public BarSkeletonBuilder createBuilder(BarSkeletonBuilderParamConfig ...
    method createBuilder (line 53) | public BarSkeletonBuilder createBuilder(Class<?> actionControllerClass) {
    method removeInOut (line 62) | public void removeInOut(Class<? extends ActionMethodInOut> inoutClass) {
    method addInOut (line 67) | public void addInOut(ActionMethodInOut inOut) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/kit/RangeBroadcast.java
  class RangeBroadcast (line 150) | @Accessors(chain = true)
    method RangeBroadcast (line 171) | public RangeBroadcast(CommunicationAggregationContext aggregationConte...
    method RangeBroadcast (line 181) | public RangeBroadcast(FlowContext flowContext) {
    method enableEmptyUserCheck (line 190) | public RangeBroadcaster enableEmptyUserCheck() {
    method listUserId (line 195) | @Override
    method setResponseMessage (line 206) | public RangeBroadcaster setResponseMessage(ResponseMessage responseMes...
    method execute (line 231) | public final void execute() {
    method logic (line 259) | protected void logic() {
    method trick (line 265) | protected void trick() {
    method broadcast (line 271) | protected void broadcast() {
    method disableSend (line 287) | protected void disableSend() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/kit/RangeBroadcaster.java
  type RangeBroadcaster (line 143) | public interface RangeBroadcaster {
    method listUserId (line 149) | Set<Long> listUserId();
    method setResponseMessage (line 157) | RangeBroadcaster setResponseMessage(ResponseMessage responseMessage);
    method execute (line 162) | void execute();
    method of (line 170) | static RangeBroadcaster of(CommunicationAggregationContext aggregation...
    method of (line 180) | static RangeBroadcaster of(FlowContext flowContext) {
    method addUserId (line 190) | default RangeBroadcaster addUserId(Collection<Long> userIds) {
    method addUserId (line 201) | default RangeBroadcaster addUserId(long userId) {
    method addUserId (line 213) | default RangeBroadcaster addUserId(Collection<Long> userIds, long excl...
    method removeUserId (line 223) | default RangeBroadcaster removeUserId(long excludeUserId) {
    method setResponseMessage (line 237) | default RangeBroadcaster setResponseMessage(CmdInfo cmdInfo) {
    method setResponseMessage (line 249) | default RangeBroadcaster setResponseMessage(CmdInfo cmdInfo, Object bi...
    method setResponseMessageList (line 261) | default RangeBroadcaster setResponseMessageList(CmdInfo cmdInfo, Colle...
    method setResponseMessage (line 273) | default RangeBroadcaster setResponseMessage(CmdInfo cmdInfo, int bizDa...
    method setResponseMessageIntList (line 285) | default RangeBroadcaster setResponseMessageIntList(CmdInfo cmdInfo, Li...
    method setResponseMessage (line 297) | default RangeBroadcaster setResponseMessage(CmdInfo cmdInfo, long bizD...
    method setResponseMessageLongList (line 309) | default RangeBroadcaster setResponseMessageLongList(CmdInfo cmdInfo, L...
    method setResponseMessage (line 321) | default RangeBroadcaster setResponseMessage(CmdInfo cmdInfo, String bi...
    method setResponseMessageStringList (line 333) | default RangeBroadcaster setResponseMessageStringList(CmdInfo cmdInfo,...
    method setResponseMessage (line 345) | default RangeBroadcaster setResponseMessage(CmdInfo cmdInfo, boolean b...
    method setResponseMessageBoolList (line 357) | default RangeBroadcaster setResponseMessageBoolList(CmdInfo cmdInfo, L...

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/BarMessage.java
  class BarMessage (line 42) | @Getter
    method setData (line 64) | public BarMessage setData(byte[] data) {
    method setData (line 69) | public BarMessage setData(Object data) {
    method setValidatorMsg (line 91) | public BarMessage setValidatorMsg(String validatorMsg) {
    method setError (line 99) | public BarMessage setError(MsgExceptionInfo msgExceptionInfo) {
    method hasError (line 113) | public boolean hasError() {
    method success (line 117) | public boolean success() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/HeadMetadata.java
  class HeadMetadata (line 43) | @Getter
    method setCmdInfo (line 230) | public HeadMetadata setCmdInfo(CmdInfo cmdInfo) {
    method getCmdInfo (line 235) | public CmdInfo getCmdInfo() {
    method setCmdMerge (line 239) | public HeadMetadata setCmdMerge(int cmdMerge) {
    method cloneHeadMetadata (line 267) | public HeadMetadata cloneHeadMetadata() {
    method cloneAll (line 281) | public HeadMetadata cloneAll() {
    method getExternalMessage (line 302) | @SuppressWarnings("unchecked")

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/RequestMessage.java
  class RequestMessage (line 32) | public final class RequestMessage extends BarMessage {
    method createResponseMessage (line 36) | public ResponseMessage createResponseMessage() {
    method settingCommonAttr (line 44) | public void settingCommonAttr(final ResponseMessage responseMessage) {
    method copyTo (line 54) | public void copyTo(RequestMessage requestMessage) {
    method createRequestMessage (line 71) | public RequestMessage createRequestMessage(CmdInfo cmdInfo) {
    method createRequestMessage (line 85) | public RequestMessage createRequestMessage(CmdInfo cmdInfo, Object dat...

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/ResponseMessage.java
  class ResponseMessage (line 33) | public final class ResponseMessage extends BarMessage {
    method getData (line 44) | public <T> T getData(Class<T> clazz) {
    method getValue (line 55) | public <T> T getValue(Class<? extends T> clazz) {
    method listValue (line 66) | @SuppressWarnings("unchecked")
    method getString (line 80) | public String getString() {
    method listString (line 89) | public List<String> listString() {
    method getInt (line 98) | public int getInt() {
    method listInt (line 107) | public List<Integer> listInt() {
    method getLong (line 116) | public long getLong() {
    method listLong (line 125) | public List<Long> listLong() {
    method getBoolean (line 134) | public boolean getBoolean() {
    method listBoolean (line 143) | public List<Boolean> listBoolean() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/collect/RequestCollectMessage.java
  class RequestCollectMessage (line 46) | @Getter

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/collect/ResponseCollectItemMessage.java
  class ResponseCollectItemMessage (line 40) | @Getter
    method ResponseCollectItemMessage (line 50) | public ResponseCollectItemMessage() {
    method ResponseCollectItemMessage (line 53) | public ResponseCollectItemMessage(String logicServerId, ResponseMessag...
    method hasData (line 58) | public boolean hasData() {
    method getData (line 70) | public <T> T getData(Class<T> dataClazz) {
    method getValue (line 86) | public <T> T getValue(Class<? extends T> clazz) {
    method listValue (line 97) | @SuppressWarnings("unchecked")
    method getString (line 111) | public String getString() {
    method listString (line 120) | public List<String> listString() {
    method getInt (line 129) | public int getInt() {
    method listInt (line 138) | public List<Integer> listInt() {
    method getLong (line 147) | public long getLong() {
    method listLong (line 156) | public List<Long> listLong() {
    method getBoolean (line 165) | public boolean getBoolean() {
    method listBoolean (line 174) | public List<Boolean> listBoolean() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/collect/ResponseCollectMessage.java
  class ResponseCollectMessage (line 46) | @Getter
    method setError (line 66) | public ResponseCollectMessage setError(MsgExceptionInfo msgExceptionIn...
    method success (line 72) | public boolean success() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/external/RequestCollectExternalMessage.java
  class RequestCollectExternalMessage (line 42) | @Getter
    method getData (line 80) | @SuppressWarnings("unchecked")

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/external/ResponseCollectExternalItemMessage.java
  class ResponseCollectExternalItemMessage (line 36) | @Getter
    method success (line 53) | public boolean success() {
    method setError (line 57) | public void setError(MsgExceptionInfo msgExceptionInfo) {
    method setError (line 62) | public void setError(MsgException msgException) {
    method getData (line 67) | @SuppressWarnings("unchecked")

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/external/ResponseCollectExternalMessage.java
  class ResponseCollectExternalMessage (line 43) | @Getter
    method anySuccess (line 57) | public boolean anySuccess() {
    method optionalAnySuccess (line 77) | public Optional<ResponseCollectExternalItemMessage> optionalAnySuccess...

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/login/SettingUserIdMessage.java
  class SettingUserIdMessage (line 34) | @Getter
    method SettingUserIdMessage (line 44) | private SettingUserIdMessage(long userId, HeadMetadata headMetadata) {
    method of (line 49) | public static SettingUserIdMessage of(long userId, HeadMetadata headMe...

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/login/SettingUserIdMessageResponse.java
  class SettingUserIdMessageResponse (line 33) | @Data

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/login/SettingUserIdResult.java
  method ofError (line 36) | public static SettingUserIdResult ofError(Exception exception) {
  method ofError (line 40) | public static SettingUserIdResult ofError(String message) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/processor/EndPointLogicServerMessage.java
  class EndPointLogicServerMessage (line 41) | @Getter
    method addLogicServerId (line 64) | public EndPointLogicServerMessage addLogicServerId(String logicServerI...
    method addLogicServerId (line 82) | public EndPointLogicServerMessage addLogicServerId(Set<String> idSet) {
    method initSet (line 89) | private void initSet() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/processor/EndPointOperationEnum.java
  type EndPointOperationEnum (line 27) | public enum EndPointOperationEnum {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/processor/SimpleServerInfo.java
  class SimpleServerInfo (line 36) | @Getter

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/wrapper/BoolValue.java
  class BoolValue (line 37) | @ToString
    method of (line 51) | public static BoolValue of(boolean value) {
    method ofTrue (line 55) | public static BoolValue ofTrue() {
    method ofFalse (line 59) | public static BoolValue ofFalse() {
    method create (line 63) | private static BoolValue create(Boolean value) {
    method encodeData (line 70) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/wrapper/BoolValueList.java
  class BoolValueList (line 34) | @ToString
    method of (line 41) | public static BoolValueList of(List<Boolean> values) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/wrapper/ByteValueList.java
  class ByteValueList (line 37) | @ToString
    method of (line 44) | public static ByteValueList of(List<byte[]> values) {
    method ofList (line 54) | public static <T> ByteValueList ofList(Collection<T> values) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/wrapper/IntValue.java
  class IntValue (line 32) | @ToString
    method of (line 39) | public static IntValue of(int value) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/wrapper/IntValueList.java
  class IntValueList (line 34) | @ToString
    method of (line 41) | public static IntValueList of(List<Integer> values) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/wrapper/LongValue.java
  class LongValue (line 34) | @ToString
    method of (line 42) | public static LongValue of(long value) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/wrapper/LongValueList.java
  class LongValueList (line 36) | @ToString
    method of (line 44) | public static LongValueList of(List<Long> values) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/wrapper/StringValue.java
  class StringValue (line 32) | @ToString
    method of (line 39) | public static StringValue of(String value) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/wrapper/StringValueList.java
  class StringValueList (line 34) | @ToString
    method of (line 41) | public static StringValueList of(List<String> values) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/wrapper/ValueRecord.java
  class ValueRecord (line 30) | @Getter
    method ValueRecord (line 35) | ValueRecord(Class<?> valueClazz, Class<?> valueListClazz) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/wrapper/WrapperKit.java
  class WrapperKit (line 32) | @UtilityClass
    method of (line 34) | public IntValue of(int value) {
    method ofListIntValue (line 38) | public IntValueList ofListIntValue(List<Integer> values) {
    method of (line 42) | public BoolValue of(boolean value) {
    method ofListBoolValue (line 46) | public BoolValueList ofListBoolValue(List<Boolean> values) {
    method of (line 50) | public LongValue of(long value) {
    method ofListLongValue (line 54) | public LongValueList ofListLongValue(List<Long> values) {
    method of (line 58) | public StringValue of(String value) {
    method ofListStringValue (line 62) | public StringValueList ofListStringValue(List<String> values) {
    method ofListByteValue (line 66) | public <T> ByteValueList ofListByteValue(List<T> values) {
    method ofList (line 70) | public <T> ByteValueList ofList(List<T> values) {
    method ofListByteValue (line 74) | public <T> ByteValueList ofListByteValue(Collection<T> values) {
    method isWrapper (line 103) | public boolean isWrapper(Class<?> clazz) {
    method optionalRefType (line 130) | @Deprecated
    method optionalValueRecord (line 135) | public Optional<ValueRecord> optionalValueRecord(Class<?> clazz) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/pulse/Pulses.java
  class Pulses (line 36) | @Getter

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/pulse/core/PulseChannel.java
  type PulseChannel (line 27) | public interface PulseChannel {
    method channel (line 33) | String channel();

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/pulse/core/PulseTransmit.java
  type PulseTransmit (line 29) | public interface PulseTransmit {
    method transmit (line 35) | void transmit(PulseSignalMessage message);

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/pulse/core/consumer/DefaultPulseConsumers.java
  class DefaultPulseConsumers (line 37) | @Slf4j
    method addPulseConsumer (line 43) | public void addPulseConsumer(PulseConsumer<?> pulseConsumer) {
    method acceptPulseSign (line 48) | public void acceptPulseSign(PulseSignalRequest request) {
    method setPulseTransmit (line 79) | @Override
    method getPulseTransmit (line 84) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/pulse/core/consumer/PulseConsumer.java
  type PulseConsumer (line 29) | public interface PulseConsumer<T extends Serializable> extends PulseSign...

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/pulse/core/consumer/PulseConsumers.java
  type PulseConsumers (line 30) | public interface PulseConsumers {
    method addPulseConsumer (line 36) | void addPulseConsumer(PulseConsumer<?> pulseConsumer);
    method acceptPulseSign (line 46) | void acceptPulseSign(PulseSignalRequest request);
    method setPulseTransmit (line 53) | void setPulseTransmit(PulseTransmit pulseTransmit);
    method getPulseTransmit (line 60) | PulseTransmit getPulseTransmit();

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/pulse/core/consumer/PulseSignalRequestAccept.java
  type PulseSignalRequestAccept (line 32) | public interface PulseSignalRequestAccept<T> extends PulseChannel {
    method accept (line 40) | Serializable accept(T message, PulseSignalRequest request);

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/pulse/core/producer/DefaultPulseProducers.java
  class DefaultPulseProducers (line 44) | @Slf4j
    method addResponseAccept (line 55) | @Override
    method addPulseProducer (line 61) | @Override
    method startup (line 74) | @Override
    method acceptPulseSign (line 85) | @Override
    method setPulseTransmit (line 96) | @Override
    method getPulseTransmit (line 101) | @Override
    class PulseTask (line 106) | private static class PulseTask {
      method PulseTask (line 110) | PulseTask(PulseProducer<?> pulseProducer) {
      method ifPresent (line 116) | void ifPresent(Consumer<PulseSignalRequest> consumer) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/pulse/core/producer/PulseCreatePeriod.java
  type PulseCreatePeriod (line 27) | public interface PulseCreatePeriod {
    method period (line 39) | int period();

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/pulse/core/producer/PulseCreateRequest.java
  type PulseCreateRequest (line 29) | public interface PulseCreateRequest {
    method createMessage (line 35) | PulseSignalRequest createMessage();

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/pulse/core/producer/PulseProducer.java
  type PulseProducer (line 34) | public interface PulseProducer<T extends Serializable> extends

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/pulse/core/producer/PulseProducers.java
  type PulseProducers (line 30) | public interface PulseProducers {
    method addPulseProducer (line 36) | void addPulseProducer(PulseProducer<?> pulseProducer);
    method addResponseAccept (line 43) | void addResponseAccept(PulseSignalResponseAccept<?> responseAccept);
    method acceptPulseSign (line 50) | void acceptPulseSign(PulseSignalResponse response);
    method setPulseTransmit (line 57) | void setPulseTransmit(PulseTransmit pulseTransmit);
    method getPulseTransmit (line 64) | PulseTransmit getPulseTransmit();
    method startup (line 69) | void startup();

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/pulse/core/producer/PulseSignalResponseAccept.java
  type PulseSignalResponseAccept (line 36) | public interface PulseSignalResponseAccept<T> extends PulseChannel {
    method accept (line 43) | void accept(T message, PulseSignalResponse response);

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/pulse/message/EmptyMessage.java
  class EmptyMessage (line 30) | public class EmptyMessage implements Serializable {
    method empty (line 36) | public static EmptyMessage empty() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/pulse/message/PulseSignalMessage.java
  class PulseSignalMessage (line 36) | @Getter
    method getData (line 70) | @SuppressWarnings("unchecked")
    method addSignalType (line 80) | public void addSignalType(int signalType) {
    method containsSignalType (line 90) | public boolean containsSignalType(int signalType) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/pulse/message/PulseSignalRequest.java
  class PulseSignalRequest (line 29) | public final class PulseSignalRequest extends PulseSignalMessage {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/pulse/message/PulseSignalResponse.java
  class PulseSignalResponse (line 33) | @Setter
    method toString (line 40) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/pulse/message/SignalType.java
  type SignalType (line 26) | public interface SignalType {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/pulse/runner/CreatePulsesRunner.java
  class CreatePulsesRunner (line 40) | public class CreatePulsesRunner implements Runner {
    method onStart (line 42) | @Override
    method getPulses (line 64) | protected Pulses getPulses(BarSkeleton skeleton) {
    method transmit (line 77) | @Override
    method transmit (line 90) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/pulse/runner/PulseRunner.java
  type PulseRunner (line 32) | public interface PulseRunner extends Runner {
    method onStart (line 41) | @Override
    method onStart (line 59) | void onStart(PulseProducers pulseProducers, PulseConsumers pulseConsum...

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/toy/BannerColorStrategy.java
  class BannerColorStrategy (line 33) | final class BannerColorStrategy {
    method anyColor (line 35) | static Ansi.Color anyColor() {
    method anyColorFun (line 47) | UnaryOperator<String> anyColorFun() {
    method colorRandomLine (line 79) | private String colorRandomLine(String banner) {
    method colorSingle (line 101) | private String colorSingle(String banner) {
    method colorRandom (line 108) | private String colorRandom(String banner) {
    method colorRandomColumn (line 124) | private String colorRandomColumn(String banner) {
    method colorColumn (line 147) | private String colorColumn(String banner) {
    class TheColorColumn (line 186) | private static class TheColorColumn {
      method TheColorColumn (line 191) | TheColorColumn(Ansi.Color color, int widthLen) {
      method reset (line 197) | void reset() {
      method create (line 201) | static TheColorColumn create() {
      method render (line 207) | void render(Ansi ansi, char c) {
      method has (line 212) | boolean has() {
    method listColor (line 217) | private List<Ansi.Color> listColor() {
    method randomColor (line 224) | private static Ansi.Color randomColor() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/toy/BannerData.java
  class BannerData (line 28) | final class BannerData {
    method listData (line 30) | List<String> listData() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/toy/BreakingNewsAbout.java
  class BreakingNewsKit (line 38) | @UtilityClass
    method getBreakingNews (line 43) | private BreakingNews getBreakingNews() {
    method randomNewsList (line 55) | List<News> randomNewsList() {
    method randomAdv (line 62) | News randomAdv() {
    method randomMainNews (line 67) | News randomMainNews() {
  method toString (line 74) | @Override
  type BreakingNews (line 80) | interface BreakingNews {
    method listMainNews (line 81) | List<News> listMainNews();
    method listAdv (line 83) | List<News> listAdv();
    method listNews (line 85) | List<News> listNews();
  class DefaultBreakingNews (line 88) | final class DefaultBreakingNews implements BreakingNews {
    method listMainNews (line 90) | @Override
    method listAdv (line 100) | @Override
    method listNews (line 109) | @Override
  class EnglishBreakingNews (line 181) | final class EnglishBreakingNews implements BreakingNews {
    method listMainNews (line 183) | @Override
    method listAdv (line 193) | @Override
    method listNews (line 202) | @Override

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/toy/InternalMemory.java
  class InternalMemory (line 28) | final class InternalMemory {
    method getMemoryMap (line 30) | Map<String, String> getMemoryMap() {
    method format (line 45) | private String format(long value) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/toy/IoGameBanner.java
  class IoGameBanner (line 48) | @Slf4j
    method render (line 63) | public static void render() {
    method initCountDownLatch (line 77) | public void initCountDownLatch(int num) {
    method countDown (line 81) | public void countDown() {
    method incErrorCount (line 87) | private void incErrorCount() {
    method ofRuntimeException (line 95) | public void ofRuntimeException(String message) {
    method printLine (line 105) | public static void printLine() {
    method printMessage (line 109) | public static void printMessage(String message) {
    method printMessage (line 113) | public static void printMessage(Object message) {
    method println1 (line 117) | public static void println1(Object message) {
    method printlnMsg (line 121) | public static void printlnMsg(String message) {
    method printlnMsg2 (line 125) | public static void printlnMsg2(String message) {
    method renderBanner1 (line 129) | private void renderBanner1() {
    method clean (line 179) | private void clean() {
    method extractedTime (line 186) | private void extractedTime(ToyTable table) {
    method extractedBreakingNews (line 200) | private void extractedBreakingNews() {
    method extractedAdv (line 210) | private void extractedAdv() {
    method extractedIoGameJavadocApi (line 217) | private void extractedIoGameJavadocApi() {
    method extractedErrorCount (line 224) | private void extractedErrorCount() {
    method extractedPrint (line 234) | private void extractedPrint(ToyTable table) {
    method getPid (line 248) | private static String getPid() {
    method IoGameBanner (line 259) | private IoGameBanner() {
    method me (line 263) | public static IoGameBanner me() {
    class Holder (line 268) | private static class Holder {
    method init (line 272) | public void init() {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/toy/ToyLine.java
  class ToyLine (line 25) | final class ToyLine {
    method render (line 34) | String render() {
    method append (line 57) | private void append(StringBuilder builder, String c, int num) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/toy/ToyTable.java
  class ToyTable (line 31) | final class ToyTable {
    method render (line 37) | void render() {
    method countRegionMaxLine (line 58) | int countRegionMaxLine() {
    method getRegion (line 72) | ToyTableRegion getRegion(String regionName) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/toy/ToyTableRegion.java
  class ToyTableRegion (line 29) | final class ToyTableRegion {
    method putLine (line 40) | void putLine(String key, String value) {
    method putAll (line 56) | void putAll(Map<?, ?> map) {
    method render (line 62) | void render() {
    method renderHead (line 95) | String renderHead() {
    method append (line 115) | private void append(StringBuilder builder, String c, int num) {
    method keyLine (line 119) | private void keyLine() {
    method counter (line 123) | private void counter(ToyLine line) {

FILE: common/common-core/src/main/java/com/iohao/game/action/skeleton/toy/ToyTableRender.java
  class ToyTableRender (line 28) | final class ToyTableRender {
    method ToyTableRender (line 35) | ToyTableRender(int bodyMaxNum) {
    method next (line 41) | void next() {
    method render (line 54) | void render() {
    method line (line 72) | void line(int keyMaxLen, int valueMaxLen) {
    method tri (line 78) | void tri(int keyMaxLen, int valueMaxLen, StringBuilder builder) {
    method append (line 88) | private void append(StringBuilder builder, String c, int num) {

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/ActionParserListenerTest.java
  class ActionParserListenerTest (line 19) | @Slf4j
    method setUp (line 23) | @Before
    method onActionCommand (line 33) | @Test
    method extractedBeeHello (line 43) | private void extractedBeeHello() {
    method extractedBeeHelloDog (line 58) | private void extractedBeeHelloDog() {

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/BarSkeletonTest.java
  class BarSkeletonTest (line 29) | @Slf4j
    method setUp (line 33) | @Before
    method newBuilder (line 39) | @Test
    method testVoid (line 61) | @Test

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/DataCodecKitTest.java
  class DataCodecKitTest (line 13) | public class DataCodecKitTest {
    method decode (line 15) | @Test

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/InOutManagerTest.java
  class InOutManagerTest (line 19) | @Slf4j
    method test (line 24) | @Test
    method extracted (line 46) | private void extracted(InOutManager inOutManager, String result, List<...
  class A_ActionMethodInOut (line 64) | @Slf4j
    method fuckIn (line 66) | @Override
    method fuckOut (line 72) | @Override
  class B_ActionMethodInOut (line 79) | @Slf4j
    method fuckIn (line 81) | @Override
    method fuckOut (line 87) | @Override
  class C_ActionMethodInOut (line 94) | @Slf4j
    method fuckIn (line 96) | @Override
    method fuckOut (line 102) | @Override

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/JSR380Test.java
  class JSR380Test (line 34) | @Slf4j
    method setUp (line 39) | @Before
    method jsr380 (line 47) | @Test

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/JSR380ValidatedGroupTest.java
  class JSR380ValidatedGroupTest (line 33) | public class JSR380ValidatedGroupTest {
    method setUp (line 36) | @Before
    method updateGroupTest (line 44) | @Test
    method createGroupTest (line 56) | @Test

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/SimpleWrapperActionTest.java
  class SimpleWrapperActionTest (line 35) | @Slf4j
    method setUp (line 40) | @Before
    method testInt (line 45) | @Test

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/WrapperIntTest.java
  class WrapperIntTest (line 41) | @Getter
    method of (line 46) | private CmdInfo of(int subCmd) {
    method createIntValueFlowContext (line 50) | private FlowContext createIntValueFlowContext(int subCmd) {
    method setUp (line 61) | @Before
    method intValue1 (line 67) | @Test
    method intValue2 (line 102) | public void intValue2() {
    method integerValue (line 121) | @Test

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/WrapperLongTest.java
  class WrapperLongTest (line 37) | @Getter
    method of (line 42) | private CmdInfo of(int subCmd) {
    method createLongValueFlowContext (line 46) | private FlowContext createLongValueFlowContext(int subCmd) {
    method setUp (line 57) | @Before
    method longValue1 (line 62) | @Test
    method longValue2 (line 82) | @Test
    method longerValue3 (line 102) | @Test

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/action/BeeAction.java
  class BeeAction (line 32) | @Slf4j(topic = IoGameLogName.CommonStdout)
    method hello (line 44) | @ActionMethod(ExampleActionCmd.BeeActionCmd.hello)
    method name (line 51) | @ActionMethod(ExampleActionCmd.BeeActionCmd.name)
    method thatVoid (line 59) | @ActionMethod(ExampleActionCmd.BeeActionCmd.test_void)
    method helloDog (line 65) | @ActionMethod(ExampleActionCmd.BeeActionCmd.hello_dog)
    method jsr380 (line 71) | @ActionMethod(ExampleActionCmd.BeeActionCmd.jsr380)
    method validateUpdate (line 76) | @ActionMethod(ExampleActionCmd.BeeActionCmd.validated_group_update)
    method validateCreate (line 81) | @ActionMethod(ExampleActionCmd.BeeActionCmd.validated_group_create)

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/action/ExampleActionCmd.java
  type ExampleActionCmd (line 22) | public interface ExampleActionCmd {
    type BeeActionCmd (line 26) | interface BeeActionCmd {
    type WrapperIntActionCmd (line 42) | interface WrapperIntActionCmd {
    type WrapperLongActionCmd (line 67) | interface WrapperLongActionCmd {
    type SimpleWrapperActionActionCmd (line 89) | interface SimpleWrapperActionActionCmd {

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/action/SimpleWrapperAction.java
  class SimpleWrapperAction (line 30) | @Slf4j
    method testInt (line 33) | @ActionMethod(ExampleActionCmd.SimpleWrapperActionActionCmd.testInt)

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/action/WrapperIntAction.java
  class WrapperIntAction (line 37) | @Slf4j(topic = IoGameLogName.CommonStdout)
    method intValue2Void (line 40) | @ActionMethod(WrapperIntActionCmd.intValue2Void)
    method intValue2Int (line 45) | @ActionMethod(WrapperIntActionCmd.intValue2Int)
    method intValue2IntValue (line 50) | @ActionMethod(WrapperIntActionCmd.intValue2IntValue)
    method intValue2IntList (line 59) | @ActionMethod(WrapperIntActionCmd.intValue2IntList)
    method IntListVoid (line 69) | @ActionMethod(WrapperIntActionCmd.intListVoid)
    method int2Void (line 76) | @ActionMethod(WrapperIntActionCmd.int2Void)
    method int2Int (line 80) | @ActionMethod(WrapperIntActionCmd.int2Int)
    method int2IntValue (line 85) | @ActionMethod(WrapperIntActionCmd.int2IntValue)
    method int2IntList (line 94) | @ActionMethod(WrapperIntActionCmd.int2IntList)
    method integer2Void (line 106) | @ActionMethod(WrapperIntActionCmd.integer2Void)
    method integer2Integer (line 110) | @ActionMethod(WrapperIntActionCmd.integer2Integer)
    method integer2IntValue (line 115) | @ActionMethod(WrapperIntActionCmd.integer2IntValue)
    method integer2IntegerList (line 124) | @ActionMethod(WrapperIntActionCmd.integer2IntegerList)

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/action/WrapperLongAction.java
  class WrapperLongAction (line 36) | @Slf4j(topic = IoGameLogName.CommonStdout)
    method longValue (line 39) | @ActionMethod(WrapperLongActionCmd.longValue2Void)
    method longValue2Long (line 44) | @ActionMethod(WrapperLongActionCmd.longValue2Long)
    method longValue2LongValue (line 49) | @ActionMethod(WrapperLongActionCmd.longValue2LongValue)
    method longValue2LongList (line 58) | @ActionMethod(WrapperLongActionCmd.longValue2LongList)
    method long2Void (line 69) | @ActionMethod(WrapperLongActionCmd.long2Void)
    method long2Long (line 74) | @ActionMethod(WrapperLongActionCmd.long2Long)
    method long2LongValue (line 79) | @ActionMethod(WrapperLongActionCmd.long2LongValue)
    method long2LongList (line 88) | @ActionMethod(WrapperLongActionCmd.long2LongList)
    method longer2Void (line 98) | @ActionMethod(WrapperLongActionCmd.longer2Void)
    method longer2Long (line 103) | @ActionMethod(WrapperLongActionCmd.longer2Long)
    method longer2LongValue (line 108) | @ActionMethod(WrapperLongActionCmd.longer2LongValue)
    method longer2LongList (line 117) | @ActionMethod(WrapperLongActionCmd.longer2LongList)

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/action/group/Create.java
  type Create (line 27) | public interface Create {

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/action/group/Update.java
  type Update (line 27) | public interface Update {

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/action/pojo/BeeApple.java
  class BeeApple (line 26) | @Data

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/action/pojo/BirdValid.java
  class BirdValid (line 34) | @ToString

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/action/pojo/DogValid.java
  class DogValid (line 33) | @ToString

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/action/pojo/Snake.java
  class Snake (line 30) | @ToString

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/data/TestDataKit.java
  class TestDataKit (line 36) | @UtilityClass
    method newBarSkeleton (line 39) | public BarSkeleton newBarSkeleton() {
    method createBuilder (line 43) | public BarSkeletonBuilder createBuilder(Predicate<Class<?>> appendPred...
    method getClasses (line 65) | private List<Class<?>> getClasses(Predicate<Class<?>> appendPredicateF...
    method createBuilder (line 87) | public BarSkeletonBuilder createBuilder() {
    method ofFlowContext (line 91) | public FlowContext ofFlowContext(CmdInfo cmdInfo) {
    method ofFlowContext (line 95) | public FlowContext ofFlowContext(CmdInfo cmdInfo, Object data) {
    method ofFlowContext (line 104) | public FlowContext ofFlowContext() {

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/flow/internal/StatActionInOutTest.java
  class StatActionInOutTest (line 17) | public class StatActionInOutTest {
    method testStatActionInOut (line 19) | @Test
    method setListener (line 38) | private void setListener(StatActionInOut inOut) {
    method extracted (line 60) | private static void extracted(StatActionInOut.StatActionRegion region,...

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/flow/internal/ThreadMonitorInOutTest.java
  class ThreadMonitorInOutTest (line 14) | @Slf4j
    method fuckIn (line 17) | @Test

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/core/flow/internal/TimeRangeInOutTest.java
  class TimeRangeInOutTest (line 20) | public class TimeRangeInOutTest {
    method fuckOut (line 22) | @Test
    method print (line 48) | private static void print(TimeRangeInOut inOut) {
    method setListener (line 57) | private void setListener(TimeRangeInOut inOut) {

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/eventbus/CustomEvent.java
  class CustomEvent (line 29) | @Slf4j
    method myMessage1 (line 35) | @EventSubscribe(order = 1, value = ExecutorSelector.simpleExecutor)
    method myMessage3 (line 41) | @EventSubscribe(order = 3, value = ExecutorSelector.simpleExecutor)
    method myMessage2 (line 47) | @EventSubscribe(order = 2, value = ExecutorSelector.simpleExecutor)
    method myRecord1 (line 53) | @EventSubscribe
    method myRecord2 (line 59) | @EventSubscribe

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/eventbus/EventBusTest.java
  class EventBusTest (line 19) | @Slf4j
    method setUp (line 24) | @Before
    method afterClass (line 32) | @AfterClass
    method initEventBus (line 37) | private void initEventBus(EventBus eventBus) {
    method createEventBrokerClientMessage (line 63) | private EventBrokerClientMessage createEventBrokerClientMessage(String...
    method fireAny (line 71) | @Test
    method testOther (line 86) | @Test
    method fireMe (line 101) | @Test
    method fireLocal (line 116) | @Test
    method fire (line 130) | @Test
    method sleep (line 148) | private void sleep() {

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/eventbus/MyMessage.java
  class MyMessage (line 31) | @Data

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/i18n/BundleTest.java
  class BundleTest (line 15) | public class BundleTest {
    method getMessage (line 17) | @Test
    method extracted (line 30) | private static void extracted() {

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/protocol/ResponseMessageTest.java
  class ResponseMessageTest (line 13) | public class ResponseMessageTest {
    method getValue (line 15) | @Test

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/protocol/Student.java
  class Student (line 29) | @ProtobufClass

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/protocol/wrapper/WrapperKitTest.java
  class WrapperKitTest (line 11) | @Slf4j
    method of (line 14) | @Test
    method isWrapper (line 24) | @Test

FILE: common/common-core/src/test/java/com/iohao/game/action/skeleton/toy/ToyTableTest.java
  class ToyTableTest (line 12) | public class ToyTableTest {
    method test (line 13) | @Test
    method render (line 30) | @Test

FILE: common/common-core/src/test/java/com/iohao/game/common/kit/ClassScannerTest.java
  class ClassScannerTest (line 30) | @Slf4j
    method scan (line 34) | public void scan() {
    method test (line 51) | @Test

FILE: common/common-kit/src/main/java/com/iohao/game/common/kit/ProtoKit.java
  class ProtoKit (line 35) | @UtilityClass
    method toBytes (line 44) | @SuppressWarnings("unchecked")
    method parseProtoByte (line 71) | public <T> T parseProtoByte(byte[] data, Class<T> clazz) {
    method create (line 88) | public void create(Class<?> clazz) {

FILE: common/common-kit/src/main/java/com/iohao/game/common/kit/asm/ClassRefInfo.java
  class ClassRefInfo (line 44) | @Getter
    method ClassRefInfo (line 62) | ClassRefInfo() {
    method newBuilder (line 70) | static ClassRefInfoBuilder newBuilder() {
    method newInstance (line 80) | public <T> T newInstance() {
    method getFieldRefInfo (line 90) | public FieldRefInfo getFieldRefInfo(String filedName) {
    method getMethodRefInfo (line 100) | public MethodRefInfo getMethodRefInfo(String methodName) {
    method invokeMethod (line 112) | public Object invokeMethod(Object object, String methodName, Object ar...
    method invokeGetter (line 126) | public <T> T invokeGetter(Object object, String filedName) {
    method invokeSetter (line 143) | public ClassRefInfo invokeSetter(Object object, String filedName, Obje...

FILE: common/common-kit/src/main/java/com/iohao/game/common/kit/asm/ClassRefInfoBuilder.java
  class ClassRefInfoBuilder (line 41) | @Setter
    method build (line 51) | ClassRefInfo build() {
    method createFieldMap (line 66) | private Map<String, FieldRefInfo> createFieldMap() {
    method createMethodMap (line 104) | private Map<String, MethodRefInfo> createMethodMap() {
    method listField (line 130) | private List<Field> listField() {
    method listMethod (line 162) | private List<Method> listMethod() {

FILE: common/common-kit/src/main/java/com/iohao/game/common/kit/asm/ClassRefInfoKit.java
  class ClassRefInfoKit (line 39) | @UtilityClass
    method getClassRefInfo (line 53) | public ClassRefInfo getClassRefInfo(Class<?> clazz) {
    method createClassRefInfo (line 71) | private ClassRefInfo createClassRefInfo(Class<?> clazz) {

FILE: common/common-kit/src/main/java/com/iohao/game/common/kit/asm/FieldRefInfo.java
  class FieldRefInfo (line 46) | @ToString

FILE: common/common-kit/src/main/java/com/iohao/game/common/kit/asm/MethodRefInfo.java
  class MethodRefInfo (line 34) | @Getter
    method MethodRefInfo (line 47) | MethodRefInfo() {
    method invokeMethod (line 57) | public Object invokeMethod(Object object, Object args) {
    method invokeMethod (line 67) | public Object invokeMethod(Object object) {

FILE: common/common-kit/src/main/java/com/iohao/game/common/kit/io/FileKit.java
  class FileKit (line 30) | @UtilityClass
    method mkdir (line 39) | public File mkdir(String dirPath) {
    method file (line 49) | public File file(String path) {
    method writeUtf8String (line 60) | public File writeUtf8String(String content, String path) {
    method isDirectory (line 70) | public boolean isDirectory(String path) {
    method exist (line 80) | public static boolean exist(File file) {

FILE: common/common-kit/src/main/java/com/iohao/game/common/kit/io/ResourceKit.java
  class ResourceKit (line 30) | @UtilityClass
    method readStr (line 32) | public static String readStr(String resource, Charset charset) {

FILE: common/common-kit/src/main/java/com/iohao/game/common/kit/system/InternalSystemPropsKit.java
  class InternalSystemPropsKit (line 31) | @UtilityClass
    method get (line 44) | public static String get(String name, boolean quiet) {

FILE: common/common-kit/src/main/java/com/iohao/game/common/kit/system/OsInfo.java
  class OsInfo (line 28) | @UtilityClass
    method getOsMatches (line 37) | private boolean getOsMatches(String osNamePrefix) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/consts/CommonConst.java
  type CommonConst (line 27) | public interface CommonConst {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/consts/IoGameLogName.java
  type IoGameLogName (line 25) | public interface IoGameLogName {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/internal/BootConfig.java
  type BootConfig (line 27) | public interface BootConfig {
    method config (line 31) | void config();

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/internal/BootItemConfig.java
  type BootItemConfig (line 27) | public interface BootItemConfig {
    method config (line 32) | void config();

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/internal/BootItemConfigKit.java
  class BootItemConfigKit (line 34) | @Slf4j
    method loadBootItemConfig (line 46) | public static void loadBootItemConfig(Class<? extends BootItemConfig> ...

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/AboutKit.java
  class OperationCodeKit (line 25) | @UtilityClass

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/ArrayKit.java
  class ArrayKit (line 34) | @UtilityClass
    method sum (line 42) | public int sum(int[] cards) {
    method copy (line 46) | public int[] copy(int[] cards) {
    method toList (line 53) | public List<Integer> toList(int[] cards) {
    method subtract (line 69) | public void subtract(int[] cards, int[] beCards) {
    method plus (line 75) | public void plus(int[] cards, int[] beCards) {
    method plus (line 81) | public void plus(int[] cards, List<Integer> beCards) {
    method random (line 87) | public List<Integer> random(int[] cards, int size) {
    method join (line 93) | public String join(Object[] array, CharSequence delimiter) {
    method notEmpty (line 99) | public boolean notEmpty(Object[] array) {
    method notEmpty (line 103) | public boolean notEmpty(byte[] array) {
    method isEmpty (line 107) | public boolean isEmpty(byte[] array) {
    method isEmpty (line 111) | public boolean isEmpty(int[] array) {
    method isEmpty (line 115) | public boolean isEmpty(Object[] array) {
    method random (line 119) | public <T> T random(T[] array) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/BaseTypeKit.java
  class BaseTypeKit (line 31) | @UtilityClass
    method isBaseType (line 63) | public boolean isBaseType(Object value) {
    method isBaseType (line 85) | public boolean isBaseType(Class<?> beanClass) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/ByteKit.java
  class ByteKit (line 28) | @UtilityClass
    method toBytes (line 36) | public byte[] toBytes(long value) {
    method getLong (line 55) | public long getLong(byte[] array) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/ClassScanner.java
  class ClassScanner (line 41) | @Slf4j(topic = IoGameLogName.CommonStdout)
    method ClassScanner (line 58) | public ClassScanner(String packagePath, Predicate<Class<?>> predicateF...
    method listScan (line 67) | public List<Class<?>> listScan() {
    method initClassLoad (line 91) | private void initClassLoad() {
    method listResource (line 100) | public List<URL> listResource() throws IOException {
    method scanJar (line 126) | private void scanJar(URL url) throws IOException {
    method scanFile (line 155) | private void scanFile(URL url) {
    method scanFile (line 163) | private void scanFile(File file, String classPath) {
    method getClassPath (line 191) | private String getClassPath(File file) {
    method loadClass (line 209) | private void loadClass(String className) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/CollKit.java
  class CollKit (line 34) | @UtilityClass
    method groupCounting (line 59) | public Map<Integer, Integer> groupCounting(List<Integer> list) {
    method notEmpty (line 66) | public boolean notEmpty(Collection<?> collection) {
    method isEmpty (line 70) | public boolean isEmpty(Collection<?> collection) {
    method findAny (line 74) | public <T> Optional<T> findAny(Set<T> set) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/CompletableFutureKit.java
  class CompletableFutureKit (line 34) | @UtilityClass
    method sequence (line 45) | public <T> List<T> sequence(List<CompletableFuture<T>> futures) {
    method sequenceAsync (line 59) | public <U> CompletableFuture<List<U>> sequenceAsync(List<CompletableFu...

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/ExecutorKit.java
  class ExecutorKit (line 33) | @UtilityClass
    method newVirtualExecutor (line 42) | public ExecutorService newVirtualExecutor(String name) {
    method newVirtualExecutor (line 54) | public ExecutorService newVirtualExecutor(String name, int start) {
    method newVirtualExecutor (line 65) | public ExecutorService newVirtualExecutor(ThreadFactory factory) {
    method newSingleThreadExecutor (line 75) | public ExecutorService newSingleThreadExecutor(String namePrefix) {
    method newSingleThreadExecutor (line 86) | public ExecutorService newSingleThreadExecutor(ThreadFactory threadFac...
    method newCacheThreadPool (line 96) | public ExecutorService newCacheThreadPool(String namePrefix) {
    method newCacheThreadPool (line 107) | public ExecutorService newCacheThreadPool(ThreadFactory threadFactory) {
    method newFixedThreadPool (line 118) | public ExecutorService newFixedThreadPool(int corePoolSize, ThreadFact...
    method newFixedThreadPool (line 129) | public ExecutorService newFixedThreadPool(int corePoolSize, String nam...
    method newSingleScheduled (line 140) | public ScheduledExecutorService newSingleScheduled(ThreadFactory threa...
    method newSingleScheduled (line 150) | public ScheduledExecutorService newSingleScheduled(String namePrefix) {
    method newScheduled (line 162) | public ScheduledExecutorService newScheduled(int corePoolSize, String ...
    method newScheduled (line 174) | public ScheduledExecutorService newScheduled(int corePoolSize, ThreadF...
    method createThreadFactory (line 187) | public ThreadFactory createThreadFactory(String namePrefix) {
    method createThreadFactory (line 198) | public ThreadFactory createThreadFactory(@NonNull String namePrefix, b...

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/HashKit.java
  class HashKit (line 29) | @UtilityClass
    method hash32 (line 31) | public int hash32(final String data) {
    method hash32 (line 35) | public int hash32(final byte[] data) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/MoreKit.java
  class MoreKit (line 30) | @UtilityClass
    method firstNonNull (line 32) | public <T> T firstNonNull(T first, T second) {
    method putIfAbsent (line 44) | public <K, T> T putIfAbsent(Map<K, T> map, K key, T value) {
    method execute (line 51) | public void execute(Executor executor, Runnable runnable) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/MurmurHash3.java
  class MurmurHash3 (line 39) | final class MurmurHash3 {
    method MurmurHash3 (line 67) | private MurmurHash3() {
    method hash32 (line 77) | public static int hash32(final long l0, final long l1) {
    method hash32 (line 87) | public static int hash32(final long l0) {
    method hash32 (line 98) | public static int hash32(final long l0, final int seed) {
    method hash32 (line 116) | public static int hash32(final long l0, final long l1, final int seed) {
    method hash32 (line 135) | public static int hash32(final byte[] data) {
    method hash32 (line 145) | public static int hash32(final String data) {
    method hash32 (line 157) | public static int hash32(final byte[] data, final int length) {
    method hash32 (line 169) | public static int hash32(final byte[] data, final int length, final in...
    method hash32 (line 182) | public static int hash32(final byte[] data, final int offset, final in...
    method hash64 (line 223) | public static long hash64(final byte[] data) {
    method hash64 (line 234) | public static long hash64(final long data) {
    method hash64 (line 256) | public static long hash64(final int data) {
    method hash64 (line 276) | public static long hash64(final short data) {
    method hash64 (line 301) | public static long hash64(final byte[] data, final int offset, final i...
    method hash64 (line 314) | public static long hash64(final byte[] data, final int offset, final i...
    method hash128 (line 371) | public static long[] hash128(final byte[] data) {
    method hash128 (line 381) | public static long[] hash128(final String data) {
    method hash128 (line 395) | public static long[] hash128(final byte[] data, final int offset, fina...
    method mix32 (line 494) | private static int mix32(int k, int hash) {
    method fmix32 (line 502) | private static int fmix32(final int length, int hash) {
    method fmix64 (line 513) | private static long fmix64(long h) {
    class IncrementalHash32 (line 522) | public static class IncrementalHash32 {
      method start (line 528) | public final void start(final int hash) {
      method add (line 533) | public final void add(final byte[] data, int offset, final int lengt...
      method end (line 591) | public final int end() {
    method orBytes (line 619) | private static int orBytes(final byte b1, final byte b2, final byte b3...

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/NetworkKit.java
  class NetworkKit (line 22) | @UtilityClass
    method hasPort (line 32) | public boolean hasPort(String hostAndPort, int port) {
    method getHost (line 42) | public String getHost(String hostAndPort) {
    method getPort (line 60) | public int getPort(String hostAndPort) {
    method isInternalIp (line 80) | public boolean isInternalIp(String ipOrHost) {
    method isInternalIp (line 90) | public boolean isInternalIp(byte[] addr) {
    method getLocalIP (line 126) | private String getLocalIP() {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/OperationCode.java
  type OperationCode (line 28) | public interface OperationCode {
    method getOperationCode (line 29) | int getOperationCode();
    method getAndIncrementCode (line 31) | static int getAndIncrementCode() {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/PresentKit.java
  class PresentKit (line 30) | @UtilityClass
    method ifNull (line 39) | public void ifNull(Object obj, Runnable runnable) {
    method ifPresent (line 52) | public <T> void ifPresent(T obj, Consumer<T> action) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/RandomKit.java
  class RandomKit (line 31) | @UtilityClass
    method randomInt (line 41) | public int randomInt(int limit) {
    method randomInt (line 52) | public int randomInt(int min, int max) {
    method randomLong (line 63) | public long randomLong(long limit) {
    method randomLong (line 75) | public long randomLong(long min, long max) {
    method random (line 86) | public int random(int start, int end) {
    method random (line 96) | public int random(int end) {
    method random (line 108) | public long random(long start, long end) {
    method random (line 119) | public long random(long end) {
    method randomBoolean (line 128) | public boolean randomBoolean() {
    method randomEle (line 132) | public <T> T randomEle(List<T> list) {
    method randomEle (line 145) | public <T> T randomEle(T[] array) {
    method nextDouble (line 153) | public double nextDouble() {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/RuntimeKit.java
  class RuntimeKit (line 30) | @UtilityClass
    method availableProcessors2n (line 61) | static int availableProcessors2n() {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/SafeKit.java
  class SafeKit (line 31) | @UtilityClass
    method getInt (line 33) | public int getInt(Integer value) {
    method getInt (line 37) | public int getInt(Integer value, int defaultValue) {
    method getInt (line 41) | public int getInt(String value, int defaultValue) {
    method getLong (line 49) | public long getLong(Long value) {
    method getLong (line 53) | public long getLong(Long value, long defaultValue) {
    method getLong (line 57) | public long getLong(String value, long defaultValue) {
    method getBoolean (line 65) | public boolean getBoolean(Boolean value) {
    method getBoolean (line 69) | public boolean getBoolean(Boolean value, boolean defaultValue) {
    method getString (line 73) | public String getString(String value, String defaultValue) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/StrKit.java
  class StrKit (line 31) | @UtilityClass
    method firstCharToUpperCase (line 40) | public String firstCharToUpperCase(String value) {
    method firstCharToLowerCase (line 51) | public String firstCharToLowerCase(String value) {
    method format (line 62) | public String format(@NonNull CharSequence template, @NonNull Map<?, ?...
    method format (line 66) | public String format(@NonNull CharSequence template, Object... params) {
    method isEmpty (line 93) | public boolean isEmpty(String str) {
    method isEmpty (line 97) | public boolean isEmpty(CharSequence str) {
    method isNotEmpty (line 121) | public boolean isNotEmpty(String str) {
    method isBlank (line 125) | public boolean isBlank(CharSequence cs) {
    method isNotBlank (line 140) | public boolean isNotBlank(CharSequence cs) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/TimeBetweenKit.java
  class TimeBetweenKit (line 34) | @Deprecated
    method betweenNowTime (line 56) | public static boolean betweenNowTime(String startTime, String endTime,...
    method betweenNowTime (line 79) | public static boolean betweenNowTime(int startTimeIndex, int endTimeIn...
    method betweenNowTime (line 123) | public static boolean betweenNowTime(String startTime, String endTime) {
    method convertTimeIndex (line 133) | private static int convertTimeIndex(LocalTime localTime) {
    method convertTimeIndex (line 145) | public static int convertTimeIndex(String time) {
    method convertTimeIndex (line 159) | private static int convertTimeIndex(int hours, int minute) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/TimeFormatterKit.java
  class TimeFormatterKit (line 37) | @Deprecated
    method ofPattern (line 47) | @Deprecated
    method formatter (line 52) | @Deprecated

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/TimeKit.java
  class TimeKit (line 40) | @Deprecated
    method nowLocalDate (line 75) | @Deprecated
    method currentTimeMillis (line 95) | @Deprecated
    method toSecond (line 120) | @Deprecated
    method toMilli (line 133) | @Deprecated
    method toMilli (line 146) | @Deprecated
    method toInstant (line 160) | @Deprecated
    method toLocalDateTime (line 174) | @Deprecated
    method formatter (line 186) | @Deprecated
    method formatter (line 197) | @Deprecated
    method formatter (line 209) | @Deprecated
    method localDateToNumber (line 220) | @Deprecated
    method expireLocalDate (line 232) | @Deprecated
    method expire (line 247) | @Deprecated
    type UpdateCurrentTimeMillis (line 253) | @Deprecated
      method getCurrentTimeMillis (line 255) | default long getCurrentTimeMillis() {
    type TimeUpdatingStrategy (line 260) | @Deprecated
      method update (line 262) | default void update() {
    class LocalDateTimeUpdatingStrategy (line 266) | @Deprecated
      method LocalDateTimeUpdatingStrategy (line 269) | private LocalDateTimeUpdatingStrategy() {
      method me (line 278) | public static LocalDateTimeUpdatingStrategy me() {
      class Holder (line 283) | private static class Holder {
    class SecondUpdatingStrategy (line 288) | @Deprecated
      method SecondUpdatingStrategy (line 290) | private SecondUpdatingStrategy() {
      method me (line 299) | public static SecondUpdatingStrategy me() {
      class Holder (line 304) | private static class Holder {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/attr/AttrOption.java
  class AttrOption (line 35) | public final class AttrOption<T> implements Serializable {
    method AttrOption (line 40) | AttrOption(String name, T devault, Supplier<T> supplier) {
    method name (line 48) | public String name() {
    method defaultValue (line 52) | public T defaultValue() {
    method valueOf (line 63) | public static <T> AttrOption<T> valueOf(String name) {
    method valueOf (line 75) | public static <T> AttrOption<T> valueOf(String name, T defaultValue) {
    method valueOf (line 87) | public static <T> AttrOption<T> valueOf(String name, Supplier<T> suppl...
    method equals (line 91) | @Override
    method hashCode (line 106) | @Override

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/attr/AttrOptionDynamic.java
  type AttrOptionDynamic (line 55) | public interface AttrOptionDynamic {
    method getOptions (line 61) | AttrOptions getOptions();
    method option (line 69) | default <T> T option(AttrOption<T> option) {
    method optionValue (line 80) | default <T> T optionValue(AttrOption<T> option, T value) {
    method option (line 99) | default <T> AttrOptions option(AttrOption<T> option, T value) {
    method ifPresent (line 110) | default <T> void ifPresent(AttrOption<T> option, Consumer<T> consumer) {
    method ifNull (line 124) | default <T> void ifNull(AttrOption<T> option, Supplier<T> supplier) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/attr/AttrOptions.java
  class AttrOptions (line 37) | public class AttrOptions implements Serializable {
    method option (line 51) | @SuppressWarnings("unchecked")
    method option (line 80) | public <T> AttrOptions option(AttrOption<T> option, T value) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/beans/property/AbstractPropertyValueObservable.java
  class AbstractPropertyValueObservable (line 34) | abstract class AbstractPropertyValueObservable<T> implements PropertyVal...
    method addListener (line 38) | @Override
    method removeListener (line 47) | @Override
    method markInvalid (line 54) | protected void markInvalid() {
    method fireValueChangedEvent (line 61) | private void fireValueChangedEvent() {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/beans/property/BooleanProperty.java
  class BooleanProperty (line 43) | @ToString
    method BooleanProperty (line 47) | public BooleanProperty() {
    method BooleanProperty (line 51) | public BooleanProperty(boolean value) {
    method getValue (line 55) | @Override
    method setValue (line 60) | @Override
    method get (line 70) | public boolean get() {
    method set (line 80) | public void set(boolean newValue) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/beans/property/IntegerProperty.java
  class IntegerProperty (line 41) | @ToString
    method IntegerProperty (line 45) | public IntegerProperty() {
    method IntegerProperty (line 49) | public IntegerProperty(int value) {
    method getValue (line 53) | @Override
    method setValue (line 58) | @Override
    method get (line 72) | public int get() {
    method set (line 82) | public void set(int newValue) {
    method increment (line 92) | public void increment() {
    method decrement (line 99) | public void decrement() {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/beans/property/LongProperty.java
  class LongProperty (line 41) | @ToString
    method LongProperty (line 45) | public LongProperty() {
    method LongProperty (line 49) | public LongProperty(long value) {
    method getValue (line 53) | @Override
    method setValue (line 58) | @Override
    method get (line 72) | public long get() {
    method set (line 82) | public void set(long newValue) {
    method increment (line 92) | public void increment() {
    method decrement (line 99) | public void decrement() {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/beans/property/NumberPropertyValueObservable.java
  class NumberPropertyValueObservable (line 25) | abstract class NumberPropertyValueObservable extends AbstractPropertyVal...

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/beans/property/ObjectProperty.java
  class ObjectProperty (line 45) | @ToString
    method ObjectProperty (line 49) | public ObjectProperty() {
    method ObjectProperty (line 53) | public ObjectProperty(T value) {
    method getValue (line 57) | @Override
    method setValue (line 62) | @Override
    method get (line 72) | public T get() {
    method set (line 82) | public void set(T newValue) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/beans/property/PropertyAbout.java
  class ChangeHelper (line 32) | abstract class ChangeHelper<T> {
    method fireValueChangedEvent (line 38) | protected abstract void fireValueChangedEvent();
    method ChangeHelper (line 40) | ChangeHelper(PropertyValueObservable<T> observable) {
    method create (line 44) | static <T> ChangeHelper<T> create(PropertyValueObservable<T> observabl...
    method create (line 48) | static <T> ChangeHelper<T> create(PropertyChangeListener<? super T> li...
    class PropertySingleChange (line 52) | private static class PropertySingleChange<T> extends ChangeHelper<T> {
      method PropertySingleChange (line 56) | PropertySingleChange(PropertyValueObservable<T> observable, T curren...
      method fireValueChangedEvent (line 62) | @Override
      method equals (line 76) | @Override
      method hashCode (line 89) | @Override
  class ChangeHelperList (line 96) | @FieldDefaults(level = AccessLevel.PRIVATE)
    method addListener (line 100) | void addListener(ChangeHelper<? super T> helper) {
    method removeListener (line 108) | void removeListener(PropertyChangeListener<? super T> listener) {
    method addListener (line 117) | void addListener(PropertyValueObservable<T> observable, PropertyChange...
    method fireValueChangedEvent (line 127) | void fireValueChangedEvent() {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/beans/property/PropertyChangeListener.java
  type PropertyChangeListener (line 27) | @FunctionalInterface
    method changed (line 36) | void changed(PropertyValueObservable<? extends T> observable, T oldVal...

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/beans/property/PropertyValueObservable.java
  type PropertyValueObservable (line 27) | public interface PropertyValueObservable<T> {
    method addListener (line 33) | void addListener(PropertyChangeListener<? super T> listener);
    method removeListener (line 40) | void removeListener(PropertyChangeListener<? super T> listener);
    method getValue (line 47) | T getValue();
    method setValue (line 54) | void setValue(T value);

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/beans/property/StringProperty.java
  class StringProperty (line 43) | @ToString
    method StringProperty (line 47) | public StringProperty() {
    method StringProperty (line 51) | public StringProperty(String value) {
    method getValue (line 55) | @Override
    method setValue (line 60) | @Override
    method get (line 70) | public String get() {
    method set (line 80) | public void set(String newValue) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/collect/ListMultiMap.java
  type ListMultiMap (line 55) | public interface ListMultiMap<K, V> extends MultiMap<K, V> {
    method asMap (line 56) | @Override
    method ofIfAbsent (line 73) | List<V> ofIfAbsent(K key, Consumer<List<V>> consumer);
    method of (line 75) | @Override
    method get (line 80) | @Override
    method entrySet (line 85) | default Set<Map.Entry<K, List<V>>> entrySet() {
    method create (line 96) | static <K, V> ListMultiMap<K, V> create() {
    method of (line 107) | static <K, V> ListMultiMap<K, V> of() {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/collect/MultiMap.java
  type MultiMap (line 29) | interface MultiMap<K, V> {
    method asMap (line 35) | Map<K, ? extends Collection<V>> asMap();
    method of (line 43) | Collection<V> of(K key);
    method get (line 51) | Collection<V> get(K key);
    method clearAll (line 59) | default Collection<V> clearAll(K key) {
    method size (line 72) | default int size() {
    method sizeValue (line 81) | default int sizeValue() {
    method put (line 94) | default boolean put(K key, V value) {
    method isEmpty (line 99) | default boolean isEmpty() {
    method containsKey (line 103) | default boolean containsKey(K key) {
    method containsValue (line 107) | default boolean containsValue(V value) {
    method clear (line 117) | default void clear() {
    method keySet (line 121) | default Set<K> keySet() {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/collect/NonBlockingListMultiMap.java
  class NonBlockingListMultiMap (line 36) | final class NonBlockingListMultiMap<K, V> implements ListMultiMap<K, V> {
    method asMap (line 39) | @Override
    method ofIfAbsent (line 44) | @Override

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/collect/NonBlockingSetMultiMap.java
  class NonBlockingSetMultiMap (line 36) | final class NonBlockingSetMultiMap<K, V> implements SetMultiMap<K, V> {
    method asMap (line 39) | @Override
    method ofIfAbsent (line 44) | @Override
    method entrySet (line 65) | @Override

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/collect/SetMultiMap.java
  type SetMultiMap (line 62) | public interface SetMultiMap<K, V> extends MultiMap<K, V> {
    method asMap (line 63) | @Override
    method ofIfAbsent (line 80) | Set<V> ofIfAbsent(K key, Consumer<Set<V>> consumer);
    method of (line 82) | @Override
    method get (line 87) | @Override
    method entrySet (line 92) | Set<Map.Entry<K, Set<V>>> entrySet();
    method create (line 101) | static <K, V> SetMultiMap<K, V> create() {
    method of (line 112) | static <K, V> SetMultiMap<K, V> of() {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/CommonTaskListener.java
  type CommonTaskListener (line 30) | interface CommonTaskListener {
    method triggerUpdate (line 36) | default boolean triggerUpdate() {
    method onUpdate (line 43) | void onUpdate();
    method onException (line 53) | default void onException(Throwable e) {
    method getExecutor (line 75) | default Executor getExecutor() {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/DaemonThreadFactory.java
  class DaemonThreadFactory (line 27) | public final class DaemonThreadFactory extends ThreadCreator implements ...
    method DaemonThreadFactory (line 29) | public DaemonThreadFactory(String threadNamePrefix) {
    method newThread (line 34) | @Override

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/FixedNameThreadFactory.java
  class FixedNameThreadFactory (line 28) | public final class FixedNameThreadFactory extends ThreadCreator implemen...
    method FixedNameThreadFactory (line 29) | public FixedNameThreadFactory(String threadNamePrefix) {
    method newThread (line 34) | @Override
    method nextThreadName (line 39) | @Override

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/IntervalTaskListener.java
  type IntervalTaskListener (line 44) | public interface IntervalTaskListener extends CommonTaskListener {
    method isActive (line 50) | default boolean isActive() {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/OnceTaskListener.java
  type OnceTaskListener (line 66) | public interface OnceTaskListener extends TimerTask, TaskListener {
    method run (line 67) | @Override
    method executeFlow (line 73) | private void executeFlow() {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/TaskKit.java
  class TaskKit (line 145) | @Slf4j
    method setTimer (line 171) | public void setTimer(Timer timer) {
    method execute (line 184) | public void execute(Runnable command) {
    method executeVirtual (line 193) | public void executeVirtual(Runnable command) {
    method supplyAsync (line 205) | public <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
    method newTimeout (line 217) | public Timeout newTimeout(TimerTask task, long delay, TimeUnit unit) {
    method runOnce (line 228) | public void runOnce(OnceTaskListener taskListener, long delay, TimeUni...
    method runOnceSecond (line 237) | public void runOnceSecond(OnceTaskListener taskListener) {
    method runOnceMillis (line 247) | public void runOnceMillis(OnceTaskListener taskListener, long delayMil...
    method runIntervalMinute (line 257) | public void runIntervalMinute(IntervalTaskListener taskListener, long ...
    method runInterval (line 271) | public void runInterval(IntervalTaskListener taskListener, long tick, ...
    method foreverTimerTask (line 287) | private void foreverTimerTask(long tick, TimeUnit timeUnit, Set<Interv...
    method executeFlowTimerListener (line 308) | private void executeFlowTimerListener(IntervalTaskListener taskListene...
    method stop (line 324) | public void stop() {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/TaskListener.java
  type TaskListener (line 38) | public interface TaskListener extends CommonTaskListener {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/ThreadCreator.java
  class ThreadCreator (line 31) | @Getter
    method ThreadCreator (line 46) | public ThreadCreator(String threadNamePrefix) {
    method setThreadGroupName (line 50) | public void setThreadGroupName(String name) {
    method createThread (line 54) | public Thread createThread(Runnable runnable) {
    method nextThreadName (line 61) | protected String nextThreadName() {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/executor/AbstractThreadExecutorRegion.java
  class AbstractThreadExecutorRegion (line 33) | @FieldDefaults(level = AccessLevel.PROTECTED)
    method AbstractThreadExecutorRegion (line 43) | AbstractThreadExecutorRegion(String threadName, int executorSize) {
    method createExecutorService (line 55) | protected ExecutorService createExecutorService(String name) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/executor/ExecutorRegion.java
  type ExecutorRegion (line 46) | public interface ExecutorRegion {
    method getUserThreadExecutorRegion (line 52) | ThreadExecutorRegion getUserThreadExecutorRegion();
    method getUserVirtualThreadExecutorRegion (line 59) | default ThreadExecutorRegion getUserVirtualThreadExecutorRegion() {
    method getSimpleThreadExecutorRegion (line 68) | ThreadExecutorRegion getSimpleThreadExecutorRegion();
    method getUserThreadExecutor (line 76) | default ThreadExecutor getUserThreadExecutor(long index) {
    method getUserVirtualThreadExecutor (line 86) | default ThreadExecutor getUserVirtualThreadExecutor(long index) {
    method getSimpleThreadExecutor (line 96) | default ThreadExecutor getSimpleThreadExecutor(long index) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/executor/ExecutorRegionKit.java
  class ExecutorRegionKit (line 40) | @UtilityClass
    method getUserThreadExecutorRegion (line 48) | @Override
    method getSimpleThreadExecutorRegion (line 53) | @Override
    method createExecutorRegion (line 63) | public ExecutorRegion createExecutorRegion() {
    method getSimpleThreadExecutor (line 73) | public ThreadExecutor getSimpleThreadExecutor(long index) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/executor/SimpleThreadExecutorRegion.java
  class SimpleThreadExecutorRegion (line 39) | @FieldDefaults(level = AccessLevel.PRIVATE)
    method SimpleThreadExecutorRegion (line 43) | SimpleThreadExecutorRegion() {
    method getThreadExecutor (line 48) | @Override
    method me (line 54) | static SimpleThreadExecutorRegion me() {
    class Holder (line 59) | private static class Holder {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/executor/ThreadExecutor.java
  method execute (line 49) | public void execute(Runnable command) {
  method executeTry (line 58) | public void executeTry(Runnable command) {
  method getWorkQueue (line 68) | public int getWorkQueue() {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/executor/ThreadExecutorRegion.java
  type ThreadExecutorRegion (line 30) | public interface ThreadExecutorRegion {
    method getThreadExecutor (line 37) | ThreadExecutor getThreadExecutor(long index);
    method execute (line 45) | default void execute(Runnable runnable, long index) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/executor/UserThreadExecutorRegion.java
  class UserThreadExecutorRegion (line 41) | final class UserThreadExecutorRegion extends AbstractThreadExecutorRegion {
    method UserThreadExecutorRegion (line 44) | UserThreadExecutorRegion() {
    method getThreadExecutor (line 55) | @Override

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/executor/UserVirtualThreadExecutorRegion.java
  class UserVirtualThreadExecutorRegion (line 35) | final class UserVirtualThreadExecutorRegion extends AbstractThreadExecut...
    method UserVirtualThreadExecutorRegion (line 38) | UserVirtualThreadExecutorRegion(String threadName) {
    method getThreadExecutor (line 49) | @Override
    method createExecutorService (line 55) | @Override
    method me (line 60) | static UserVirtualThreadExecutorRegion me() {
    class Holder (line 65) | private static class Holder {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/timer/delay/DelayTask.java
  type DelayTask (line 32) | public interface DelayTask {
    method getTaskId (line 39) | String getTaskId();
    method getTaskListener (line 47) | <T extends TaskListener> T getTaskListener();
    method isActive (line 54) | boolean isActive();
    method cancel (line 59) | void cancel();
    method getMillis (line 66) | long getMillis();
    method plusTime (line 74) | default DelayTask plusTime(Duration duration) {
    method plusTimeMillis (line 91) | DelayTask plusTimeMillis(long millis);
    method minusTimeMillis (line 106) | default DelayTask minusTimeMillis(long millis) {
    method minusTime (line 116) | default DelayTask minusTime(Duration duration) {
    method task (line 125) | DelayTask task();

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/timer/delay/DelayTaskKit.java
  class DelayTaskKit (line 36) | @UtilityClass
    method setDelayTaskRegion (line 47) | public void setDelayTaskRegion(DelayTaskRegion delayTaskRegion) {
    method cancel (line 63) | public void cancel(String taskId) {
    method optional (line 73) | public Optional<DelayTask> optional(String taskId) {
    method ifPresent (line 83) | public void ifPresent(String taskId, Consumer<DelayTask> consumer) {
    method of (line 93) | public DelayTask of(TaskListener taskListener) {
    method of (line 104) | public DelayTask of(String taskId, TaskListener taskListener) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/timer/delay/DelayTaskRegion.java
  type DelayTaskRegion (line 32) | public interface DelayTaskRegion {
    method optional (line 40) | Optional<DelayTask> optional(String taskId);
    method cancel (line 47) | void cancel(String taskId);
    method count (line 54) | int count();
    method of (line 68) | DelayTask of(TaskListener taskListener);
    method of (line 83) | DelayTask of(String taskId, TaskListener taskListener);

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/timer/delay/InternalDelayAbout.java
  type DelayTaskExecutor (line 38) | interface DelayTaskExecutor extends DelayTask {
    method triggerUpdate (line 44) | boolean triggerUpdate();
    method onUpdate (line 49) | void onUpdate();
    method onException (line 56) | default void onException(Throwable e) {
    method getExecutor (line 65) | Executor getExecutor();
  type DelayTaskRegionEnhance (line 68) | interface DelayTaskRegionEnhance extends DelayTaskRegion {
    method stop (line 69) | void stop();
    method forEach (line 71) | void forEach(Consumer<DelayTaskExecutor> consumer);
    method runDelayTask (line 73) | void runDelayTask(DelayTaskExecutor delayTaskExecutor);
  class DelayIntervalTaskListener (line 76) | @Getter
    method DelayIntervalTaskListener (line 81) | DelayIntervalTaskListener(DelayTaskRegionEnhance delayTaskRegion) {
    method onUpdate (line 85) | @Override
    method extractedFlowTaskListener (line 98) | private void extractedFlowTaskListener(DelayTaskExecutor task) {
  class SimpleDelayTask (line 115) | @Getter
    method SimpleDelayTask (line 125) | SimpleDelayTask(TaskListener taskListener, DelayTaskRegionEnhance dela...
    method SimpleDelayTask (line 129) | SimpleDelayTask(String taskId, TaskListener taskListener, DelayTaskReg...
    method isActive (line 135) | @Override
    method cancel (line 140) | @Override
    method getMillis (line 147) | @Override
    method plusTimeMillis (line 153) | @Override
    method onUpdate (line 162) | @Override
    method triggerUpdate (line 174) | @Override
    method onException (line 182) | @Override
    method getExecutor (line 187) | @Override
    method task (line 192) | @Override
    method toString (line 201) | @Override
  class SimpleDelayTaskRegion (line 211) | class SimpleDelayTaskRegion implements DelayTaskRegion, DelayTaskRegionE...
    method SimpleDelayTaskRegion (line 217) | SimpleDelayTaskRegion() {
    method forEach (line 222) | @Override
    method runDelayTask (line 227) | @Override
    method optional (line 232) | @Override
    method cancel (line 238) | @Override
    method count (line 246) | @Override
    method stop (line 251) | @Override
    method of (line 256) | @Override
    method of (line 261) | @Override
  class DebugDelayTask (line 267) | @Slf4j
    method DebugDelayTask (line 271) | DebugDelayTask(String taskId, TaskListener taskListener, DelayTaskRegi...
    method DebugDelayTask (line 275) | DebugDelayTask(TaskListener taskListener, DelayTaskRegionEnhance delay...
    method onUpdate (line 279) | @Override
    method triggerUpdate (line 285) | @Override
    method toString (line 293) | @Override
  class DebugDelayTaskRegion (line 304) | final class DebugDelayTaskRegion extends SimpleDelayTaskRegion {
    method of (line 305) | @Override
    method of (line 310) | @Override

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/exception/CommonIllegalArgumentException.java
  class CommonIllegalArgumentException (line 28) | public class CommonIllegalArgumentException extends IllegalArgumentExcep...
    method CommonIllegalArgumentException (line 29) | public CommonIllegalArgumentException(String s) {
    method CommonIllegalArgumentException (line 33) | public CommonIllegalArgumentException(String message, Throwable cause) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/exception/CommonNullPointerException.java
  class CommonNullPointerException (line 28) | public class CommonNullPointerException extends NullPointerException {
    method CommonNullPointerException (line 29) | public CommonNullPointerException() {
    method CommonNullPointerException (line 32) | public CommonNullPointerException(String s) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/exception/CommonRuntimeException.java
  class CommonRuntimeException (line 28) | public class CommonRuntimeException extends RuntimeException {
    method CommonRuntimeException (line 29) | public CommonRuntimeException(String message) {
    method CommonRuntimeException (line 33) | public CommonRuntimeException(String message, Throwable cause) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/exception/ThrowKit.java
  class ThrowKit (line 30) | @UtilityClass
    method ofIllegalArgumentException (line 32) | public void ofIllegalArgumentException(String msg) throws CommonIllega...
    method ofIllegalArgumentException (line 36) | public void ofIllegalArgumentException(String msg, Exception e) throws...
    method ofRuntimeException (line 40) | public void ofRuntimeException(String msg) throws CommonRuntimeExcepti...
    method ofRuntimeException (line 44) | public void ofRuntimeException(Throwable e) throws CommonRuntimeExcept...
    method ofNullPointerException (line 48) | public void ofNullPointerException(String msg) throws NullPointerExcep...

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/id/CacheKeyKit.java
  class CacheKeyKit (line 39) | @Slf4j
    method getTimeBasedUuid (line 154) | private UUID getTimeBasedUuid() {
    method uuid (line 170) | public String uuid() {
    method main (line 174) | public static void main(String[] args) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/id/IdKit.java
  class IdKit (line 30) | @UtilityClass
    method sid (line 41) | public String sid() {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/id/StringIdSupplier.java
  type StringIdSupplier (line 27) | public interface StringIdSupplier extends Supplier<String> {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/micro/room/MicroRoom.java
  type MicroRoom (line 27) | public interface MicroRoom {
    method setId (line 28) | void setId(long id);
    method getId (line 30) | long getId();

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/micro/room/MicroRooms.java
  class MicroRooms (line 39) | @FieldDefaults(level = AccessLevel.PRIVATE)
    method contains (line 47) | public boolean contains(long id) {
    method remove (line 51) | public Room remove(long id) {
    method getRoom (line 55) | public Room getRoom(long id) {
    method add (line 59) | public Room add(Room room) {
    method optionalRoom (line 70) | public Optional<Room> optionalRoom(long id) {
    method ofRoom (line 83) | public Room ofRoom(long id) {
    method stream (line 97) | public Stream<Room> stream() {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/time/CacheTimeKit.java
  class CacheTimeKit (line 57) | @UtilityClass
    method nowLocalDate (line 72) | public LocalDate nowLocalDate() {
    method nowLocalDateTime (line 81) | public LocalDateTime nowLocalDateTime() {
    method nowLocalTime (line 90) | public LocalTime nowLocalTime() {
    method currentTimeMillis (line 99) | public long currentTimeMillis() {
    method enableCache (line 106) | public void enableCache() {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/time/ConfigTimeKit.java
  class ConfigTimeKit (line 34) | @UtilityClass

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/time/ExpireTimeKit.java
  class ExpireTimeKit (line 32) | @UtilityClass
    method expireLocalDate (line 41) | public boolean expireLocalDate(long epochDay) {
    method expireLocalDate (line 52) | public boolean expireLocalDate(LocalDate localDate) {
    method expireMillis (line 62) | public boolean expireMillis(long timeMillis) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/time/FormatTimeKit.java
  class FormatTimeKit (line 37) | @UtilityClass
    method ofPattern (line 48) | public DateTimeFormatter ofPattern(String pattern) {
    method format (line 64) | public String format() {
    method format (line 74) | public String format(long timeMillis) {
    method format (line 85) | public String format(TemporalAccessor temporal) {
    method format (line 96) | public String format(TemporalAccessor temporal, String pattern) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/time/ToTimeKit.java
  class ToTimeKit (line 33) | @UtilityClass
    method toMillis (line 42) | public long toMillis(LocalDateTime localDateTime) {
    method toSeconds (line 52) | public int toSeconds(LocalDateTime localDateTime) {
    method toLocalDateTime (line 62) | public LocalDateTime toLocalDateTime(long timeMillis) {
    method toInstant (line 74) | public Instant toInstant(LocalDateTime localDateTime) {

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/trace/TraceIdSupplier.java
  type TraceIdSupplier (line 29) | @FunctionalInterface

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/trace/TraceKit.java
  class TraceKit (line 33) | @UtilityClass
    method setDefaultTraceIdSupplier (line 39) | public void setDefaultTraceIdSupplier(TraceIdSupplier traceIdSupplier) {
    method putTraceIdSupplier (line 43) | public void putTraceIdSupplier(String name, TraceIdSupplier traceIdSup...
    method newTraceId (line 47) | public String newTraceId(String name) {
    method newTraceId (line 51) | public String newTraceId() {
    class SimpleTraceIdSupplier (line 55) | private final class SimpleTraceIdSupplier implements TraceIdSupplier {
      method get (line 58) | @Override

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/weight/Weight.java
  type Weight (line 27) | public interface Weight {
    method getWeightVal (line 33) | int getWeightVal();

FILE: common/common-micro-kit/src/main/java/com/iohao/game/common/kit/weight/WeightKit.java
  class WeightKit (line 33) | public class WeightKit {
    method roll (line 46) | @SuppressWarnings("unchecked")

FILE: common/common-micro-kit/src/test/java/com/iohao/game/common/kit/ByteKitTest.java
  class ByteKitTest (line 10) | public class ByteKitTest {
    method toBytes (line 12) | @Test
    method assertLong (line 19) | private void assertLong(long value) {

FILE: common/common-micro-kit/src/test/java/com/iohao/game/common/kit/TimeKitTest.java
  class TimeKitTest (line 13) | public class TimeKitTest {
    method test (line 14) | @Test

FILE: common/common-micro-kit/src/test/java/com/iohao/game/common/kit/attr/AttrOptionDynamicTest.java
  class AttrOptionDynamicTest (line 11) | public class AttrOptionDynamicTest {
    method ifNull (line 17) | @Test
    class AttrCat (line 35) | private static class AttrCat {
    class MyAttrOptions (line 39) | @Getter

FILE: common/common-micro-kit/src/test/java/com/iohao/game/common/kit/beans/property/PropertyValueObservableTest.java
  class PropertyValueObservableTest (line 14) | @Slf4j
    method testInt (line 19) | @Test
    method testLong (line 47) | @Test
    method testString (line 75) | @Test
    method testBool (line 91) | @Test
    method testObject (line 107) | @Test
    class YourUser (line 130) | @ToString
    method remove1 (line 135) | @Test
    method remove2 (line 156) | @Test
    class OnePropertyChangeListener (line 171) | class OnePropertyChangeListener implements PropertyChangeListener<Numb...
      method changed (line 172) | @Override

FILE: common/common-micro-kit/src/test/java/com/iohao/game/common/kit/collect/ListMultiMapTest.java
  class ListMultiMapTest (line 13) | public class ListMultiMapTest {
    method test (line 16) | @Test

FILE: common/common-micro-kit/src/test/java/com/iohao/game/common/kit/collect/SetMultiMapTest.java
  class SetMultiMapTest (line 12) | public class SetMultiMapTest {
    method test (line 15) | @Test

FILE: common/common-micro-kit/src/test/java/com/iohao/game/common/kit/concurrent/TaskKitTest.java
  class TaskKitTest (line 20) | @Slf4j
    method tearDown (line 22) | @After
    method execute (line 27) | @Test
    method runOnce (line 40) | @Test
    method runInterval (line 66) | @Test
    method testException (line 134) | @Test
    method example (line 153) | @Test

FILE: common/common-micro-kit/src/test/java/com/iohao/game/common/kit/concurrent/executor/ExecutorRegionKitTest.java
  class ExecutorRegionKitTest (line 16) | @Slf4j
    method tearDown (line 19) | @After
    method name (line 24) | @Test
    method userThreadExecutor (line 55) | @Test
    method extracted (line 65) | private void extracted(ThreadExecutor threadExecutor) {
    method userVirtualThreadExecutor (line 89) | @Test
    method simpleThreadExecutor (line 107) | @Test
    method sleep (line 115) | void sleep() {
    class Amount (line 123) | static final class Amount {
      method inc (line 126) | void inc() {
      method toString (line 130) | @Override

FILE: common/common-micro-kit/src/test/java/com/iohao/game/common/kit/concurrent/timer/delay/DelayTaskTest.java
  class DelayTaskTest (line 21) | @Slf4j
    method setUp (line 25) | @Before
    method tearDown (line 31) | @After
    method runDelayTask (line 37) | @Test
    method plusDelayTime (line 54) | @Test
    method minusDelayTime (line 77) | @Test
    method coverDelayTask (line 104) | @Test
    method cancelDelayTask (line 136) | @Test
    method optionalDelayTask (line 181) | @Test
    method customTaskListener (line 204) | @Test
    method more (line 237) | @Test
    class ShootTaskListener (line 255) | @Slf4j
      method ShootTaskListener (line 263) | public ShootTaskListener(String targetEntity) {
      method onUpdate (line 267) | @Override

FILE: common/common-micro-kit/src/test/java/com/iohao/game/common/kit/time/CacheTimeKitTest.java
  class CacheTimeKitTest (line 16) | public class CacheTimeKitTest {
    method nowLocalDate (line 18) | @Test

FILE: common/common-micro-kit/src/test/java/com/iohao/game/common/kit/time/ExpireTimeKitTest.java
  class ExpireTimeKitTest (line 15) | public class ExpireTimeKitTest {
    method expireLocalDate (line 17) | @Test

FILE: common/common-micro-kit/src/test/java/com/iohao/game/common/kit/time/FormatTimeKitTest.java
  class FormatTimeKitTest (line 14) | @Slf4j
    method format (line 17) | @Test
    method name (line 29) | @Test

FILE: common/common-micro-kit/src/test/java/com/iohao/game/common/kit/trace/TraceKitTest.java
  class TraceKitTest (line 21) | @Slf4j
    method tearDown (line 29) | @After
    method newTraceId (line 36) | @Test
    method newTraceIdUUID (line 41) | @Test
    method newTraceIdTemp (line 49) | @Test
    method newTraceIdProcess (line 67) | void newTraceIdProcess() {
    method await (line 91) | void await() {
    method loopTraceId (line 99) | void loopTraceId(Consumer<String[]> consumer) {
    method name (line 114) | @Test
    method testMDC (line 128) | @Test
    method extractedVirtual (line 142) | private void extractedVirtual(long userId) {
    method extracted (line 170) | private void extracted(ThreadExecutor userVirtualThreadExecutor, Strin...
    method sleep (line 188) | void sleep(int milliseconds) {

FILE: common/common-validation/src/main/java/com/iohao/game/common/validation/Validation.java
  class Validation (line 38) | @Slf4j
    method getValidator (line 53) | public Validator getValidator() throws Exception {
    method getValidatorClassName (line 98) | private String getValidatorClassName() {
    method getValidatorPackage (line 119) | private String getValidatorPackage(String className) {

FILE: common/common-validation/src/main/java/com/iohao/game/common/validation/Validator.java
  type Validator (line 26) | public interface Validator {
    method validate (line 35) | String validate(Object data, Class<?>... groups);
    method isValidator (line 43) | boolean isValidator(Class<?> paramClazz);

FILE: common/common-validation/src/main/java/com/iohao/game/common/validation/processor/ValidationProcessor.java
  class ValidationProcessor (line 41) | @AutoService(Processor.class)
    method process (line 53) | @Override
    method getEnableValidation (line 76) | private static EnableValidation getEnableValidation(RoundEnvironment r...
    method createMetaInf (line 93) | private static void createMetaInf(ProcessingEnvironment processingEnv,...

FILE: common/common-validation/src/main/java/com/iohao/game/common/validation/support/JakartaValidator.java
  class JakartaValidator (line 35) | public class JakartaValidator implements Validator {
    method JakartaValidator (line 39) | public JakartaValidator() {
    method validate (line 52) | @Override
    method isValidator (line 74) | @Override

FILE: common/common-validation/src/main/java/com/iohao/game/common/validation/support/JavaxValidator.java
  class JavaxValidator (line 34) | public class JavaxValidator implements Validator {
    method JavaxValidator (line 38) | public JavaxValidator() {
    method validate (line 51) | @Override
    method isValidator (line 73) | @Override

FILE: external/external-core/src/main/java/com/iohao/game/external/core/ExternalCore.java
  type ExternalCore (line 33) | public interface ExternalCore {
    method createMicroBootstrap (line 37) | MicroBootstrap createMicroBootstrap();

FILE: external/external-core/src/main/java/com/iohao/game/external/core/ExternalCoreSetting.java
  type ExternalCoreSetting (line 33) | public interface ExternalCoreSetting extends AwareInject, AttrOptionDyna...

FILE: external/external-core/src/main/java/com/iohao/game/external/core/ExternalServer.java
  type ExternalServer (line 32) | public interface ExternalServer {
    method startup (line 36) | void startup();

FILE: external/external-core/src/main/java/com/iohao/game/external/core/aware/ExternalCoreSettingAware.java
  type ExternalCoreSettingAware (line 29) | public interface ExternalCoreSettingAware {
    method setExternalCoreSetting (line 35) | void setExternalCoreSetting(ExternalCoreSetting externalCoreSetting);

FILE: external/external-core/src/main/java/com/iohao/game/external/core/aware/UserSessionsAware.java
  type UserSessionsAware (line 29) | public interface UserSessionsAware {
    method setUserSessions (line 35) | void setUserSessions(UserSessions<?, ?> userSessions);

FILE: external/external-core/src/main/java/com/iohao/game/external/core/broker/client/ExternalBrokerClientStartup.java
  class ExternalBrokerClientStartup (line 44) | @Setter
    method createBarSkeletonBuilder (line 48) | protected BarSkeletonBuilder createBarSkeletonBuilder() {
    method createBarSkeleton (line 56) | @Override
    method createBrokerClientBuilder (line 61) | @Override
    method registerUserProcessor (line 76) | @Override

FILE: external/external-core/src/main/java/com/iohao/game/external/core/broker/client/enhance/ExternalEnhance.java
  type ExternalEnhance (line 27) | public interface ExternalEnhance {
    method enhance (line 28) | void enhance(BarSkeletonBuilder builder);

FILE: external/external-core/src/main/java/com/iohao/game/external/core/broker/client/enhance/ExternalEnhances.java
  class ExternalEnhances (line 33) | @Slf4j
    method add (line 42) | void add(ExternalEnhance enhance) {
    method enhance (line 46) | public void enhance(BarSkeletonBuilder builder) {

FILE: external/external-core/src/main/java/com/iohao/game/external/core/broker/client/ext/ExternalBizRegion.java
  type ExternalBizRegion (line 50) | public interface ExternalBizRegion {
    method getBizCode (line 59) | int getBizCode();
    method request (line 71) | Serializable request(ExternalBizRegionContext regionContext) throws Ms...

FILE: external/external-core/src/main/java/com/iohao/game/external/core/broker/client/ext/ExternalBizRegionContext.java
  class ExternalBizRegionContext (line 33) | @Getter

FILE: external/external-core/src/main/java/com/iohao/game/external/core/broker/client/ext/ExternalBizRegions.java
  class ExternalBizRegions (line 34) | @UtilityClass
    method add (line 53) | public void add(ExternalBizRegion externalBizRegion) {
    method getExternalRegion (line 64) | public ExternalBizRegion getExternalRegion(int bizCode) {

FILE: external/external-core/src/main/java/com/iohao/game/external/core/broker/client/ext/impl/AttachmentExternalBizRegion.java
  class AttachmentExternalBizRegion (line 36) | public final class AttachmentExternalBizRegion implements ExternalBizReg...
    method getBizCode (line 37) | @Override
    method request (line 42) | @Override

FILE: external/external-core/src/main/java/com/iohao/game/external/core/broker/client/ext/impl/ExistUserExternalBizRegion.java
  class ExistUserExternalBizRegion (line 37) | public final class ExistUserExternalBizRegion implements ExternalBizRegi...
    method getBizCode (line 39) | @Override
    method request (line 44) | @Override

FILE: external/external-core/src/main/java/com/iohao/game/external/core/broker/client/ext/impl/ExternalBizRegionKit.java
  class ExternalBizRegionKit (line 30) | @UtilityClass
    method checkUserExist (line 37) | public void checkUserExist(ExternalBizRegionContext regionContext) {

FILE: external/external-core/src/main/java/com/iohao/game/external/core/broker/client/ext/impl/ForcedOfflineExternalBizRegion.java
  class ForcedOfflineExternalBizRegion (line 40) | public final class ForcedOfflineExternalBizRegion implements ExternalBiz...
    method ForcedOfflineExternalBizRegion (line 43) | public ForcedOfflineExternalBizRegion() {
    method getBizCode (line 50) | @Override
    method request (line 55) | @Override

FILE: external/external-core/src/main/java/com/iohao/game/external/core/broker/client/ext/impl/UserHeadMetadataExternalBizRegion.java
  class UserHeadMetadataExternalBizRegion (line 54) | public final class UserHeadMetadataExternalBizRegion implements External...
    method getBizCode (line 55) | @Override
    method request (line 60) | @Override

FILE: external/external-core/src/main/java/com/iohao/game/external/core/broker/client/processor/BroadcastMessageExternalProcessor.java
  class BroadcastMessageExternalProcessor (line 38) | @Slf4j(topic = IoGameLogName.MsgTransferTopic)
    method setUserSessions (line 43) | @Override
    method handleRequest (line 48) | @Override
    method interest (line 57) | @Override

FILE: external/external-core/src/main/java/com/iohao/game/external/core/broker/client/processor/BroadcastOrderMessageExternalProcessor.java
  class BroadcastOrderMessageExternalProcessor (line 39) | public final class BroadcastOrderMessageExternalProcessor extends AsyncU...
    method setUserSessions (line 45) | @Override
    method handleRequest (line 50) | @Override
    method getExecutor (line 55) | @Override
    method interest (line 60) | @Override

FILE: external/external-core/src/main/java/com/iohao/game/external/core/broker/client/processor/BrokerClientOfflineMessageExternalProcessor.java
  class BrokerClientOfflineMessageExternalProcessor (line 40) | @Setter
    method handleRequest (line 47) | @Override
    method interest (line 60) | @Override

FILE: external/external-core/src/main/java/com/iohao/game/external/core/broker/client/processor/BrokerClientOnlineMessageExternalProcessor.java
  class BrokerClientOnlineMessageExternalProcessor (line 38) | @Setter
    method handleRequest (line 45) | @Override
    method interest (line 57) | @Override

FILE: external/external-core/src/main/java/com/iohao/game/external/core/broker/client/processor/EndPointLogicServerMessageExternalProcessor.java
  class EndPointLogicServerMessageExternalProcessor (line 41) | public final class EndPointLogicServerMessageExternalProcessor extends A...
    method handleRequest (line 45) | @Override
    method listLogicServerId (line 84) | private List<Integer> listLogicServerId(EndPointLogicServerMessage mes...
    method interest (line 96) | @Override
    method setUserSessions (line 101) | @Override

FILE: external/external-core/src/main/java/com/iohao/game/external/core/broker/client/processor/RequestCollectExternalMessageExternalProcessor.java
  class RequestCollectExternalMessageExternalProcessor (line 47) | @Slf4j(topic = IoGameLogName.ExternalTopic)
    method setUserSessions (line 52) | @Override
    method handleRequest (line 57) | @Override
    method interest (line 111) | @Override

FILE: external/external-core/src/main/java/com/iohao/game/external/core/broker/client/processor/ResponseMessageExternalProcessor.java
  class ResponseMessageExternalProcessor (line 47) | @Slf4j(topic = IoGameLogName.MsgTransferTopic)
    method handleRequest (line 53) | @Override
    method interest (line 91) | @Override
    method setUserSessions (line 96) | @Override

FILE: external/external-core/src/main/java/com/iohao/game/external/core/broker/client/processor/SettingUserIdMessageExternalProcessor.java
  class SettingUserIdMessageExternalProcessor (line 40) | public final class SettingUserIdMessageExternalProcessor extends Abstrac...
    method handleRequest (line 44) | @Override
    method interest (line 74) | @Override
    method setUserSessions (line 79) | @Override

FILE: external/external-core/src/main/java/com/iohao/game/external/core/broker/client/processor/listener/CmdRegionBrokerClientListener.java
  class CmdRegionBrokerClientListener (line 32) | public class CmdRegionBrokerClientListener implements BrokerClientListen...
    method onlineLogic (line 34) | @Override
    method offlineLogic (line 41) | @Override
    method me (line 52) | public static CmdRegionBrokerClientListener me() {
    class Holder (line 57) | private static class Holder {

FILE: external/external-core/src/main/java/com/iohao/game/external/core/config/ExternalGlobalConfig.java
  class ExternalGlobalConfig (line 31) | @UtilityClass
    class CoreOption (line 52) | @UtilityClass

FILE: external/external-core/src/main/java/com/iohao/game/external/core/config/ExternalJoinEnum.java
  type ExternalJoinEnum (line 29) | @Getter
    method ExternalJoinEnum (line 48) | ExternalJoinEnum(String name, int index) {
    method cocPort (line 68) | public int cocPort(int port) {

FILE: external/external-core/src/main/java/com/iohao/game/external/core/hook/AccessAuthenticationHook.java
  type AccessAuthenticationHook (line 32) | public interface AccessAuthenticationHook {
    method setVerifyIdentity (line 39) | void setVerifyIdentity(boolean verifyIdentity);
    method addIgnoreAuthCmd (line 47) | void addIgnoreAuthCmd(int cmd, int subCmd);
    method addIgnoreAuthCmd (line 54) | void addIgnoreAuthCmd(int cmd);
    method removeIgnoreAuthCmd (line 62) | void removeIgnoreAuthCmd(int cmd, int subCmd);
    method removeIgnoreAuthCmd (line 69) | void removeIgnoreAuthCmd(int cmd);
    method pass (line 81) | boolean pass(boolean loginSuccess, int cmdMerge);
    method addRejectionCmd (line 91) | void addRejectionCmd(int cmd);
    method addRejectionCmd (line 102) | void addRejectionCmd(int cmd, int subCmd);
    method removeRejectCmd (line 110) | void removeRejectCmd(int cmd, int subCmd);
    method removeRejectCmd (line 117) | void removeRejectCmd(int cmd);
    method reject (line 128) | boolean reject(int cmdMerge);
    method clear (line 133) | void clear();

FILE: external/external-core/src/main/java/com/iohao/game/external/core/hook/BrokerClientExternalAttr.java
  type BrokerClientExternalAttr (line 30) | public interface BrokerClientExternalAttr {

FILE: external/external-core/src/main/java/com/iohao/game/external/core/hook/IdleHook.java
  type IdleHook (line 33) | public interface IdleHook<IdleEvent> {
    method callback (line 44) | boolean callback(UserSession userSession, IdleEvent event);
    method pongBefore (line 64) | default void pongBefore(BarMessage idleMessage) {

FILE: external/external-core/src/main/java/com/iohao/game/external/core/hook/UserHook.java
  type UserHook (line 43) | public interface UserHook {
    method into (line 49) | void into(UserSession userSession);
    method quit (line 56) | void quit(UserSession userSession);

FILE: external/external-core/src/main/java/com/iohao/game/external/core/hook/cache/CmdCacheOption.java
  class CmdCacheOption (line 36) | @Getter
    method CmdCacheOption (line 46) | private CmdCacheOption(Duration expireTime, int cacheLimit, Duration e...
    method newBuilder (line 52) | public static CmdCacheOption.Builder newBuilder() {
    class Builder (line 56) | @Setter
      method build (line 87) | public Cmd
Condensed preview — 906 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,933K chars).
[
  {
    "path": ".github/ISSUE_TEMPLATE/ask-question.md",
    "chars": 211,
    "preview": "---\nname: 提问与交流\nabout: 对框架使用过程中遇到的问题、不清楚或模糊的地方;询问框架能否支持某类需求\n\n---\n\n### 你的问题 | 使用场景\n\n描述你遇到的问题,或使用场景(询问框架能否满足此类需求)\n\n\n\n### 预"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.md",
    "chars": 149,
    "preview": "---\nname: bug\nabout: 疑似 bug\n---\n\n### 你的问题\n\n描述你遇到的问题\n\n\n\n### 预期值\n\n期望的预期值\n\n\n\n\n### 实际值\n\n实际值\n\n\n\n### 复现步骤\n\n描述复现步骤,并提供复现 demo\n\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/empty-issues.md",
    "chars": 61,
    "preview": "---\nname: empty issues\nabout: 自定义 issues 描述\n---\n\n### 提问\n\n\n\n\n\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/enhance-task.md",
    "chars": 91,
    "preview": "---\nname: 功能增强建议\nabout: 对框架功能增强、新增...等相关建议\n---\n\n### 新增功能的使用场景\n\n描述功能的使用场景、作用;或描述功能所带来的好处\n\n\n\n"
  },
  {
    "path": ".gitignore",
    "chars": 947,
    "preview": "### other dir ###\nclasses/\n.temp/\nlogs/\nlog/\n.svn/\nsvn/\nlib/\n.act.*\nsystem/\n\nHELP.md\n!**/src/main/**\n!**/src/test/**\n\n*."
  },
  {
    "path": "BACKERS.md",
    "chars": 976,
    "preview": "#### 支持名单\n\n通过 wx、alipay 支付时,不能看见全称,下面使用 '-' 来代替 *。\n\n\n\n#### 2025\n\n##### 小星星\n\n\n| 称号 | 名单                                  "
  },
  {
    "path": "LICENSE",
    "chars": 34523,
    "preview": "                    GNU AFFERO GENERAL PUBLIC LICENSE\n                       Version 3, 19 November 2007\n\n Copyright (C)"
  },
  {
    "path": "README.md",
    "chars": 28860,
    "preview": "<h2 align=\"center\" style=\"text-align:center;\">\n  ioGame\n</h2>\n<p align=\"center\">\n  <strong>Lock-free, async, event-drive"
  },
  {
    "path": "README_CN.md",
    "chars": 18641,
    "preview": "<h2 align=\"center\" style=\"text-align:center;\">\n  ioGame\n</h2>\n<p align=\"center\">\n  <strong>无锁异步化、事件驱动的架构设计;轻量级,无需依赖任何第三方"
  },
  {
    "path": "changeLog_ioGame.md",
    "chars": 82874,
    "preview": "文档与日志\n- [框架版本更新日志](https://iohao.github.io/game/docs/version_log)\n- [ioGame 真.轻量级网络编程框架 - 在线使用文档 ](https://game.iohao.co"
  },
  {
    "path": "common/README.md",
    "chars": 55,
    "preview": "```text\n.\n├── common-core 业务框架\n└── common-kit 工具相关\n\n```"
  },
  {
    "path": "common/common-core/README.md",
    "chars": 382,
    "preview": "## 业务框架\n\n如果说  [sofa-bolt](https://www.sofastack.tech/projects/sofa-bolt/overview/) 是为了让 Java 程序员能将更多的精力放在基于网络通信的业务逻辑实现上。"
  },
  {
    "path": "common/common-core/pom.xml",
    "chars": 3380,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/IoGameVersion.java",
    "chars": 1182,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/annotation/ActionController.java",
    "chars": 1175,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/annotation/ActionMethod.java",
    "chars": 1210,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/annotation/DocActionSend.java",
    "chars": 1423,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/annotation/DocActionSends.java",
    "chars": 1253,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/annotation/ValidatedGroup.java",
    "chars": 1221,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/annotation/package-info.java",
    "chars": 921,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionCommand.java",
    "chars": 14750,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionCommandDocParser.java",
    "chars": 4234,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionCommandFlowExecute.java",
    "chars": 1895,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionCommandHandler.java",
    "chars": 2237,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionCommandParser.java",
    "chars": 13662,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionCommandRegion.java",
    "chars": 2997,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionCommandRegionGlobalCheckKit.java",
    "chars": 3037,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionCommandRegions.java",
    "chars": 6200,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionFactoryBean.java",
    "chars": 1531,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionParserListenerAbout.java",
    "chars": 4834,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ActionSend.java",
    "chars": 1057,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/BarMessageKit.java",
    "chars": 3161,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/BarSkeleton.java",
    "chars": 3495,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/BarSkeletonBuilder.java",
    "chars": 9308,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/BarSkeletonBuilderParamConfig.java",
    "chars": 6533,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/BarSkeletonSetting.java",
    "chars": 3256,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/CmdInfo.java",
    "chars": 3141,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/CmdInfoFlyweightFactory.java",
    "chars": 2019,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/CmdKit.java",
    "chars": 2582,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/DataCodecKit.java",
    "chars": 1846,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/DefaultActionCommandFlowExecute.java",
    "chars": 3088,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/DefaultActionFactoryBean.java",
    "chars": 1463,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/DependencyInjectionPart.java",
    "chars": 2425,
    "preview": "/*\n * ioGame \n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # io"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/DevConfig.java",
    "chars": 1899,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/Handler.java",
    "chars": 1176,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/InOutManager.java",
    "chars": 2614,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/InOutManagerAbout.java",
    "chars": 3384,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/IoGameCommonCoreConfig.java",
    "chars": 1326,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/IoGameGlobalSetting.java",
    "chars": 1247,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/PrintActionKit.java",
    "chars": 11548,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/SkeletonAttr.java",
    "chars": 1936,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/ValidatorKit.java",
    "chars": 2111,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/action/parser/ActionParserContext.java",
    "chars": 1445,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/action/parser/ActionParserListener.java",
    "chars": 1445,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/action/parser/package-info.java",
    "chars": 1540,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/codec/DataCodec.java",
    "chars": 1530,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/codec/DataSelfEncode.java",
    "chars": 1091,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/codec/JsonDataCodec.java",
    "chars": 1435,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/codec/ProtoDataCodec.java",
    "chars": 1597,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/codec/package-info.java",
    "chars": 2425,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/commumication/BroadcastContext.java",
    "chars": 2723,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/commumication/BroadcastOrderContext.java",
    "chars": 2877,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/commumication/BrokerClientContext.java",
    "chars": 2769,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/commumication/ChannelContext.java",
    "chars": 1227,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/commumication/CommunicationAggregationContext.java",
    "chars": 1139,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/commumication/InvokeExternalModuleContext.java",
    "chars": 2545,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/commumication/InvokeModuleContext.java",
    "chars": 13833,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/commumication/ProcessorContext.java",
    "chars": 1323,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/commumication/SimpleServer.java",
    "chars": 1130,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/commumication/package-info.java",
    "chars": 931,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ActionCommandDoc.java",
    "chars": 1502,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ActionCommandDocKit.java",
    "chars": 3933,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ActionDoc.java",
    "chars": 3017,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ActionDocs.java",
    "chars": 1334,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ActionDocument.java",
    "chars": 3077,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ActionMemberCmdDocument.java",
    "chars": 1477,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ActionMethodDocument.java",
    "chars": 5664,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ActionSendDoc.java",
    "chars": 2327,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ActionSendDocs.java",
    "chars": 2550,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ActionSendDocsRegion.java",
    "chars": 1328,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/BarSkeletonDoc.java",
    "chars": 2026,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/BroadcastDoc.java",
    "chars": 1353,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/BroadcastDocBuilder.java",
    "chars": 3600,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/BroadcastDocument.java",
    "chars": 2344,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/BroadcastDocumentBuilder.java",
    "chars": 5534,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/DocInfo.java",
    "chars": 6620,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/DocumentAccessAuthentication.java",
    "chars": 1146,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/DocumentAnalyseKit.java",
    "chars": 5829,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/DocumentGenerate.java",
    "chars": 1110,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/DocumentMethod.java",
    "chars": 1275,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ErrorCodeDoc.java",
    "chars": 1102,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ErrorCodeDocs.java",
    "chars": 1544,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ErrorCodeDocsRegion.java",
    "chars": 1549,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ErrorCodeDocument.java",
    "chars": 1301,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/IoGameDocument.java",
    "chars": 1259,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/IoGameDocumentHelper.java",
    "chars": 6999,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/JavaClassDocInfo.java",
    "chars": 3550,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/TextDocumentGenerate.java",
    "chars": 6249,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/TypeMappingDocument.java",
    "chars": 1910,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/TypeMappingRecord.java",
    "chars": 1855,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/package-info.java",
    "chars": 2329,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/enhance/BarSkeletonBuilderEnhance.java",
    "chars": 1064,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/enhance/BarSkeletonBuilderEnhances.java",
    "chars": 1636,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/exception/ActionErrorEnum.java",
    "chars": 2151,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/exception/MsgException.java",
    "chars": 2049,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/exception/MsgExceptionInfo.java",
    "chars": 3746,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/exception/MsgExceptionKit.java",
    "chars": 1912,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/exception/package-info.java",
    "chars": 1626,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/ActionAfter.java",
    "chars": 1196,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/ActionMethodExceptionProcess.java",
    "chars": 1176,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/ActionMethodInOut.java",
    "chars": 1781,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/ActionMethodInvoke.java",
    "chars": 1420,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/ActionMethodParamParser.java",
    "chars": 1262,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/ActionMethodResultWrap.java",
    "chars": 1251,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/FlowContext.java",
    "chars": 4237,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/FlowContextFactory.java",
    "chars": 1194,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/FlowContextKit.java",
    "chars": 3667,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/InternalAboutFlowContext.java",
    "chars": 47547,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/ResponseMessageCreate.java",
    "chars": 1150,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/UserAttachment.java",
    "chars": 1081,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/attr/FlowAttr.java",
    "chars": 2239,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/attr/FlowOption.java",
    "chars": 1075,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/attr/FlowOptionDynamic.java",
    "chars": 1973,
    "preview": "/*\n * ioGame \n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # io"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/attr/package-info.java",
    "chars": 925,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/DebugInOut.java",
    "chars": 11959,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/DefaultActionAfter.java",
    "chars": 2034,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/DefaultActionMethodExceptionProcess.java",
    "chars": 1639,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/DefaultActionMethodInvoke.java",
    "chars": 2234,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/DefaultActionMethodParamParser.java",
    "chars": 3331,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/DefaultActionMethodResultWrap.java",
    "chars": 2953,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/DefaultResponseMessageCreate.java",
    "chars": 1265,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/StatActionInOut.java",
    "chars": 12600,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/ThreadMonitorInOut.java",
    "chars": 6070,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/TimeRangeInOut.java",
    "chars": 13790,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/TraceIdInOut.java",
    "chars": 1750,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/package-info.java",
    "chars": 1893,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/package-info.java",
    "chars": 986,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/parser/BoolValueMethodParser.java",
    "chars": 2830,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/parser/DefaultMethodParser.java",
    "chars": 3583,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/parser/IntValueMethodParser.java",
    "chars": 2855,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/parser/LongValueMethodParser.java",
    "chars": 2871,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/parser/MethodParser.java",
    "chars": 3010,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/parser/MethodParsers.java",
    "chars": 5012,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/parser/StringValueMethodParser.java",
    "chars": 2788,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/parser/package-info.java",
    "chars": 951,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/package-info.java",
    "chars": 915,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/runner/InternalRunner.java",
    "chars": 1217,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/runner/Runner.java",
    "chars": 3499,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/runner/Runners.java",
    "chars": 3109,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/core/runner/package-info.java",
    "chars": 2675,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/AbstractEventBusRunner.java",
    "chars": 1068,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/EventBrokerClientMessage.java",
    "chars": 2093,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/EventBus.java",
    "chars": 11625,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/EventBusFireType.java",
    "chars": 1602,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/EventBusListener.java",
    "chars": 1621,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/EventBusMessage.java",
    "chars": 2361,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/EventBusMessageCreator.java",
    "chars": 1159,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/EventBusRegion.java",
    "chars": 2690,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/EventBusRunner.java",
    "chars": 4812,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/EventBusSubscriber.java",
    "chars": 1108,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/EventSubscribe.java",
    "chars": 2254,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/EventTopicMessage.java",
    "chars": 1009,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/ExecutorSelector.java",
    "chars": 3679,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/InternalAboutAny.java",
    "chars": 8338,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/InternalAboutEventBus.java",
    "chars": 28119,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/SubscribeExecutorStrategy.java",
    "chars": 1532,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/Subscriber.java",
    "chars": 2250,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/SubscriberInvoke.java",
    "chars": 1116,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/SubscriberInvokeCreator.java",
    "chars": 1251,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/eventbus/package-info.java",
    "chars": 5017,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/ext/spring/ActionFactoryBeanForSpring.java",
    "chars": 2955,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/ext/spring/package-info.java",
    "chars": 1315,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/i18n/Bundle.java",
    "chars": 1433,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/i18n/MessageKey.java",
    "chars": 3723,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/kit/ExecutorSelectEnum.java",
    "chars": 2386,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/kit/ExecutorSelectKit.java",
    "chars": 3330,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/kit/FixedCmd.java",
    "chars": 1164,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/kit/LogicServerCreateKit.java",
    "chars": 2359,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/kit/RangeBroadcast.java",
    "chars": 8666,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/kit/RangeBroadcaster.java",
    "chars": 11405,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/kit/package-info.java",
    "chars": 936,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/package-info.java",
    "chars": 2608,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/BarMessage.java",
    "chars": 3261,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/HeadMetadata.java",
    "chars": 10094,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/RequestMessage.java",
    "chars": 2952,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/ResponseMessage.java",
    "chars": 4079,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/collect/RequestCollectMessage.java",
    "chars": 1742,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/collect/ResponseCollectItemMessage.java",
    "chars": 4935,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/collect/ResponseCollectMessage.java",
    "chars": 2239,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/collect/package-info.java",
    "chars": 1502,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/external/RequestCollectExternalMessage.java",
    "chars": 2231,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/external/ResponseCollectExternalItemMessage.java",
    "chars": 2209,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/external/ResponseCollectExternalMessage.java",
    "chars": 2470,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/external/package-info.java",
    "chars": 1023,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/login/SettingUserIdMessage.java",
    "chars": 1703,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/login/SettingUserIdMessageResponse.java",
    "chars": 1322,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/login/SettingUserIdResult.java",
    "chars": 1559,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/package-info.java",
    "chars": 919,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/processor/EndPointLogicServerMessage.java",
    "chars": 2580,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  },
  {
    "path": "common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/processor/EndPointOperationEnum.java",
    "chars": 1822,
    "preview": "/*\n * ioGame\n * Copyright (C) 2021 - present  渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.\n * # ioh"
  }
]

// ... and 706 more files (download for full content)

About this extraction

This page contains the full source code of the iohao/iogame GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 906 files (2.4 MB), approximately 688.9k tokens, and a symbol index with 3949 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!