牛奶煮汤圆
LittleSkin皮肤站可以支持登陆插件吗?有可能实现以下功能吗?

当玩家用启动器外置登陆时,进入到游戏内会跳过联动的登陆插件并成功进入游戏。如果玩家没有用启动器外置登陆,那么到游戏内会被登陆插件拦截,需要输入密码进行登陆。。

以上就是我想要的功能 但是不知道能不能实现 主要是因为boat等多个手机端都不支持外置登陆 所以想以此方式来解决这个问题

hxyzg
公共的皮肤站是不支持给你对接这个的,建议自己搭建皮肤站

牛奶煮汤圆
hxyzg 发表于 2021-6-28 11:21
公共的皮肤站是不支持给你对接这个的,建议自己搭建皮肤站

我就是用这个自己架设的

Molean
本帖最后由 Molean 于 2021-6-28 20:53 编辑

理论上是可行的, 原理和FastLogin这个插件是类似的.

无外置登陆的玩家登陆流程是这样的:
玩家首次尝试登陆->服务器进行Yggdrasil验证, 并记录玩家登陆行为->验证失败(回退到服务器列表)->再次进入服务器->服务器检测到玩家刚才使用Yggdrasil登陆失败, 关闭Yggdrasil验证, 将玩家发送到登陆服.

有外置登陆的玩家登陆流程是这样的:
玩家首次尝试登陆->服务器进行Yggdrasil验证, 并记录玩家登陆行为->验证成功->服务器将玩家发送到大厅(跳过登陆服)


BC端代码差不多大概长这样, 里面有个PlayerParameter工具类, 是用来存取配置的.
需要注意的是, 最后一个EventHandler需要把玩家UUID反射修改成离线UUID, 否则会存在数据不同步问题.
当然可以根据自己情况来 :

    @EventHandler
    public void playerPreLogin(PreLoginEvent event) {
        String name = event.getConnection().getName();
        String lastLoginString = PlayerParameter.get(name, "lastLogin");
        if (lastLoginString == null || lastLoginString.isEmpty()) {
            lastLoginString = "0";
        }
        long lastLogin = Long.parseLong(lastLoginString);
        if (System.currentTimeMillis() - lastLogin > 60 * 1000) {
            PendingConnection connection = event.getConnection();
            connection.setOnlineMode(true);
        }
        PlayerParameter.set(name, "lastLogin", System.currentTimeMillis() + "");
    }
    @EventHandler
    public void on(ServerConnectEvent event) {
        boolean onlineMode = event.getPlayer().getPendingConnection().isOnlineMode();
        boolean isLogin = event.getTarget().getName().equalsIgnoreCase("login");
        if (onlineMode && isLogin) {
            PlayerParameter.set(event.getPlayer().getName(), "lastLogin", "0");
            ServerInfo lobby= ProxyServer.getInstance().getServerInfo("lobby");
            event.setTarget(lobby);
        }
    }
    @EventHandler(priority = EventPriority.LOWEST)
    public void loginEvent(LoginEvent event) {
        String name = event.getConnection().getName();
        try {
            Field uniqueIdField = ((InitialHandler) event.getConnection()).getClass().getDeclaredField("uniqueId");
            uniqueIdField.setAccessible(true);
            uniqueIdField.set(event.getConnection(), getUUID(name));
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }
补充一下: 如果不是BC, 实现起来比较麻烦, 需要用ProtocolLib捕获登陆包, 可以参考FastLogin源代码