diff --git a/README.md b/README.md index da2ad76..6be7123 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,9 @@ -# BanList -## Cos'è questo BanList? -BanList è un semplicissimo plugin per _Spigot/Bukkit_ che ti permette di avere in formato JSON la lista di utenti bannati nel tuo server Minecraft, sia per indirizzo IP che per username! -## Storia di BanList -Un giorno, non sapendo cosa fare a causa del coronavirus 🦠, ho perso quaranta minuti della mia vita a realizzare il plugin... +# DataList +## Cos'è questo DataList? +Questo plugin è un [fork](https://github.com/rospino74/BanList) sviluppato apposta per il progetto _Build The Earth_ italiano come integrazione con il [sito web](https://github.com/BuildTheEarth-Italia/Wordpress-Theme). ## Come si installa? ### Requisiti -Il plugin [Essentials](https://github.com/EssentialsX/Essentials) è necessario per visualizzare gli utenti mutati, ma ritengo che questo ottimo plugin tu lo abbia già installato! -Inoltre, se vuoi vedere la lista di utenti congelati, installa il mio plugin [Freezer](https://github.com/rospino74/Freezer). Non ti basta ancora? Con [Vault](https://github.com/MilkBowl/Vault) installato potrai addirittura ottenere i gruppi di utenti e i loro bilanci! -### Utenti base -* Scarica l'[ultima relase](https://github.com/rospino74/BanList/releases/latest) -* Sposta il file `BanList-.jar` nella cartella `plugins` del tuo server Minecraft -* Riavvia il server e all'indirizzo `http://:80/ban` troverai la lista di utenti bannati -### Utenti Avanzati -* Clona il repository e importalo nel tuo IDE -* Compila i files Java e Kotlin (è necessario che il tuo IDE sia configurato per quest'ultimo) -* Chiudi tutto in un Jar e dallo da mangiare al tuo server 😋! +Il plugin [Vault](https://github.com/milkbowl/Vault) è necessario per visualizzare i permessi, ma ritengo che questo ottimo plugin tu lo abbia già installato! ## Configurazione La configurazione di default del plugin è questa: ```yaml @@ -30,6 +19,7 @@ output: onlinePlayers: "/online" permissions: "/permissions" points: "/points" + playtime: "/playtime" port: 80 ``` ### SSL @@ -133,8 +123,32 @@ Deve essere un intero compreso tra `0` e `65565`, il numero scelto inoltre non d | :--- | :---: | --- | | `name` | `String` | Nome del gruppo | | `members` | `Array` di `String` | Membri del gruppo | +### Playtime +```json +{ + "playtime": [ + { + "name": "MemoryOfLife", + "ticks": 2281 + } + ] +} +``` +| Chiave | Tipo | Significato | +| :--- | :---: | --- | +| `name` | `String` | Nome del player | +| `ticks` | `int` | Numero di ticks in cui il player è stato online | + +⚠ Se il **server non ha attivato** il le **statistiche** **non** sarà possibile **visualizzarle**. Per info visita [Spigot Configuration page](https://www.spigotmc.org/wiki/spigot-configuration/) alla voce _Stats_. ## Errori comuni * `java.net.BindException`: La porta scelta è già in uso, cambiarla nel file di configurazione * `java.io.IOException`: Si è verificato un errore nel comunicare con un altro sistema * `org.yaml.snakeyaml.error.YAMLException`: Si è verificato un errore nel leggere il file di configurazione, verifica se è valido! +* `java.lang.ClassNotFoundException` oppure `java.lang.InstantiationException`: La classe che hai specificato in `config.yml` non è valida. [Vedi sotto](#nota-per-i-developer). +* `java.lang.NoSuchMethodException` oppure `java.lang.ClassCastException`: La classe che hai specificato in `config.yml` non estende la classe [RequestHandler](https://github.com/BuildTheEarth-Italia/DataList/blob/master/src/main/java/it/bteitalia/datalist/server/RequestHandler.java). + +## Nota per i Developer +Ogni child di `output.path` nella [configurazione](#configurazione) ha un nome speciale. +Il plugin a ogni startup carica la classe `it.bteitalia.datalist.handlers.RequestHandler` come handler per il percorso specificato in `output.path.`. +Per cui se sbagliate il nome in `config.yml` il plugin genererà un eccezione [`java.lang.ClassNotFoundException`](#errori-comuni) \ No newline at end of file diff --git a/src/main/java/it/bteitalia/datalist/DataList.java b/src/main/java/it/bteitalia/datalist/DataList.java index eaf23bc..caf1bb7 100644 --- a/src/main/java/it/bteitalia/datalist/DataList.java +++ b/src/main/java/it/bteitalia/datalist/DataList.java @@ -166,7 +166,7 @@ private void enableRoutes(String path, Set list) { } catch (ClassNotFoundException e) { printError("Classe " + className + "non trovata", e); - } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) { + } catch (ClassCastException | IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) { printError("Classe " + className + "non creabile", e); } } diff --git a/src/main/java/it/bteitalia/datalist/server/RequestHandler.java b/src/main/java/it/bteitalia/datalist/server/RequestHandler.java index 2c6f805..8fedf87 100644 --- a/src/main/java/it/bteitalia/datalist/server/RequestHandler.java +++ b/src/main/java/it/bteitalia/datalist/server/RequestHandler.java @@ -18,7 +18,7 @@ public abstract class RequestHandler implements HttpHandler { private HttpExchange exchange; @Override - public void handle(HttpExchange httpExchange) throws IOException { + public final void handle(HttpExchange httpExchange) throws IOException { //se httpExchange == null esco if (httpExchange == null) return; diff --git a/src/main/kotlin/it/bteitalia/datalist/handlers/PlaytimeRequestHandler.kt b/src/main/kotlin/it/bteitalia/datalist/handlers/PlaytimeRequestHandler.kt new file mode 100644 index 0000000..be0b3bc --- /dev/null +++ b/src/main/kotlin/it/bteitalia/datalist/handlers/PlaytimeRequestHandler.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 Build The Earth Italia + * This file (PlaytimeRequestHandler.kt) and its related project (DataList) are governed by the Apache 2.0 license. + * You may not use them except in compliance with the License which can be found at: + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +package it.bteitalia.datalist.handlers + +import com.google.gson.JsonObject +import com.sun.net.httpserver.HttpExchange +import it.bteitalia.datalist.DataList +import it.bteitalia.datalist.listers.PlaytimeLister +import it.bteitalia.datalist.server.RequestHandler +import org.bukkit.Bukkit + +@Suppress("unused") +internal class PlaytimeRequestHandler : RequestHandler() { + override fun onIncomingRequest(httpExchange: HttpExchange) { + val out = JsonObject() + + //json di player online + out.add("playtime", PlaytimeLister().getJSON()) + + //invio i dati + flushData(out.toString()) + } + + companion object { + init { + Bukkit.getPluginManager().registerEvents(PlaytimeLister(), DataList.getInstance()) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/it/bteitalia/datalist/listers/PlaytimeLister.kt b/src/main/kotlin/it/bteitalia/datalist/listers/PlaytimeLister.kt new file mode 100644 index 0000000..a6f5d2f --- /dev/null +++ b/src/main/kotlin/it/bteitalia/datalist/listers/PlaytimeLister.kt @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2021 Build The Earth Italia + * This file (PlaytimeLister.kt) and its related project (DataList) are governed by the Apache 2.0 license. + * You may not use them except in compliance with the License which can be found at: + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +package it.bteitalia.datalist.listers + +import com.google.gson.JsonArray +import com.google.gson.JsonObject +import com.google.gson.JsonParser +import it.bteitalia.datalist.DataList +import org.bukkit.Bukkit +import org.bukkit.Statistic +import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority +import org.bukkit.event.Listener +import org.bukkit.event.player.PlayerJoinEvent +import org.bukkit.event.player.PlayerQuitEvent +import java.io.FileReader +import java.io.FileWriter +import java.util.* +import kotlin.collections.HashMap + + +@Suppress("unused") +internal class PlaytimeLister : Listener { + fun getJSON(): JsonArray { + //oggetto di out + val out = JsonArray() + + for (player in Bukkit.getOfflinePlayers()) { + val playtime: Int = + if (DataList.getInstance().version <= 1.13) + player.player?.getStatistic(Statistic.PLAY_ONE_TICK) + else { + val statistic = Statistic.valueOf("PLAY_ONE_MINUTE") + player.player?.getStatistic(statistic) + } ?: getPlaytimeFromList(player.uniqueId) + + // Se playtime è 0 ignoro + if (playtime <= 0) + continue + + // Creo oggetto + val jsonPlayerEntry = JsonObject() + jsonPlayerEntry.addProperty("name", player.name) + jsonPlayerEntry.addProperty("ticks", playtime) + + out.add(jsonPlayerEntry) + } + + //ritorno l'array + return out + } + + @EventHandler(priority = EventPriority.MONITOR) + fun onPlayerLogout(evt: PlayerQuitEvent) { + val playtime: Int? = + if (DataList.getInstance().version <= 1.12) + evt.player?.getStatistic(Statistic.PLAY_ONE_TICK) + else { + val statistic = Statistic.valueOf("PLAY_ONE_MINUTE") + evt.player?.getStatistic(statistic) + } + + PlaytimeLister.playtime[evt.player.uniqueId] = playtime ?: return + + updateFile() + } + + @EventHandler(priority = EventPriority.MONITOR) + fun onPlayerLogin(evt: PlayerJoinEvent) { + val playtime: Int? = + if (DataList.getInstance().version <= 1.12) + evt.player?.getStatistic(Statistic.PLAY_ONE_TICK) + else { +// val statistic = Statistic::class.java.enumConstants.find { it.name == "PLAY_ONE_MINUTE" } + val statistic = Statistic.valueOf("PLAY_ONE_MINUTE") + evt.player?.getStatistic(statistic) + } + + PlaytimeLister.playtime[evt.player.uniqueId] = playtime ?: return + + updateFile() + } + + private fun getPlaytimeFromList(uuid: UUID): Int { + return playtime[uuid] ?: 0 + } + + private fun updateFile() { + val file = DataList.getInstance().dataFolder.resolve("playtime.json") + + // Controllo che esista + if (!file.exists()) + file.createNewFile() + + // salvo nel file nell'hashmap + val toSave = JsonObject() + + playtime.forEach { (uuid, value) -> + toSave.addProperty(uuid.toString(), value) + } + + val writer = FileWriter(file) + writer.write(toSave.toString()) + writer.close() + } + + companion object { + @JvmStatic + private val playtime = HashMap() + + init { + val file = DataList.getInstance().dataFolder.resolve("playtime.json") + + // Controllo che esista + if (!file.exists()) + file.createNewFile() + + // Leggo il file nell'hashmap + try { + val parser = JsonParser().parse(FileReader(file)) + + parser.asJsonObject.entrySet().forEach { (key, value) -> + val uuid = UUID.fromString(key) + val ticks = value.asInt + + playtime[uuid] = ticks + } + } catch (e: Exception) { + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index a04c8d9..300f51b 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -14,4 +14,5 @@ output: onlinePlayers: "/online" permissions: "/permissions" points: "/points" + playtime: "/playtime" port: 80