From 1204423f2c6a02f6f84e9c22811159483ebff304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Bro=C4=8Dko?= Date: Fri, 12 Oct 2018 21:49:10 +0200 Subject: [PATCH] split stats and sessions --- Auth/.classpath | 21 +++++++ Auth/.gitignore | 2 + Auth/.project | 23 ++++++++ Auth/.settings/org.eclipse.jdt.core.prefs | 13 +++++ Auth/.settings/org.eclipse.m2e.core.prefs | 4 ++ Auth/pom.xml | 56 +++++++++++++++++++ Auth/resources/create.sql | 12 ++++ Auth/resources/session.sql | 7 +++ Auth/src/cz/marwland/mc/features/Auth.java | 56 +++++++++++++++++++ .../mc/features/auth}/PlayerSession.java | 18 +----- .../mc/features/auth}/SessionManager.java | 4 +- Stats/resources/create.sql | 7 +-- Stats/resources/session.sql | 9 --- Stats/resources/stats.sql | 7 +++ Stats/src/cz/marwland/mc/features/Stats.java | 52 ++++++++++++++--- .../mc/features/stats/IStatsSaver.java | 9 +++ .../mc/features/stats/PlayerStats.java | 41 ++++++++++++++ .../mc/features/stats/SQLStatsSaver.java | 55 ++++++++++++++++++ 18 files changed, 354 insertions(+), 42 deletions(-) create mode 100644 Auth/.classpath create mode 100644 Auth/.gitignore create mode 100644 Auth/.project create mode 100644 Auth/.settings/org.eclipse.jdt.core.prefs create mode 100644 Auth/.settings/org.eclipse.m2e.core.prefs create mode 100644 Auth/pom.xml create mode 100644 Auth/resources/create.sql create mode 100644 Auth/resources/session.sql create mode 100644 Auth/src/cz/marwland/mc/features/Auth.java rename {Stats/src/cz/marwland/mc/features/stats => Auth/src/cz/marwland/mc/features/auth}/PlayerSession.java (72%) rename {Stats/src/cz/marwland/mc/features/stats => Auth/src/cz/marwland/mc/features/auth}/SessionManager.java (98%) delete mode 100644 Stats/resources/session.sql create mode 100644 Stats/resources/stats.sql create mode 100644 Stats/src/cz/marwland/mc/features/stats/IStatsSaver.java create mode 100644 Stats/src/cz/marwland/mc/features/stats/PlayerStats.java create mode 100644 Stats/src/cz/marwland/mc/features/stats/SQLStatsSaver.java diff --git a/Auth/.classpath b/Auth/.classpath new file mode 100644 index 0000000..e18f43d --- /dev/null +++ b/Auth/.classpath @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Auth/.gitignore b/Auth/.gitignore new file mode 100644 index 0000000..09e3bc9 --- /dev/null +++ b/Auth/.gitignore @@ -0,0 +1,2 @@ +/bin/ +/target/ diff --git a/Auth/.project b/Auth/.project new file mode 100644 index 0000000..7bf3573 --- /dev/null +++ b/Auth/.project @@ -0,0 +1,23 @@ + + + Auth + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + org.eclipse.jdt.core.javanature + + diff --git a/Auth/.settings/org.eclipse.jdt.core.prefs b/Auth/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..43c686f --- /dev/null +++ b/Auth/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,13 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=10 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=10 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=10 diff --git a/Auth/.settings/org.eclipse.m2e.core.prefs b/Auth/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/Auth/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/Auth/pom.xml b/Auth/pom.xml new file mode 100644 index 0000000..dab4375 --- /dev/null +++ b/Auth/pom.xml @@ -0,0 +1,56 @@ + + 4.0.0 + cz.marwland.mc.features + Auth + + cz.marwland.mc + MarwStuff + 0.0.1-SNAPSHOT + ../../MarwStuff + + + src + + + maven-compiler-plugin + 3.7.0 + + 10 + + + + exec-maven-plugin + 1.6.0 + org.codehaus.mojo + + + deploy + + exec + + + + + ${project.parent.basedir}/deploy_feature.sh + + ${project.build.directory}/${project.build.finalName}.jar + ${project.artifactId} + + + + + maven-resources-plugin + + ${project.build.outputDirectory}/resources + + + + + + + cz.marwland.mc + MarwCore + ${project.parent.version} + + + \ No newline at end of file diff --git a/Auth/resources/create.sql b/Auth/resources/create.sql new file mode 100644 index 0000000..13da9a3 --- /dev/null +++ b/Auth/resources/create.sql @@ -0,0 +1,12 @@ +CREATE TABLE IF NOT EXISTS `{prefix}sessions` ( + `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, + `server` bigint UNSIGNED NOT NULL, + `uuid` binary(16) NOT NULL, + `serverNick` varchar(32) NOT NULL, + `ip` int UNSIGNED NOT NULL, + `date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `playtime` mediumint UNSIGNED DEFAULT 0, + `server` + PRIMARY KEY `id` (`id`), + UNIQUE KEY `date_player` (`uuid`, `date`) +) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/Auth/resources/session.sql b/Auth/resources/session.sql new file mode 100644 index 0000000..223db4d --- /dev/null +++ b/Auth/resources/session.sql @@ -0,0 +1,7 @@ +INSERT INTO `{prefix}sessions` + (`uuid`, `server`, `serverNick`, `ip`, `date`, `playtime`) VALUES + (?, ?, ?, ?, ?, ?, ?, ?) + ON DUPLICATE KEY + UPDATE + `playtime` = `playtime` + VALUES(`playtime`), + `date` = VALUES(`date`); \ No newline at end of file diff --git a/Auth/src/cz/marwland/mc/features/Auth.java b/Auth/src/cz/marwland/mc/features/Auth.java new file mode 100644 index 0000000..1fe51ab --- /dev/null +++ b/Auth/src/cz/marwland/mc/features/Auth.java @@ -0,0 +1,56 @@ +package cz.marwland.mc.features; + +import java.io.IOException; +import java.sql.SQLException; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +import cz.marwland.mc.core.MarwCore; +import cz.marwland.mc.core.features.Feature; +import cz.marwland.mc.core.storage.SQLStorage; +import cz.marwland.mc.features.auth.SessionManager; + +public class Auth extends Feature { + + private final SQLStorage database = MarwCore.getInstance().getStorage(); + public SessionManager manager; + + public Auth() { + super(); + manager = new SessionManager(); + } + + @Override + public void onEnable() { + super.onEnable(); + createTables(); + manager.start(); + } + + @Override + public void onDisable() { + super.onDisable(); + manager.shutdown(); + } + + public void createTables() { + try { + database.executeRaw(this.getClass().getResourceAsStream("/resources/create.sql")); + } catch (SQLException | IOException e) { + e.printStackTrace(); + } + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + manager.startPlayer(event.getPlayer()); + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) { + manager.endPlayer(event.getPlayer()); + } + +} diff --git a/Stats/src/cz/marwland/mc/features/stats/PlayerSession.java b/Auth/src/cz/marwland/mc/features/auth/PlayerSession.java similarity index 72% rename from Stats/src/cz/marwland/mc/features/stats/PlayerSession.java rename to Auth/src/cz/marwland/mc/features/auth/PlayerSession.java index 34ae37c..4c24aea 100644 --- a/Stats/src/cz/marwland/mc/features/stats/PlayerSession.java +++ b/Auth/src/cz/marwland/mc/features/auth/PlayerSession.java @@ -1,4 +1,4 @@ -package cz.marwland.mc.features.stats; +package cz.marwland.mc.features.auth; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -14,8 +14,6 @@ public class PlayerSession { private Player player; private volatile long lastRecorded = 0; - private volatile int killsSinceRecord = 0; - private volatile int deathsSinceRecord = 0; private java.sql.Timestamp dateJoined; private int ipAddress; @@ -43,26 +41,12 @@ public class PlayerSession { prepst.setString(i++, player.getName()); // serverNick prepst.setInt(i++, this.ipAddress); // ip prepst.setTimestamp(i++, this.dateJoined); // date - prepst.setInt(i++, this.killsSinceRecord); // kills - prepst.setInt(i++, this.deathsSinceRecord); // deaths prepst.setLong(i++, playtime); // playtime prepst.addBatch(); - System.out.println("Recording: " + this.dateJoined + ", " + playtime); } catch (SQLException e) { - // TODO: Notify admins about errors. e.printStackTrace(); } this.lastRecorded = System.currentTimeMillis(); - this.killsSinceRecord = 0; - this.deathsSinceRecord = 0; - } - - public void addKill() { - this.killsSinceRecord++; - } - - public void addDeath() { - this.deathsSinceRecord++; } } diff --git a/Stats/src/cz/marwland/mc/features/stats/SessionManager.java b/Auth/src/cz/marwland/mc/features/auth/SessionManager.java similarity index 98% rename from Stats/src/cz/marwland/mc/features/stats/SessionManager.java rename to Auth/src/cz/marwland/mc/features/auth/SessionManager.java index 8b528fd..21248ee 100644 --- a/Stats/src/cz/marwland/mc/features/stats/SessionManager.java +++ b/Auth/src/cz/marwland/mc/features/auth/SessionManager.java @@ -1,4 +1,4 @@ -package cz.marwland.mc.features.stats; +package cz.marwland.mc.features.auth; import java.io.IOException; import java.sql.Connection; @@ -71,7 +71,7 @@ public class SessionManager { } private void recordSessions() { - try (Connection conn = this.database.getConnectionFactory().getConnection();) { + try (Connection conn = this.database.getConnectionFactory().getConnection()) { PreparedStatement prepst = conn.prepareStatement(this.sessionQuery); int i = 0; for (PlayerSession ps : this.sessions.values()) { diff --git a/Stats/resources/create.sql b/Stats/resources/create.sql index 1d32f43..a4ffa41 100644 --- a/Stats/resources/create.sql +++ b/Stats/resources/create.sql @@ -1,12 +1,9 @@ -CREATE TABLE IF NOT EXISTS `{prefix}sessions` ( +CREATE TABLE IF NOT EXISTS `{prefix}stats` ( `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, `uuid` binary(16) NOT NULL, - `serverNick` varchar(32) NOT NULL, - `ip` int UNSIGNED NOT NULL, - `date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `date` date NOT NULL, `kills` int DEFAULT 0, `deaths` int UNSIGNED DEFAULT 0, - `playtime` mediumint UNSIGNED DEFAULT 0, PRIMARY KEY `id` (`id`), UNIQUE KEY `date_player` (`uuid`, `date`) ) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/Stats/resources/session.sql b/Stats/resources/session.sql deleted file mode 100644 index 16b451d..0000000 --- a/Stats/resources/session.sql +++ /dev/null @@ -1,9 +0,0 @@ -INSERT INTO `{prefix}sessions` - (`uuid`, `serverNick`, `ip`, `date`, `kills`, `deaths`, `playtime`) VALUES - (?, ?, ?, ?, ?, ?, ?) - ON DUPLICATE KEY - UPDATE - `kills` = `kills` + VALUES(`kills`), - `deaths` = `deaths` + VALUES(`deaths`), - `playtime` = `playtime` + VALUES(`playtime`), - `date` = VALUES(`date`); \ No newline at end of file diff --git a/Stats/resources/stats.sql b/Stats/resources/stats.sql new file mode 100644 index 0000000..abb06c0 --- /dev/null +++ b/Stats/resources/stats.sql @@ -0,0 +1,7 @@ +INSERT INTO `{prefix}stats` + (`uuid`, `date`, `kills`, `deaths`) VALUES + (?, ?, ?, ?) + ON DUPLICATE KEY + UPDATE + `kills` = `kills` + VALUES(`kills`), + `deaths` = `deaths` + VALUES(`deaths`); \ No newline at end of file diff --git a/Stats/src/cz/marwland/mc/features/Stats.java b/Stats/src/cz/marwland/mc/features/Stats.java index 285ac59..e510415 100644 --- a/Stats/src/cz/marwland/mc/features/Stats.java +++ b/Stats/src/cz/marwland/mc/features/Stats.java @@ -3,6 +3,9 @@ package cz.marwland.mc.features; import java.io.IOException; import java.sql.SQLException; import java.util.Arrays; +import java.util.HashMap; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; import org.bukkit.command.CommandSender; import org.bukkit.command.defaults.BukkitCommand; @@ -16,12 +19,17 @@ import org.bukkit.event.player.PlayerQuitEvent; import cz.marwland.mc.core.MarwCore; import cz.marwland.mc.core.features.Feature; import cz.marwland.mc.core.storage.SQLStorage; -import cz.marwland.mc.features.stats.SessionManager; +import cz.marwland.mc.features.stats.IStatsSaver; +import cz.marwland.mc.features.stats.PlayerStats; +import cz.marwland.mc.features.stats.SQLStatsSaver; public class Stats extends Feature { private final SQLStorage database = MarwCore.getInstance().getStorage(); - public SessionManager manager; + private HashMap tracked = new HashMap<>(); + private IStatsSaver saver; + private final long WRITE_PERIOD = 15; + private ScheduledFuture recordTask; public Stats() { super(); @@ -40,20 +48,30 @@ public class Stats extends Feature { return getPermissionPath(); } }); - manager = new SessionManager(); } @Override public void onEnable() { super.onEnable(); createTables(); - manager.start(); + try { + saver = new SQLStatsSaver(); + } catch (IOException e) { + e.printStackTrace(); + } + recordTask = MarwCore.getInstance().getStorageExecutor().scheduleAtFixedRate(() -> this.save(), WRITE_PERIOD, WRITE_PERIOD, TimeUnit.SECONDS); + for (Player p : MarwCore.getInstance().getServer().getOnlinePlayers()) { + this.startPlayer(p); + } } @Override public void onDisable() { + recordTask.cancel(false); + for (Player p : MarwCore.getInstance().getServer().getOnlinePlayers()) { + this.endPlayer(p); + } super.onDisable(); - manager.shutdown(); } public void createTables() { @@ -66,24 +84,40 @@ public class Stats extends Feature { @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { - manager.startPlayer(event.getPlayer()); + this.startPlayer(event.getPlayer()); } @EventHandler public void onPlayerQuit(PlayerQuitEvent event) { - manager.endPlayer(event.getPlayer()); + this.endPlayer(event.getPlayer()); } @EventHandler public void onPlayerDeath(PlayerDeathEvent event) { - this.manager.getPlayerSession(event.getEntity()).addDeath(); + this.getTracker(event.getEntity()).addDeath(); Entity killerEntity = event.getEntity().getLastDamageCause().getEntity(); if (killerEntity instanceof Player) { Player killerPlayer = (Player) killerEntity; if (!killerPlayer.equals(killerEntity) && killerPlayer.isOnline()) - this.manager.getPlayerSession(killerPlayer).addKill(); + this.getTracker(killerPlayer).addKill(); } } + + public void startPlayer(Player player) { + this.tracked.put(player, new PlayerStats(player)); + } + + public void endPlayer(Player player) { + this.tracked.remove(player); + } + + public PlayerStats getTracker(Player player) { + return this.tracked.get(player); + } + + public void save() { + saver.save(this.tracked.values()); + } } diff --git a/Stats/src/cz/marwland/mc/features/stats/IStatsSaver.java b/Stats/src/cz/marwland/mc/features/stats/IStatsSaver.java new file mode 100644 index 0000000..b0fc05d --- /dev/null +++ b/Stats/src/cz/marwland/mc/features/stats/IStatsSaver.java @@ -0,0 +1,9 @@ +package cz.marwland.mc.features.stats; + +import java.util.Collection; + +public interface IStatsSaver { + + void save(Collection pstats); + +} diff --git a/Stats/src/cz/marwland/mc/features/stats/PlayerStats.java b/Stats/src/cz/marwland/mc/features/stats/PlayerStats.java new file mode 100644 index 0000000..2ec764d --- /dev/null +++ b/Stats/src/cz/marwland/mc/features/stats/PlayerStats.java @@ -0,0 +1,41 @@ +package cz.marwland.mc.features.stats; + +import org.bukkit.entity.Player; + +public class PlayerStats { + + private final Player player; + + private volatile int killsSinceRecord = 0; + private volatile int deathsSinceRecord = 0; + + public PlayerStats(Player player) { + this.player = player; + } + + public void addKill() { + this.killsSinceRecord++; + } + + public void addDeath() { + this.deathsSinceRecord++; + } + + public int getNewKills() { + return this.killsSinceRecord; + } + + public int getNewDeaths() { + return this.deathsSinceRecord; + } + + public void reset() { + this.deathsSinceRecord = 0; + this.killsSinceRecord = 0; + } + + public Player getPlayer() { + return this.player; + } + +} diff --git a/Stats/src/cz/marwland/mc/features/stats/SQLStatsSaver.java b/Stats/src/cz/marwland/mc/features/stats/SQLStatsSaver.java new file mode 100644 index 0000000..1a9d03a --- /dev/null +++ b/Stats/src/cz/marwland/mc/features/stats/SQLStatsSaver.java @@ -0,0 +1,55 @@ +package cz.marwland.mc.features.stats; + +import java.io.IOException; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Collection; + +import cz.marwland.mc.core.MarwCore; +import cz.marwland.mc.core.storage.SQLStorage; +import cz.marwland.mc.core.util.FileUtil; +import cz.marwland.mc.core.util.UuidUtils; + +public class SQLStatsSaver implements IStatsSaver { + + private final SQLStorage database = MarwCore.getInstance().getStorage(); + private final String statsQuery; + + public SQLStatsSaver() throws IOException { + String query = FileUtil.readFileFromJAR(this.getClass(), "/resources/stats.sql"); + query = this.database.getStatementProcessor().apply(query); + this.statsQuery = query; + } + + @Override + public void save(Collection pstats) { + try (Connection conn = this.database.getConnectionFactory().getConnection()) { + PreparedStatement prepst = conn.prepareStatement(this.statsQuery); + int i = 0; + for (PlayerStats ps : pstats) { + this.addPlayer(prepst, ps); + ps.reset(); + i++; + } + if (i > 0) + prepst.executeBatch(); + prepst.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + private void addPlayer(PreparedStatement prepst, PlayerStats ps) { + try { + int i = 1; + prepst.setBytes(i++, UuidUtils.asBytes(ps.getPlayer().getUniqueId())); // uuid + prepst.setInt(i++, ps.getNewKills()); // kills + prepst.setInt(i++, ps.getNewDeaths()); // deaths + prepst.addBatch(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + +}