1
mirror of https://github.com/carm-outsource/TimeReward.git synced 2026-06-04 15:28:16 +08:00

fix(claim): 修复了每日奖励可能被多次重复领取的bug。

This commit is contained in:
2025-07-04 15:22:37 +08:00
parent 2f5d8c93bd
commit cc451cd1f4
6 changed files with 44 additions and 11 deletions
+1 -1
View File
@@ -18,7 +18,7 @@
<groupId>cc.carm.plugin</groupId>
<artifactId>timereward</artifactId>
<version>3.1.5</version>
<version>3.1.6</version>
<name>TimeReward</name>
<description>在线时长自动领奖插件,通过指令发放奖励,基于EasyPlugin实现。</description>
@@ -30,6 +30,11 @@ public class ClaimCommand extends SubCommand<MainCommand> {
Player player = (Player) sender;
RewardManager manager = TimeRewardAPI.getRewardManager();
if(manager.isClaiming(player.getUniqueId())){
PluginMessages.ALREADY_CLAIMING.sendTo(sender);
return null;
}
@Nullable String rewardID = args.length > 0 ? args[0] : null;
if (rewardID == null) {
@@ -91,6 +91,10 @@ public interface PluginMessages extends Configuration {
"&c&l抱歉!&f但您暂时未满足领取奖励 &e%(award) &f的条件。"
).params("award").build();
ConfiguredMessage<BaseComponent[]> ALREADY_CLAIMING = list().defaults(
"&e&l请稍候...&f您当前有正在领取的奖励任务,单次只可领取一份奖励。"
).build();
ConfiguredMessage<BaseComponent[]> NO_UNCLAIMED_REWARD = list().defaults(
"&f您暂时没有未领取的奖励。"
).build();
@@ -17,7 +17,7 @@ public enum IntervalType {
),
DAILY(
1, Duration.ofDays(1), time -> DateTimeUtils.sameDay(time.toLocalDate()),
1, Duration.ofDays(1), time -> !DateTimeUtils.sameDay(time.toLocalDate()),
(timeRecord, join) -> {
LocalDateTime now = LocalDateTime.now();
if (!now.toLocalDate().isEqual(join.toLocalDate())) {
@@ -18,12 +18,15 @@ import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
public class RewardManager {
protected BukkitRunnable runnable;
protected Map<UUID, CompletableFuture<Boolean>> claiming = new ConcurrentHashMap<>();
public RewardManager(Main main) {
this.runnable = new BukkitRunnable() {
@Override
@@ -31,6 +34,8 @@ public class RewardManager {
if (Bukkit.getOnlinePlayers().isEmpty()) return;
for (Player player : Bukkit.getOnlinePlayers()) {
if (isClaiming(player.getUniqueId())) continue; // 如果正在领取奖励,则跳过
List<RewardContents> rewards = getUnclaimedRewards(player).stream()
.filter(RewardContents::isAutoClaimed)
.collect(Collectors.toList());
@@ -61,6 +66,14 @@ public class RewardManager {
return Collections.unmodifiableMap(RewardsConfig.getContents());
}
public boolean isClaiming(@NotNull UUID uuid) {
return claiming.containsKey(uuid) && !claiming.get(uuid).isDone();
}
public CompletableFuture<Boolean> getClaiming(@NotNull UUID uuid) {
return claiming.get(uuid);
}
@Unmodifiable
public @NotNull List<RewardContents> getUnclaimedRewards(@NotNull Player player) {
return listRewards().values().stream()
@@ -97,22 +110,27 @@ public class RewardManager {
}
public CompletableFuture<Boolean> claimRewards(Player player, Collection<RewardContents> rewards, boolean check) {
CompletableFuture<Boolean> exists = claiming.get(player.getUniqueId());
if (exists != null) return CompletableFuture.completedFuture(false); // 如果玩家正在领取奖励,则直接返回false
Set<RewardContents> contents = rewards.stream()
.filter(r -> !check || isClaimable(player, r))
.collect(Collectors.toSet());
if (contents.isEmpty()) {
return CompletableFuture.completedFuture(true); // 没有可领取的奖励,直接返回true。
}
Map<String, LocalDateTime> map = new LinkedHashMap<>();
contents.forEach(reward -> map.put(reward.getRewardID(), LocalDateTime.now()));
return Main.getInstance().supplyAsync(() -> {
try {
UserRewardData user = TimeRewardAPI.getUserManager().get(player);
if (user == null) return false; // 玩家数据加载中
if (user == null) return CompletableFuture.completedFuture(false); // 玩家数据加载中
CompletableFuture<Boolean> task = Main.getInstance().supplyAsync(() -> {
try {
Main.getStorage().addClaimedData(player.getUniqueId(), map);
contents.forEach(user::updateClaimed);
return true;
} catch (Exception ex) {
Main.severe("为玩家 " + player.getName() + " 领取奖励时发生错误。");
@@ -129,6 +147,12 @@ public class RewardManager {
return CompletableFuture.completedFuture(false);
}
});
claiming.put(player.getUniqueId(), task);
return task.whenComplete((b, t) -> {
claiming.remove(player.getUniqueId());
});
}
public void executeCommand(Player player, RewardContents reward) {
@@ -1,6 +1,6 @@
package cc.carm.plugin.timereward.user;
import cc.carm.lib.easyplugin.user.UserData;
import cc.carm.lib.easyplugin.user.AbstractUserData;
import cc.carm.plugin.timereward.data.IntervalType;
import cc.carm.plugin.timereward.data.RewardContents;
import cc.carm.plugin.timereward.data.TimeRecord;
@@ -15,7 +15,7 @@ import java.util.UUID;
/**
* 用户奖励数据,用于存储用户的奖励的领取情况。
*/
public class UserRewardData extends UserData<UUID> {
public class UserRewardData extends AbstractUserData<UUID> {
private final @NotNull Map<String, LocalDateTime> claimedRewards; // 记录已领取的奖励ID
@@ -35,7 +35,7 @@ public class UserRewardData extends UserData<UUID> {
}
public @NotNull UUID getUserUUID() {
return getKey();
return key();
}
/**