Browse Source

Merge branch 'main' into equip

tangbin 1 year ago
parent
commit
e2c1428aca

+ 28 - 0
common/common-core/src/main/java/com/iohao/mmo/common/config/MyExternalBizCodeCont.java

@@ -0,0 +1,28 @@
+/*
+ * ioGame
+ * Copyright (C) 2021 - 2023  渔民小镇 (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.mmo.common.config;
+
+/**
+ * @author 渔民小镇
+ * @date 2023-08-17
+ */
+public interface MyExternalBizCodeCont {
+    /** 获取玩家 ip */
+    int userIp = 1;
+}

+ 34 - 6
common/common-core/src/main/java/com/iohao/mmo/common/core/flow/MyFlowContext.java

@@ -21,16 +21,25 @@ package com.iohao.mmo.common.core.flow;
 import com.iohao.game.action.skeleton.core.CmdInfo;
 import com.iohao.game.action.skeleton.core.commumication.BroadcastContext;
 import com.iohao.game.action.skeleton.core.commumication.BrokerClientContext;
+import com.iohao.game.action.skeleton.core.commumication.InvokeExternalModuleContext;
 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.RequestMessage;
 import com.iohao.game.action.skeleton.protocol.ResponseMessage;
+import com.iohao.game.action.skeleton.protocol.external.RequestCollectExternalMessage;
+import com.iohao.game.action.skeleton.protocol.external.ResponseCollectExternalMessage;
 import com.iohao.game.common.kit.ArrayKit;
 
+import java.io.Serializable;
 import java.util.Objects;
 
 /**
+ * 自定义 FlowContext
+ * <pre>
+ *
+ * </pre>
+ *
  * @author 渔民小镇
  * @date 2023-07-24
  */
@@ -80,10 +89,28 @@ public class MyFlowContext extends FlowContext {
         broadcastContext.broadcast(responseMessage, getUserId());
     }
 
+    public ResponseCollectExternalMessage invokeExternal(Serializable data, int bizCode) {
+        HeadMetadata headMetadata = getHeadMetadata();
+        // 得到游戏对外服 id
+        int sourceClientId = headMetadata.getSourceClientId();
+
+        var requestCollectExternalMessage = new RequestCollectExternalMessage()
+                // 根据业务码,调用游戏对外服与业务码对应的业务实现类 (AttachmentDataExternalBizRegion)
+                .setBizCode(bizCode)
+                // 元信息
+                .setData(data)
+                // 指定游戏对外服
+                .setSourceClientId(sourceClientId);
+
+        BrokerClientContext brokerClientContext = this.option(FlowAttr.brokerClientContext);
+        InvokeExternalModuleContext context = brokerClientContext.getInvokeExternalModuleContext();
+        return context.invokeExternalModuleCollectMessage(requestCollectExternalMessage);
+    }
+
     @Override
     protected RequestMessage createRequestMessage(CmdInfo cmdInfo, Object data) {
 
-        HeadMetadata headMetadata = getRequest().getHeadMetadata();
+        HeadMetadata headMetadata = getHeadMetadata();
 
         RequestMessage requestMessage = super.createRequestMessage(cmdInfo, data);
 
@@ -95,11 +122,8 @@ public class MyFlowContext extends FlowContext {
         return requestMessage;
     }
 
-
     private ResponseMessage createResponseMessage(CmdInfo cmdInfo, Object data) {
-        // 创建一个响应对象
-        RequestMessage request = this.getRequest();
-        HeadMetadata headMetadata = request.getHeadMetadata();
+        HeadMetadata headMetadata = getHeadMetadata();
         /*
          * 创建一个 HeadMetadata,并使用原有的一些信息;
          * 在广播时,只会给 HeadMetadata 中指定的游戏对外服广播。
@@ -110,6 +134,7 @@ public class MyFlowContext extends FlowContext {
                 .setEndPointClientId(headMetadata.getEndPointClientId())
                 .setSourceClientId(headMetadata.getSourceClientId());
 
+        // 创建一个响应对象
         ResponseMessage responseMessage = new ResponseMessage();
         responseMessage.setHeadMetadata(headMetadataClone);
         responseMessage.setData(data);
@@ -117,4 +142,7 @@ public class MyFlowContext extends FlowContext {
         return responseMessage;
     }
 
-}
+    private HeadMetadata getHeadMetadata() {
+        return this.getRequest().getHeadMetadata();
+    }
+}

+ 49 - 0
common/common-core/src/main/java/com/iohao/mmo/common/kit/MyExternalCommunicationKit.java

@@ -0,0 +1,49 @@
+/*
+ * ioGame
+ * Copyright (C) 2021 - 2023  渔民小镇 (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.mmo.common.kit;
+
+import com.iohao.game.action.skeleton.protocol.external.ResponseCollectExternalItemMessage;
+import com.iohao.game.action.skeleton.protocol.external.ResponseCollectExternalMessage;
+import com.iohao.mmo.common.config.MyExternalBizCodeCont;
+import com.iohao.mmo.common.core.flow.MyFlowContext;
+import lombok.experimental.UtilityClass;
+
+import java.util.Objects;
+
+/**
+ * @author 渔民小镇
+ * @date 2023-08-17
+ */
+@UtilityClass
+public class MyExternalCommunicationKit {
+    public String getUserIp(MyFlowContext flowContext) {
+        long userId = flowContext.getUserId();
+        // 得到游戏对外服 id
+        ResponseCollectExternalMessage message = flowContext.invokeExternal(userId, MyExternalBizCodeCont.userIp);
+
+        return message
+                .optionalAnySuccess()
+                // 得到返回值
+                .map(ResponseCollectExternalItemMessage::getData)
+                // 将为 String
+                .map(Objects::toString)
+                // 如果没获取到给个空串,调用方就不需要做 null 判断了。
+                .orElse("");
+    }
+}

+ 35 - 3
external/src/main/java/com/iohao/mmo/external/MyExternalServer.java

@@ -21,10 +21,15 @@ package com.iohao.mmo.external;
 import com.iohao.game.bolt.broker.core.client.BrokerAddress;
 import com.iohao.game.bolt.broker.core.common.IoGameGlobalConfig;
 import com.iohao.game.external.core.ExternalServer;
+import com.iohao.game.external.core.broker.client.ext.ExternalBizRegions;
 import com.iohao.game.external.core.config.ExternalGlobalConfig;
 import com.iohao.game.external.core.config.ExternalJoinEnum;
+import com.iohao.game.external.core.micro.PipelineContext;
 import com.iohao.game.external.core.netty.DefaultExternalServer;
 import com.iohao.game.external.core.netty.DefaultExternalServerBuilder;
+import com.iohao.game.external.core.netty.handler.ws.HttpRealIpHandler;
+import com.iohao.game.external.core.netty.micro.WebSocketMicroBootstrapFlow;
+import com.iohao.mmo.external.core.broker.client.ext.impl.UserIpExternalBizRegion;
 import com.iohao.mmo.login.cmd.LoginCmd;
 
 /**
@@ -34,7 +39,9 @@ import com.iohao.mmo.login.cmd.LoginCmd;
 public class MyExternalServer {
 
     public ExternalServer createExternalServer(int externalPort) {
-        extractedAccess();
+
+        // 游戏对外服配置
+        extractedConfig();
 
         // 游戏对外服 - 构建器
         DefaultExternalServerBuilder builder = DefaultExternalServer.newBuilder(externalPort)
@@ -43,11 +50,37 @@ public class MyExternalServer {
                 // Broker (游戏网关)的连接地址;如果不设置,默认也是这个配置
                 .brokerAddress(new BrokerAddress("127.0.0.1", IoGameGlobalConfig.brokerPort));
 
-        // 构建游戏对外服
+        builder.setting().setMicroBootstrapFlow(new WebSocketMicroBootstrapFlow() {
+            @Override
+            protected void httpHandler(PipelineContext context) {
+                super.httpHandler(context);
+                /*
+                 * HttpRealIpHandler 是框架内置的一个 handler。
+                 * 添加上后,即使是通过 nginx 转发,也可以得到玩家真实的 ip
+                 */
+                context.addLast("HttpRealIpHandler", new HttpRealIpHandler());
+            }
+        });
+
+        // 构建游戏对外服 https://www.yuque.com/iohao/game/ea6geg
         return builder.build();
     }
 
+    private static void extractedConfig() {
+        // 对外服业务扩展
+        extractedExternalBizRegion();
+
+        // 路由访问权限控制
+        extractedAccess();
+    }
+
+    private static void extractedExternalBizRegion() {
+        ExternalBizRegions.add(new UserIpExternalBizRegion());
+    }
+
     private static void extractedAccess() {
+        // https://www.yuque.com/iohao/game/nap5y8p5fevhv99y
+
         var accessAuthenticationHook = ExternalGlobalConfig.accessAuthenticationHook;
         // 表示登录才能访问业务方法
         accessAuthenticationHook.setVerifyIdentity(true);
@@ -62,5 +95,4 @@ public class MyExternalServer {
 
         externalServer.startup();
     }
-
 }

+ 56 - 0
external/src/main/java/com/iohao/mmo/external/core/broker/client/ext/impl/UserIpExternalBizRegion.java

@@ -0,0 +1,56 @@
+/*
+ * ioGame
+ * Copyright (C) 2021 - 2023  渔民小镇 (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.mmo.external.core.broker.client.ext.impl;
+
+import com.iohao.game.action.skeleton.core.exception.ActionErrorEnum;
+import com.iohao.game.action.skeleton.core.exception.MsgException;
+import com.iohao.game.action.skeleton.protocol.external.RequestCollectExternalMessage;
+import com.iohao.game.external.core.broker.client.ext.ExternalBizRegion;
+import com.iohao.game.external.core.broker.client.ext.ExternalBizRegionContext;
+import com.iohao.game.external.core.session.UserSession;
+import com.iohao.mmo.common.config.MyExternalBizCodeCont;
+
+import java.io.Serializable;
+
+/**
+ * 玩家 ip 获取
+ *
+ * @author 渔民小镇
+ * @date 2023-08-17
+ */
+public class UserIpExternalBizRegion implements ExternalBizRegion {
+    @Override
+    public int getBizCode() {
+        return MyExternalBizCodeCont.userIp;
+    }
+
+    @Override
+    public Serializable request(ExternalBizRegionContext regionContext) throws MsgException {
+        RequestCollectExternalMessage request = regionContext.getRequestCollectExternalMessage();
+        long userId = request.getData();
+
+        // 得到玩家 session
+        var userSessions = regionContext.getUserSessions();
+        UserSession userSession = userSessions.getUserSession(userId);
+        ActionErrorEnum.dataNotExist.assertNonNull(userSession);
+
+        // 获取玩家 ip
+        return userSession.getIp();
+    }
+}

+ 0 - 1
logic/bag-logic/src/main/java/com/iohao/mmo/bag/action/BagAction.java

@@ -62,7 +62,6 @@ public class BagAction {
     @Resource
     UseRegion useRegion;
 
-
     /**
      * 查询玩家背包
      *

+ 14 - 0
logic/login-logic/src/main/java/com/iohao/mmo/login/action/LoginAction.java

@@ -27,6 +27,8 @@ import com.iohao.game.bolt.broker.client.kit.ExternalCommunicationKit;
 import com.iohao.game.bolt.broker.client.kit.UserIdSettingKit;
 import com.iohao.mmo.common.annotation.IoThread;
 import com.iohao.mmo.common.core.flow.MyAttachment;
+import com.iohao.mmo.common.core.flow.MyFlowContext;
+import com.iohao.mmo.common.kit.MyExternalCommunicationKit;
 import com.iohao.mmo.login.cmd.LoginCmd;
 import com.iohao.mmo.login.proto.LoginVerify;
 import com.iohao.mmo.login.proto.UserInfo;
@@ -77,6 +79,18 @@ public class LoginAction {
         return userInfo;
     }
 
+    /**
+     * 获取玩家 ip
+     *
+     * @param flowContext flowContext
+     * @return 玩家 ip
+     */
+    @ActionMethod(LoginCmd.userIp)
+    public String getUserIp(MyFlowContext flowContext) {
+        // 这个 action 写着玩的,目前没什么作用,只是为了演示 ip 获取
+        return MyExternalCommunicationKit.getUserIp(flowContext);
+    }
+
     private MyAttachment settingAttachment(long userId, FlowContext flowContext) {
         // 创建自定义的元附加信息对象
         MyAttachment myAttachment = new MyAttachment();

+ 1 - 1
pom.xml

@@ -58,7 +58,7 @@
         <encoding>UTF-8</encoding>
 
         <!-- 项目版本 -->
-        <ioGame.version>17.1.53</ioGame.version>
+        <ioGame.version>17.1.54</ioGame.version>
         <spring-boot.version>3.1.2</spring-boot.version>
         <!-- lombok 消除冗长的 Java 代码 https://mvnrepository.com/artifact/org.projectlombok/lombok -->
         <lombok.version>1.18.24</lombok.version>

+ 7 - 0
provide/login-provide/src/main/java/com/iohao/mmo/login/client/LoginInputCommandRegion.java

@@ -18,6 +18,7 @@
  */
 package com.iohao.mmo.login.client;
 
+import com.iohao.game.action.skeleton.protocol.wrapper.StringValue;
 import com.iohao.game.common.kit.InternalKit;
 import com.iohao.game.common.kit.StrKit;
 import com.iohao.game.external.client.AbstractInputCommandRegion;
@@ -39,6 +40,7 @@ public class LoginInputCommandRegion extends AbstractInputCommandRegion {
     @Override
     public void initInputCommand() {
         this.inputCommandCreate.cmd = LoginCmd.cmd;
+        this.inputCommandCreate.cmdName = "大厅";
 
         String jwt = clientUser.getJwt();
         AssertKit.assertTrueThrow(StrKit.isEmpty(jwt), "必须设置登录用的 jwt");
@@ -63,5 +65,10 @@ public class LoginInputCommandRegion extends AbstractInputCommandRegion {
             // 自动登录
             ofRequestCommand(LoginCmd.loginVerify).request();
         }, 200, TimeUnit.MILLISECONDS);
+
+        ofCommand(LoginCmd.userIp).callback(StringValue.class, result -> {
+            StringValue value = result.getValue();
+            log.info("玩家 ip : {}", value.value);
+        }).setDescription("演示获取玩家 ip");
     }
 }

+ 3 - 0
provide/login-provide/src/main/java/com/iohao/mmo/login/cmd/LoginCmd.java

@@ -28,4 +28,7 @@ import com.iohao.mmo.common.provide.cmd.CmdModule;
 public interface LoginCmd {
     int cmd = CmdModule.loginCmd;
     int loginVerify = 1;
+
+    int userIp = 2;
+
 }