commit d7898e333f8612dc003f9ad3594b4c02f20a5c04 Author: Kyoukawa Meishin Date: Fri Oct 17 15:34:37 2025 +0800 完成PlayerExpSystem diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..480bdf5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,39 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ +.kotlin + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..359bb53 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..eda147d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..abe542d --- /dev/null +++ b/pom.xml @@ -0,0 +1,42 @@ + + 4.0.0 + com.mmlsystem + PlayerExpSystem + 1.0.1 + + + + central + https://repo.maven.apache.org/maven2/ + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + jitpack-io + https://jitpack.io/ + + + + + + org.spigotmc + spigot-api + 1.21.8-R0.1-SNAPSHOT + provided + + + com.github.MilkBowl + VaultAPI + 1.7 + provided + + + org.jetbrains + annotations + 24.1.0 + compile + + + diff --git a/src/main/java/com/mmlsystem/PlayerExpSystem/Foundation.java b/src/main/java/com/mmlsystem/PlayerExpSystem/Foundation.java new file mode 100644 index 0000000..b87a86a --- /dev/null +++ b/src/main/java/com/mmlsystem/PlayerExpSystem/Foundation.java @@ -0,0 +1,68 @@ +package com.mmlsystem.PlayerExpSystem; + +import org.bukkit.Bukkit; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.File; +import java.sql.*; + +public class Foundation extends JavaPlugin { + + private Connection connection; + private SaveManager manager; + + @Override + public void onEnable() { + getLogger().info("世界上有10种人:"); + getLogger().info("一种是了解三进制的"); + getLogger().info("一种是不了解三进制的"); + getLogger().info("还有一种是觉得这是个二进制笑话的"); + setupDatabase(); + PlayerJoinListener listener = new PlayerJoinListener(this); + manager = new SaveManager(this, listener); + Bukkit.getServer().getPluginManager().registerEvents(listener, this); + Bukkit.getScheduler().scheduleSyncRepeatingTask(this, () -> { + manager.saveAllPlayers(); + }, 1200L, 1200L); + getLogger().info("插件启用成功。"); + } + + @Override + public void onDisable() { + closeDatabase(); + } + + public Connection getConnection() { + return connection; + } + + public void setupDatabase() { + try { + File dbFile = new File(getDataFolder(), "players.db"); + if (!dbFile.getParentFile().exists()) dbFile.getParentFile().mkdirs(); + + connection = DriverManager.getConnection("jdbc:sqlite:" + dbFile.getAbsolutePath()); + Statement stmt = connection.createStatement(); + stmt.executeUpdate("CREATE TABLE IF NOT EXISTS playtime (" + + "uuid TEXT PRIMARY KEY, " + + "name TEXT, " + + "total BIGINT DEFAULT 0" + + ")"); + getLogger().info("初始化SQLite数据库成功。"); + } catch (SQLException e) { + getLogger().severe(e.getMessage()); + getLogger().severe("无法连接SQLite数据库!"); + getServer().getPluginManager().disablePlugin(this); + } + } + + private void closeDatabase() { + try { + if (connection != null && !connection.isClosed()) + connection.close(); + } catch (SQLException e) { + getLogger().severe(e.getMessage()); + } + getLogger().info("插件禁用成功。"); + } +} diff --git a/src/main/java/com/mmlsystem/PlayerExpSystem/PlayerJoinListener.java b/src/main/java/com/mmlsystem/PlayerExpSystem/PlayerJoinListener.java new file mode 100644 index 0000000..ed88bf4 --- /dev/null +++ b/src/main/java/com/mmlsystem/PlayerExpSystem/PlayerJoinListener.java @@ -0,0 +1,62 @@ +package com.mmlsystem.PlayerExpSystem; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class PlayerJoinListener implements Listener { + + private final Connection connection; + public final Map joinTimes = new HashMap<>(); + private final Foundation plugin; + + public PlayerJoinListener(Foundation plugin) { + this.connection = plugin.getConnection(); + this.plugin = plugin; + } + + @EventHandler + public void onJoin(PlayerJoinEvent e) { + joinTimes.put(e.getPlayer().getUniqueId(), System.currentTimeMillis()); + } + + @EventHandler + public void onQuit(PlayerQuitEvent e) { + Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + savePlayer(e.getPlayer()); + }); + joinTimes.remove(e.getPlayer().getUniqueId()); + } + + public boolean savePlayer(Player player) { + long joinTime = joinTimes.getOrDefault(player.getUniqueId(), System.currentTimeMillis()); + long session = System.currentTimeMillis() - joinTime; + + try (PreparedStatement ps = connection.prepareStatement( + "INSERT INTO playtime (uuid, name, total) VALUES (?, ?, ?) " + + "ON CONFLICT(uuid) DO UPDATE SET " + + "name = excluded.name, total = total + excluded.total")) { + ps.setString(1, player.getUniqueId().toString()); + ps.setString(2, player.getName()); + ps.setLong(3, session); + ps.executeUpdate(); + ps.close(); + joinTimes.put(player.getUniqueId(), System.currentTimeMillis()); + return true; + } catch (SQLException e) { + plugin.getLogger().severe(e.getMessage()); + plugin.getLogger().severe("试图保存玩家" + player.getName() + "的在线时长时发生错误。"); + return false; + } + } +} diff --git a/src/main/java/com/mmlsystem/PlayerExpSystem/SaveManager.java b/src/main/java/com/mmlsystem/PlayerExpSystem/SaveManager.java new file mode 100644 index 0000000..cb6e1a7 --- /dev/null +++ b/src/main/java/com/mmlsystem/PlayerExpSystem/SaveManager.java @@ -0,0 +1,30 @@ +package com.mmlsystem.PlayerExpSystem; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +public class SaveManager { + private final Foundation foundation; + private final PlayerJoinListener listener; + + public SaveManager(Foundation foundation, PlayerJoinListener listener) { + this.foundation = foundation; + this.listener = listener; + } + + public void saveAllPlayers() { + boolean isFail = false; + for (Player player : Bukkit.getOnlinePlayers()) { + if (!listener.savePlayer(player)) { + isFail = true; + } + listener.joinTimes.put(player.getUniqueId(), System.currentTimeMillis()); + } + if (isFail) { + foundation.getLogger().warning("已完成自动保存例程,但发生了错误。"); + } + else { + foundation.getLogger().info("已完成自动保存例程。"); + } + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..55ebf3b --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,6 @@ +name: PlayerExpSystem +main: com.mmlsystem.PlayerExpSystem.Foundation +version: 1.0.1 +api-version: 1.21 +author: 杏川铭心 +description: 提供服务器计分板UI功能。 \ No newline at end of file