diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..b58b603
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,5 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/.idea/artifacts/ReviveTechnicalTest_jar.xml b/.idea/artifacts/ReviveTechnicalTest_jar.xml
new file mode 100644
index 0000000..ceba5c4
--- /dev/null
+++ b/.idea/artifacts/ReviveTechnicalTest_jar.xml
@@ -0,0 +1,12 @@
+
+
+ $PROJECT_DIR$/..
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..aa00ffa
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..67e1e61
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..6e6f43f
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 3477929..5ae0492 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,11 @@
1.18.36
provided
+
+ org.xerial
+ sqlite-jdbc
+ 3.42.0.0
+
-
+
\ No newline at end of file
diff --git a/src/main/java/fr/revivemc/Main.java b/src/main/java/fr/revivemc/Main.java
index 521e16b..b6aec15 100644
--- a/src/main/java/fr/revivemc/Main.java
+++ b/src/main/java/fr/revivemc/Main.java
@@ -1,13 +1,76 @@
package fr.revivemc;
+import fr.revivemc.data.Cache;
+import fr.revivemc.events.EntityDamageListener;
+import fr.revivemc.events.EntityDeathListener;
+import fr.revivemc.events.EntityRegenListener;
+import fr.revivemc.events.PlayerJoinListener;
+import fr.revivemc.data.Sql;
+import fr.revivemc.yaml.ConfigYaml;
+import fr.revivemc.yaml.LangYaml;
+import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
+import java.io.File;
+import java.util.HashMap;
+import java.util.UUID;
+
public class Main extends JavaPlugin {
+ /**
+ * Configuration variable, lang or data
+ */
+ public static ConfigYaml config_yaml;
+ public static LangYaml lang_yaml;
+ public static Sql sql;
+
+ // Variable for the cache
+ public static HashMap cache;
+
+ /**
+ * Create the plugin folder if it hasn't been created
+ */
+ private void loadDataFolder() {
+ File data_folder = Main.getPlugin(Main.class).getDataFolder();
+
+ if (!data_folder.exists())
+ data_folder.mkdir();
+ }
+
+ /**
+ * Server Startup
+ */
@Override
- public void onEnable() {}
+ public void onEnable() {
+ loadDataFolder();
+
+ sql = new Sql();
+ sql.init();
+ config_yaml = new ConfigYaml();
+ config_yaml.init();
+
+ lang_yaml = new LangYaml();
+ lang_yaml.init();
+
+ cache = new HashMap<>();
+
+ Bukkit.getPluginManager().registerEvents(new PlayerJoinListener(), this);
+ Bukkit.getPluginManager().registerEvents(new EntityDeathListener(), this);
+ Bukkit.getPluginManager().registerEvents(new EntityDamageListener(), this);
+ Bukkit.getPluginManager().registerEvents(new EntityRegenListener(), this);
+ System.out.println("Plugin enabled");
+ }
+
+ /**
+ * Server Stop
+ */
@Override
- public void onDisable() {}
+ public void onDisable() {
+ sql.saveData();
+ sql.close();
+
+ System.out.println("Plugin disabled");
+ }
}
diff --git a/src/main/java/fr/revivemc/data/Cache.java b/src/main/java/fr/revivemc/data/Cache.java
new file mode 100644
index 0000000..ca6b8bc
--- /dev/null
+++ b/src/main/java/fr/revivemc/data/Cache.java
@@ -0,0 +1,43 @@
+package fr.revivemc.data;
+
+public class Cache {
+
+ // Kills and Deaths variables
+ private int kills;
+ private int deaths;
+
+ /**
+ * Constructor for cache
+ * @param kills Number of kills
+ * @param deaths Number of deaths
+ */
+ public Cache(int kills, int deaths) {
+ this.kills = kills;
+ this.deaths = deaths;
+ }
+
+ /**
+ * @return Returns the number of kills
+ */
+ public int getKills() {
+ return (kills);
+ }
+
+ /**
+ * @return Returns the number of deaths
+ */
+ public int getDeaths() {
+ return (deaths);
+ }
+
+ // Add 1 to kill count
+ public void addKill() {
+ kills++;
+ }
+
+ // Add 1 to death count
+ public void addDeath() {
+ deaths++;
+ }
+
+}
diff --git a/src/main/java/fr/revivemc/data/Sql.java b/src/main/java/fr/revivemc/data/Sql.java
new file mode 100644
index 0000000..9d3f48a
--- /dev/null
+++ b/src/main/java/fr/revivemc/data/Sql.java
@@ -0,0 +1,79 @@
+package fr.revivemc.data;
+
+import fr.revivemc.Main;
+import fr.revivemc.data.wrapper.Players;
+import org.bukkit.entity.Player;
+
+import java.io.File;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Map;
+import java.util.UUID;
+
+public class Sql {
+
+ // Information of connection
+ private Connection connection;
+
+ /**
+ * This function allows you to create the different tables
+ * @param stmt A parameter to run SQL commands
+ * @throws SQLException Returns an exception if a sql error occurred
+ */
+ private void createTable(Statement stmt) throws SQLException {
+ stmt.execute("CREATE TABLE IF NOT EXISTS players (uuid TEXT PRIMARY KEY, kill INTEGER, death INTEGER)");
+ }
+
+ /**
+ * Allows you to close the db
+ */
+ public void close() {
+ try {
+ if (connection != null && !connection.isClosed())
+ connection.close();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Allows you to initialize the db when the server is launched
+ */
+ public void init() {
+ try {
+ Class.forName("org.sqlite.JDBC");
+
+ File data_folder = Main.getPlugin(Main.class).getDataFolder();
+
+ connection = DriverManager.getConnection("jdbc:sqlite:" + data_folder + "/data.db");
+ Statement statement = connection.createStatement();
+ createTable(statement);
+ statement.close();
+ System.out.println("Database connection established");
+ } catch (SQLException | ClassNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ /**
+ * Save data in the db
+ */
+ public void saveData() {
+ for (Map.Entry cache : Main.cache.entrySet()) {
+ Players.addPlayer(cache.getKey());
+ Players.setKillByUuid(cache.getKey(), cache.getValue().getKills());
+ Players.setDeathByUuid(cache.getKey(), cache.getValue().getDeaths());
+ }
+ }
+
+ /**
+ * @return Returns the connection
+ */
+ public Connection getConnection() {
+ return (connection);
+ }
+
+}
diff --git a/src/main/java/fr/revivemc/data/wrapper/Players.java b/src/main/java/fr/revivemc/data/wrapper/Players.java
new file mode 100644
index 0000000..c5aeba8
--- /dev/null
+++ b/src/main/java/fr/revivemc/data/wrapper/Players.java
@@ -0,0 +1,128 @@
+package fr.revivemc.data.wrapper;
+
+import fr.revivemc.Main;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+
+public class Players {
+
+ /**
+ * This function allows the player to be initialized in the table
+ * @param uuid Player uuid
+ */
+ public static void addPlayer(UUID uuid) {
+ try {
+ Connection connection = Main.sql.getConnection();
+
+ String query = "INSERT INTO players (uuid, kill, death) VALUES (?, 0, 0)";
+ PreparedStatement ps = connection.prepareStatement(query);
+ ps.setString(1, uuid.toString());
+
+ ps.executeUpdate();
+
+ } catch (SQLException e) {
+ System.err.println("Error while executing SQL statement " + e.getMessage());
+ }
+ }
+
+ /**
+ * This function allows you to add n to the player's kills
+ * @param uuid Player uuid
+ * @param n Number to add
+ */
+ public static void setKillByUuid(UUID uuid, int n) {
+ try {
+ Connection connection = Main.sql.getConnection();
+
+ String query = "UPDATE players SET kill = ? WHERE uuid = ?";
+ PreparedStatement ps = connection.prepareStatement(query);
+ ps.setString(1, String.valueOf(n));
+ ps.setString(2, uuid.toString());
+
+ ps.executeUpdate();
+
+ } catch (SQLException e) {
+ System.err.println("Error while executing SQL statement " + e.getMessage());
+ }
+ }
+
+ /**
+ * This function allows you to add n to the player's deaths
+ * @param uuid Player uuid
+ * @param n Number to add
+ */
+ public static void setDeathByUuid(UUID uuid, int n) {
+ try {
+ Connection connection = Main.sql.getConnection();
+
+ String query = "UPDATE players SET death = ? WHERE uuid = ?";
+ PreparedStatement ps = connection.prepareStatement(query);
+ ps.setString(1, String.valueOf(n));
+ ps.setString(2, uuid.toString());
+
+ ps.executeUpdate();
+
+ } catch (SQLException e) {
+ System.err.println("Error while executing SQL statement " + e.getMessage());
+ }
+ }
+
+ /**
+ * Function that allows you to retrieve the number of kills in relation to the player's UUID
+ * @param uuid Player uuid
+ * @return Returns the correct value or 0
+ */
+ public static int getKillByUuid(UUID uuid) {
+ int kills = 0;
+
+ try {
+ Connection connection = Main.sql.getConnection();
+
+ String query = "SELECT kill FROM players WHERE uuid=?";
+ PreparedStatement ps = connection.prepareStatement(query);
+ ps.setString(1, uuid.toString());
+
+ ResultSet row = ps.executeQuery();
+
+ if (row.next())
+ kills = row.getInt("kill");
+
+ } catch (SQLException e) {
+ System.err.println("Error while executing SQL statement " + e.getMessage());
+ }
+
+ return (kills);
+ }
+
+ /**
+ * Function that allows you to retrieve the number of deaths in relation to the player's UUID
+ * @param uuid Player uuid
+ * @return Returns the correct value or 0
+ */
+ public static int getDeathByUuid(UUID uuid) {
+ int deaths = 0;
+
+ try {
+ Connection connection = Main.sql.getConnection();
+
+ String query = "SELECT death FROM players WHERE uuid=?";
+ PreparedStatement ps = connection.prepareStatement(query);
+ ps.setString(1, uuid.toString());
+
+ ResultSet row = ps.executeQuery();
+
+ if (row.next())
+ deaths = row.getInt("death");
+
+ } catch (SQLException e) {
+ System.err.println("Error while executing SQL statement " + e.getMessage());
+ }
+
+ return (deaths);
+ }
+
+}
diff --git a/src/main/java/fr/revivemc/events/EntityDamageListener.java b/src/main/java/fr/revivemc/events/EntityDamageListener.java
new file mode 100644
index 0000000..b147788
--- /dev/null
+++ b/src/main/java/fr/revivemc/events/EntityDamageListener.java
@@ -0,0 +1,22 @@
+package fr.revivemc.events;
+
+import fr.revivemc.scoreboard.ScoreBoard;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityDamageEvent;
+
+public class EntityDamageListener implements Listener {
+
+ /**
+ * Function that is triggered when a player takes damage
+ * @param event All information related to the event
+ */
+ @EventHandler
+ public void onPlayerDamage(EntityDamageEvent event) {
+ if (event.getEntity() instanceof Player) {
+ ScoreBoard.init((Player) event.getEntity(), ((Player) event.getEntity()).getHealth() - event.getDamage());
+ }
+ }
+
+}
diff --git a/src/main/java/fr/revivemc/events/EntityDeathListener.java b/src/main/java/fr/revivemc/events/EntityDeathListener.java
new file mode 100644
index 0000000..df7270d
--- /dev/null
+++ b/src/main/java/fr/revivemc/events/EntityDeathListener.java
@@ -0,0 +1,36 @@
+package fr.revivemc.events;
+
+import fr.revivemc.Main;
+import fr.revivemc.data.Cache;
+import fr.revivemc.scoreboard.ScoreBoard;
+import fr.revivemc.data.wrapper.Players;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityDeathEvent;
+
+public class EntityDeathListener implements Listener {
+
+ /**
+ * Function that is triggered when an entity dies
+ * @param event All information related to the event
+ */
+ @EventHandler
+ public void onEntityDeath(EntityDeathEvent event) {
+ Player killer = event.getEntity().getKiller();
+ Entity victim = event.getEntity();
+
+ if (killer != null && victim instanceof Player) {
+ Cache cache = Main.cache.get(killer.getUniqueId());
+ cache.addKill();
+ ScoreBoard.init(killer, killer.getHealth());
+ }
+ if (victim instanceof Player) {
+ Cache cache = Main.cache.get(victim.getUniqueId());
+ cache.addDeath();
+ ScoreBoard.init((Player) victim, ((Player) victim).getHealth());
+ }
+ }
+
+}
diff --git a/src/main/java/fr/revivemc/events/EntityRegenListener.java b/src/main/java/fr/revivemc/events/EntityRegenListener.java
new file mode 100644
index 0000000..f3feee2
--- /dev/null
+++ b/src/main/java/fr/revivemc/events/EntityRegenListener.java
@@ -0,0 +1,22 @@
+package fr.revivemc.events;
+
+import fr.revivemc.scoreboard.ScoreBoard;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityRegainHealthEvent;
+
+public class EntityRegenListener implements Listener {
+
+ /**
+ * Function that is triggered when a player gets a regeneration
+ * @param event All information related to the event
+ */
+ @EventHandler
+ public void onPlayerRegen(EntityRegainHealthEvent event) {
+ if (event.getEntity() instanceof Player) {
+ ScoreBoard.init((Player) event.getEntity(), ((Player) event.getEntity()).getHealth() + event.getAmount());
+ }
+ }
+
+}
diff --git a/src/main/java/fr/revivemc/events/PlayerJoinListener.java b/src/main/java/fr/revivemc/events/PlayerJoinListener.java
new file mode 100644
index 0000000..76a4ab0
--- /dev/null
+++ b/src/main/java/fr/revivemc/events/PlayerJoinListener.java
@@ -0,0 +1,31 @@
+package fr.revivemc.events;
+
+import fr.revivemc.Main;
+import fr.revivemc.data.Cache;
+import fr.revivemc.data.wrapper.Players;
+import fr.revivemc.scoreboard.ScoreBoard;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerJoinEvent;
+
+public class PlayerJoinListener implements Listener {
+
+ /**
+ * Function that is triggered when a player joins
+ * @param event All information related to the event
+ */
+ @EventHandler
+ public void onPlayerJoin(PlayerJoinEvent event) {
+ Player player = event.getPlayer();
+
+ Cache cache = Main.cache.get(player.getUniqueId());
+ if (cache == null) {
+ java.util.UUID uuid = player.getUniqueId();
+ Main.cache.put(player.getUniqueId(), new Cache(Players.getKillByUuid(uuid), Players.getDeathByUuid(uuid)));
+ }
+
+ ScoreBoard.init(player, player.getHealth());
+ }
+
+}
diff --git a/src/main/java/fr/revivemc/scoreboard/ScoreBoard.java b/src/main/java/fr/revivemc/scoreboard/ScoreBoard.java
new file mode 100644
index 0000000..c041a92
--- /dev/null
+++ b/src/main/java/fr/revivemc/scoreboard/ScoreBoard.java
@@ -0,0 +1,40 @@
+package fr.revivemc.scoreboard;
+
+import fr.revivemc.Main;
+import fr.revivemc.data.Cache;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.scoreboard.*;
+
+public class ScoreBoard {
+
+ /**
+ * Function for creating the scoreboard
+ * @param player The player
+ * @param life The life of player
+ */
+ public static void init(Player player, double life) {
+ Scoreboard scoreboard = Bukkit.getScoreboardManager().getNewScoreboard();
+
+ Cache cache = Main.cache.get(player.getUniqueId());
+
+ Objective objective = scoreboard.registerNewObjective("revivemc", "dummy");
+ objective.setDisplayName(Main.lang_yaml.title_scoreboard);
+ objective.setDisplaySlot(DisplaySlot.SIDEBAR);
+
+ Score line_1 = objective.getScore(Main.lang_yaml.name_scoreboard + player.getDisplayName());
+ line_1.setScore(0);
+
+ Score line_2 = objective.getScore(Main.lang_yaml.kills_scoreboard + cache.getKills());
+ line_2.setScore(1);
+
+ Score line_3 = objective.getScore(Main.lang_yaml.heart_scoreboard + life);
+ line_3.setScore(2);
+
+ Score line_4 = objective.getScore(Main.lang_yaml.deaths_scoreboard + cache.getDeaths());
+ line_4.setScore(3);
+
+ player.setScoreboard(scoreboard);
+ }
+
+}
diff --git a/src/main/java/fr/revivemc/yaml/ConfigYaml.java b/src/main/java/fr/revivemc/yaml/ConfigYaml.java
new file mode 100644
index 0000000..8182887
--- /dev/null
+++ b/src/main/java/fr/revivemc/yaml/ConfigYaml.java
@@ -0,0 +1,48 @@
+package fr.revivemc.yaml;
+
+import fr.revivemc.Main;
+import org.bukkit.configuration.file.YamlConfiguration;
+
+import java.io.File;
+import java.io.IOException;
+
+public class ConfigYaml {
+
+ /**
+ * Variable for config and subfolder
+ */
+ private YamlConfiguration config;
+ public String lang_file_name;
+
+ /**
+ * Create the file and fill it with the basic information if it does not exist
+ */
+ private void loadYaml() {
+ File data_folder = Main.getPlugin(Main.class).getDataFolder();
+
+ File config_file = new File(data_folder, "config.yml");
+ config = YamlConfiguration.loadConfiguration(config_file);
+
+ if (!config_file.exists()) {
+ try {
+ config_file.createNewFile();
+ config.set("lang", "en_us.yml");
+ config.save(config_file);
+
+ System.out.println("config.yml has been created");
+ } catch (IOException e) {
+ System.out.println(e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Initialize the yaml part
+ */
+ public void init() {
+ loadYaml();
+
+ lang_file_name = config.getString("lang");
+ }
+
+}
diff --git a/src/main/java/fr/revivemc/yaml/LangYaml.java b/src/main/java/fr/revivemc/yaml/LangYaml.java
new file mode 100644
index 0000000..11e5ae6
--- /dev/null
+++ b/src/main/java/fr/revivemc/yaml/LangYaml.java
@@ -0,0 +1,77 @@
+package fr.revivemc.yaml;
+
+import fr.revivemc.Main;
+import org.bukkit.configuration.file.YamlConfiguration;
+
+import java.io.File;
+import java.io.IOException;
+
+public class LangYaml {
+
+ /**
+ * Variable for config and values for lang
+ */
+ private YamlConfiguration config;
+ public String title_scoreboard;
+ public String kills_scoreboard;
+ public String deaths_scoreboard;
+ public String heart_scoreboard;
+ public String name_scoreboard;
+
+ /**
+ * Function that allows you to create the folder if it does not have the default values
+ * @param config_file File to create
+ * @param lang_folder Folder of lang
+ */
+ private void createFile(File config_file, File lang_folder) {
+ try {
+ config_file = new File(lang_folder, "en_us.yml");
+
+ config_file.createNewFile();
+ config.set("title_scoreboard", "ReviveMC");
+ config.set("kills_scoreboard", "Kills: ");
+ config.set("deaths_scoreboard", "Deaths: ");
+ config.set("heart_scoreboard", "Hearts: ");
+ config.set("name_scoreboard", "Name: ");
+ config.save(config_file);
+
+ System.out.println("en_us.yml has been created");
+ } catch (IOException e) {
+ System.out.println(e.getMessage());
+ }
+ }
+
+ /**
+ * File and fill it with the basic information if it does not exist
+ */
+ private void loadYaml() {
+ File data_folder = Main.getPlugin(Main.class).getDataFolder();
+ File lang_folder = new File(data_folder, "lang");
+
+ if (!lang_folder.exists())
+ lang_folder.mkdir();
+
+ File config_file = new File(lang_folder, Main.config_yaml.lang_file_name);
+ config = YamlConfiguration.loadConfiguration(config_file);
+
+ if (!config_file.exists())
+ createFile(config_file, lang_folder);
+
+ title_scoreboard = config.getString("title_scoreboard");
+ kills_scoreboard = config.getString("kills_scoreboard");
+ deaths_scoreboard = config.getString("deaths_scoreboard");
+ name_scoreboard = config.getString("name_scoreboard");
+ heart_scoreboard = config.getString("heart_scoreboard");
+ if (title_scoreboard == null || kills_scoreboard == null || deaths_scoreboard == null
+ || name_scoreboard == null || heart_scoreboard == null)
+ createFile(config_file, lang_folder);
+ }
+
+ /**
+ * Initialize the yaml part
+ */
+ public void init() {
+ loadYaml();
+ }
+
+}