You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java游戏新玩家在线1小时动作限制逻辑实现问题求助

现有代码核心逻辑问题

  1. 时间类型选择错误:LocalTime仅表示当日的时分秒,跨天场景下计算时间差会出现异常,且无法正确记录跨天的在线时长
  2. 字段设计错误:你不需要startedTime/currentTime/finishTime三个时间点字段,核心应该记录历史累计在线时长 + 本次登录的起始时间即可
  3. 计时逻辑写反:count和logout方法中使用minus减少时长的操作完全错误,你应该累加玩家的在线时长
  4. 没有持久化累计时长:现有字段如果重启服务或者玩家重新登录,所有计时都会重置,需要把累计在线时长做序列化持久化

修正后完整代码

package com.rs.game.player;

import com.rs.utils.Utils;

import java.io.Serializable;
import java.time.Duration;
import java.time.Instant;

public class AccountRestriction implements Serializable {
    public enum RestrictionType {
        TRADING,DROPPING_ITEMS,PVP
    }

    private transient Player player;
    // 持久化存储:历史累计在线时长
    private Duration totalOnlineDuration = Duration.ZERO;
    // transient不持久化:本次登录的开始时间,每次登录重新赋值
    private transient Instant loginStartTime;
    // 新玩家限制阈值:累计在线满1小时解除
    private static final Duration RESTRICT_THRESHOLD = Duration.ofHours(1);

    public void setPlayer(Player player) {
        this.player = player;
        // 登录绑定玩家实例时,记录本次登录开始时间
        this.loginStartTime = Instant.now();
    }

    /**
     * 每tick(600ms)更新玩家累计在线时长
     */
    public void count() {
        Instant now = Instant.now();
        // 累加本次计时周期的在线时长
        Duration delta = Duration.between(loginStartTime, now);
        totalOnlineDuration = totalOnlineDuration.plus(delta);
        // 更新计时起始点,避免重复累加
        loginStartTime = now;
        System.out.println("累计在线时长:" + totalOnlineDuration.toMinutes() + "分钟");
    }

    /**
     * 玩家登出时结算本次在线时长
     */
    public void logout() {
        Instant now = Instant.now();
        Duration delta = Duration.between(loginStartTime, now);
        totalOnlineDuration = totalOnlineDuration.plus(delta);
    }

    /**
     * 构造方法
     * @param player 玩家实例
     */
    public AccountRestriction(Player player) {
        this.player = player;
        this.loginStartTime = Instant.now();
    }

    /**
     * 检查账号是否处于限制状态
     * @return 处于限制状态返回{@code true},否则返回{@code false}
     */
    public boolean isRestricted(RestrictionType type) {
        // 累计在线时长满1小时直接解除限制
        if (totalOnlineDuration.compareTo(RESTRICT_THRESHOLD) >= 0) {
            return false;
        }
        player.sm(getRestriction(type));
        return true;
    }

    /**
     * 获取限制提示文案
     * @param type 限制类型
     * @return 限制提示字符串
     */
    public String getRestriction(RestrictionType type) {
        long timeLeft = RESTRICT_THRESHOLD.minus(totalOnlineDuration).toMinutes();
        String timeText;
        if (timeLeft >= 60) {
            timeText = "1</col> 小时";
        } else if (timeLeft > 1) {
            timeText = timeLeft + "</col> 分钟";
        } else if (timeLeft == 1) {
            timeText = "1</col> 分钟";
        } else {
            timeText = "不到1</col> 分钟";
        }
        return "你还有 <col=ff0000>" + timeText + " 的新玩家限制,无法使用功能:<col=ff0000>" + Utils.formatPlayerNameForDisplay(type.name()) + "</col>!";
    }

    public Duration getTotalOnlineDuration() {
        return totalOnlineDuration;
    }
}

逻辑说明

  • 所有时间计算改用Instant,不受时区、跨天影响,计算更准确
  • 每次登录、每tick、登出三个节点都正确累加在线时长,离线不会产生时长增量
  • 限制判断直接对比累计在线时长和1小时的阈值即可,逻辑清晰没有歧义
  • 累计时长做了序列化持久化,重启服务、玩家重新登录都不会丢失计时数据

内容的提问来源于stack exchange,提问作者wyvern800

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 06:18:00