> protobufClassPredicate = c -> c.getAnnotation(ProtobufClass.class) == null;
+ ProtobufActionParserListener.collect(context, protobufClassPredicate, protoSet);
+ }
+
+ @Override
+ public void onAfter(BarSkeleton barSkeleton) {
+ if (this.protoSet.isEmpty()) {
+ return;
+ }
+
+ log.error("======== 注意,协议类没有添加 ProtobufClass 注解 ========");
+ for (Class> protoClass : this.protoSet) {
+ log.error(protoClass.toString());
+ }
+ }
+
+ private ProtobufCheckActionParserListener() {
+ }
+
+ public static ProtobufCheckActionParserListener me() {
+ return Holder.ME;
+ }
+
+ /** 通过 JVM 的类加载机制, 保证只加载一次 (singleton) */
+ private static class Holder {
+ static final ProtobufCheckActionParserListener ME = new ProtobufCheckActionParserListener();
+ }
+}
\ No newline at end of file
diff --git a/common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/DocInfo.java b/common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/DocInfo.java
index d410de953..e04a48ead 100644
--- a/common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/DocInfo.java
+++ b/common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/DocInfo.java
@@ -65,7 +65,7 @@ void add(ActionCommand subBehavior) {
// 方法参数
Arrays.stream(subBehavior.getParamInfos())
- .filter(paramInfo -> !paramInfo.isExtension())
+ .filter(paramInfo -> !paramInfo.isFlowContext())
.map(this::paramInfoToString)
.forEach(methodParam -> paramMap.put("methodParam", methodParam));
diff --git a/common/common-core/src/main/java/com/iohao/game/action/skeleton/core/exception/MsgExceptionInfo.java b/common/common-core/src/main/java/com/iohao/game/action/skeleton/core/exception/MsgExceptionInfo.java
index 5809ec98c..9680bd724 100644
--- a/common/common-core/src/main/java/com/iohao/game/action/skeleton/core/exception/MsgExceptionInfo.java
+++ b/common/common-core/src/main/java/com/iohao/game/action/skeleton/core/exception/MsgExceptionInfo.java
@@ -92,6 +92,27 @@ default void assertNonNull(Object value) throws MsgException {
assertTrue(Objects.nonNull(value));
}
+ /**
+ * 断言值 value 为 null, 就抛出异常
+ *
+ * @param value 断言值
+ * @throws MsgException e
+ */
+ default void assertNullThrows(Object value) throws MsgException {
+ assertTrueThrows(Objects.isNull(value));
+ }
+
+ /**
+ * 断言值 value 为 null, 就抛出异常
+ *
+ * @param value 断言值
+ * @param msg 自定义消息
+ * @throws MsgException e
+ */
+ default void assertNullThrows(Object value, String msg) throws MsgException {
+ assertTrueThrows(Objects.isNull(value), msg);
+ }
+
/**
* 断言必须是 true, 否则抛出异常
*
diff --git a/common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/DefaultActionMethodParamParser.java b/common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/DefaultActionMethodParamParser.java
index 873710568..2808c425e 100644
--- a/common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/DefaultActionMethodParamParser.java
+++ b/common/common-core/src/main/java/com/iohao/game/action/skeleton/core/flow/internal/DefaultActionMethodParamParser.java
@@ -58,15 +58,15 @@ public Object[] listParam(final FlowContext flowContext) {
for (int i = 0; i < len; i++) {
// 方法参数信息
ActionCommand.ParamInfo paramInfo = paramInfos[i];
- Class> paramClazz = paramInfo.getActualTypeArgumentClazz();
// flow 上下文
- if (FlowContext.class.isAssignableFrom(paramClazz)) {
+ if (paramInfo.isFlowContext()) {
params[i] = flowContext;
continue;
}
// 得到方法参数解析器,把字节解析成 action 业务参数
+ Class> paramClazz = paramInfo.getActualTypeArgumentClazz();
var methodParser = MethodParsers.getMethodParser(paramClazz);
var param = methodParser.parseParam(request.getData(), paramInfo);
params[i] = param;
diff --git a/common/common-core/src/main/java/com/iohao/game/action/skeleton/kit/RangeBroadcast.java b/common/common-core/src/main/java/com/iohao/game/action/skeleton/kit/RangeBroadcast.java
index d9029f2e9..fc5a4f228 100644
--- a/common/common-core/src/main/java/com/iohao/game/action/skeleton/kit/RangeBroadcast.java
+++ b/common/common-core/src/main/java/com/iohao/game/action/skeleton/kit/RangeBroadcast.java
@@ -54,14 +54,26 @@
* .addUserId(List.of(3L, 4L, 5L))
* // 排除一些用户,被排除的用户将不会接收到广播
* .removeUserId(1)
- * // 执行广播
+ * .removeUserId(4)
+ * // 执行广播,只有 2、3、5 可以接收到广播
* .execute();
*
* // example - 2
* new RangeBroadcast(flowContext)
- * // 需要广播的数据
- * .setResponseMessage(cmdInfo, playerReady)
- * // // 添加需要接收广播的用户
+ * // 需要广播的数据(路由、业务数据)
+ * .setResponseMessage(cmdInfo, StringValue.of("hello"))
+ * // 添加需要接收广播的用户
+ * .addUserId(1)
+ * // 执行广播
+ * .execute();
+ *
+ * // example - 3
+ * BrokerClientContext brokerClient = ...;
+ * var aggregationContext = brokerClient.getCommunicationAggregationContext();
+ * new RangeBroadcast(aggregationContext)
+ * // 需要广播的数据(路由、业务数据)
+ * .setResponseMessage(cmdInfo, StringValue.of("hello"))
+ * // 添加需要接收广播的用户
* .addUserId(1)
* // 执行广播
* .execute();
@@ -81,6 +93,8 @@ public class RangeBroadcast {
ResponseMessage responseMessage;
/** 是否执行发送领域事件操作: true 执行推送操作 */
boolean doSend = true;
+ /** 检查 userIds ;当值为 true 时,userIds 必须有元素 */
+ boolean checkEmptyUser = true;
public RangeBroadcast(CommunicationAggregationContext aggregationContext) {
Objects.requireNonNull(aggregationContext);
@@ -92,7 +106,7 @@ public RangeBroadcast(FlowContext flowContext) {
}
/**
- * 响应消息到远程, 此方法是同步推送
+ * 响应消息到远程端(用户、玩家)
*
* 模板方法模式:
* 在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。
@@ -125,12 +139,8 @@ public final void execute() {
Objects.requireNonNull(this.responseMessage);
- if (CollKit.isEmpty(this.userIds)) {
- throw new RuntimeException("没有添加消息推送人 " + this.getClass());
- }
-
- // 推送响应 (广播消息)给指定的用户列表
- this.aggregationContext.broadcast(this.responseMessage, this.userIds);
+ // 开始广播
+ this.broadcast();
}
/**
@@ -155,6 +165,21 @@ protected void logic() {
protected void trick() {
}
+ /**
+ * 广播数据
+ */
+ protected void broadcast() {
+ boolean emptyUser = CollKit.isEmpty(this.userIds);
+ if (checkEmptyUser && emptyUser) {
+ throw new RuntimeException("没有添加消息推送人 " + this.getClass());
+ }
+
+ // 推送响应(广播消息)给指定的用户列表
+ if (!emptyUser) {
+ this.aggregationContext.broadcast(this.responseMessage, this.userIds);
+ }
+ }
+
public RangeBroadcast setResponseMessage(ResponseMessage responseMessage) {
this.responseMessage = responseMessage;
return this;
@@ -218,4 +243,13 @@ public RangeBroadcast removeUserId(long excludeUserId) {
protected void disableSend() {
this.doSend = false;
}
+
+ public RangeBroadcast disableEmptyUserCheck() {
+ this.checkEmptyUser = false;
+ return this;
+ }
+
+ protected CommunicationAggregationContext getAggregationContext() {
+ return this.aggregationContext;
+ }
}
diff --git a/common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/wrapper/WrapperKit.java b/common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/wrapper/WrapperKit.java
index 3ac94a7c0..efc20d2be 100644
--- a/common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/wrapper/WrapperKit.java
+++ b/common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/wrapper/WrapperKit.java
@@ -20,9 +20,11 @@
import com.iohao.game.action.skeleton.core.DataCodecKit;
import com.iohao.game.common.kit.CollKit;
+import com.sun.jdi.BooleanValue;
import lombok.experimental.UtilityClass;
import java.util.List;
+import java.util.Set;
/**
* 装箱、拆箱包装工具
@@ -73,4 +75,33 @@ public ByteValueList ofListByteValue(List values) {
return ByteValueList.of(values.stream().map(DataCodecKit::encode).toList());
}
+
+ /** 框架支持的协议碎片类型 */
+ final Set> wrapperTypeSet = Set.of(
+ int.class,
+ Integer.class,
+ IntValue.class,
+
+ long.class,
+ Long.class,
+ LongValue.class,
+
+ boolean.class,
+ Boolean.class,
+ BoolValue.class,
+
+ String.class,
+ StringValue.class
+ );
+
+ /**
+ * 框架支持的协议碎片类型
+ *
+ * @param clazz class
+ * @return true 是框架支持的协议碎片类型
+ * @since 21.7
+ */
+ public boolean isWrapper(Class> clazz) {
+ return wrapperTypeSet.contains(clazz);
+ }
}
diff --git a/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/ActionParserListenerTest.java b/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/ActionParserListenerTest.java
new file mode 100644
index 000000000..2bf99d0bc
--- /dev/null
+++ b/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/ActionParserListenerTest.java
@@ -0,0 +1,72 @@
+package com.iohao.game.action.skeleton.core;
+
+import com.iohao.game.action.skeleton.core.action.ExampleActionCmd;
+import com.iohao.game.action.skeleton.core.action.pojo.BeeApple;
+import com.iohao.game.action.skeleton.core.action.pojo.DogValid;
+import com.iohao.game.action.skeleton.core.data.TestDataKit;
+import com.iohao.game.action.skeleton.core.flow.FlowContext;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author 渔民小镇
+ * @date 2024-05-01
+ */
+@Slf4j
+public class ActionParserListenerTest {
+ BarSkeleton barSkeleton;
+
+ @Before
+ public void setUp() throws InterruptedException {
+ BarSkeletonBuilder builder = TestDataKit.createBuilder();
+
+ barSkeleton = builder.build();
+
+ // 等待 protobuf proxy class 加载完成。 see JProtobufParserActionListener
+ TimeUnit.MILLISECONDS.sleep(1000);
+ }
+
+ @Test
+ public void onActionCommand() {
+ long l = System.currentTimeMillis();
+
+ extractedBeeHello();
+ extractedBeeHelloDog();
+
+ log.info("l : {}", System.currentTimeMillis() - l);
+ }
+
+ private void extractedBeeHello() {
+ var bizData = new BeeApple();
+ bizData.content = "a";
+
+ CmdInfo cmdInfo = CmdInfo.of(ExampleActionCmd.BeeActionCmd.cmd, ExampleActionCmd.BeeActionCmd.hello);
+ FlowContext flowContext = TestDataKit.ofFlowContext(cmdInfo, bizData);
+ flowContext.inOutStartTime();
+
+ barSkeleton.handle(flowContext);
+
+ var data = flowContext.getResponse().getData(BeeApple.class);
+
+ Assert.assertEquals(data.content, "a,I'm hello");
+ }
+
+ private void extractedBeeHelloDog() {
+ var bizData = new DogValid();
+ bizData.name = "a";
+
+ CmdInfo cmdInfo = CmdInfo.of(ExampleActionCmd.BeeActionCmd.cmd, ExampleActionCmd.BeeActionCmd.hello_dog);
+ FlowContext flowContext = TestDataKit.ofFlowContext(cmdInfo, bizData);
+ flowContext.inOutStartTime();
+
+ barSkeleton.handle(flowContext);
+
+ var data = flowContext.getResponse().getData(DogValid.class);
+
+ Assert.assertEquals(data.name, "a");
+ }
+}
\ No newline at end of file
diff --git a/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/BarSkeletonTest.java b/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/BarSkeletonTest.java
index f7609e8ca..02f1ad1c4 100644
--- a/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/BarSkeletonTest.java
+++ b/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/BarSkeletonTest.java
@@ -21,39 +21,30 @@
import com.iohao.game.action.skeleton.core.action.ExampleActionCmd;
import com.iohao.game.action.skeleton.core.action.pojo.BeeApple;
import com.iohao.game.action.skeleton.core.data.TestDataKit;
-import com.iohao.game.action.skeleton.core.flow.FlowContext;
-import com.iohao.game.action.skeleton.protocol.HeadMetadata;
-import com.iohao.game.action.skeleton.protocol.RequestMessage;
+import org.junit.Before;
import org.junit.Test;
public class BarSkeletonTest {
+ BarSkeleton barSkeleton;
+
+ @Before
+ public void setUp() {
+ // 构建业务框架
+ barSkeleton = TestDataKit.newBarSkeleton();
+ }
@Test
public void newBuilder() {
- // 构建业务框架
- BarSkeleton barSkeleton = TestDataKit.newBarSkeleton();
// 模拟路由信息
CmdInfo cmdInfo = CmdInfo.of(ExampleActionCmd.BeeActionCmd.cmd, ExampleActionCmd.BeeActionCmd.hello);
- // 模拟请求
- HeadMetadata headMetadata = new HeadMetadata();
- headMetadata.setCmdInfo(cmdInfo);
-
- RequestMessage requestMessage = new RequestMessage();
- requestMessage.setHeadMetadata(headMetadata);
-
// 模拟请求数据 (一般由前端传入)
BeeApple beeApple = new BeeApple();
beeApple.setContent("hello 塔姆!");
beeApple.setId(101);
- // 把模拟请求的数据,放入请求对象中
-
- byte[] data = DataCodecKit.encode(beeApple);
- requestMessage.setData(data);
- var flowContext = new FlowContext()
- .setRequest(requestMessage);
+ var flowContext = TestDataKit.ofFlowContext(cmdInfo, beeApple);
// 业务框架处理用户请求
barSkeleton.handle(flowContext);
@@ -66,29 +57,16 @@ public void newBuilder() {
@Test
public void testVoid() {
- // 构建业务框架
- BarSkeleton barSkeleton = TestDataKit.newBarSkeleton();
// 模拟路由信息
CmdInfo cmdInfo = CmdInfo.of(ExampleActionCmd.BeeActionCmd.cmd, ExampleActionCmd.BeeActionCmd.test_void);
- // 模拟请求
- HeadMetadata headMetadata = new HeadMetadata();
- headMetadata.setCmdInfo(cmdInfo);
-
- RequestMessage requestMessage = new RequestMessage();
- requestMessage.setHeadMetadata(headMetadata);
-
// 模拟请求数据 (一般由前端传入)
BeeApple beeApple = new BeeApple();
beeApple.setContent("hello 塔姆!");
beeApple.setId(1010);
- // 把模拟请求的数据,放入请求对象中
- byte[] data = DataCodecKit.encode(beeApple);
- requestMessage.setData(data);
- var flowContext = new FlowContext()
- .setRequest(requestMessage);
+ var flowContext = TestDataKit.ofFlowContext(cmdInfo, beeApple);
// 业务框架处理用户请求
barSkeleton.handle(flowContext);
diff --git a/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/JSR380Test.java b/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/JSR380Test.java
index 6e7e7d6bb..0a1d9fcb2 100644
--- a/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/JSR380Test.java
+++ b/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/JSR380Test.java
@@ -1,5 +1,5 @@
/*
- * ioGame
+ * ioGame
* Copyright (C) 2021 - present 渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.
* # iohao.com . 渔民小镇
*
@@ -22,7 +22,8 @@
import com.iohao.game.action.skeleton.core.action.pojo.DogValid;
import com.iohao.game.action.skeleton.core.data.TestDataKit;
import com.iohao.game.action.skeleton.core.flow.FlowContext;
-import com.iohao.game.action.skeleton.protocol.RequestMessage;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -30,6 +31,7 @@
* @author 渔民小镇
* @date 2022-07-09
*/
+@Slf4j
public class JSR380Test {
BarSkeleton barSkeleton;
@@ -48,39 +50,10 @@ public void jsr380() {
CmdInfo cmdInfo = CmdInfo.of(ExampleActionCmd.BeeActionCmd.cmd, ExampleActionCmd.BeeActionCmd.jsr380);
- RequestMessage requestMessage = TestDataKit.createRequestMessage(cmdInfo);
- requestMessage.setData(dogValid);
-
- FlowContext flowContext = new FlowContext();
- flowContext.setRequest(requestMessage);
+ FlowContext flowContext = TestDataKit.ofFlowContext(cmdInfo, dogValid);
barSkeleton.handle(flowContext);
- }
-
-// @Test
-// public void name() {
-// DogValid dogValid = new DogValid();
-// dogValid.name = "abc";
-// Validator validator = ValidatorKit.getValidator();
-//
-//
-// BeanDescriptor constraintsForClass = validator.getConstraintsForClass(DogValid.class);
-// Set constrainedProperties = constraintsForClass.getConstrainedProperties();
-// log.info("c : {}", constraintsForClass);
-//
-// Set> validate = validator.validate(dogValid);
-//
-//
-// log.info("{}", validate.size());
-//
-// for (ConstraintViolation violation : validate) {
-// log.info("{}", validate);
-// String message = violation.getMessage();
-// Path propertyPath = violation.getPropertyPath();
-//
-// log.info("message {}, path: {}", message, propertyPath.toString());
-// }
-//
-// }
+ Assert.assertTrue(flowContext.getResponse().hasError());
+ }
}
diff --git a/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/JSR380ValidatedGroupTest.java b/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/JSR380ValidatedGroupTest.java
index b21f5c203..aeaf13adf 100644
--- a/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/JSR380ValidatedGroupTest.java
+++ b/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/JSR380ValidatedGroupTest.java
@@ -22,7 +22,7 @@
import com.iohao.game.action.skeleton.core.action.pojo.BirdValid;
import com.iohao.game.action.skeleton.core.data.TestDataKit;
import com.iohao.game.action.skeleton.core.flow.FlowContext;
-import com.iohao.game.action.skeleton.protocol.RequestMessage;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -44,31 +44,24 @@ public void setUp() {
@Test
public void updateGroupTest() {
BirdValid birdValid = new BirdValid();
-
CmdInfo cmdInfo = CmdInfo.of(ExampleActionCmd.BeeActionCmd.cmd, ExampleActionCmd.BeeActionCmd.validated_group_update);
- RequestMessage requestMessage = TestDataKit.createRequestMessage(cmdInfo);
- requestMessage.setData(birdValid);
-
- FlowContext flowContext = new FlowContext();
- flowContext.setRequest(requestMessage);
+ FlowContext flowContext = TestDataKit.ofFlowContext(cmdInfo, birdValid);
barSkeleton.handle(flowContext);
+
+ Assert.assertTrue(flowContext.getResponse().hasError());
}
@Test
public void createGroupTest() {
BirdValid birdValid = new BirdValid();
-
CmdInfo cmdInfo = CmdInfo.of(ExampleActionCmd.BeeActionCmd.cmd, ExampleActionCmd.BeeActionCmd.validated_group_create);
- RequestMessage requestMessage = TestDataKit.createRequestMessage(cmdInfo);
- requestMessage.setData(birdValid);
-
- FlowContext flowContext = new FlowContext();
- flowContext.setRequest(requestMessage);
+ FlowContext flowContext = TestDataKit.ofFlowContext(cmdInfo, birdValid);
barSkeleton.handle(flowContext);
- }
+ Assert.assertTrue(flowContext.getResponse().hasError());
+ }
}
diff --git a/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/SimpleWrapperActionTest.java b/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/SimpleWrapperActionTest.java
new file mode 100644
index 000000000..099a0f3ac
--- /dev/null
+++ b/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/SimpleWrapperActionTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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 .
+ */
+package com.iohao.game.action.skeleton.core;
+
+import com.iohao.game.action.skeleton.core.action.SimpleWrapperAction;
+import com.iohao.game.action.skeleton.core.data.TestDataKit;
+import com.iohao.game.action.skeleton.core.flow.FlowContext;
+import com.iohao.game.action.skeleton.protocol.wrapper.IntValue;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Before;
+import org.junit.Test;
+
+import static com.iohao.game.action.skeleton.core.action.ExampleActionCmd.SimpleWrapperActionActionCmd.*;
+
+/**
+ * @author 渔民小镇
+ * @date 2024-05-02
+ */
+@Slf4j
+public class SimpleWrapperActionTest {
+
+ BarSkeleton barSkeleton;
+
+ @Before
+ public void setUp() {
+ barSkeleton = TestDataKit.createBuilder(SimpleWrapperAction.class::equals).build();
+ }
+
+ @Test
+ public void testInt() {
+ CmdInfo cmdInfo = CmdInfo.of(cmd, testInt);
+
+ FlowContext flowContext = TestDataKit.ofFlowContext(cmdInfo, IntValue.of(100));
+
+ barSkeleton.handle(flowContext);
+ }
+}
diff --git a/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/WrapperIntTest.java b/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/WrapperIntTest.java
index 776b33297..022bfd4e2 100644
--- a/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/WrapperIntTest.java
+++ b/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/WrapperIntTest.java
@@ -1,5 +1,5 @@
/*
- * ioGame
+ * ioGame
* Copyright (C) 2021 - present 渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.
* # iohao.com . 渔民小镇
*
@@ -27,6 +27,8 @@
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.FieldDefaults;
+import org.junit.Before;
+import org.junit.Test;
import java.util.ArrayList;
@@ -51,24 +53,21 @@ private FlowContext createIntValueFlowContext(int subCmd) {
IntValue intValue = new IntValue();
intValue.value = 100;
- RequestMessage requestMessage = TestDataKit.createRequestMessage(cmdInfo);
- requestMessage.setData(intValue);
-
- return new FlowContext()
- .setRequest(requestMessage);
+ return TestDataKit.ofFlowContext(cmdInfo, intValue);
}
BarSkeleton barSkeleton;
- // @Before
+ @Before
public void setUp() {
barSkeleton = TestDataKit.newBarSkeleton();
}
- // @Test
+ @Test
public void intValue1() {
FlowContext flowContext;
+
flowContext = this.createIntValueFlowContext(WrapperIntActionCmd.intValue2Void);
// 业务框架处理用户请求
barSkeleton.handle(flowContext);
@@ -119,7 +118,7 @@ public void intValue2() {
barSkeleton.handle(flowContext);
}
- // @Test
+ @Test
public void integerValue() {
FlowContext flowContext;
flowContext = this.createIntValueFlowContext(WrapperIntActionCmd.integer2Void);
diff --git a/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/WrapperLongTest.java b/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/WrapperLongTest.java
index 53e1834b7..374c38f19 100644
--- a/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/WrapperLongTest.java
+++ b/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/WrapperLongTest.java
@@ -20,12 +20,13 @@
import com.iohao.game.action.skeleton.core.data.TestDataKit;
import com.iohao.game.action.skeleton.core.flow.FlowContext;
-import com.iohao.game.action.skeleton.protocol.RequestMessage;
import com.iohao.game.action.skeleton.protocol.wrapper.LongValue;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.FieldDefaults;
+import org.junit.Before;
+import org.junit.Test;
import static com.iohao.game.action.skeleton.core.action.ExampleActionCmd.WrapperLongActionCmd;
@@ -48,21 +49,17 @@ private FlowContext createLongValueFlowContext(int subCmd) {
LongValue longValue = new LongValue();
longValue.value = 100;
- RequestMessage requestMessage = TestDataKit.createRequestMessage(cmdInfo);
- requestMessage.setData(longValue);
-
- return new FlowContext()
- .setRequest(requestMessage);
+ return TestDataKit.ofFlowContext(cmdInfo, longValue);
}
BarSkeleton barSkeleton;
- // @Before
+ @Before
public void setUp() {
barSkeleton = TestDataKit.newBarSkeleton();
}
- // @Test
+ @Test
public void longValue1() {
FlowContext flowContext = null;
flowContext = this.createLongValueFlowContext(WrapperLongActionCmd.longValue2Void);
@@ -82,7 +79,7 @@ public void longValue1() {
barSkeleton.handle(flowContext);
}
- // @Test
+ @Test
public void longValue2() {
FlowContext flowContext = null;
flowContext = this.createLongValueFlowContext(WrapperLongActionCmd.long2Void);
@@ -102,9 +99,9 @@ public void longValue2() {
barSkeleton.handle(flowContext);
}
- // @Test
+ @Test
public void longerValue3() {
- FlowContext flowContext = null;
+ FlowContext flowContext;
flowContext = this.createLongValueFlowContext(WrapperLongActionCmd.longer2Void);
// 业务框架处理用户请求
barSkeleton.handle(flowContext);
diff --git a/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/action/BeeAction.java b/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/action/BeeAction.java
index e9bda5d1a..6f2b8ee61 100644
--- a/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/action/BeeAction.java
+++ b/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/action/BeeAction.java
@@ -62,6 +62,12 @@ public void thatVoid(BeeApple beeApple) {
that.setContent(beeApple.content + ",I'm thatVoid");
}
+ @ActionMethod(ExampleActionCmd.BeeActionCmd.hello_dog)
+ public DogValid helloDog(DogValid dogValid) {
+ log.info("dogValid : {}", dogValid);
+ return dogValid;
+ }
+
@ActionMethod(ExampleActionCmd.BeeActionCmd.jsr380)
public void jsr380(DogValid dogValid) {
log.info("{}", dogValid);
diff --git a/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/action/ExampleActionCmd.java b/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/action/ExampleActionCmd.java
index c4f8fa127..f6338eebd 100644
--- a/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/action/ExampleActionCmd.java
+++ b/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/action/ExampleActionCmd.java
@@ -35,6 +35,7 @@ interface BeeActionCmd {
int jsr380 = 4;
int validated_group_update = 5;
int validated_group_create = 6;
+ int hello_dog = 7;
}
@@ -84,4 +85,9 @@ interface WrapperLongActionCmd {
int longer2LongValue = 10;
int longer2LongList = 11;
}
+
+ interface SimpleWrapperActionActionCmd {
+ int cmd = 13;
+ int testInt = 0;
+ }
}
diff --git a/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/action/SimpleWrapperAction.java b/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/action/SimpleWrapperAction.java
new file mode 100644
index 000000000..89a6008c9
--- /dev/null
+++ b/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/action/SimpleWrapperAction.java
@@ -0,0 +1,36 @@
+/*
+ * 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 .
+ */
+package com.iohao.game.action.skeleton.core.action;
+
+import com.iohao.game.action.skeleton.annotation.ActionController;
+import com.iohao.game.action.skeleton.annotation.ActionMethod;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author 渔民小镇
+ * @date 2024-05-02
+ */
+@Slf4j
+@ActionController(ExampleActionCmd.SimpleWrapperActionActionCmd.cmd)
+public class SimpleWrapperAction {
+ @ActionMethod(ExampleActionCmd.SimpleWrapperActionActionCmd.testInt)
+ public void testInt(int age) {
+ System.out.println(age);
+ }
+}
\ No newline at end of file
diff --git a/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/data/TestDataKit.java b/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/data/TestDataKit.java
index 8daaf2ea1..f054b66dd 100644
--- a/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/data/TestDataKit.java
+++ b/common/common-core/src/test/java/com/iohao/game/action/skeleton/core/data/TestDataKit.java
@@ -19,63 +19,79 @@
package com.iohao.game.action.skeleton.core.data;
import com.iohao.game.action.skeleton.annotation.ActionController;
-import com.iohao.game.action.skeleton.core.BarSkeleton;
-import com.iohao.game.action.skeleton.core.BarSkeletonBuilder;
-import com.iohao.game.action.skeleton.core.CmdInfo;
+import com.iohao.game.action.skeleton.core.*;
import com.iohao.game.action.skeleton.core.action.BeeAction;
+import com.iohao.game.action.skeleton.core.flow.FlowContext;
import com.iohao.game.action.skeleton.core.flow.internal.DebugInOut;
-import com.iohao.game.action.skeleton.protocol.HeadMetadata;
import com.iohao.game.action.skeleton.protocol.RequestMessage;
import com.iohao.game.common.kit.ClassScanner;
import lombok.experimental.UtilityClass;
import java.util.List;
+import java.util.Objects;
import java.util.function.Predicate;
@UtilityClass
public class TestDataKit {
public BarSkeleton newBarSkeleton() {
- BarSkeletonBuilder builder = createBuilder();
- builder.setActionAfter(flowContext -> {
-
- });
- return builder.build();
+ return createBuilder().build();
}
- public BarSkeletonBuilder createBuilder() {
+ public BarSkeletonBuilder createBuilder(Predicate> appendPredicateFilter) {
// 尽量做到所有操作是可插拔的. 详细配置 see BarSkeletonBuilder.build
BarSkeletonBuilder builder = BarSkeleton.newBuilder();
builder.addInOut(new DebugInOut());
- // 添加(请求响应)处理类. 用户可以定义自己的业务控制器 - 这里推荐实现扫描包的形式添加 tcp 处理类
-// builder
-// .addActionController(BeeAction.class)
-// .addActionController(BirdAction.class)
-// ;
+ builder.setActionAfter(flowContext -> System.out.println());
- Predicate> predicateFilter = (clazz) -> clazz.getAnnotation(ActionController.class) != null;
-
- String packagePath = BeeAction.class.getPackageName();
-
- ClassScanner classScanner = new ClassScanner(packagePath, predicateFilter);
- List> classList = classScanner.listScan();
+ List> classList = getClasses(appendPredicateFilter);
classList.forEach(builder::addActionController);
+ BarSkeletonSetting setting = builder.getSetting();
+ setting.setPrintHandler(false);
+ setting.setPrintInout(false);
+ setting.setPrintDataCodec(false);
+ setting.setPrintRunners(false);
+ setting.setPrintHandler(false);
return builder;
}
- public RequestMessage createRequestMessage(CmdInfo cmdInfo) {
- // 模拟请求
- HeadMetadata headMetadata = new HeadMetadata();
- headMetadata.setCmdInfo(cmdInfo);
+ private List> getClasses(Predicate> appendPredicateFilter) {
+ Predicate> predicateFilter = (clazz) -> {
+ if (clazz.getAnnotation(ActionController.class) == null) {
+ return false;
+ }
+
+ if (Objects.nonNull(appendPredicateFilter)) {
+ if (appendPredicateFilter.test(clazz)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ return true;
+ };
+
+ String packagePath = BeeAction.class.getPackageName();
+ ClassScanner classScanner = new ClassScanner(packagePath, predicateFilter);
+ return classScanner.listScan();
+ }
+
+ public BarSkeletonBuilder createBuilder() {
+ return createBuilder(null);
+ }
+
+ public FlowContext ofFlowContext(CmdInfo cmdInfo, Object data) {
+ RequestMessage requestMessage = BarMessageKit.createRequestMessage(cmdInfo, data);
- RequestMessage requestMessage = new RequestMessage();
- requestMessage.setHeadMetadata(headMetadata);
+ FlowContext flowContext = new FlowContext();
+ flowContext.setRequest(requestMessage);
- return requestMessage;
+ return flowContext;
}
}
diff --git a/common/common-core/src/test/java/com/iohao/game/action/skeleton/protocol/wrapper/WrapperKitTest.java b/common/common-core/src/test/java/com/iohao/game/action/skeleton/protocol/wrapper/WrapperKitTest.java
index 6e44bbb08..13581dd57 100644
--- a/common/common-core/src/test/java/com/iohao/game/action/skeleton/protocol/wrapper/WrapperKitTest.java
+++ b/common/common-core/src/test/java/com/iohao/game/action/skeleton/protocol/wrapper/WrapperKitTest.java
@@ -1,6 +1,7 @@
package com.iohao.game.action.skeleton.protocol.wrapper;
import lombok.extern.slf4j.Slf4j;
+import org.junit.Assert;
import org.junit.Test;
/**
@@ -19,4 +20,22 @@ public void of() {
Object of1 = WrapperKit.of(intV);
log.info("of1 : {}", of1);
}
+
+ @Test
+ public void isWrapper() {
+ Assert.assertTrue(WrapperKit.isWrapper(int.class));
+ Assert.assertTrue(WrapperKit.isWrapper(Integer.class));
+ Assert.assertTrue(WrapperKit.isWrapper(IntValue.class));
+
+ Assert.assertTrue(WrapperKit.isWrapper(long.class));
+ Assert.assertTrue(WrapperKit.isWrapper(Long.class));
+ Assert.assertTrue(WrapperKit.isWrapper(LongValue.class));
+
+ Assert.assertTrue(WrapperKit.isWrapper(boolean.class));
+ Assert.assertTrue(WrapperKit.isWrapper(Boolean.class));
+ Assert.assertTrue(WrapperKit.isWrapper(BoolValue.class));
+
+ Assert.assertTrue(WrapperKit.isWrapper(String.class));
+ Assert.assertTrue(WrapperKit.isWrapper(StringValue.class));
+ }
}
\ No newline at end of file
diff --git a/common/common-core/src/test/resources/logback.xml b/common/common-core/src/test/resources/logback.xml
new file mode 100644
index 000000000..002a55233
--- /dev/null
+++ b/common/common-core/src/test/resources/logback.xml
@@ -0,0 +1,114 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${log.pattern}
+ utf8
+
+
+
+
+
+ ${log.base}/${log.moduleName}.log
+
+
+ ${log.base}/archive/${log.moduleName}_all_%d{yyyy-MM-dd}.%i.log.zip
+
+
+ ${log.max.size}
+
+
+
+
+ %date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{80}.%method:%L -%msg%n
+
+
+
+
+
+ ${log.base}/${log.moduleName}_other.log
+
+ ${log.base}/archive/${log.moduleName}_other_%d{yyyy-MM-dd}.%i.log.zip
+
+
+ ${log.max.size}
+
+
+
+ %date{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{56}.%method:%L -%msg%n
+
+
+
+
+
+ ${log.base}/${log.moduleName}_err.log
+
+ ${log.base}/archive/${log.moduleName}_err_%d{yyyy-MM-dd}.%i.log.zip
+
+
+ ${log.max.size}
+
+
+
+ %date{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{56}.%method:%L - %msg%n
+
+
+
+ ERROR
+ ACCEPT
+ DENY
+
+
+
+
+
+
+
+ 0
+ 256
+ true
+
+
+
+
+
+ 0
+ 256
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/common/common-kit/pom.xml b/common/common-kit/pom.xml
index 6e5fd8635..2124a9e75 100644
--- a/common/common-kit/pom.xml
+++ b/common/common-kit/pom.xml
@@ -5,7 +5,7 @@
ioGame
com.iohao.game
- 21.6
+ 21.7
../../pom.xml
4.0.0
diff --git a/common/common-kit/src/main/java/com/iohao/game/common/kit/ProtoKit.java b/common/common-kit/src/main/java/com/iohao/game/common/kit/ProtoKit.java
index ea790c8ec..5a203d367 100644
--- a/common/common-kit/src/main/java/com/iohao/game/common/kit/ProtoKit.java
+++ b/common/common-kit/src/main/java/com/iohao/game/common/kit/ProtoKit.java
@@ -22,6 +22,7 @@
import com.baidu.bjf.remoting.protobuf.ProtobufProxy;
import com.iohao.game.common.consts.CommonConst;
import com.iohao.game.common.consts.IoGameLogName;
+import com.iohao.game.common.kit.concurrent.TaskKit;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
@@ -83,4 +84,11 @@ public T parseProtoByte(byte[] data, Class clazz) {
return null;
}
+
+ public void create(Class> clazz) {
+ TaskKit.executeVirtual(() -> {
+ // create a protobuf proxy class
+ ProtobufProxy.create(clazz);
+ });
+ }
}
diff --git a/common/common-micro-kit/pom.xml b/common/common-micro-kit/pom.xml
index 6aa6098e6..e322bfcc1 100644
--- a/common/common-micro-kit/pom.xml
+++ b/common/common-micro-kit/pom.xml
@@ -6,7 +6,7 @@
com.iohao.game
ioGame
- 21.6
+ 21.7
../../pom.xml
diff --git a/common/common-micro-kit/src/main/java/com/iohao/game/common/kit/RuntimeKit.java b/common/common-micro-kit/src/main/java/com/iohao/game/common/kit/RuntimeKit.java
new file mode 100644
index 000000000..e03e66688
--- /dev/null
+++ b/common/common-micro-kit/src/main/java/com/iohao/game/common/kit/RuntimeKit.java
@@ -0,0 +1,37 @@
+/*
+ * 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 .
+ */
+package com.iohao.game.common.kit;
+
+import lombok.experimental.UtilityClass;
+
+/**
+ * Runtime 相关工具
+ *
+ * @author 渔民小镇
+ * @date 2024-05-01
+ * @since 21.7
+ */
+@UtilityClass
+public class RuntimeKit {
+ /**
+ * 默认使用 Runtime.getRuntime().availableProcessors()。
+ * 如果有一些特殊环境需要模拟的,可以设置该变量。
+ */
+ public int availableProcessors = Runtime.getRuntime().availableProcessors();
+}
diff --git a/common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/executor/UserThreadExecutorRegion.java b/common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/executor/UserThreadExecutorRegion.java
index da619e4a9..5a2b835f3 100644
--- a/common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/executor/UserThreadExecutorRegion.java
+++ b/common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/executor/UserThreadExecutorRegion.java
@@ -18,6 +18,8 @@
*/
package com.iohao.game.common.kit.concurrent.executor;
+import com.iohao.game.common.kit.RuntimeKit;
+
/**
* 用户线程执行器管理域
*
@@ -58,7 +60,7 @@ public ThreadExecutor getThreadExecutor(long userId) {
}
static int availableProcessors2n() {
- int n = Runtime.getRuntime().availableProcessors();
+ int n = RuntimeKit.availableProcessors;
n |= (n >> 1);
n |= (n >> 2);
n |= (n >> 4);
diff --git a/common/common-validation/pom.xml b/common/common-validation/pom.xml
index adc3c337d..838191255 100644
--- a/common/common-validation/pom.xml
+++ b/common/common-validation/pom.xml
@@ -5,7 +5,7 @@
ioGame
com.iohao.game
- 21.6
+ 21.7
../../pom.xml
4.0.0
diff --git a/external/external-core/pom.xml b/external/external-core/pom.xml
index 0e21f3998..5533b5448 100644
--- a/external/external-core/pom.xml
+++ b/external/external-core/pom.xml
@@ -6,7 +6,7 @@
com.iohao.game
ioGame
- 21.6
+ 21.7
../../pom.xml
diff --git a/external/external-core/src/main/java/com/iohao/game/external/core/config/ExternalGlobalConfig.java b/external/external-core/src/main/java/com/iohao/game/external/core/config/ExternalGlobalConfig.java
index 8ec4999a8..1255b8034 100644
--- a/external/external-core/src/main/java/com/iohao/game/external/core/config/ExternalGlobalConfig.java
+++ b/external/external-core/src/main/java/com/iohao/game/external/core/config/ExternalGlobalConfig.java
@@ -42,7 +42,8 @@ public class ExternalGlobalConfig {
public AccessAuthenticationHook accessAuthenticationHook = new DefaultAccessAuthenticationHook();
/** 游戏对外服路由缓存 */
public ExternalCmdCache externalCmdCache;
-
+ /** true 表示开启简单日志打印 netty handler. see SimpleLoggerHandler */
+ public boolean enableLoggerHandler = true;
/**
* 协议开关,用于一些协议级别的开关控制,比如 安全加密校验等。 : 0 不校验
*
diff --git a/external/external-netty/pom.xml b/external/external-netty/pom.xml
index 58f5a07e9..2eb6543d6 100644
--- a/external/external-netty/pom.xml
+++ b/external/external-netty/pom.xml
@@ -6,7 +6,7 @@
com.iohao.game
ioGame
- 21.6
+ 21.7
../../pom.xml
diff --git a/external/external-netty/src/main/java/com/iohao/game/external/core/netty/DefaultExternalCore.java b/external/external-netty/src/main/java/com/iohao/game/external/core/netty/DefaultExternalCore.java
index 6242f8e32..131447814 100644
--- a/external/external-netty/src/main/java/com/iohao/game/external/core/netty/DefaultExternalCore.java
+++ b/external/external-netty/src/main/java/com/iohao/game/external/core/netty/DefaultExternalCore.java
@@ -18,13 +18,17 @@
*/
package com.iohao.game.external.core.netty;
+import com.iohao.game.action.skeleton.core.DataCodecKit;
+import com.iohao.game.action.skeleton.core.codec.ProtoDataCodec;
import com.iohao.game.bolt.broker.core.common.IoGameGlobalConfig;
import com.iohao.game.common.consts.IoGameLogName;
import com.iohao.game.common.kit.PresentKit;
+import com.iohao.game.common.kit.ProtoKit;
import com.iohao.game.external.core.ExternalCore;
import com.iohao.game.external.core.config.ExternalJoinEnum;
import com.iohao.game.external.core.hook.UserHook;
import com.iohao.game.external.core.hook.internal.DefaultUserHook;
+import com.iohao.game.external.core.message.ExternalMessage;
import com.iohao.game.external.core.micro.MicroBootstrap;
import com.iohao.game.external.core.micro.join.ExternalJoinSelector;
import com.iohao.game.external.core.micro.join.ExternalJoinSelectors;
@@ -102,6 +106,11 @@ private void defaultSetting() {
// 当前游戏对外服所使用的连接方式
userSessions.option(UserSessionOption.externalJoin, joinEnum);
+
+ // ================== 其他 ==================
+ if (DataCodecKit.getDataCodec() instanceof ProtoDataCodec) {
+ ProtoKit.create(ExternalMessage.class);
+ }
}
private void aware() {
diff --git a/external/external-netty/src/main/java/com/iohao/game/external/core/netty/handler/SimpleLoggerHandler.java b/external/external-netty/src/main/java/com/iohao/game/external/core/netty/handler/SimpleLoggerHandler.java
new file mode 100644
index 000000000..ea95c485a
--- /dev/null
+++ b/external/external-netty/src/main/java/com/iohao/game/external/core/netty/handler/SimpleLoggerHandler.java
@@ -0,0 +1,60 @@
+/*
+ * 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 .
+ */
+package com.iohao.game.external.core.netty.handler;
+
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 简单日志打印,通常是不活跃的连接、触发异常的连接
+ *
+ * @author 渔民小镇
+ * @date 2024-05-01
+ * @since 21.7
+ */
+@Slf4j
+@ChannelHandler.Sharable
+public final class SimpleLoggerHandler extends ChannelInboundHandlerAdapter {
+
+ @Override
+ public void channelInactive(ChannelHandlerContext ctx) throws Exception {
+ log.info("channelInactive channel.remoteAddress() : {}", ctx.channel().remoteAddress());
+ super.channelInactive(ctx);
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+ log.error(cause.getMessage(), cause);
+ super.exceptionCaught(ctx, cause);
+ }
+
+ private SimpleLoggerHandler() {
+ }
+
+ public static SimpleLoggerHandler me() {
+ return Holder.ME;
+ }
+
+ /** 通过 JVM 的类加载机制, 保证只加载一次 (singleton) */
+ private static class Holder {
+ static final SimpleLoggerHandler ME = new SimpleLoggerHandler();
+ }
+}
diff --git a/external/external-netty/src/main/java/com/iohao/game/external/core/netty/handler/SocketUserSessionHandler.java b/external/external-netty/src/main/java/com/iohao/game/external/core/netty/handler/SocketUserSessionHandler.java
index 0b1ea8c81..b6cf0457d 100644
--- a/external/external-netty/src/main/java/com/iohao/game/external/core/netty/handler/SocketUserSessionHandler.java
+++ b/external/external-netty/src/main/java/com/iohao/game/external/core/netty/handler/SocketUserSessionHandler.java
@@ -51,7 +51,7 @@ public void setUserSessions(UserSessions, ?> userSessions) {
}
@Override
- public void channelActive(ChannelHandlerContext ctx) {
+ public void channelActive(ChannelHandlerContext ctx) throws Exception {
BrokerClientModuleMessage moduleMessage = brokerClient.getBrokerClientModuleMessage();
int idHash = moduleMessage.getIdHash();
@@ -59,20 +59,24 @@ public void channelActive(ChannelHandlerContext ctx) {
SocketUserSession userSession = userSessions.add(ctx);
userSession.setExternalClientId(idHash);
- ctx.fireChannelActive();
+ super.channelActive(ctx);
}
@Override
- public void channelInactive(ChannelHandlerContext ctx) {
+ public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// 从 session 管理中移除
var userSession = this.userSessions.getUserSession(ctx);
this.userSessions.removeUserSession(userSession);
+
+ super.channelInactive(ctx);
}
@Override
- public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// 从 session 管理中移除
var userSession = this.userSessions.getUserSession(ctx);
this.userSessions.removeUserSession(userSession);
+
+ super.exceptionCaught(ctx, cause);
}
}
diff --git a/external/external-netty/src/main/java/com/iohao/game/external/core/netty/micro/SocketMicroBootstrapFlow.java b/external/external-netty/src/main/java/com/iohao/game/external/core/netty/micro/SocketMicroBootstrapFlow.java
index 02ddacfdf..bdf9df70e 100644
--- a/external/external-netty/src/main/java/com/iohao/game/external/core/netty/micro/SocketMicroBootstrapFlow.java
+++ b/external/external-netty/src/main/java/com/iohao/game/external/core/netty/micro/SocketMicroBootstrapFlow.java
@@ -79,6 +79,10 @@ public void pipelineIdle(PipelineContext context) {
@Override
public void pipelineCustom(PipelineContext context) {
+ // 日志打印(异常时)
+ if (ExternalGlobalConfig.enableLoggerHandler) {
+ context.addLast("SimpleLoggerHandler", SimpleLoggerHandler.me());
+ }
// 路由存在检测
context.addLast("CmdCheckHandler", CmdCheckHandler.me());
diff --git a/net-bolt/bolt-broker-server/pom.xml b/net-bolt/bolt-broker-server/pom.xml
index e3de352e1..49b940208 100644
--- a/net-bolt/bolt-broker-server/pom.xml
+++ b/net-bolt/bolt-broker-server/pom.xml
@@ -5,7 +5,7 @@
ioGame
com.iohao.game
- 21.6
+ 21.7
../../pom.xml
4.0.0
diff --git a/net-bolt/bolt-broker-server/src/main/java/com/iohao/game/bolt/broker/server/balanced/BalancedManager.java b/net-bolt/bolt-broker-server/src/main/java/com/iohao/game/bolt/broker/server/balanced/BalancedManager.java
index fb8330c1a..56b8e93f7 100644
--- a/net-bolt/bolt-broker-server/src/main/java/com/iohao/game/bolt/broker/server/balanced/BalancedManager.java
+++ b/net-bolt/bolt-broker-server/src/main/java/com/iohao/game/bolt/broker/server/balanced/BalancedManager.java
@@ -1,5 +1,5 @@
/*
- * ioGame
+ * ioGame
* Copyright (C) 2021 - present 渔民小镇 (262610965@qq.com、luoyizhu@gmail.com) . All Rights Reserved.
* # iohao.com . 渔民小镇
*
@@ -29,10 +29,7 @@
import lombok.experimental.FieldDefaults;
import org.jctools.maps.NonBlockingHashMap;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
/**
* 负载管理器
@@ -96,6 +93,10 @@ public void register(BrokerClientModuleMessage brokerClientModuleMessage) {
public BrokerClientProxy remove(String address) {
BrokerClientProxy brokerClientProxy = this.refMap.get(address);
+ if (Objects.isNull(brokerClientProxy)) {
+ return null;
+ }
+
BrokerClientType brokerClientType = brokerClientProxy.getBrokerClientType();
var loadBalanced = this.getRegionLoadBalanced(brokerClientType);
diff --git a/net-bolt/bolt-broker-server/src/main/java/com/iohao/game/bolt/broker/server/processor/ConnectionCloseEventBrokerProcessor.java b/net-bolt/bolt-broker-server/src/main/java/com/iohao/game/bolt/broker/server/processor/ConnectionCloseEventBrokerProcessor.java
index 8cda05221..d1630f46f 100644
--- a/net-bolt/bolt-broker-server/src/main/java/com/iohao/game/bolt/broker/server/processor/ConnectionCloseEventBrokerProcessor.java
+++ b/net-bolt/bolt-broker-server/src/main/java/com/iohao/game/bolt/broker/server/processor/ConnectionCloseEventBrokerProcessor.java
@@ -54,22 +54,21 @@ public final class ConnectionCloseEventBrokerProcessor implements ConnectionEven
@Override
public void onEvent(String remoteAddress, Connection connection) {
- if (IoGameGlobalConfig.openLog) {
- log.info("Broker ConnectionEventType:【{}】 remoteAddress:【{}】,Connection:【{}】",
- ConnectionEventType.CLOSE, remoteAddress, connection
- );
- }
-
Objects.requireNonNull(connection);
BalancedManager balancedManager = this.brokerServer.getBalancedManager();
// 当前下线的逻辑服
BrokerClientProxy brokerClientProxy = balancedManager.remove(remoteAddress);
- extractedPrint(remoteAddress, brokerClientProxy);
- BrokerPrintKit.print(this.brokerServer);
-
Optional.ofNullable(brokerClientProxy).ifPresent(proxy -> {
+ if (IoGameGlobalConfig.openLog) {
+ log.info("Broker ConnectionEventType:【{}】,remoteAddress:【{}】,brokerClientProxy:【{}】,Connection:【{}】",
+ ConnectionEventType.CLOSE, remoteAddress, brokerClientProxy, connection
+ );
+
+ BrokerPrintKit.print(this.brokerServer);
+ }
+
String id = proxy.getId();
BrokerClientModuleMessage moduleMessage = this.brokerClientModules.removeById(id);
@@ -83,12 +82,4 @@ public void onEvent(String remoteAddress, Connection connection) {
LineKit.offline(context);
});
}
-
- private void extractedPrint(String remoteAddress, BrokerClientProxy brokerClientProxy) {
- if (IoGameGlobalConfig.openLog) {
- log.info("Broker ConnectionEventType:【{}】 remoteAddress:【{}】,brokerClientProxy:【{}】",
- ConnectionEventType.CLOSE, remoteAddress, brokerClientProxy
- );
- }
- }
}
diff --git a/net-bolt/bolt-client/pom.xml b/net-bolt/bolt-client/pom.xml
index 709775aa5..9238ea664 100644
--- a/net-bolt/bolt-client/pom.xml
+++ b/net-bolt/bolt-client/pom.xml
@@ -5,7 +5,7 @@
ioGame
com.iohao.game
- 21.6
+ 21.7
../../pom.xml
4.0.0
diff --git a/net-bolt/bolt-core/pom.xml b/net-bolt/bolt-core/pom.xml
index 4054197df..f2dc2e337 100644
--- a/net-bolt/bolt-core/pom.xml
+++ b/net-bolt/bolt-core/pom.xml
@@ -5,7 +5,7 @@
ioGame
com.iohao.game
- 21.6
+ 21.7
../../pom.xml
4.0.0
diff --git a/net-bolt/bolt-core/src/main/java/com/iohao/game/bolt/broker/core/common/DefaultUserProcessorExecutorStrategy.java b/net-bolt/bolt-core/src/main/java/com/iohao/game/bolt/broker/core/common/DefaultUserProcessorExecutorStrategy.java
index 6f8c2d8e7..325001014 100644
--- a/net-bolt/bolt-core/src/main/java/com/iohao/game/bolt/broker/core/common/DefaultUserProcessorExecutorStrategy.java
+++ b/net-bolt/bolt-core/src/main/java/com/iohao/game/bolt/broker/core/common/DefaultUserProcessorExecutorStrategy.java
@@ -20,6 +20,7 @@
import com.iohao.game.bolt.broker.core.aware.UserProcessorExecutorAware;
import com.iohao.game.common.kit.MoreKit;
+import com.iohao.game.common.kit.RuntimeKit;
import com.iohao.game.common.kit.concurrent.DaemonThreadFactory;
import lombok.extern.slf4j.Slf4j;
import org.jctools.maps.NonBlockingHashMap;
@@ -70,7 +71,7 @@ Executor ofExecutor(String name) {
Executor executor = this.executorMap.get(name);
if (Objects.isNull(executor)) {
- int corePoolSize = Runtime.getRuntime().availableProcessors();
+ int corePoolSize = RuntimeKit.availableProcessors;
var tempExecutor = createExecutor(name, corePoolSize, corePoolSize);
executor = MoreKit.firstNonNull(this.executorMap.putIfAbsent(name, tempExecutor), tempExecutor);
diff --git a/pom.xml b/pom.xml
index 189b3a1b9..ddec8de1f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.iohao.game
ioGame
- 21.6
+ 21.7
ioGame
生产资料公有制。
diff --git a/run-one/run-one-netty/pom.xml b/run-one/run-one-netty/pom.xml
index 7ce67d9a5..b614222ca 100644
--- a/run-one/run-one-netty/pom.xml
+++ b/run-one/run-one-netty/pom.xml
@@ -6,7 +6,7 @@
com.iohao.game
ioGame
- 21.6
+ 21.7
../../pom.xml
diff --git a/widget/light-client/pom.xml b/widget/light-client/pom.xml
index 6ce95fea5..a319ce5f3 100644
--- a/widget/light-client/pom.xml
+++ b/widget/light-client/pom.xml
@@ -6,7 +6,7 @@
com.iohao.game
ioGame
- 21.6
+ 21.7
../../pom.xml
diff --git a/widget/light-domain-event/pom.xml b/widget/light-domain-event/pom.xml
index 5e1293aab..f827430bf 100644
--- a/widget/light-domain-event/pom.xml
+++ b/widget/light-domain-event/pom.xml
@@ -5,7 +5,7 @@
ioGame
com.iohao.game
- 21.6
+ 21.7
../../pom.xml
4.0.0
diff --git a/widget/light-game-room/pom.xml b/widget/light-game-room/pom.xml
index 77ee41fa6..a57f36ddc 100644
--- a/widget/light-game-room/pom.xml
+++ b/widget/light-game-room/pom.xml
@@ -5,7 +5,7 @@
ioGame
com.iohao.game
- 21.6
+ 21.7
../../pom.xml
4.0.0
@@ -19,14 +19,6 @@
${project.parent.version}
provided
-
-
- com.iohao.game
- light-domain-event
- ${project.parent.version}
- provided
-
-
diff --git a/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/AbstractFlowContextSend.java b/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/AbstractFlowContextSend.java
deleted file mode 100644
index d5e6e2e46..000000000
--- a/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/AbstractFlowContextSend.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * 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 .
- */
-package com.iohao.game.widget.light.room;
-
-import com.iohao.game.action.skeleton.core.ActionSend;
-import com.iohao.game.action.skeleton.core.commumication.CommunicationAggregationContext;
-import com.iohao.game.action.skeleton.core.flow.FlowContext;
-import com.iohao.game.action.skeleton.core.flow.attr.FlowAttr;
-import com.iohao.game.action.skeleton.protocol.HeadMetadata;
-import com.iohao.game.action.skeleton.protocol.ResponseMessage;
-import com.iohao.game.widget.light.domain.event.message.Eo;
-import com.iohao.game.widget.light.domain.event.message.Topic;
-import lombok.AccessLevel;
-import lombok.experimental.Accessors;
-import lombok.experimental.FieldDefaults;
-import lombok.extern.slf4j.Slf4j;
-import org.jctools.maps.NonBlockingHashSet;
-
-import java.util.Collection;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * 抽象响应消息 推送
- *
- * @author 渔民小镇
- * @date 2022-03-31
- */
-@Slf4j
-@Accessors(chain = true)
-@FieldDefaults(level = AccessLevel.PRIVATE)
-public abstract class AbstractFlowContextSend implements Topic, Eo, ActionSend {
-
- /** 需要推送的用户id列表 */
- final Set userIds = new NonBlockingHashSet<>();
- final CommunicationAggregationContext aggregationContext;
-
- /** 是否执行发送领域事件操作: true 执行推送操作 */
- boolean doSend = true;
-
- /** 业务框架 flow 上下文 */
- protected FlowContext flowContext;
-
- protected AbstractFlowContextSend(FlowContext flowContext) {
- this.flowContext = flowContext;
- this.aggregationContext = flowContext.option(FlowAttr.aggregationContext);
- }
-
- public AbstractFlowContextSend(CommunicationAggregationContext aggregationContext) {
- this.aggregationContext = aggregationContext;
- }
-
- /**
- * 在将数据推送到调用方之前,触发的方法
- *
- * 可以做一些逻辑,在逻辑中可以决定是否执行推送
- *
- */
- protected void logic() {
-
- }
-
- /**
- * 小把戏 (钩子方法). 子类可以做些其他的事情
- *
- * 在将数据推送到调用方之前,触发的方法
- *
- */
- protected void trick() {
- }
-
- /**
- * 响应消息到远程, 此方法是同步推送
- *
- * 如果没有特殊情况 , 使用异步推送 (当前类的) send 方法
- *
- * 模板方法模式:
- *
- * 在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。
- * 模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
- * 要点:
- * - “模板方法”定义了算法的步骤,把这些步骤的实现延迟到子类。
- * - 模板方法模式为我们提供了一种代码复用的重要技巧。
- * - 模板方法的抽象类可以定义具体方法、抽象方法和钩子。
- * - 抽象方法由子类实现。
- * - 钩子是一种方法,它在抽象类中不做事,或者只做默认的事情,子类可以选择要不要去覆盖它。
- * - 为了防止子类改变模板方法中的算法,可以将模板方法声明为final。
- * - 好莱坞原则告诉我们,将决策权放在高层模块中,以便决定如何以及何时调用低层模块。
- * - 你将在真实世界代码中看到模板方法模式的许多变体,不要期待它们全都是一眼就可以被你一眼认出的。
- * - 策略模式和模板方法模式都封装算法,一个用组合,一个用继承。
- * - 工厂方法是模板方法的一种特殊版本。
- *
- */
- public final void execute() {
- Objects.requireNonNull(this.flowContext, "flowContext must not be null");
-
- if (userIds.isEmpty()) {
- throw new RuntimeException("没有添加消息推送人 " + this.getClass());
- }
-
- // 子类构建响应内容
- this.logic();
-
- // 钩子方法
- if (!doSend) {
- return;
- }
-
- // 响应对象
- ResponseMessage responseMessage = this.flowContext.getResponse();
- HeadMetadata headMetadata = responseMessage.getHeadMetadata();
-
- // 路由设置
- int cmdMerge = this.getCmdMerge();
- headMetadata.setCmdMerge(cmdMerge);
-
- // 在将数据推送前调用的钩子方法
- this.trick();
-
- // 推送响应 (广播消息)给指定的用户列表
- flowContext.broadcast(responseMessage, this.userIds);
- }
-
- /**
- * 接收广播的用户
- *
- * @param userIds 用户id列表
- * @return me
- */
- public AbstractFlowContextSend addUserId(Collection userIds) {
- this.userIds.addAll(userIds);
- return this;
- }
-
- /**
- * 接收广播的用户
- *
- * @param userId 用户id
- * @return me
- */
- public AbstractFlowContextSend addUserId(long userId) {
- this.userIds.add(userId);
- return this;
- }
-
- /**
- * 添加用户id列表
- *
- * @param userIds 用户id列表
- * @param excludeUserId 需要排除的用户id
- * @return me
- */
- public AbstractFlowContextSend addUserId(Collection userIds, long excludeUserId) {
- return this.addUserId(userIds)
- .removeUserId(excludeUserId);
- }
-
- @Override
- public Class> getTopic() {
- return AbstractFlowContextSend.class;
- }
-
-
- @Override
- public int getCmdMerge() {
- return flowContext.getActionCommand().getCmdInfo().getCmdMerge();
- }
-
- /**
- * 不执行推送数据的操作
- */
- protected void disableSend() {
- this.doSend = false;
- }
-
- /**
- * 排除用户id
- *
- * @param userId 用户id
- * @return me
- */
- private AbstractFlowContextSend removeUserId(long userId) {
- if (userId > 0) {
- this.userIds.remove(userId);
- }
-
- return this;
- }
-}
diff --git a/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/GameFlow.java b/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/GameFlow.java
index bb1b69542..330a63802 100644
--- a/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/GameFlow.java
+++ b/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/GameFlow.java
@@ -58,14 +58,14 @@ public class GameFlow {
/**
* 游戏开始
*
- * @param abstractRoom room
+ * @param room room
* @return true 游戏开始
*/
- public boolean startGame(AbstractRoom abstractRoom) {
- boolean startBefore = this.roomGameStartCustom.startBefore(abstractRoom);
+ public boolean startGame(Room room) {
+ boolean startBefore = this.roomGameStartCustom.startBefore(room);
if (startBefore) {
- this.roomGameStartCustom.startAfter(abstractRoom);
+ this.roomGameStartCustom.startAfter(room);
}
return startBefore;
@@ -77,20 +77,20 @@ public boolean startGame(AbstractRoom abstractRoom) {
* 根据 创建游戏规则
*
* @param createRoomInfo 创建房间信息
- * @param AbstractRoom
+ * @param {@link Room}
* @return 房间
*/
- public T createRoom(CreateRoomInfo createRoomInfo) {
+ public T createRoom(CreateRoomInfo createRoomInfo) {
return this.roomCreateCustom.createRoom(createRoomInfo);
}
/**
* 构建房间内的玩家
*
- * @param AbstractPlayer
+ * @param {@link Player}
* @return 玩家
*/
- public T createPlayer() {
+ public T createPlayer() {
return this.roomPlayerCreateCustom.createPlayer();
}
@@ -98,12 +98,12 @@ public T createPlayer() {
* 进入房间
*
* @param userId 玩家 id
- * @param abstractRoom 玩家所在房间
+ * @param room 玩家所在房间
* @param roomEnterInfo 进入房间请求信息
* @return enter Response
*/
- public RoomEnterInfo enterRoom(long userId, AbstractRoom abstractRoom, RoomEnterInfo roomEnterInfo) {
- return this.roomEnterCustom.enterRoom(userId, abstractRoom, roomEnterInfo);
+ public RoomEnterInfo enterRoom(long userId, Room room, RoomEnterInfo roomEnterInfo) {
+ return this.roomEnterCustom.enterRoom(userId, room, roomEnterInfo);
}
/**
diff --git a/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/AbstractPlayer.java b/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/Player.java
similarity index 96%
rename from widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/AbstractPlayer.java
rename to widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/Player.java
index 34e0cf2c8..56912e907 100644
--- a/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/AbstractPlayer.java
+++ b/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/Player.java
@@ -37,7 +37,7 @@
@Setter
@Accessors(chain = true)
@FieldDefaults(level = AccessLevel.PROTECTED)
-public abstract class AbstractPlayer implements Serializable {
+public class Player implements Serializable {
@Serial
private static final long serialVersionUID = -26338708253909097L;
/** userId 玩家 id */
diff --git a/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/AbstractRoom.java b/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/Room.java
similarity index 83%
rename from widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/AbstractRoom.java
rename to widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/Room.java
index 3b257ee44..14d18eeae 100644
--- a/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/AbstractRoom.java
+++ b/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/Room.java
@@ -31,6 +31,7 @@
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Predicate;
+import java.util.stream.Stream;
/**
* 抽象房间
@@ -41,8 +42,9 @@
@Getter
@Setter
@Accessors(chain = true)
+@SuppressWarnings("unchecked")
@FieldDefaults(level = AccessLevel.PROTECTED)
-public abstract class AbstractRoom implements Serializable
+public class Room implements Serializable
// 房间广播增强
, RoomBroadcastEnhance {
@@ -56,7 +58,7 @@ public abstract class AbstractRoom implements Serializable
* value is player
*
*/
- final Map playerMap = new NonBlockingHashMap<>();
+ final Map playerMap = new NonBlockingHashMap<>();
/**
* 玩家位置
@@ -86,12 +88,15 @@ public abstract class AbstractRoom implements Serializable
* @param 玩家
* @return 所有玩家信息 (包括退出房间的玩家信息)
*/
- @SuppressWarnings("unchecked")
- public Collection listPlayer() {
+ public Collection listPlayer() {
return (Collection) this.playerMap.values();
}
- public List listPlayer(Predicate predicate) {
+ public Stream streamPlayer() {
+ return this.playerMap.values().stream();
+ }
+
+ public List listPlayer(Predicate predicate) {
return listPlayer().stream()
.filter(predicate)
.toList();
@@ -108,8 +113,7 @@ public Collection listPlayerId() {
return this.playerMap.keySet();
}
- @SuppressWarnings("unchecked")
- public T getPlayerById(long userId) {
+ public T getPlayerById(long userId) {
return (T) this.playerMap.get(userId);
}
@@ -122,18 +126,18 @@ public boolean existUser(long userId) {
*
* @param player 玩家
*/
- public void addPlayer(AbstractPlayer player) {
+ public void addPlayer(Player player) {
long userId = player.getId();
this.playerMap.put(userId, player);
this.playerSeatMap.put(player.getSeat(), userId);
}
/**
- * 移出玩家
+ * 移除玩家
*
* @param player 玩家
*/
- public void removePlayer(AbstractPlayer player) {
+ public void removePlayer(Player player) {
long userId = player.getId();
this.playerMap.remove(userId);
this.playerSeatMap.remove(player.getSeat());
@@ -150,7 +154,7 @@ public boolean isStatus(RoomStatusEnum roomStatusEnum) {
* @param action 给定操作
* @param t
*/
- public void ifPlayerExist(long userId, Consumer action) {
+ public void ifPlayerExist(long userId, Consumer action) {
T player = this.getPlayerById(userId);
Optional.ofNullable(player).ifPresent(action);
}
@@ -165,4 +169,12 @@ public void ifPlayerNotExist(long userId, Runnable runnable) {
var player = this.getPlayerById(userId);
PresentKit.ifNull(player, runnable);
}
+
+ public int countPlayer() {
+ return this.getPlayerMap().size();
+ }
+
+ public boolean isEmptyPlayer() {
+ return this.playerMap.isEmpty();
+ }
}
\ No newline at end of file
diff --git a/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/RoomService.java b/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/RoomService.java
index d07df6712..4ffeed034 100644
--- a/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/RoomService.java
+++ b/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/RoomService.java
@@ -41,7 +41,7 @@ public class RoomService {
* value : room
*
*/
- final Map roomMap = new ConcurrentHashMap<>();
+ final Map roomMap = new ConcurrentHashMap<>();
/**
* 玩家对应的房间 map
@@ -53,7 +53,7 @@ public class RoomService {
final Map userRoomMap = new ConcurrentHashMap<>();
@SuppressWarnings("unchecked")
- public T getRoomByUserId(long userId) {
+ public T getRoomByUserId(long userId) {
// 通过 userId 得到 roomId
Long roomId = userRoomMap.get(userId);
@@ -66,11 +66,11 @@ public T getRoomByUserId(long userId) {
}
@SuppressWarnings("unchecked")
- public T getRoom(long roomId) {
+ public T getRoom(long roomId) {
return (T) this.roomMap.get(roomId);
}
- public void addRoom(AbstractRoom room) {
+ public void addRoom(Room room) {
long roomId = room.getRoomId();
this.roomMap.put(roomId, room);
}
@@ -80,12 +80,12 @@ public void addRoom(AbstractRoom room) {
*
* @param room 房间
*/
- public void removeRoom(AbstractRoom room) {
+ public void removeRoom(Room room) {
long roomId = room.getRoomId();
this.roomMap.remove(roomId);
}
- public void addPlayer(AbstractRoom room, AbstractPlayer player) {
+ public void addPlayer(Room room, Player player) {
room.addPlayer(player);
this.userRoomMap.put(player.getId(), room.getRoomId());
}
@@ -96,13 +96,13 @@ public void addPlayer(AbstractRoom room, AbstractPlayer player) {
* @param room 房间
* @param player 玩家
*/
- public void removePlayer(AbstractRoom room, AbstractPlayer player) {
+ public void removePlayer(Room room, Player player) {
room.removePlayer(player);
this.userRoomMap.remove(player.getId());
}
@SuppressWarnings("unchecked")
- public Collection listRoom() {
+ public Collection listRoom() {
return (Collection) this.roomMap.values();
}
}
diff --git a/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/flow/RoomCreateCustom.java b/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/flow/RoomCreateCustom.java
index 4375c97c7..372686837 100644
--- a/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/flow/RoomCreateCustom.java
+++ b/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/flow/RoomCreateCustom.java
@@ -18,7 +18,7 @@
*/
package com.iohao.game.widget.light.room.flow;
-import com.iohao.game.widget.light.room.AbstractRoom;
+import com.iohao.game.widget.light.room.Room;
import com.iohao.game.widget.light.room.CreateRoomInfo;
/**
@@ -37,8 +37,8 @@ public interface RoomCreateCustom {
* 根据 创建游戏规则
*
* @param createRoomInfo 创建房间信息
- * @param AbstractRoom
+ * @param Room
* @return 房间
*/
- T createRoom(CreateRoomInfo createRoomInfo);
+ T createRoom(CreateRoomInfo createRoomInfo);
}
diff --git a/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/flow/RoomEnterCustom.java b/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/flow/RoomEnterCustom.java
index 2eb081c8d..2ef0ad155 100644
--- a/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/flow/RoomEnterCustom.java
+++ b/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/flow/RoomEnterCustom.java
@@ -18,7 +18,7 @@
*/
package com.iohao.game.widget.light.room.flow;
-import com.iohao.game.widget.light.room.AbstractRoom;
+import com.iohao.game.widget.light.room.Room;
/**
* 进入房间 (重连)
@@ -32,10 +32,10 @@ public interface RoomEnterCustom {
* 进入房间
*
* @param userId 玩家 id
- * @param abstractRoom 玩家所在房间
+ * @param room 玩家所在房间
* @param roomEnterInfo 进入房间请求信息
* @return enter Response
*/
- RoomEnterInfo enterRoom(long userId, AbstractRoom abstractRoom, RoomEnterInfo roomEnterInfo);
+ RoomEnterInfo enterRoom(long userId, Room room, RoomEnterInfo roomEnterInfo);
}
diff --git a/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/flow/RoomGameStartCustom.java b/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/flow/RoomGameStartCustom.java
index 59ef3a14d..7aeb2a04a 100644
--- a/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/flow/RoomGameStartCustom.java
+++ b/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/flow/RoomGameStartCustom.java
@@ -18,7 +18,7 @@
*/
package com.iohao.game.widget.light.room.flow;
-import com.iohao.game.widget.light.room.AbstractRoom;
+import com.iohao.game.widget.light.room.Room;
/**
* 游戏开始
@@ -39,10 +39,10 @@ public interface RoomGameStartCustom {
* 所以最好预留一个这样的验证接口, 交给子类游戏来定义开始游戏的规则
*
*
- * @param abstractRoom 房间
+ * @param room 房间
* @return 返回 true, 会执行 {@link RoomGameStartCustom#startAfter}. 并更新用户的状态为战斗状态
*/
- boolean startBefore(AbstractRoom abstractRoom);
+ boolean startBefore(Room room);
/**
* 游戏开始前的 after 逻辑. 这里可以游戏正式开始的逻辑
@@ -52,7 +52,7 @@ public interface RoomGameStartCustom {
* 回合制 进入战斗
*
*
- * @param abstractRoom 房间
+ * @param room 房间
*/
- void startAfter(AbstractRoom abstractRoom);
+ void startAfter(Room room);
}
diff --git a/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/flow/RoomPlayerCreateCustom.java b/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/flow/RoomPlayerCreateCustom.java
index 1399762c1..83cc8e97b 100644
--- a/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/flow/RoomPlayerCreateCustom.java
+++ b/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/flow/RoomPlayerCreateCustom.java
@@ -18,7 +18,7 @@
*/
package com.iohao.game.widget.light.room.flow;
-import com.iohao.game.widget.light.room.AbstractPlayer;
+import com.iohao.game.widget.light.room.Player;
/**
* 创建玩家 - 自定义
@@ -33,8 +33,8 @@ public interface RoomPlayerCreateCustom {
/**
* 构建房间内的玩家
*
- * @param AbstractPlayer
+ * @param {@link Player}
* @return 玩家
*/
- T createPlayer();
+ T createPlayer();
}
diff --git a/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/kit/RoomKit.java b/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/kit/RoomKit.java
new file mode 100644
index 000000000..3ec3cd79a
--- /dev/null
+++ b/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/kit/RoomKit.java
@@ -0,0 +1,49 @@
+/*
+ * 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 .
+ */
+package com.iohao.game.widget.light.room.kit;
+
+import com.iohao.game.widget.light.room.Room;
+import lombok.experimental.UtilityClass;
+
+/**
+ * @author 渔民小镇
+ * @date 2024-04-30
+ * @since 21.7
+ */
+@UtilityClass
+public class RoomKit {
+ /**
+ * 从房间内获取一个空位置
+ *
+ * @param room 房间
+ * @return 空的位置
+ */
+ public int getEmptySeatNo(Room room) {
+ // 玩家位置 map
+ var playerSeatMap = room.getPlayerSeatMap();
+
+ for (int i = 0; i < room.getSpaceSize(); i++) {
+ if (!playerSeatMap.containsKey(i)) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+}
diff --git a/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/operation/OperationContext.java b/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/operation/OperationContext.java
index c82dd41c8..7b75996d1 100644
--- a/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/operation/OperationContext.java
+++ b/widget/light-game-room/src/main/java/com/iohao/game/widget/light/room/operation/OperationContext.java
@@ -18,8 +18,8 @@
*/
package com.iohao.game.widget.light.room.operation;
-import com.iohao.game.widget.light.room.AbstractPlayer;
-import com.iohao.game.widget.light.room.AbstractRoom;
+import com.iohao.game.widget.light.room.Player;
+import com.iohao.game.widget.light.room.Room;
/**
* 操作上下文
@@ -31,7 +31,7 @@ public class OperationContext {
/** 操作类型 */
int operation;
- AbstractRoom room;
+ Room room;
- AbstractPlayer player;
+ Player player;
}
diff --git a/widget/light-jprotobuf/pom.xml b/widget/light-jprotobuf/pom.xml
index 4d5cb1d31..01ed60342 100644
--- a/widget/light-jprotobuf/pom.xml
+++ b/widget/light-jprotobuf/pom.xml
@@ -5,7 +5,7 @@
ioGame
com.iohao.game
- 21.6
+ 21.7
../../pom.xml
4.0.0
diff --git a/widget/light-profile/pom.xml b/widget/light-profile/pom.xml
index e3cc54363..dc72b1ed3 100644
--- a/widget/light-profile/pom.xml
+++ b/widget/light-profile/pom.xml
@@ -5,7 +5,7 @@
ioGame
com.iohao.game
- 21.6
+ 21.7
../../pom.xml
4.0.0
diff --git a/widget/light-redis-lock-spring-boot-starter/pom.xml b/widget/light-redis-lock-spring-boot-starter/pom.xml
index dc0b7ef92..ff692f66c 100644
--- a/widget/light-redis-lock-spring-boot-starter/pom.xml
+++ b/widget/light-redis-lock-spring-boot-starter/pom.xml
@@ -8,7 +8,7 @@
ioGame
com.iohao.game
- 21.6
+ 21.7
../../pom.xml
diff --git a/widget/light-redis-lock/pom.xml b/widget/light-redis-lock/pom.xml
index d0d1ab9d9..3fc0eb300 100644
--- a/widget/light-redis-lock/pom.xml
+++ b/widget/light-redis-lock/pom.xml
@@ -5,7 +5,7 @@
ioGame
com.iohao.game
- 21.6
+ 21.7
../../pom.xml
4.0.0
diff --git a/widget/light-timer-task/pom.xml b/widget/light-timer-task/pom.xml
index 7acde3fad..dbd2dd988 100644
--- a/widget/light-timer-task/pom.xml
+++ b/widget/light-timer-task/pom.xml
@@ -5,7 +5,7 @@
ioGame
com.iohao.game
- 21.6
+ 21.7
../../pom.xml
4.0.0
diff --git a/widget/other-tool/pom.xml b/widget/other-tool/pom.xml
index 0cad0a536..92f976bca 100644
--- a/widget/other-tool/pom.xml
+++ b/widget/other-tool/pom.xml
@@ -6,7 +6,7 @@
com.iohao.game
ioGame
- 21.6
+ 21.7
../../pom.xml