diff --git a/SpigotCore_Main/src/de/steamwar/sql/Punishment.java b/SpigotCore_Main/src/de/steamwar/sql/Punishment.java
new file mode 100644
index 0000000..19b0296
--- /dev/null
+++ b/SpigotCore_Main/src/de/steamwar/sql/Punishment.java
@@ -0,0 +1,146 @@
+/*
+ This file is a part of the SteamWar software.
+
+ Copyright (C) 2020 SteamWar.de-Serverteam
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+ */
+
+package de.steamwar.sql;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+
+public class Punishment {
+
+ private static final Statement getPunishment = new Statement("SELECT * FROM Punishments WHERE UserId = ? AND Type = ? ORDER BY PunishmentId DESC LIMIT 1");
+ private static final Statement getPunishments = new Statement("SELECT * FROM Punishments WHERE PunishmentId IN (SELECT MAX(PunishmentId) FROM Punishments WHERE UserId = ? GROUP BY Type)");
+ private static final Statement getAllPunishments = new Statement("SELECT * FROM Punishments WHERE UserId = ? ORDER BY `PunishmentId` DESC");
+ private static final Statement insert = new Statement("INSERT INTO Punishments (UserId, Punisher, Type, Reason, EndTime, Perma) VALUES (?, ?, ?, ?, ?, ?)");
+
+ public static Punishment getPunishmentOfPlayer(int user, PunishmentType type) {
+ return getPunishment.select(rs -> {
+ if (rs.next())
+ return new Punishment(rs);
+ return null;
+ }, user, type.name());
+ }
+
+ public static Map getPunishmentsOfPlayer(int user) {
+ return getPunishments.select(rs -> {
+ Map punishments = new HashMap<>();
+ while (rs.next())
+ punishments.put(PunishmentType.valueOf(rs.getString("Type")), new Punishment(rs));
+ return punishments;
+ }, user);
+ }
+
+ public static List getAllPunishmentsOfPlayer(int user) {
+ return getAllPunishments.select(rs -> {
+ List punishments = new ArrayList<>();
+ while (rs.next())
+ punishments.add(new Punishment(rs));
+ return punishments;
+ }, user);
+ }
+
+ public static Punishment createPunishment(int user, int executor, PunishmentType type, String reason, Timestamp endTime, boolean perma) {
+ insert.update(user, executor, type.name(), reason, endTime, perma);
+ return getPunishmentOfPlayer(user, type);
+ }
+
+ private final Timestamp startTime;
+ private Timestamp endTime;
+ private final PunishmentType type;
+ private final int user;
+ private final int id;
+ private String reason;
+ private final int punisher;
+ private boolean perma;
+
+ private Punishment(ResultSet set) throws SQLException {
+ user = set.getInt("UserId");
+ reason = set.getString("Reason");
+ type = PunishmentType.valueOf(set.getString("Type"));
+ startTime = set.getTimestamp("StartTime");
+ endTime = set.getTimestamp("EndTime");
+ punisher = set.getInt("Punisher");
+ perma = set.getBoolean("Perma");
+ id = set.getInt("PunishmentId");
+ }
+
+ public Timestamp getStartTime() {
+ return startTime;
+ }
+
+ public Timestamp getEndTime() {
+ return endTime;
+ }
+
+ public PunishmentType getType() {
+ return type;
+ }
+
+ public int getUser() {
+ return user;
+ }
+
+ public String getReason() {
+ return reason;
+ }
+
+ public int getPunisher() {
+ return punisher;
+ }
+
+ public boolean isPerma() {
+ return perma;
+ }
+
+ public String getBantime(Timestamp endTime, boolean perma) {
+ if (perma) {
+ return "permanent";
+ } else {
+ return endTime.toLocalDateTime().format(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"));
+ }
+ }
+
+ public boolean isCurrent() {
+ return isPerma() || getEndTime().after(new Date());
+ }
+
+ @AllArgsConstructor
+ @Getter
+ public enum PunishmentType {
+ Ban(false, "BAN_TEAM", "BAN_PERMA", "BAN_UNTIL", "UNBAN_ERROR", "UNBAN"),
+ Mute( false, "MUTE_TEAM", "MUTE_PERMA", "MUTE_UNTIL", "UNMUTE_ERROR", "UNMUTE"),
+ NoSchemReceiving(false, "NOSCHEMRECEIVING_TEAM", "NOSCHEMRECEIVING_PERMA", "NOSCHEMRECEIVING_UNTIL", "UNNOSCHEMRECEIVING_ERROR", "UNNOSCHEMRECEIVING"),
+ NoSchemSharing(false, "NOSCHEMSHARING_TEAM", "NOSCHEMSHARING_PERMA", "NOSCHEMSHARING_UNTIL", "UNNOSCHEMSHARING_ERROR", "UNNOSCHEMSHARING"),
+ NoSchemSubmitting(true, "NOSCHEMSUBMITTING_TEAM", "NOSCHEMSUBMITTING_PERMA", "NOSCHEMSUBMITTING_UNTIL", "UNNOSCHEMSUBMITTING_ERROR", "UNNOSCHEMSUBMITTING"),
+ NoDevServer(true, "NODEVSERVER_TEAM", "NODEVSERVER_PERMA", "NODEVSERVER_UNTIL", "UNNODEVSERVER_ERROR", "UNNODEVSERVER");
+
+ private final boolean needsAdmin;
+ private final String teamMessage;
+ private final String playerMessagePerma;
+ private final String playerMessageUntil;
+ private final String usageNotPunished;
+ private final String unpunishmentMessage;
+ }
+}
diff --git a/SpigotCore_Main/src/de/steamwar/sql/Statement.java b/SpigotCore_Main/src/de/steamwar/sql/Statement.java
new file mode 100644
index 0000000..db75983
--- /dev/null
+++ b/SpigotCore_Main/src/de/steamwar/sql/Statement.java
@@ -0,0 +1,130 @@
+package de.steamwar.sql;
+
+import de.steamwar.core.Core;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+
+public class Statement {
+
+ private static final List statements = new ArrayList<>();
+
+ private static Connection con;
+ private static String url;
+ private static String user;
+ private static String password;
+
+ public static void connect(String url, String user, String password) {
+ Statement.url = url;
+ Statement.user = user;
+ Statement.password = password;
+ try {
+ con = DriverManager.getConnection(url + "?autoReconnect=true&useServerPrepStmts=true", user, password);
+ } catch (SQLException e) {
+ throw new SecurityException("Could not start SQL-Connection", e);
+ }
+ }
+
+ private static void reset() {
+ close();
+ connect(url, user, password);
+ try {
+ for (Statement statement : statements) {
+ statement.init();
+ }
+ } catch (SQLException e) {
+ throw new SecurityException("Could not reprepare SQL statements", e);
+ }
+ }
+
+ public static void close() {
+ synchronized (statements) {
+ for (Statement statement : statements) {
+ try {
+ statement.st.close();
+ } catch (SQLException e) {
+ Core.getInstance().getLogger().log(Level.INFO, "Could not close statement", e);
+ }
+ }
+
+ try {
+ con.close();
+ } catch (SQLException e) {
+ Core.getInstance().getLogger().log(Level.INFO, "Could not close SQL connection", e);
+ }
+ }
+ }
+
+ public static boolean connectionStable() {
+ try {
+ return !con.isClosed();
+ } catch (SQLException e) {
+ return false;
+ }
+ }
+
+ private final String sql;
+ private PreparedStatement st;
+
+ public Statement(String sql) {
+ this.sql = sql;
+ statements.add(this);
+ try {
+ init();
+ } catch (SQLException e) {
+ throw new SecurityException("Could not init SQL statement", e);
+ }
+ }
+
+ private void init() throws SQLException {
+ st = con.prepareStatement(sql);
+ }
+
+ public T select(ResultSetUser user, Object... objects) {
+ synchronized (statements) {
+ return prepare(() -> {
+ ResultSet rs = st.executeQuery();
+ T result = user.use(rs);
+ rs.close();
+ return result;
+ }, objects);
+ }
+ }
+
+ public void update(Object... objects) {
+ synchronized (statements) {
+ prepare(st::executeUpdate, objects);
+ }
+ }
+
+ private T prepare(SQLRunnable runnable, Object... objects) {
+ try {
+ setObjects(objects);
+ return runnable.run();
+ } catch (SQLException e) {
+ reset();
+ throw new SecurityException("Could not execute SQL statement", e);
+ }
+ }
+
+ private void setObjects(Object... objects) throws SQLException {
+ for (int i = 0; i < objects.length; i++) {
+ st.setObject(i + 1, objects[i]);
+ }
+ }
+
+ public interface ResultSetUser {
+ T use(ResultSet rs) throws SQLException;
+ }
+
+ private interface SQLRunnable {
+ T run() throws SQLException;
+ }
+
+}