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

feat(time): 支持在周期内循环时间发奖

This commit is contained in:
2023-09-07 05:09:21 +08:00
parent 9a85f84119
commit 1078c7e03d
8 changed files with 57 additions and 33 deletions
+1 -1
View File
@@ -18,7 +18,7 @@
<groupId>cc.carm.plugin</groupId> <groupId>cc.carm.plugin</groupId>
<artifactId>timereward</artifactId> <artifactId>timereward</artifactId>
<version>3.0.0</version> <version>3.1.0</version>
<name>TimeReward</name> <name>TimeReward</name>
<description>在线时长自动领奖插件,通过指令发放奖励,基于EasyPlugin实现。</description> <description>在线时长自动领奖插件,通过指令发放奖励,基于EasyPlugin实现。</description>
@@ -17,6 +17,12 @@ import java.util.Map;
" [type] 奖励的类型序号", " [type] 奖励的类型序号",
" | “0”代表总计时间奖励,“1”代表每日在线奖励,", " | “0”代表总计时间奖励,“1”代表每日在线奖励,",
" | “2”代表每周在线奖励,“3”代表每月在线奖励。", " | “2”代表每周在线奖励,“3”代表每月在线奖励。",
" [time] 奖励发放要求的时间(秒)",
" [loop] 奖励是否按循环时间发放",
" | 可以填入 true 或 false",
" | 若启用,则在规定的周期内,每满足指定时间一次则发放一次奖励",
" | 如 类型为 “每周在线奖励” 时间为 “12小时” ",
" | 则 代表 代表在这周内每12小时发放一次奖励,下一周时间重新开始算",
" [name] 奖励的显示名称,可以是任意字符串", " [name] 奖励的显示名称,可以是任意字符串",
" | 可以在 commands 中使用 %(name) 来获取该奖励的名称", " | 可以在 commands 中使用 %(name) 来获取该奖励的名称",
" | 也可以使用变量 %TimeReward_reward_<奖励ID>% 来获取对应奖励的名称", " | 也可以使用变量 %TimeReward_reward_<奖励ID>% 来获取对应奖励的名称",
@@ -60,14 +60,14 @@ public enum IntervalType {
); );
private final int id; private final int id;
private final @NotNull Predicate<LocalDateTime> reclaimPreficate; private final @NotNull Predicate<LocalDateTime> periodChangePredicate;
private final @NotNull BiFunction<TimeRecord, LocalDateTime, Duration> calculator; private final @NotNull BiFunction<TimeRecord, LocalDateTime, Duration> calculator;
IntervalType(int id, IntervalType(int id,
@NotNull Predicate<LocalDateTime> reclaimablePredicate, @NotNull Predicate<LocalDateTime> periodChangePredicate,
@NotNull BiFunction<TimeRecord, LocalDateTime, Duration> calculator) { @NotNull BiFunction<TimeRecord, LocalDateTime, Duration> calculator) {
this.id = id; this.id = id;
this.reclaimPreficate = reclaimablePredicate; this.periodChangePredicate = periodChangePredicate;
this.calculator = calculator; this.calculator = calculator;
} }
@@ -79,16 +79,16 @@ public enum IntervalType {
return calculator; return calculator;
} }
public @NotNull Predicate<LocalDateTime> getReclaimablePredicate() { public @NotNull Predicate<LocalDateTime> getPreiodChangePredicate() {
return reclaimPreficate; return periodChangePredicate;
} }
public Duration calculate(@NotNull TimeRecord timeRecord, @NotNull LocalDateTime joinTime) { public Duration calculate(@NotNull TimeRecord timeRecord, @NotNull LocalDateTime joinTime) {
return calculator.apply(timeRecord, joinTime); return calculator.apply(timeRecord, joinTime);
} }
public boolean isReclaimable(@NotNull LocalDateTime claimedDate) { public boolean isPeriodChanged(@NotNull LocalDateTime claimedDate) {
return reclaimPreficate.test(claimedDate); return periodChangePredicate.test(claimedDate);
} }
public static IntervalType parse(String input) { public static IntervalType parse(String input) {
@@ -15,6 +15,7 @@ public class RewardContents {
public final @NotNull IntervalType type; public final @NotNull IntervalType type;
private final long time; private final long time;
private final boolean loop;
private final @Nullable String name; private final @Nullable String name;
private final @Nullable String permission; private final @Nullable String permission;
@@ -22,12 +23,13 @@ public class RewardContents {
private final boolean auto; private final boolean auto;
public RewardContents(@NotNull String id, @NotNull IntervalType type, long time, public RewardContents(@NotNull String id, @NotNull IntervalType type, long time, boolean loop,
@Nullable String name, @Nullable String permission, @Nullable String name, @Nullable String permission,
@NotNull List<String> commands, boolean auto) { @NotNull List<String> commands, boolean auto) {
this.id = id; this.id = id;
this.type = type; this.type = type;
this.time = time; this.time = time;
this.loop = loop;
this.name = name; this.name = name;
this.permission = permission; this.permission = permission;
this.commands = commands; this.commands = commands;
@@ -42,6 +44,10 @@ public class RewardContents {
return type; return type;
} }
public boolean isLoop() {
return loop;
}
public long getTime() { public long getTime() {
return time; return time;
} }
@@ -70,11 +76,11 @@ public class RewardContents {
return permission == null || player.hasPermission(permission); return permission == null || player.hasPermission(permission);
} }
public Map<String, Object> serialize() { public Map<String, Object> serialize() {
Map<String, Object> map = new LinkedHashMap<>(); Map<String, Object> map = new LinkedHashMap<>();
map.put("time", getTime()); map.put("time", getTime());
map.put("type", getType().getID()); map.put("type", getType().getID());
map.put("loop", isLoop());
if (getName() != null) map.put("name", getName()); if (getName() != null) map.put("name", getName());
if (getPermission() != null) map.put("permission", getPermission()); if (getPermission() != null) map.put("permission", getPermission());
map.put("commands", getCommands()); map.put("commands", getCommands());
@@ -96,17 +102,15 @@ public class RewardContents {
} }
return new RewardContents( return new RewardContents(
id, intervalType, time, id, intervalType, time, section.getBoolean("loop", false),
section.getString("name"), section.getString("name"), section.getString("permission"),
section.getString("permission"), section.getStringList("commands"), section.getBoolean("auto", false)
section.getStringList("commands"),
section.getBoolean("auto", false)
); );
} }
public static RewardContents defaults(String id) { public static RewardContents defaults(String id) {
return new RewardContents( return new RewardContents(
id, IntervalType.TOTAL, 7200, id, IntervalType.TOTAL, 7200, false,
"&f[初级奖励] &e总在线时长 2小时", "TimeReward.vip", "&f[初级奖励] &e总在线时长 2小时", "TimeReward.vip",
Collections.singletonList("say &f恭喜 &b%player_name% &f领取了奖励 &r%(name) &f"), Collections.singletonList("say &f恭喜 &b%player_name% &f领取了奖励 &r%(name) &f"),
true true
@@ -4,6 +4,7 @@ import cc.carm.lib.easyplugin.utils.MessageUtils;
import cc.carm.plugin.timereward.Main; import cc.carm.plugin.timereward.Main;
import cc.carm.plugin.timereward.TimeRewardAPI; import cc.carm.plugin.timereward.TimeRewardAPI;
import cc.carm.plugin.timereward.conf.RewardsConfig; import cc.carm.plugin.timereward.conf.RewardsConfig;
import cc.carm.plugin.timereward.data.IntervalType;
import cc.carm.plugin.timereward.data.RewardContents; import cc.carm.plugin.timereward.data.RewardContents;
import cc.carm.plugin.timereward.user.UserRewardData; import cc.carm.plugin.timereward.user.UserRewardData;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@@ -13,6 +14,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Unmodifiable; import org.jetbrains.annotations.Unmodifiable;
import java.time.Duration;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.*; import java.util.*;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@@ -67,11 +69,25 @@ public class RewardManager {
} }
public boolean isClaimable(Player player, RewardContents reward) { public boolean isClaimable(Player player, RewardContents reward) {
UserRewardData user = TimeRewardAPI.getUserManager().get(player); if (!reward.checkPermission(player)) return false; // 满足权限
return !user.isClaimed(reward) // 未曾领取 UserRewardData user = TimeRewardAPI.getUserManager().get(player);
&& user.isTimeEnough(reward)// 时间足够 IntervalType intervalType = reward.getType();
&& reward.checkPermission(player); // 满足权限 LocalDateTime lastClaimed = user.getClaimedDate(reward);
if (reward.isLoop()) { // 循环奖励
if (lastClaimed == null || intervalType.isPeriodChanged(lastClaimed)) {
// 无上次领取记录或上次领取的时间不在一个周期内,则直接判断时间是否足够一次循环领取的时间
return user.getOnlineDuration(intervalType).getSeconds() > reward.getTime();
} else {
// 有上次领取记录,且在同一周期内,则直接判断相隔时间是否满足一个周期
return Duration.between(lastClaimed, LocalDateTime.now()).getSeconds() > reward.getTime();
}
} else { // 非循环奖励
if (lastClaimed == null || intervalType.isPeriodChanged(lastClaimed)) { // 无上次领取记录,则直接判断时间是否足够领取的时间
return user.getOnlineDuration(intervalType).getSeconds() > reward.getTime();
} else return false; // 有同一周期内的领取记录,则玩家不得重复领取了
}
} }
public CompletableFuture<Boolean> claimReward(Player player, RewardContents reward, boolean check) { public CompletableFuture<Boolean> claimReward(Player player, RewardContents reward, boolean check) {
@@ -91,7 +107,7 @@ public class RewardManager {
UserRewardData user = TimeRewardAPI.getUserManager().get(player); UserRewardData user = TimeRewardAPI.getUserManager().get(player);
Main.getStorage().addClaimedData(player.getUniqueId(), map); Main.getStorage().addClaimedData(player.getUniqueId(), map);
contents.forEach(user::addClaimedReward); contents.forEach(user::updateClaimed);
return true; return true;
} catch (Exception ex) { } catch (Exception ex) {
@@ -59,7 +59,6 @@ public class MySQLStorage {
public @Nullable UserRewardData loadData(@NotNull UUID uuid) throws Exception { public @Nullable UserRewardData loadData(@NotNull UUID uuid) throws Exception {
TimeRecord recordDate = loadTimeRecord(uuid); TimeRecord recordDate = loadTimeRecord(uuid);
System.out.println(recordDate.toString());
Map<String, LocalDateTime> claimedData = loadClaimedData(uuid); Map<String, LocalDateTime> claimedData = loadClaimedData(uuid);
return new UserRewardData(uuid, recordDate, claimedData); return new UserRewardData(uuid, recordDate, claimedData);
} }
@@ -85,7 +84,7 @@ public class MySQLStorage {
public Map<String, LocalDateTime> loadClaimedData(@NotNull UUID uuid) throws Exception { public Map<String, LocalDateTime> loadClaimedData(@NotNull UUID uuid) throws Exception {
return DatabaseTables.USER_CLAIMED.createQuery() return DatabaseTables.USER_CLAIMED.createQuery()
.addCondition("uuid", uuid).build() .addCondition("uuid", uuid).build()
.executeFunction((query) -> { .executeFunction(query -> {
ResultSet rs = query.getResultSet(); ResultSet rs = query.getResultSet();
Map<String, LocalDateTime> map = new LinkedHashMap<>(); Map<String, LocalDateTime> map = new LinkedHashMap<>();
@@ -30,8 +30,7 @@ public class LockedRewardData extends UserRewardData {
} }
@Override @Override
public boolean addClaimedReward(@NotNull RewardContents reward) { public void updateClaimed(@NotNull RewardContents reward) {
return false;
} }
} }
@@ -5,6 +5,7 @@ import cc.carm.plugin.timereward.data.IntervalType;
import cc.carm.plugin.timereward.data.RewardContents; import cc.carm.plugin.timereward.data.RewardContents;
import cc.carm.plugin.timereward.data.TimeRecord; import cc.carm.plugin.timereward.data.TimeRecord;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.time.Duration; import java.time.Duration;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@@ -64,21 +65,20 @@ public class UserRewardData extends UserData<UUID> {
return getOnlineDuration(reward.getType()).getSeconds() >= reward.getTime(); return getOnlineDuration(reward.getType()).getSeconds() >= reward.getTime();
} }
public @NotNull Map<String, LocalDateTime> getClaimedRewards() { public @NotNull Map<String, LocalDateTime> getClaimedRewards() {
return claimedRewards; return claimedRewards;
} }
public @Nullable LocalDateTime getClaimedDate(@NotNull RewardContents reward) {
return claimedRewards.get(reward.getRewardID());
}
public boolean isClaimed(@NotNull RewardContents reward) { public boolean isClaimed(@NotNull RewardContents reward) {
LocalDateTime claimedDate = claimedRewards.get(reward.getRewardID()); return claimedRewards.containsKey(reward.getRewardID());
if (claimedDate == null) return false;
return !reward.getType().isReclaimable(claimedDate);
} }
public boolean addClaimedReward(@NotNull RewardContents reward) { public void updateClaimed(@NotNull RewardContents reward) {
if (isClaimed(reward)) return false; // 已经领取过了
this.claimedRewards.put(reward.getRewardID(), LocalDateTime.now()); this.claimedRewards.put(reward.getRewardID(), LocalDateTime.now());
return true;
} }
} }