diff --git a/README.md b/README.md
index 2e03195..276740f 100644
--- a/README.md
+++ b/README.md
@@ -103,6 +103,8 @@
若您觉得本插件做的不错,您可以捐赠支持我,感谢您成为开源项目的支持者!
+万分感谢 [egg_拿]() 赞助本项目的开发与维护!
+
Many thanks to Jetbrains for kindly providing a license for me to work on this and other open-source projects.
[![](https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg)](https://www.jetbrains.com/?from=https://github.com/CarmJos/UserPrefix)
diff --git a/pom.xml b/pom.xml
index bde699d..eb28232 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,12 +13,12 @@
1.5.5
0.4.7
- 2.5.1
+ 2.8.0
cc.carm.plugin
timereward
- 2.2.1
+ 3.0.0
TimeReward
在线时长自动领奖插件,通过指令发放奖励,基于EasyPlugin实现。
diff --git a/src/main/java/cc/carm/plugin/timereward/command/sub/ClaimCommand.java b/src/main/java/cc/carm/plugin/timereward/command/sub/ClaimCommand.java
index a54d1b7..9e7fe39 100644
--- a/src/main/java/cc/carm/plugin/timereward/command/sub/ClaimCommand.java
+++ b/src/main/java/cc/carm/plugin/timereward/command/sub/ClaimCommand.java
@@ -6,7 +6,7 @@ import cc.carm.plugin.timereward.TimeRewardAPI;
import cc.carm.plugin.timereward.command.MainCommand;
import cc.carm.plugin.timereward.conf.PluginMessages;
import cc.carm.plugin.timereward.manager.RewardManager;
-import cc.carm.plugin.timereward.storage.RewardContents;
+import cc.carm.plugin.timereward.data.RewardContents;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
diff --git a/src/main/java/cc/carm/plugin/timereward/command/sub/ListCommand.java b/src/main/java/cc/carm/plugin/timereward/command/sub/ListCommand.java
index 8fc901c..fe7bcc8 100644
--- a/src/main/java/cc/carm/plugin/timereward/command/sub/ListCommand.java
+++ b/src/main/java/cc/carm/plugin/timereward/command/sub/ListCommand.java
@@ -4,7 +4,7 @@ import cc.carm.lib.easyplugin.command.SubCommand;
import cc.carm.plugin.timereward.TimeRewardAPI;
import cc.carm.plugin.timereward.command.MainCommand;
import cc.carm.plugin.timereward.conf.PluginMessages;
-import cc.carm.plugin.timereward.storage.RewardContents;
+import cc.carm.plugin.timereward.data.RewardContents;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
diff --git a/src/main/java/cc/carm/plugin/timereward/command/sub/TestCommand.java b/src/main/java/cc/carm/plugin/timereward/command/sub/TestCommand.java
index 91ce625..8f26b98 100644
--- a/src/main/java/cc/carm/plugin/timereward/command/sub/TestCommand.java
+++ b/src/main/java/cc/carm/plugin/timereward/command/sub/TestCommand.java
@@ -5,7 +5,7 @@ import cc.carm.lib.easyplugin.command.SubCommand;
import cc.carm.plugin.timereward.TimeRewardAPI;
import cc.carm.plugin.timereward.command.MainCommand;
import cc.carm.plugin.timereward.conf.PluginMessages;
-import cc.carm.plugin.timereward.storage.RewardContents;
+import cc.carm.plugin.timereward.data.RewardContents;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
diff --git a/src/main/java/cc/carm/plugin/timereward/command/sub/UserCommand.java b/src/main/java/cc/carm/plugin/timereward/command/sub/UserCommand.java
index fedff96..5a7b69c 100644
--- a/src/main/java/cc/carm/plugin/timereward/command/sub/UserCommand.java
+++ b/src/main/java/cc/carm/plugin/timereward/command/sub/UserCommand.java
@@ -5,7 +5,7 @@ import cc.carm.lib.easyplugin.command.SubCommand;
import cc.carm.plugin.timereward.TimeRewardAPI;
import cc.carm.plugin.timereward.command.MainCommand;
import cc.carm.plugin.timereward.conf.PluginMessages;
-import cc.carm.plugin.timereward.storage.UserData;
+import cc.carm.plugin.timereward.data.UserData;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
diff --git a/src/main/java/cc/carm/plugin/timereward/conf/PluginConfig.java b/src/main/java/cc/carm/plugin/timereward/conf/PluginConfig.java
index a5627cf..be3cfcd 100644
--- a/src/main/java/cc/carm/plugin/timereward/conf/PluginConfig.java
+++ b/src/main/java/cc/carm/plugin/timereward/conf/PluginConfig.java
@@ -4,7 +4,8 @@ import cc.carm.lib.configuration.core.ConfigurationRoot;
import cc.carm.lib.configuration.core.annotation.HeaderComment;
import cc.carm.lib.configuration.core.value.ConfigValue;
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
-import cc.carm.plugin.timereward.storage.RewardContents;
+
+import java.time.DayOfWeek;
public class PluginConfig extends ConfigurationRoot {
@@ -23,7 +24,14 @@ public class PluginConfig extends ConfigurationRoot {
"检查更新为异步操作,绝不会影响性能与使用体验。"
})
public static final ConfigValue CHECK_UPDATE = ConfiguredValue.of(Boolean.class, true);
-
+
+ @HeaderComment("周起始日,用于判断周度奖励的结算日期。")
+ public static final ConfigValue WEEK_FIRST_DAY = ConfiguredValue.builderOf(DayOfWeek.class)
+ .from(Integer.class).serializeSource(i -> i).parseSource(i -> (Integer) i)
+ .parseValue((v, d) -> DayOfWeek.of(v))
+ .serializeValue(DayOfWeek::getValue)
+ .defaults(DayOfWeek.MONDAY).build();
+
@HeaderComment({"奖励相关设定,包含以下设定:",
" [id] 配置键名即奖励ID,支持英文、数字与下划线。",
" | 确定后请不要更改,因为该键值用于存储玩家是否领取的数据",
@@ -38,11 +46,11 @@ public class PluginConfig extends ConfigurationRoot {
" [auto] 该奖励是否自动领取,可以不设置,默认为true。",
" | 若关闭自动领取,则需要玩家手动输入/tr claim 领取奖励。",
})
- public static final ConfigValue REWARDS = ConfigValue.builder()
- .asValue(RewardContents.Group.class).fromSection()
- .parseValue((v, d) -> RewardContents.Group.parse(v))
- .serializeValue(RewardContents.Group::serialize)
- .defaults(RewardContents.Group.defaults())
+ public static final ConfigValue REWARDS = ConfigValue.builder()
+ .asValue(RewardsConfig.RewardGroup.class).fromSection()
+ .parseValue((v, d) -> RewardsConfig.RewardGroup.parse(v))
+ .serializeValue(RewardsConfig.RewardGroup::serialize)
+ .defaults(RewardsConfig.RewardGroup.defaults())
.build();
}
diff --git a/src/main/java/cc/carm/plugin/timereward/conf/RewardsConfig.java b/src/main/java/cc/carm/plugin/timereward/conf/RewardsConfig.java
new file mode 100644
index 0000000..3b6ced7
--- /dev/null
+++ b/src/main/java/cc/carm/plugin/timereward/conf/RewardsConfig.java
@@ -0,0 +1,90 @@
+package cc.carm.plugin.timereward.conf;
+
+import cc.carm.lib.configuration.core.ConfigurationRoot;
+import cc.carm.lib.configuration.core.annotation.HeaderComment;
+import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
+import cc.carm.lib.configuration.core.value.ConfigValue;
+import cc.carm.plugin.timereward.data.RewardContents;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+@HeaderComment({"奖励相关设定,包含以下设定:",
+ " [id] 配置键名即奖励ID,支持英文、数字与下划线。",
+ " | 确定后请不要更改,因为该键值用于存储玩家是否领取的数据",
+ " | 如果更改,原先领取过该奖励的玩家将会自动再领取一次!",
+ " [name] 奖励的显示名称,可以是任意字符串",
+ " | 可以在 commands 中使用 %(name) 来获取该奖励的名称",
+ " | 也可以使用变量 %TimeReward_reward_<奖励ID>% 来获取对应奖励的名称",
+ " [permission] 领取奖励时后台执行的指令",
+ " | 支持PlaceholderAPI变量,指令中可以使用 %(name) 来获取该奖励的名称。",
+ " [commands] 该奖励领取权限,可以不设置。",
+ " | 若为空则所有人都可以领取;若不为空,则需要拥有该权限的玩家才能领取。",
+ " [auto] 该奖励是否自动领取,可以不设置,默认为true。",
+ " | 若关闭自动领取,则需要玩家手动输入/tr claim 领取奖励。",
+})
+public class RewardsConfig extends ConfigurationRoot {
+
+ @HeaderComment("每日在线时长的奖励")
+ public static final ConfigValue DAILY = create();
+
+ @HeaderComment("每周在线时长的奖励")
+ public static final ConfigValue WEEKLY = create();
+
+ @HeaderComment("每月在线时长的奖励")
+ public static final ConfigValue MONTHLY = create();
+
+ @HeaderComment("总在线时长的奖励")
+ public static final ConfigValue TOTAL = create();
+
+ private static ConfigValue create() {
+ return ConfigValue.builder()
+ .asValue(RewardGroup.class).fromSection()
+ .parseValue((v, d) -> RewardGroup.parse(v))
+ .serializeValue(RewardGroup::serialize)
+ .defaults(RewardGroup.defaults())
+ .build();
+ }
+
+ public static final class RewardGroup {
+ final @NotNull Map contents;
+
+ public RewardGroup(@NotNull Map contents) {
+ this.contents = contents;
+ }
+
+ public @NotNull Map getContents() {
+ return contents;
+ }
+
+ public Map serialize() {
+ Map map = new LinkedHashMap<>();
+ for (Map.Entry entry : contents.entrySet()) {
+ map.put(entry.getKey(), entry.getValue().serialize());
+ }
+ return map;
+ }
+
+ public static RewardGroup parse(@NotNull ConfigurationWrapper> section) {
+ Map rewards = new LinkedHashMap<>();
+ for (String rewardID : section.getKeys(false)) {
+ ConfigurationWrapper> rewardSection = section.getConfigurationSection(rewardID);
+ if (rewardSection == null) continue;
+
+ RewardContents c = RewardContents.parse(rewardID, rewardSection);
+ if (c == null) continue;
+ rewards.put(rewardID, c);
+ }
+ return new RewardGroup(rewards);
+ }
+
+ public static RewardGroup defaults() {
+ Map rewards = new LinkedHashMap<>();
+ rewards.put("example", RewardContents.defaults("example"));
+ return new RewardGroup(rewards);
+ }
+
+ }
+
+}
diff --git a/src/main/java/cc/carm/plugin/timereward/storage/RewardContents.java b/src/main/java/cc/carm/plugin/timereward/data/RewardContents.java
similarity index 68%
rename from src/main/java/cc/carm/plugin/timereward/storage/RewardContents.java
rename to src/main/java/cc/carm/plugin/timereward/data/RewardContents.java
index 69e123f..86276ea 100644
--- a/src/main/java/cc/carm/plugin/timereward/storage/RewardContents.java
+++ b/src/main/java/cc/carm/plugin/timereward/data/RewardContents.java
@@ -1,4 +1,4 @@
-package cc.carm.plugin.timereward.storage;
+package cc.carm.plugin.timereward.data;
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
import cc.carm.lib.easyplugin.utils.ColorParser;
@@ -116,44 +116,6 @@ public class RewardContents {
return Objects.hash(id);
}
- public static final class Group {
- final @NotNull Map contents;
- public Group(@NotNull Map contents) {
- this.contents = contents;
- }
-
- public @NotNull Map getContents() {
- return contents;
- }
-
- public Map serialize() {
- Map map = new LinkedHashMap<>();
- for (Map.Entry entry : contents.entrySet()) {
- map.put(entry.getKey(), entry.getValue().serialize());
- }
- return map;
- }
-
- public static Group parse(@NotNull ConfigurationWrapper> section) {
- Map rewards = new LinkedHashMap<>();
- for (String rewardID : section.getKeys(false)) {
- ConfigurationWrapper> rewardSection = section.getConfigurationSection(rewardID);
- if (rewardSection == null) continue;
-
- RewardContents c = RewardContents.parse(rewardID, rewardSection);
- if (c == null) continue;
- rewards.put(rewardID, c);
- }
- return new Group(rewards);
- }
-
- public static Group defaults() {
- Map rewards = new LinkedHashMap<>();
- rewards.put("example", RewardContents.defaults("example"));
- return new Group(rewards);
- }
-
- }
}
diff --git a/src/main/java/cc/carm/plugin/timereward/data/TimeRecord.java b/src/main/java/cc/carm/plugin/timereward/data/TimeRecord.java
new file mode 100644
index 0000000..e9293ef
--- /dev/null
+++ b/src/main/java/cc/carm/plugin/timereward/data/TimeRecord.java
@@ -0,0 +1,63 @@
+package cc.carm.plugin.timereward.data;
+
+import cc.carm.plugin.timereward.conf.PluginConfig;
+import org.jetbrains.annotations.NotNull;
+
+import java.time.LocalDate;
+import java.time.temporal.TemporalField;
+import java.time.temporal.WeekFields;
+
+public class TimeRecord {
+
+ protected final @NotNull LocalDate date;
+
+ protected final int daily;
+ protected final int weekly;
+ protected final int monthly;
+
+ protected final int total;
+
+ public TimeRecord(@NotNull LocalDate date, int daily, int weekly, int monthly, int total) {
+ this.date = date;
+ this.daily = daily;
+ this.weekly = weekly;
+ this.monthly = monthly;
+ this.total = total;
+ }
+
+ public @NotNull LocalDate getDate() {
+ return date;
+ }
+
+ public int getDailyTime() {
+ return isDayUpdated() ? 0 : daily;
+ }
+
+ public int getWeeklyTime() {
+ return isWeekUpdated() ? 0 : weekly;
+ }
+
+ public int getMonthlyTime() {
+ return isMonthUpdated() ? 0 : monthly;
+ }
+
+ public boolean isDayUpdated() {
+ return !LocalDate.now().equals(getDate());
+ }
+
+ public boolean isWeekUpdated() {
+ if (!isDayUpdated()) return false; // Same day always same week
+
+ TemporalField woy = WeekFields.of(PluginConfig.WEEK_FIRST_DAY.getNotNull(), 4).weekOfWeekBasedYear();
+ return getDate().get(woy) != LocalDate.now().get(woy);
+ }
+
+ public boolean isMonthUpdated() {
+ if (!isDayUpdated()) return false; // Same day always same month
+
+ // Predicate current month is after the month of the date
+ return LocalDate.now().getMonth().compareTo(getDate().getMonth()) > 0;
+ }
+
+
+}
diff --git a/src/main/java/cc/carm/plugin/timereward/storage/UserData.java b/src/main/java/cc/carm/plugin/timereward/data/UserData.java
similarity index 98%
rename from src/main/java/cc/carm/plugin/timereward/storage/UserData.java
rename to src/main/java/cc/carm/plugin/timereward/data/UserData.java
index 360d789..fce996e 100644
--- a/src/main/java/cc/carm/plugin/timereward/storage/UserData.java
+++ b/src/main/java/cc/carm/plugin/timereward/data/UserData.java
@@ -1,4 +1,4 @@
-package cc.carm.plugin.timereward.storage;
+package cc.carm.plugin.timereward.data;
import org.jetbrains.annotations.NotNull;
diff --git a/src/main/java/cc/carm/plugin/timereward/hooker/PAPIExpansion.java b/src/main/java/cc/carm/plugin/timereward/hooker/PAPIExpansion.java
index 25d126b..ff4537e 100644
--- a/src/main/java/cc/carm/plugin/timereward/hooker/PAPIExpansion.java
+++ b/src/main/java/cc/carm/plugin/timereward/hooker/PAPIExpansion.java
@@ -3,8 +3,8 @@ package cc.carm.plugin.timereward.hooker;
import cc.carm.lib.easyplugin.papi.EasyPlaceholder;
import cc.carm.lib.easyplugin.papi.handler.PlaceholderHandler;
import cc.carm.plugin.timereward.TimeRewardAPI;
-import cc.carm.plugin.timereward.storage.RewardContents;
-import cc.carm.plugin.timereward.storage.UserData;
+import cc.carm.plugin.timereward.data.RewardContents;
+import cc.carm.plugin.timereward.data.UserData;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
diff --git a/src/main/java/cc/carm/plugin/timereward/manager/RewardManager.java b/src/main/java/cc/carm/plugin/timereward/manager/RewardManager.java
index 2517dcc..6aed813 100644
--- a/src/main/java/cc/carm/plugin/timereward/manager/RewardManager.java
+++ b/src/main/java/cc/carm/plugin/timereward/manager/RewardManager.java
@@ -4,8 +4,8 @@ import cc.carm.lib.easyplugin.utils.MessageUtils;
import cc.carm.plugin.timereward.Main;
import cc.carm.plugin.timereward.TimeRewardAPI;
import cc.carm.plugin.timereward.conf.PluginConfig;
-import cc.carm.plugin.timereward.storage.RewardContents;
-import cc.carm.plugin.timereward.storage.UserData;
+import cc.carm.plugin.timereward.data.RewardContents;
+import cc.carm.plugin.timereward.data.UserData;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
diff --git a/src/main/java/cc/carm/plugin/timereward/manager/UserManager.java b/src/main/java/cc/carm/plugin/timereward/manager/UserManager.java
index 31226d8..9dea736 100644
--- a/src/main/java/cc/carm/plugin/timereward/manager/UserManager.java
+++ b/src/main/java/cc/carm/plugin/timereward/manager/UserManager.java
@@ -2,7 +2,7 @@ package cc.carm.plugin.timereward.manager;
import cc.carm.plugin.timereward.Main;
import cc.carm.plugin.timereward.util.DataTaskRunner;
-import cc.carm.plugin.timereward.storage.UserData;
+import cc.carm.plugin.timereward.data.UserData;
import cc.carm.plugin.timereward.storage.database.MySQLStorage;
import com.google.common.collect.ImmutableMap;
import org.bukkit.Bukkit;
diff --git a/src/main/java/cc/carm/plugin/timereward/storage/database/DatabaseTables.java b/src/main/java/cc/carm/plugin/timereward/storage/database/DatabaseTables.java
index 2056534..19d1e7d 100644
--- a/src/main/java/cc/carm/plugin/timereward/storage/database/DatabaseTables.java
+++ b/src/main/java/cc/carm/plugin/timereward/storage/database/DatabaseTables.java
@@ -15,16 +15,21 @@ public enum DatabaseTables implements SQLTable {
/**
* 用于记录用户在线时间的表
*/
- USER_TIMES(DatabaseConfig.TABLES.USER_TIMES, (table) -> {
+ USER_TIMES(DatabaseConfig.TABLES.USER_TIMES, table -> {
table.addColumn("uuid", "CHAR(36) NOT NULL PRIMARY KEY"); // 用户的UUID
+ table.addColumn("date", "DATE NOT NULL"); // 日期
- table.addColumn("time", "INT UNSIGNED NOT NULL DEFAULT 0"); // 用户在线时间(秒)
+ table.addColumn("day_time", "MEDIUMINT UNSIGNED NOT NULL DEFAULT 0"); // 用户日在线时间(秒)
+ table.addColumn("week_time", "MEDIUMINT UNSIGNED NOT NULL DEFAULT 0"); // 用户周在线时间(秒)
+ table.addColumn("month_time", "INT UNSIGNED NOT NULL DEFAULT 0"); // 用户月在线时间(秒)
+ table.addColumn("total_time", "INT UNSIGNED NOT NULL DEFAULT 0"); // 用户总在线时间(秒)
table.addColumn("update",
"DATETIME NOT NULL " +
- "DEFAULT CURRENT_TIMESTAMP " +
- "ON UPDATE CURRENT_TIMESTAMP"
+ "DEFAULT CURRENT_TIMESTAMP " +
+ "ON UPDATE CURRENT_TIMESTAMP"
);
+
}),
/**
@@ -35,12 +40,7 @@ public enum DatabaseTables implements SQLTable {
table.addColumn("uuid", "CHAR(36) NOT NULL PRIMARY KEY"); // 用户的UUID 主键
table.addColumn("value", "MEDIUMTEXT"); // 已领取的奖励ID
-
- table.addColumn("update",
- "DATETIME NOT NULL " +
- "DEFAULT CURRENT_TIMESTAMP " +
- "ON UPDATE CURRENT_TIMESTAMP"
- );
+ table.addColumn("time", "DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP"); // 领取时间
});
private final Consumer builder;
diff --git a/src/main/java/cc/carm/plugin/timereward/storage/database/MySQLStorage.java b/src/main/java/cc/carm/plugin/timereward/storage/database/MySQLStorage.java
index 3d3cb4e..e99553e 100644
--- a/src/main/java/cc/carm/plugin/timereward/storage/database/MySQLStorage.java
+++ b/src/main/java/cc/carm/plugin/timereward/storage/database/MySQLStorage.java
@@ -3,7 +3,7 @@ package cc.carm.plugin.timereward.storage.database;
import cc.carm.lib.easysql.EasySQL;
import cc.carm.lib.easysql.api.SQLManager;
import cc.carm.plugin.timereward.Main;
-import cc.carm.plugin.timereward.storage.UserData;
+import cc.carm.plugin.timereward.data.UserData;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
diff --git a/src/test/java/TimeTest.java b/src/test/java/TimeTest.java
new file mode 100644
index 0000000..74b0674
--- /dev/null
+++ b/src/test/java/TimeTest.java
@@ -0,0 +1,57 @@
+import org.jetbrains.annotations.NotNull;
+import org.junit.Test;
+
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.time.temporal.TemporalField;
+import java.time.temporal.WeekFields;
+
+public class TimeTest {
+
+ LocalDate date = LocalDate.of(2023, 8, 30);
+
+ @Test
+ public void test() {
+
+ LocalDate date1 = LocalDate.of(2023, 9, 2);
+ LocalDate date2 = LocalDate.of(2023, 8, 28);
+ LocalDate date3 = LocalDate.of(2023, 8, 27);
+
+ System.out.println(isDayUpdated(date1));
+ System.out.println(isWeekUpdated(date1));
+ System.out.println(isMonthUpdated(date1));
+
+ System.out.println(isDayUpdated(date2));
+ System.out.println(isWeekUpdated(date2));
+ System.out.println(isMonthUpdated(date2));
+
+ System.out.println(isDayUpdated(date3));
+ System.out.println(isWeekUpdated(date3));
+ System.out.println(isMonthUpdated(date3));
+
+ System.out.println(isDayUpdated(date));
+
+ }
+
+ public @NotNull LocalDate getDate() {
+ return date;
+ }
+
+ public boolean isDayUpdated(LocalDate d) {
+ return !d.equals(getDate());
+ }
+
+ public boolean isWeekUpdated(LocalDate d) {
+ if (!isDayUpdated(d)) return false; // Same day always same week
+
+ TemporalField woy = WeekFields.of(DayOfWeek.MONDAY, 4).weekOfWeekBasedYear();
+ return getDate().get(woy) != d.get(woy);
+ }
+
+ public boolean isMonthUpdated(LocalDate d) {
+ if (!isDayUpdated(d)) return false; // Same day always same month
+
+ // Predicate current month is after the month of the date
+ return d.getMonth().compareTo(getDate().getMonth()) > 0;
+ }
+}