split stats and sessions

This commit is contained in:
2018-10-12 21:49:10 +02:00
parent 78597f6a91
commit 1204423f2c
18 changed files with 354 additions and 42 deletions

21
Auth/.classpath Normal file
View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-10">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/classes" path="src">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="resources"/>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

2
Auth/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/bin/
/target/

23
Auth/.project Normal file
View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Auth</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -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

View File

@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

56
Auth/pom.xml Normal file
View File

@ -0,0 +1,56 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cz.marwland.mc.features</groupId>
<artifactId>Auth</artifactId>
<parent>
<groupId>cz.marwland.mc</groupId>
<artifactId>MarwStuff</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../MarwStuff</relativePath>
</parent>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<release>10</release>
</configuration>
</plugin>
<plugin>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<groupId>org.codehaus.mojo</groupId>
<executions>
<execution>
<phase>deploy</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>${project.parent.basedir}/deploy_feature.sh</executable>
<arguments>
<argument>${project.build.directory}/${project.build.finalName}.jar</argument>
<argument>${project.artifactId}</argument>
</arguments>
</configuration>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<outputDirectory>${project.build.outputDirectory}/resources</outputDirectory>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>cz.marwland.mc</groupId>
<artifactId>MarwCore</artifactId>
<version>${project.parent.version}</version>
</dependency>
</dependencies>
</project>

12
Auth/resources/create.sql Normal file
View File

@ -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;

View File

@ -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`);

View File

@ -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());
}
}

View File

@ -0,0 +1,52 @@
package cz.marwland.mc.features.auth;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.bukkit.entity.Player;
import cz.marwland.mc.core.util.UuidUtils;
public class PlayerSession {
private Player player;
private volatile long lastRecorded = 0;
private java.sql.Timestamp dateJoined;
private int ipAddress;
public PlayerSession(Player player) {
this.player = player;
this.lastRecorded = System.currentTimeMillis();
this.dateJoined = new java.sql.Timestamp(System.currentTimeMillis());
ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES).order(ByteOrder.BIG_ENDIAN);
buffer.put(player.getAddress().getAddress().getAddress());
buffer.position(0);
this.ipAddress = buffer.getInt();
}
public Player getPlayer() {
return this.player;
}
public void update(PreparedStatement prepst) {
try {
int i = 1;
long playtime = (System.currentTimeMillis() - this.lastRecorded) / 1000;
prepst.setBytes(i++, UuidUtils.asBytes(player.getUniqueId())); // uuid
prepst.setString(i++, player.getName()); // serverNick
prepst.setInt(i++, this.ipAddress); // ip
prepst.setTimestamp(i++, this.dateJoined); // date
prepst.setLong(i++, playtime); // playtime
prepst.addBatch();
} catch (SQLException e) {
e.printStackTrace();
}
this.lastRecorded = System.currentTimeMillis();
}
}

View File

@ -0,0 +1,110 @@
package cz.marwland.mc.features.auth;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.bukkit.entity.Player;
import cz.marwland.mc.core.MarwCore;
import cz.marwland.mc.core.storage.SQLStorage;
import cz.marwland.mc.core.util.FileUtil;
public class SessionManager {
private String sessionQuery;
private final SQLStorage database = MarwCore.getInstance().getStorage();
public HashMap<Player, PlayerSession> sessions = new HashMap<>();
private final long WRITE_PERIOD = 15;
private ScheduledFuture<?> recordTask;
public SessionManager() {
}
public void start() {
loadSQLQueries();
recordTask = MarwCore.getInstance().getStorageExecutor().scheduleAtFixedRate(() -> this.recordSessions(), WRITE_PERIOD, WRITE_PERIOD, TimeUnit.SECONDS);
for (Player p : MarwCore.getInstance().getServer().getOnlinePlayers()) {
this.startPlayer(p);
}
recordSessions();
}
public void shutdown() {
recordTask.cancel(false);
for (Player p : MarwCore.getInstance().getServer().getOnlinePlayers()) {
this.endPlayer(p);
}
}
public void loadSQLQueries() {
try {
sessionQuery = FileUtil.readFileFromJAR(PlayerSession.class, "/resources/session.sql");
sessionQuery = this.database.getStatementProcessor().apply(sessionQuery);
} catch (IOException e) {
e.printStackTrace();
}
}
public void startPlayer(Player p) {
PlayerSession ps = new PlayerSession(p);
this.sessions.put(p, ps);
}
public void endPlayer(Player p) {
PlayerSession ps = this.sessions.get(p);
// TODO: null handling - cannot happen
if (ps == null)
return;
this.recordSinglePlayer(p);
this.sessions.remove(p);
}
public PlayerSession getPlayerSession(Player p) {
return this.sessions.get(p);
}
private void recordSessions() {
try (Connection conn = this.database.getConnectionFactory().getConnection()) {
PreparedStatement prepst = conn.prepareStatement(this.sessionQuery);
int i = 0;
for (PlayerSession ps : this.sessions.values()) {
ps.update(prepst);
i++;
}
if (i > 0)
prepst.execute();
prepst.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
private void recordSinglePlayer(Player p) {
PlayerSession ps = this.getPlayerSession(p);
if (ps == null)
return;
this.recordSinglePlayer(ps);
}
private void recordSinglePlayer(PlayerSession ps) {
MarwCore.getInstance().getStorageExecutor().execute(() -> {
try (Connection conn = this.database.getConnectionFactory().getConnection();) {
PreparedStatement prepst = conn.prepareStatement(this.sessionQuery);
ps.update(prepst);
prepst.executeBatch();
conn.commit();
prepst.close();
} catch (SQLException e) {
e.printStackTrace();
}
});
}
}