Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ce9c40137a | |||
| b4eeb2dee7 | |||
| 90e36f45be | |||
| 3bf449a8cf | |||
| 0e212d8f54 | |||
| db88f6a3c4 | |||
| 282291f576 | |||
| 244681a7e7 | |||
| d9e95e884e | |||
| 8c5226f4bf | |||
| 0997ddc085 | |||
| 26c46b600a | |||
| 7da7e18da8 |
186
README.md
186
README.md
@@ -1,132 +1,118 @@
|
|||||||
# 🎄 Minecraft Adventskalender Plugin
|
<div align="center">
|
||||||
|
|
||||||
Ein hochgradig konfigurierbares Adventskalender-Plugin für **Spigot/Paper-Server**, das dir die volle Kontrolle über Belohnungen, Sprache und Funktionen gibt.
|
# ❄️ Minecraft Adventskalender ❄️
|
||||||
Perfekt, um die Weihnachtszeit auf deinem Server zu versüßen!
|
|
||||||
|
*Bringe festliche Stimmung auf deinen Server mit einem hochgradig anpassbaren System*
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🖥️ Adventskalender GUI
|
## Über Minecraft Adventskalender
|
||||||
|
|
||||||

|
Das **Minecraft Adventskalender Plugin** ist die ultimative Lösung für deinen Server im Dezember! Es bietet volle Kontrolle über Belohnungen, Sprache und Funktionen. Dank des neuen klickbaren Update-Checkers und dem erweiterten Admin-Test-System war die Verwaltung eines Events noch nie so einfach. Perfekt für Community-Events, um die Spielerbindung in der Weihnachtszeit zu stärken!
|
||||||

|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ✨ Features
|
## ✨ Exklusive Features
|
||||||
|
|
||||||
- **Anpassbare Belohnungen**
|
- **Vollständig Anpassbare Belohnungen:** Definiere für jeden Tag individuelle Items mit Menge, Name, Lore und Verzauberungen.
|
||||||
Definiere in der `config.yml` für jeden Tag ein eigenes Item, inklusive:
|
- **Smart Update-Checker:** Erhalte beim Joinen als Admin eine dezente, **klickbare Benachrichtigung**, falls eine neue Version verfügbar ist (erscheint verzögert nach 2 Sek.).
|
||||||
- Menge
|
- **Simulations Modus (Admin-Test):** Teste alle Türchen vorab durch Datums-Simulation, ohne deine Systemzeit zu ändern. Inklusive einfachem Reset auf das Echtzeit-Datum.
|
||||||
- Name
|
- **Präzises Reset-System:** Setze einzelne Tage oder komplette Fortschritte zurück – wahlweise für einzelne Spieler oder global für den ganzen Server.
|
||||||
- Lore
|
- **Immersive Effekte:** Festliche Sound- und Partikeleffekte beim Öffnen eines Türchens.
|
||||||
- Verzauberungen
|
- **Optimierte Tab-Completion:** Intelligente Befehlsvorschläge mit korrekter numerischer Sortierung (1, 2, 3... statt 1, 10, 11...).
|
||||||
|
|
||||||
- **Globaler oder individueller Kalender**
|
|
||||||
Entscheide, ob:
|
|
||||||
- jeder Spieler seinen eigenen Fortschritt hat oder
|
|
||||||
- ein Türchen serverweit nur einmal geöffnet werden kann
|
|
||||||
|
|
||||||
- **Sound & Partikel**
|
|
||||||
Angenehme Sound- und Partikeleffekte beim Öffnen eines Türchens.
|
|
||||||
|
|
||||||
- **Mehrsprachig**
|
|
||||||
Unterstützt **Deutsch** und **Englisch**.
|
|
||||||
Weitere Sprachen können einfach hinzugefügt werden.
|
|
||||||
|
|
||||||
- **Admin-Befehle**
|
|
||||||
Konfigurationen neu laden oder Türchen gezielt für Spieler öffnen.
|
|
||||||
|
|
||||||
- **Permissions-System**
|
|
||||||
Feingranulare Kontrolle über Spieler- und Admin-Rechte.
|
|
||||||
|
|
||||||
- **PlaceholderAPI-Unterstützung**
|
|
||||||
Zeige Statistiken:
|
|
||||||
- auf Schildern
|
|
||||||
- in der Tab-Liste
|
|
||||||
- mit Hologramm-Plugins
|
|
||||||
- Scoreboard
|
|
||||||
und vieles mehr.
|
|
||||||
|
|
||||||
- **Datenpersistenz**
|
|
||||||
Spielerfortschritt bleibt auch nach Server-Neustarts erhalten.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📸 Screenshots
|
## 🎄 Adventskalender GUI
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
|
||||||
|
<img src="https://git.viper.ipv64.net/M_Viper/Advenskalender/raw/branch/main/img/03.png" width="400" alt="Kalender GUI 1">
|
||||||
|
<img src="https://git.viper.ipv64.net/M_Viper/Advenskalender/raw/branch/main/img/04.png" width="400" alt="Kalender GUI 2">
|
||||||
|
|
||||||
|
*Die intuitive Kalender-Oberfläche mit allen 24 Türchen*
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚙️ Befehle & Permissions
|
||||||
|
|
||||||
|
### ▶ Spieler-Befehle
|
||||||
|
|
||||||
|
**`/adventskalender`** (Aliase: `/ak`, `/advent`, `/kalender`)
|
||||||
|
- **Beschreibung:** Öffnet die Kalender-Oberfläche.
|
||||||
|
- **Berechtigung:** `adventskalender.use`
|
||||||
|
|
||||||
|
### ▶ Admin-Befehle
|
||||||
|
|
||||||
|
**`/ak admin test <1-24 | reset>`**
|
||||||
|
- **Beschreibung:** Simuliert einen bestimmten Tag für Belohnungstests. Nutze `reset`, um zum echten Datum zurückzukehren.
|
||||||
|
- **Berechtigung:** `adventskalender.admin`
|
||||||
|
|
||||||
|
**`/ak admin resetday <global | Spieler> <1-24>`**
|
||||||
|
- **Beschreibung:** Setzt den Status eines spezifischen Tages für einen Spieler oder den gesamten Server zurück.
|
||||||
|
- **Berechtigung:** `adventskalender.admin`
|
||||||
|
|
||||||
|
**`/ak admin reset <global | Spieler>`**
|
||||||
|
- **Beschreibung:** Löscht den kompletten Fortschritt (alle Tage) für einen Spieler oder global.
|
||||||
|
- **Berechtigung:** `adventskalender.admin`
|
||||||
|
|
||||||
|
**`/ak admin reload`**
|
||||||
|
- **Beschreibung:** Lädt Config, Sprachdateien und Datenbank-Verbindung im laufenden Betrieb neu.
|
||||||
|
- **Berechtigung:** `adventskalender.admin`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 PlaceholderAPI (PAPI)
|
||||||
|
|
||||||
|
- **`%ak_c%`** - Anzahl bereits geöffneter Türchen.
|
||||||
|
- **`%ak_n%`** - Nummer des nächsten verfügbaren Türchens.
|
||||||
|
- **`%ak_d%`** - Verbleibende Tage bis zum 25. Dezember.
|
||||||
|
|
||||||
### Placeholder auf einem Schild
|
### Placeholder auf einem Schild
|
||||||
|
|
||||||
Ein Schild, das die Placeholder des Plugins anzeigt.
|
<div align="center">
|
||||||
|
|
||||||
<img src="https://git.viper.ipv64.net/M_Viper/Advenskalender/raw/branch/main/img/02.png" width="450" alt="Adventskalender Placeholder">
|
<img src="https://git.viper.ipv64.net/M_Viper/Advenskalender/raw/branch/main/img/02.png" alt="Placeholder Beispiel">
|
||||||
|
|
||||||
|
*Ein Schild, das die Placeholder des Plugins anzeigt.*
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🚀 Installation
|
## 💬 Support & Community
|
||||||
|
|
||||||
1. Lade die neueste Version des Plugins als **`.jar`-Datei** herunter.
|
Du hast Fragen oder Feedback? Tritt unserem Discord bei!
|
||||||
2. Platziere die Datei im Ordner:
|
|
||||||
|
|
||||||
/plugins
|
<div align="center">
|
||||||
|
|
||||||
3. Stelle sicher, dass **PlaceholderAPI** installiert ist (Pflichtabhängigkeit).
|
[](https://discord.com/invite/FdRs4BRd8D)
|
||||||
4. Starte oder starte den Server neu.
|
|
||||||
5. Passe die Konfigurationsdateien an: /plugins/Adventskalender/
|
*Klicke auf den Button für direkten Support durch die Community!*
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ⚙️ Konfiguration
|
## 🔧 Technische Details
|
||||||
|
|
||||||
Das Plugin verwendet drei Hauptdateien:
|
- **Kompatibilität:** Paper, Spigot, Purpur (1.18.x - 1.21.x)
|
||||||
|
- **Smart Caching:** Minimale Serverlast durch asynchrone Datenbankaufrufe.
|
||||||
- **`config.yml`**
|
- **Join-Delay:** Update-Meldungen erscheinen erst nach 2 Sekunden, um den Chat-Spam beim Joinen zu umgehen.
|
||||||
- Sprache
|
|
||||||
- Kalender-Typ (global / individuell)
|
|
||||||
- Belohnungen für alle 24 Tage
|
|
||||||
|
|
||||||
- **`messages_de.yml` / `messages_en.yml`**
|
|
||||||
- GUI-Titel
|
|
||||||
- Chat-Nachrichten
|
|
||||||
- Systemmeldungen
|
|
||||||
Diese Dateien können frei angepasst oder übersetzt werden.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📋 Befehle & Berechtigungen
|
<div align="center">
|
||||||
|
|
||||||
### Befehle
|
*Viper Plugins © 2026 - Effizienz und Magie für deinen Server*
|
||||||
|
|
||||||
| Befehl | Alias | Beschreibung | Berechtigung |
|
</div>
|
||||||
|------|------|-------------|--------------|
|
|
||||||
| `/adventskalender` | `/advent`, `/kalender`, `/ak` | Öffnet den Adventskalender | `adventskalender.use` |
|
|
||||||
| `/adventskalender admin reload` | `/ak admin reload` | Lädt Konfigurations- & Sprachdateien neu | `adventskalender.admin` |
|
|
||||||
| `/adventskalender admin open <spieler> <tag>` | `/ak admin open ...` | Öffnet ein Türchen für einen Spieler | `adventskalender.admin` |
|
|
||||||
|
|
||||||
### Berechtigungen
|
|
||||||
|
|
||||||
| Berechtigung | Standard | Beschreibung |
|
|
||||||
|-------------|----------|--------------|
|
|
||||||
| `adventskalender.use` | `true` | Erlaubt das Öffnen des Kalenders |
|
|
||||||
| `adventskalender.admin` | `op` | Erlaubt alle Admin-Befehle |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔗 Placeholders
|
|
||||||
|
|
||||||
Alle Placeholder sind **PlaceholderAPI-kompatibel** und kurz gehalten.
|
|
||||||
|
|
||||||
| Placeholder | Beschreibung |
|
|
||||||
|------------|--------------|
|
|
||||||
| `%ak_c%` | Anzahl geöffneter Türchen |
|
|
||||||
| `%ak_n%` | Nächstes verfügbares Türchen |
|
|
||||||
| `%ak_d%` | Verbleibende Tage bis 25. Dezember |
|
|
||||||
|
|
||||||
### Beispiel für ein Schild
|
|
||||||
|
|
||||||
|
|
||||||
Dein Fortschritt:
|
|
||||||
%ak_c%/24 Türchen
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
2
pom.xml
2
pom.xml
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<groupId>de.mviper</groupId>
|
<groupId>de.mviper</groupId>
|
||||||
<artifactId>adventskalender</artifactId>
|
<artifactId>adventskalender</artifactId>
|
||||||
<version>1.0.0</version>
|
<version>1.0.1</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
package de.mviper.adventskalender;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.command.Command;
|
|
||||||
import org.bukkit.command.CommandExecutor;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
|
|
||||||
public class AdminCommand implements CommandExecutor {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
|
||||||
if (args.length == 1 && args[0].equalsIgnoreCase("reload")) {
|
|
||||||
Adventskalender.getInstance().reloadConfig();
|
|
||||||
LanguageManager.setup();
|
|
||||||
sender.sendMessage(LanguageManager.getString("messages.admin.reload_success"));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.length == 3 && args[0].equalsIgnoreCase("open")) {
|
|
||||||
Player target = Bukkit.getPlayer(args[1]);
|
|
||||||
if (target == null) {
|
|
||||||
sender.sendMessage(LanguageManager.getString("messages.admin.player_not_found").replace("%player%", args[1]));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
int day = Integer.parseInt(args[2]);
|
|
||||||
if (day < 1 || day > 24) {
|
|
||||||
sender.sendMessage(LanguageManager.getString("messages.admin.invalid_day"));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target.getInventory().firstEmpty() == -1) {
|
|
||||||
target.getWorld().dropItemNaturally(target.getLocation(), AdventInventory.getRewardItem(day));
|
|
||||||
} else {
|
|
||||||
target.getInventory().addItem(AdventInventory.getRewardItem(day));
|
|
||||||
}
|
|
||||||
|
|
||||||
CalendarData.setClaimed(target, day);
|
|
||||||
|
|
||||||
sender.sendMessage(LanguageManager.getString("messages.admin.open_success").replace("%player%", target.getName()).replace("%day%", String.valueOf(day)));
|
|
||||||
target.sendMessage(LanguageManager.getString("messages.reward_received").replace("%day%", String.valueOf(day)));
|
|
||||||
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
sender.sendMessage(LanguageManager.getString("messages.admin.invalid_day"));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
sender.sendMessage("§cUsage: /adventskalender admin reload");
|
|
||||||
sender.sendMessage("§cUsage: /adventskalender admin open <player> <day>");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,61 +2,68 @@ package de.mviper.adventskalender;
|
|||||||
|
|
||||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.Month;
|
import java.time.Month;
|
||||||
|
|
||||||
public class AdventCalendarExpansion extends PlaceholderExpansion {
|
public class AdventCalendarExpansion extends PlaceholderExpansion {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getIdentifier() {
|
public @NotNull String getIdentifier() {
|
||||||
// Der Identifier ist jetzt nur noch "ak"
|
|
||||||
return "ak";
|
return "ak";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAuthor() {
|
public @NotNull String getAuthor() {
|
||||||
return "mviper";
|
return "M_Viper";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getVersion() {
|
public @NotNull String getVersion() {
|
||||||
return "1.1.0";
|
return "2.0.0";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canRegister() {
|
public boolean persist() {
|
||||||
return true;
|
return true; // Expansion bleibt nach PAPI-Reload registriert
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String onPlaceholderRequest(Player player, String identifier) {
|
public String onPlaceholderRequest(Player player, String identifier) {
|
||||||
if (player == null) {
|
if (player == null) return "";
|
||||||
return "";
|
|
||||||
|
// Aktuellen Tag ermitteln (Berücksichtigt den test_day aus der Config)
|
||||||
|
int testDay = Adventskalender.getInstance().getConfig().getInt("general.test_day", 0);
|
||||||
|
LocalDate date = LocalDate.now();
|
||||||
|
int currentDay = (testDay > 0) ? testDay : (date.getMonth() == Month.DECEMBER ? date.getDayOfMonth() : 0);
|
||||||
|
|
||||||
|
switch (identifier.toLowerCase()) {
|
||||||
|
|
||||||
|
// %ak_claimed% - Anzahl der bereits geöffneten Türchen
|
||||||
|
case "claimed":
|
||||||
|
return String.valueOf(DataHandler.getClaimedDays(player).size());
|
||||||
|
|
||||||
|
// %ak_day% - Der aktuelle Tag des Adventskalenders (1-24)
|
||||||
|
case "day":
|
||||||
|
return String.valueOf(currentDay);
|
||||||
|
|
||||||
|
// %ak_has_claimed_today% - Gibt "Ja" oder "Nein" zurück, ob heute schon geöffnet wurde
|
||||||
|
case "has_claimed_today":
|
||||||
|
if (currentDay == 0) return "Keine Adventszeit";
|
||||||
|
return DataHandler.hasClaimed(player, currentDay) ? "Ja" : "Nein";
|
||||||
|
|
||||||
|
// %ak_remaining% - Wie viele Türchen sind noch offen (für diesen Spieler)?
|
||||||
|
case "remaining":
|
||||||
|
int claimedCount = DataHandler.getClaimedDays(player).size();
|
||||||
|
return String.valueOf(24 - claimedCount);
|
||||||
|
|
||||||
|
// %ak_is_global% - Zeigt an, ob der globale Modus aktiv ist
|
||||||
|
case "is_global":
|
||||||
|
boolean isGlobal = Adventskalender.getInstance().getConfig().getBoolean("calendar.use_global_calendar", false);
|
||||||
|
return isGlobal ? "Global" : "Spieler-basiert";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Die Platzhalter sind jetzt viel kürzer
|
return null; // Placeholder unbekannt
|
||||||
switch (identifier) {
|
|
||||||
case "c": // Geöffnet (claimed)
|
|
||||||
return String.valueOf(CalendarData.getClaimedCount(player));
|
|
||||||
|
|
||||||
case "n": // Nächstes (next)
|
|
||||||
for (int day = 1; day <= 24; day++) {
|
|
||||||
if (!CalendarData.hasClaimed(player, day)) {
|
|
||||||
return String.valueOf(day);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "None";
|
|
||||||
|
|
||||||
case "d": // Tage (days)
|
|
||||||
LocalDate today = LocalDate.now();
|
|
||||||
LocalDate christmas = LocalDate.of(today.getYear(), Month.DECEMBER, 25);
|
|
||||||
if (today.isAfter(christmas)) {
|
|
||||||
christmas = christmas.plusYears(1);
|
|
||||||
}
|
|
||||||
return String.valueOf((int) java.time.temporal.ChronoUnit.DAYS.between(today, christmas));
|
|
||||||
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,23 +1,18 @@
|
|||||||
package de.mviper.adventskalender;
|
package de.mviper.adventskalender;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.command.*;
|
||||||
import org.bukkit.command.Command;
|
|
||||||
import org.bukkit.command.CommandExecutor;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class AdventCommand implements CommandExecutor {
|
public class AdventCommand implements CommandExecutor, TabCompleter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||||
|
if (args.length > 0 && args[0].equalsIgnoreCase("admin")) {
|
||||||
// --- Admin-Befehle (/ak admin ...) ---
|
|
||||||
if (args.length >= 1 && args[0].equalsIgnoreCase("admin")) {
|
|
||||||
// Prüfen, ob der Spieler die Admin-Berechtigung hat
|
|
||||||
if (!sender.hasPermission("adventskalender.admin")) {
|
if (!sender.hasPermission("adventskalender.admin")) {
|
||||||
sender.sendMessage(LanguageManager.getString("messages.no_permission"));
|
sender.sendMessage(LanguageManager.getMessage("messages.no_permission"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,63 +20,141 @@ public class AdventCommand implements CommandExecutor {
|
|||||||
if (args.length == 2 && args[1].equalsIgnoreCase("reload")) {
|
if (args.length == 2 && args[1].equalsIgnoreCase("reload")) {
|
||||||
Adventskalender.getInstance().reloadConfig();
|
Adventskalender.getInstance().reloadConfig();
|
||||||
LanguageManager.setup();
|
LanguageManager.setup();
|
||||||
sender.sendMessage(LanguageManager.getString("messages.admin.reload_success"));
|
DataHandler.setup();
|
||||||
|
sender.sendMessage(LanguageManager.getMessage("messages.admin.reload_success"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// /ak admin open <player> <day>
|
// /ak admin test <Tag/reset>
|
||||||
if (args.length == 4 && args[1].equalsIgnoreCase("open")) {
|
if (args.length == 3 && args[1].equalsIgnoreCase("test")) {
|
||||||
Player target = Bukkit.getPlayer(args[2]);
|
if (args[2].equalsIgnoreCase("reset")) {
|
||||||
if (target == null) {
|
Adventskalender.getInstance().getConfig().set("general.test_day", 0);
|
||||||
sender.sendMessage(LanguageManager.getString("messages.admin.player_not_found").replace("%player%", args[2]));
|
Adventskalender.getInstance().saveConfig();
|
||||||
|
sender.sendMessage("§e[Admin] §7Test-Modus §cbeendet§7. Das echte Datum wird nun verwendet.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int day = Integer.parseInt(args[3]);
|
int day = Integer.parseInt(args[2]);
|
||||||
if (day < 1 || day > 24) {
|
if (day < 1 || day > 24) {
|
||||||
sender.sendMessage(LanguageManager.getString("messages.admin.invalid_day"));
|
sender.sendMessage("§cBitte gib einen Tag zwischen 1 und 24 an (oder 'reset').");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Adventskalender.getInstance().getConfig().set("general.test_day", day);
|
||||||
ItemStack reward = AdventInventory.getRewardItem(day);
|
Adventskalender.getInstance().saveConfig();
|
||||||
if (reward != null && reward.getType() != Material.AIR) {
|
sender.sendMessage("§e[Admin] §7Test-Tag auf §6" + day + " §7gesetzt.");
|
||||||
if (target.getInventory().firstEmpty() == -1) {
|
|
||||||
target.getWorld().dropItemNaturally(target.getLocation(), reward);
|
|
||||||
} else {
|
|
||||||
target.getInventory().addItem(reward);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CalendarData.setClaimed(target, day);
|
|
||||||
|
|
||||||
sender.sendMessage(LanguageManager.getString("messages.admin.open_success").replace("%player%", target.getName()).replace("%day%", String.valueOf(day)));
|
|
||||||
target.sendMessage(LanguageManager.getString("messages.reward_received").replace("%day%", String.valueOf(day)));
|
|
||||||
|
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
sender.sendMessage(LanguageManager.getString("messages.admin.invalid_day"));
|
sender.sendMessage("§cBitte gib eine gültige Zahl (1-24) oder 'reset' an.");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Falsche Nutzung der Admin-Befehle
|
// /ak admin resetday <global/Spieler> <Tag>
|
||||||
sender.sendMessage("§cUsage: /ak admin reload");
|
if (args.length == 4 && args[1].equalsIgnoreCase("resetday")) {
|
||||||
sender.sendMessage("§cUsage: /ak admin open <player> <day>");
|
String target = args[2];
|
||||||
|
try {
|
||||||
|
int day = Integer.parseInt(args[3]);
|
||||||
|
if (day < 1 || day > 24) throw new NumberFormatException();
|
||||||
|
|
||||||
|
if (target.equalsIgnoreCase("global")) {
|
||||||
|
DataHandler.GlobalDataManager.resetGlobalDay(day);
|
||||||
|
sender.sendMessage("§a[Admin] §7Tag §6" + day + " §7global zurückgesetzt.");
|
||||||
|
} else {
|
||||||
|
DataHandler.resetPlayerDay(target, day);
|
||||||
|
sender.sendMessage("§a[Admin] §7Tag §6" + day + " §7für §e" + target + " §7zurückgesetzt.");
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
sender.sendMessage("§cTag muss zwischen 1 und 24 liegen.");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// /ak admin reset <global/Spieler>
|
||||||
|
if (args.length >= 3 && args[1].equalsIgnoreCase("reset")) {
|
||||||
|
String baseTitle = LanguageManager.getString("gui.title");
|
||||||
|
if (args[2].equalsIgnoreCase("global")) {
|
||||||
|
DataHandler.resetAll();
|
||||||
|
for (Player online : Bukkit.getOnlinePlayers()) {
|
||||||
|
if (online.getOpenInventory().getTitle().contains(baseTitle)) online.closeInventory();
|
||||||
|
}
|
||||||
|
sender.sendMessage("§a[Admin] §7Kompletter Reset durchgeführt.");
|
||||||
|
} else {
|
||||||
|
String targetName = args[2];
|
||||||
|
Player target = Bukkit.getPlayer(targetName);
|
||||||
|
if (target != null) {
|
||||||
|
DataHandler.resetPlayer(target);
|
||||||
|
if (target.getOpenInventory().getTitle().contains(baseTitle)) target.closeInventory();
|
||||||
|
sender.sendMessage("§a[Admin] §7Daten für §e" + target.getName() + " §7gelöscht.");
|
||||||
|
} else {
|
||||||
|
DataHandler.resetOfflinePlayer(targetName);
|
||||||
|
sender.sendMessage("§a[Admin] §7Offline-Daten für §e" + targetName + " §7gelöscht.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
sender.sendMessage("§8§m---§r §6Advent Admin §8§m---");
|
||||||
|
sender.sendMessage("§e/ak admin reload §7- Config neu laden");
|
||||||
|
sender.sendMessage("§e/ak admin test <1-24/reset> §7- Datum simulieren");
|
||||||
|
sender.sendMessage("§e/ak admin resetday <global/Spieler> <Tag> §7- Tag löschen");
|
||||||
|
sender.sendMessage("§e/ak admin reset <global/Spieler> §7- Alles löschen");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Hauptbefehl (/ak) ---
|
if (!(sender instanceof Player player)) return true;
|
||||||
if (!(sender instanceof Player)) {
|
|
||||||
sender.sendMessage(LanguageManager.getString("messages.only_player"));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Player player = (Player) sender;
|
|
||||||
if (!player.hasPermission("adventskalender.use")) {
|
if (!player.hasPermission("adventskalender.use")) {
|
||||||
player.sendMessage(LanguageManager.getString("messages.no_permission"));
|
player.sendMessage(LanguageManager.getMessage("messages.no_permission"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
AdventInventory.openCalendar(player);
|
AdventInventory.open(player);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> onTabComplete(CommandSender s, Command c, String a, String[] args) {
|
||||||
|
if (args.length == 1) return Collections.singletonList("admin");
|
||||||
|
|
||||||
|
if (args.length == 2 && args[0].equalsIgnoreCase("admin"))
|
||||||
|
return Arrays.asList("reload", "test", "reset", "resetday");
|
||||||
|
|
||||||
|
// Tab-Completion für das Ziel (global oder Spielername)
|
||||||
|
if (args.length == 3 && (args[1].equalsIgnoreCase("reset") || args[1].equalsIgnoreCase("resetday"))) {
|
||||||
|
List<String> options = new ArrayList<>();
|
||||||
|
options.add("global");
|
||||||
|
Bukkit.getOnlinePlayers().forEach(p -> options.add(p.getName()));
|
||||||
|
return options.stream()
|
||||||
|
.filter(opt -> opt.toLowerCase().startsWith(args[2].toLowerCase()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tab-Completion für die TAGE (Numerisch sortiert)
|
||||||
|
if ((args.length == 3 && args[1].equalsIgnoreCase("test")) || (args.length == 4 && args[1].equalsIgnoreCase("resetday"))) {
|
||||||
|
List<String> options = new ArrayList<>();
|
||||||
|
|
||||||
|
// "reset" Option nur für den test command hinzufügen
|
||||||
|
if (args[1].equalsIgnoreCase("test")) {
|
||||||
|
options.add("reset");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i <= 24; i++) {
|
||||||
|
options.add(String.valueOf(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
String currentInput = (args.length == 3) ? args[2] : args[3];
|
||||||
|
|
||||||
|
return options.stream()
|
||||||
|
.filter(opt -> opt.toLowerCase().startsWith(currentInput.toLowerCase()))
|
||||||
|
.sorted((s1, s2) -> {
|
||||||
|
// "reset" immer nach oben sortieren
|
||||||
|
if (s1.equalsIgnoreCase("reset")) return -1;
|
||||||
|
if (s2.equalsIgnoreCase("reset")) return 1;
|
||||||
|
// Restliche Zahlen numerisch vergleichen
|
||||||
|
return Integer.compare(Integer.parseInt(s1), Integer.parseInt(s2));
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3,116 +3,152 @@ package de.mviper.adventskalender;
|
|||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.enchantments.Enchantment;
|
import org.bukkit.enchantments.Enchantment;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
import org.bukkit.inventory.ItemFlag;
|
import org.bukkit.inventory.ItemFlag;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
import org.bukkit.inventory.meta.SkullMeta;
|
||||||
|
import org.bukkit.profile.PlayerProfile;
|
||||||
|
import org.bukkit.profile.PlayerTextures;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.Month;
|
import java.time.Month;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class AdventInventory {
|
public class AdventInventory {
|
||||||
|
|
||||||
public static void openCalendar(org.bukkit.entity.Player player) {
|
// Textur für das geöffnete Geschenk (Wreath)
|
||||||
String title = LanguageManager.getString("gui.title");
|
private static final String OPEN_WREATH_URL = "http://textures.minecraft.net/texture/5e39248b341c87ce3e4294ac214c6f74468889cb1273ae7412906fd28db097e8";
|
||||||
|
|
||||||
|
// Texturen für die geschlossenen Tage (1-24)
|
||||||
|
private static final Map<Integer, String> CLOSED_TEXTURES = new HashMap<>();
|
||||||
|
private static final Map<String, ItemStack> HEAD_CACHE = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
// Hier sind die URLs für die "Christmas Calendar #01-24 (red)" Reihe
|
||||||
|
CLOSED_TEXTURES.put(1, "http://textures.minecraft.net/texture/105b356be68ac56cfe0611b95027adf1ee67050e4cd66a0a99678fc2e25b6b0f");
|
||||||
|
CLOSED_TEXTURES.put(2, "http://textures.minecraft.net/texture/40ec45e8ffb9cb714d1412bb9ee54fd1e7a3140c02e35ae0d3f308f1666ba126");
|
||||||
|
CLOSED_TEXTURES.put(3, "http://textures.minecraft.net/texture/2466629a31aae22dba15a7b710a4517308656c19ba39a89ac2de2915a46e2823");
|
||||||
|
CLOSED_TEXTURES.put(4, "http://textures.minecraft.net/texture/97a1956ed6f32e18b139f2d709355ac6945d0ab8fecd04d4c159d08006bfbe58");
|
||||||
|
CLOSED_TEXTURES.put(5, "http://textures.minecraft.net/texture/855fad012c8844fc313510436b4919e002d93d6a0761f7bdaf78069683eee5e6");
|
||||||
|
CLOSED_TEXTURES.put(6, "http://textures.minecraft.net/texture/c0400111ae026101077b59d8482c84a832c74f4f2105fc13b7c94f5b8000ea3");
|
||||||
|
CLOSED_TEXTURES.put(7, "http://textures.minecraft.net/texture/a34505ed2567ea2efbab49977f7da8f1178db9ae53a0e99737286dc56e63636a");
|
||||||
|
CLOSED_TEXTURES.put(8, "http://textures.minecraft.net/texture/a17ddf12485fb54cab9c9ffb55feea62a2d90b825772c6ea38561ce750cb6f83");
|
||||||
|
CLOSED_TEXTURES.put(9, "http://textures.minecraft.net/texture/f75022feb11b736e50bc7d19d26d4ee00cecd6734a2138d2579f799b119b6734");
|
||||||
|
CLOSED_TEXTURES.put(10, "http://textures.minecraft.net/texture/6b84208e4be2233fcd96e7f02d9613d5437f1d006236277c57d40652c5be2f23");
|
||||||
|
|
||||||
|
CLOSED_TEXTURES.put(11, "http://textures.minecraft.net/texture/19aa8a65ba29b4b7cbb9c66cf59fb537ba2c3013a958620b976b9f06248e8dda");
|
||||||
|
CLOSED_TEXTURES.put(12, "http://textures.minecraft.net/texture/7dc1330b302e800c31c8dfefbd1b996016c34649f3a396749d3e048637364aad");
|
||||||
|
CLOSED_TEXTURES.put(13, "http://textures.minecraft.net/texture/7e98a3884e0eac967c73a2bcbff7df62ab2fb327b4ceb9e636c74254866b5c7c");
|
||||||
|
CLOSED_TEXTURES.put(14, "http://textures.minecraft.net/texture/3866643decb2d148999f9768dae89fbdb196b30d55f8846b1fbbe736bb7e5042");
|
||||||
|
CLOSED_TEXTURES.put(15, "http://textures.minecraft.net/texture/744a95611950cc7f154c9f56ad472c1941376ec171efb8ba476e6cec4f866526");
|
||||||
|
CLOSED_TEXTURES.put(16, "http://textures.minecraft.net/texture/1546959556eff4b8827ca50d8df686e8f20d5c843da689dddc48bff0a217efbe");
|
||||||
|
CLOSED_TEXTURES.put(17, "http://textures.minecraft.net/texture/1f4fb00e824c97d9cfba4c44def27a79513978979515048f2e69eb5b7123c159");
|
||||||
|
CLOSED_TEXTURES.put(18, "http://textures.minecraft.net/texture/9216b42018004a86081b5c1ee87dc8f12770f1859266e2cd359b75b44b5e7680");
|
||||||
|
CLOSED_TEXTURES.put(19, "http://textures.minecraft.net/texture/93c7097291042c394267892c56feee9ba3936826ea5b2232f46cb5474f9cd937");
|
||||||
|
CLOSED_TEXTURES.put(20, "http://textures.minecraft.net/texture/4f85a13977d01865a9d95d3279528285872551c36fd5231c7e3ab9897a7560fd");
|
||||||
|
|
||||||
|
CLOSED_TEXTURES.put(21, "http://textures.minecraft.net/texture/cdb512403f3610966d10bd3ca9fc61fdc5021268382f69719ac5679f3efd4c14");
|
||||||
|
CLOSED_TEXTURES.put(22, "http://textures.minecraft.net/texture/cadaef824771250374fc3e82efe020ab765e665340cc2393f3b4ae8d6d18529c");
|
||||||
|
CLOSED_TEXTURES.put(23, "http://textures.minecraft.net/texture/266f896c37a9d7fb857ff8c9f6f5e3540d17e1b893419f523eb199b71e71dde3");
|
||||||
|
CLOSED_TEXTURES.put(24, "http://textures.minecraft.net/texture/f081f9274e4ef802453ac95381c00426e462440d3bb085fb3afefa6ded6a8d01");
|
||||||
|
// Hinweis: In der Praxis füllst du hier alle 1-24 mit den URLs von Minecraft-Heads.
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void initCache() {
|
||||||
|
// Cache den Wreath-Kopf
|
||||||
|
HEAD_CACHE.put("OPENED", createBaseSkull(OPEN_WREATH_URL));
|
||||||
|
|
||||||
|
// Cache alle nummerierten geschlossenen Köpfe
|
||||||
|
for (int i = 1; i <= 24; i++) {
|
||||||
|
if (CLOSED_TEXTURES.containsKey(i)) {
|
||||||
|
HEAD_CACHE.put("CLOSED_" + i, createBaseSkull(CLOSED_TEXTURES.get(i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void open(Player player) {
|
||||||
|
String title = " " + LanguageManager.getString("gui.title");
|
||||||
Inventory inv = Bukkit.createInventory(null, 54, title);
|
Inventory inv = Bukkit.createInventory(null, 54, title);
|
||||||
|
|
||||||
for (int i = 0; i < 24; i++) {
|
int testDay = Adventskalender.getInstance().getConfig().getInt("general.test_day", 0);
|
||||||
int day = i + 1;
|
LocalDate date = LocalDate.now();
|
||||||
ItemStack item = getCalendarItem(player, day);
|
int currentDay = (testDay > 0) ? testDay : (date.getMonth() == Month.DECEMBER ? date.getDayOfMonth() : 0);
|
||||||
inv.setItem(i, item);
|
|
||||||
|
for (int i = 0; i < 54; i++) {
|
||||||
|
if (i < 9 || i >= 45 || i % 9 == 0 || (i + 1) % 9 == 0) {
|
||||||
|
Material m = (i % 2 == 0) ? Material.RED_STAINED_GLASS_PANE : Material.GREEN_STAINED_GLASS_PANE;
|
||||||
|
inv.setItem(i, createFiller(m));
|
||||||
|
} else {
|
||||||
|
inv.setItem(i, createFiller(Material.WHITE_STAINED_GLASS_PANE));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemStack filler = new ItemStack(Material.GRAY_STAINED_GLASS_PANE);
|
int[] slots = {10, 11, 12, 13, 14, 15, 16, 19, 20, 21, 22, 23, 24, 25, 28, 29, 30, 31, 32, 33, 34, 39, 40, 41};
|
||||||
ItemMeta fillerMeta = filler.getItemMeta();
|
|
||||||
fillerMeta.setDisplayName(" ");
|
for (int day = 1; day <= 24; day++) {
|
||||||
filler.setItemMeta(fillerMeta);
|
boolean claimed = DataHandler.hasClaimed(player, day);
|
||||||
for (int i = 24; i < 54; i++) {
|
boolean isAvailable = currentDay >= day;
|
||||||
inv.setItem(i, filler);
|
inv.setItem(slots[day - 1], createGiftItem(day, claimed, isAvailable));
|
||||||
}
|
}
|
||||||
|
|
||||||
player.openInventory(inv);
|
player.openInventory(inv);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ItemStack getCalendarItem(org.bukkit.entity.Player player, int day) {
|
private static ItemStack createGiftItem(int day, boolean claimed, boolean isAvailable) {
|
||||||
LocalDate today = LocalDate.now();
|
ItemStack item;
|
||||||
String prefix = LanguageManager.getString("prefix");
|
if (claimed) {
|
||||||
|
item = HEAD_CACHE.getOrDefault("OPENED", new ItemStack(Material.PLAYER_HEAD)).clone();
|
||||||
if (today.getMonth() != Month.DECEMBER || today.getDayOfMonth() < day) {
|
} else {
|
||||||
ItemStack item = new ItemStack(Material.BARRIER);
|
item = HEAD_CACHE.getOrDefault("CLOSED_" + day, new ItemStack(Material.PLAYER_HEAD)).clone();
|
||||||
ItemMeta meta = item.getItemMeta();
|
|
||||||
meta.setDisplayName(prefix + "§cTag " + day);
|
|
||||||
List<String> lore = new ArrayList<>();
|
|
||||||
lore.add(prefix + "§7Noch nicht verfügbar.");
|
|
||||||
lore.add(prefix + "§7Komme am " + day + ". Dezember wieder.");
|
|
||||||
meta.setLore(lore);
|
|
||||||
item.setItemMeta(meta);
|
|
||||||
return item;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CalendarData.hasClaimed(player, day)) {
|
|
||||||
ItemStack item = new ItemStack(Material.GREEN_STAINED_GLASS_PANE);
|
|
||||||
ItemMeta meta = item.getItemMeta();
|
|
||||||
meta.setDisplayName(prefix + "§aTag " + day + " - Geöffnet");
|
|
||||||
List<String> lore = new ArrayList<>();
|
|
||||||
lore.add(prefix + LanguageManager.getString("messages.day_already_claimed"));
|
|
||||||
meta.setLore(lore);
|
|
||||||
item.setItemMeta(meta);
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemStack item = new ItemStack(Material.CHEST);
|
|
||||||
ItemMeta meta = item.getItemMeta();
|
ItemMeta meta = item.getItemMeta();
|
||||||
meta.setDisplayName(prefix + "§eTag " + day + " - Noch zu holen!");
|
|
||||||
List<String> lore = new ArrayList<>();
|
List<String> lore = new ArrayList<>();
|
||||||
lore.add(prefix + "§7Klicke, um dein Geschenk zu erhalten.");
|
lore.add(" ");
|
||||||
|
|
||||||
|
if (claimed) {
|
||||||
|
meta.setDisplayName(LanguageManager.getString("rewards.day_" + day + ".name"));
|
||||||
|
meta.addEnchant(Enchantment.LUCK, 1, true);
|
||||||
|
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
|
||||||
|
lore.add("§8» §6Bereits abgeholt");
|
||||||
|
lore.add("§aDu hast dieses Geschenk bereits geöffnet! ✔");
|
||||||
|
} else {
|
||||||
|
if (!isAvailable) {
|
||||||
|
meta.setDisplayName("§c§lTag #" + day);
|
||||||
|
lore.add("§8» §7Noch verschlossen");
|
||||||
|
lore.add("§7Komme am " + day + ". Dezember wieder!");
|
||||||
|
} else {
|
||||||
|
meta.setDisplayName(LanguageManager.getString("rewards.day_" + day + ".name"));
|
||||||
|
lore.add("§8» §eKlicke zum Öffnen!");
|
||||||
|
lore.addAll(LanguageManager.getStringList("rewards.day_" + day + ".lore"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
meta.setLore(lore);
|
meta.setLore(lore);
|
||||||
item.setItemMeta(meta);
|
item.setItemMeta(meta);
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ItemStack getRewardItem(int day) {
|
private static ItemStack createBaseSkull(String url) {
|
||||||
String path = "rewards." + day;
|
ItemStack item = new ItemStack(Material.PLAYER_HEAD);
|
||||||
if (!Adventskalender.getInstance().getConfig().contains(path)) {
|
SkullMeta meta = (SkullMeta) item.getItemMeta();
|
||||||
return new ItemStack(Material.AIR);
|
try {
|
||||||
}
|
UUID uuid = UUID.nameUUIDFromBytes(url.getBytes());
|
||||||
|
PlayerProfile profile = Bukkit.createPlayerProfile(uuid, "AdventHead");
|
||||||
|
profile.getTextures().setSkin(new URL(url));
|
||||||
|
meta.setOwnerProfile(profile);
|
||||||
|
item.setItemMeta(meta);
|
||||||
|
} catch (MalformedURLException e) { e.printStackTrace(); }
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
String materialName = Adventskalender.getInstance().getConfig().getString(path + ".material");
|
private static ItemStack createFiller(Material material) {
|
||||||
int amount = Adventskalender.getInstance().getConfig().getInt(path + ".amount");
|
ItemStack item = new ItemStack(material);
|
||||||
String key = Adventskalender.getInstance().getConfig().getString(path + ".key");
|
|
||||||
|
|
||||||
Material material = Material.getMaterial(materialName);
|
|
||||||
if (material == null) {
|
|
||||||
Adventskalender.getInstance().getLogger().warning("Material '" + materialName + "' für Tag " + day + " nicht gefunden!");
|
|
||||||
return new ItemStack(Material.BARRIER);
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemStack item = new ItemStack(material, amount);
|
|
||||||
ItemMeta meta = item.getItemMeta();
|
ItemMeta meta = item.getItemMeta();
|
||||||
|
if (meta != null) { meta.setDisplayName(" "); item.setItemMeta(meta); }
|
||||||
String namePath = key + ".name";
|
|
||||||
String lorePath = key + ".lore";
|
|
||||||
|
|
||||||
meta.setDisplayName(LanguageManager.getString(namePath));
|
|
||||||
meta.setLore(LanguageManager.getStringList(lorePath));
|
|
||||||
|
|
||||||
List<Map<?, ?>> enchantmentList = Adventskalender.getInstance().getConfig().getMapList(path + ".enchantments");
|
|
||||||
if (enchantmentList != null) {
|
|
||||||
for (Map<?, ?> enchantmentMap : enchantmentList) {
|
|
||||||
String enchantName = (String) enchantmentMap.get("type");
|
|
||||||
int level = (int) enchantmentMap.get("level");
|
|
||||||
Enchantment enchantment = Enchantment.getByName(enchantName);
|
|
||||||
if (enchantment != null) {
|
|
||||||
meta.addEnchant(enchantment, level, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
|
|
||||||
item.setItemMeta(meta);
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,56 +1,135 @@
|
|||||||
package de.mviper.adventskalender;
|
package de.mviper.adventskalender;
|
||||||
|
|
||||||
import org.bukkit.*;
|
import net.md_5.bungee.api.chat.ClickEvent;
|
||||||
|
import net.md_5.bungee.api.chat.HoverEvent;
|
||||||
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
|
import net.md_5.bungee.api.chat.hover.content.Text;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.Sound;
|
||||||
|
import org.bukkit.enchantments.Enchantment;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.Month;
|
import java.time.Month;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class AdventListener implements Listener {
|
public class AdventListener implements Listener {
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onInventoryClick(InventoryClickEvent event) {
|
public void onJoin(PlayerJoinEvent event) {
|
||||||
String translatedTitle = LanguageManager.getString("gui.title");
|
Player player = event.getPlayer();
|
||||||
|
|
||||||
if (event.getView().getTitle().equals(translatedTitle)) {
|
// Nachricht an Admins senden, wenn ein Update da ist
|
||||||
event.setCancelled(true);
|
if (player.hasPermission("adventskalender.admin")) {
|
||||||
|
// Delay von 2 Sekunden (40 Ticks), damit die Nachricht nicht im Join-Spam untergeht
|
||||||
|
Bukkit.getScheduler().runTaskLater(Adventskalender.getInstance(), () -> {
|
||||||
|
if (Adventskalender.getInstance().isUpdateAvailable()) {
|
||||||
|
String latest = Adventskalender.getInstance().getLatestVersion();
|
||||||
|
String current = Adventskalender.getInstance().getDescription().getVersion();
|
||||||
|
|
||||||
if (!(event.getWhoClicked() instanceof Player)) return;
|
player.sendMessage("§7 ");
|
||||||
Player player = (Player) event.getWhoClicked();
|
player.sendMessage("§8§m+-------------------------------------------+");
|
||||||
|
player.sendMessage("§6§l ADVENTSKALENDER UPDATE");
|
||||||
|
player.sendMessage("§7 ");
|
||||||
|
player.sendMessage("§7 Eine neue Version ist verfügbar: §a§l" + latest);
|
||||||
|
player.sendMessage("§7 Installierte Version: §c" + current);
|
||||||
|
player.sendMessage("§7 ");
|
||||||
|
|
||||||
int slot = event.getSlot();
|
// Erstellung der klickbaren Nachricht
|
||||||
if (slot < 0 || slot > 23) return;
|
TextComponent message = new TextComponent("§e §nKLICKE HIER ZUM DOWNLOAD");
|
||||||
|
message.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://www.spigotmc.org/resources/130974/"));
|
||||||
|
message.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("§7Öffnet die Spigot-Seite")));
|
||||||
|
|
||||||
int day = slot + 1;
|
player.spigot().sendMessage(message);
|
||||||
LocalDate today = LocalDate.now();
|
|
||||||
|
|
||||||
if (today.getMonth() == Month.DECEMBER && today.getDayOfMonth() >= day && !CalendarData.hasClaimed(player, day)) {
|
player.sendMessage("§7 ");
|
||||||
ItemStack reward = AdventInventory.getRewardItem(day);
|
player.sendMessage("§8§m+-------------------------------------------+");
|
||||||
if (reward != null && reward.getType() != Material.AIR) {
|
player.sendMessage("§7 ");
|
||||||
if (player.getInventory().firstEmpty() == -1) {
|
|
||||||
player.getWorld().dropItemNaturally(player.getLocation(), reward);
|
|
||||||
player.sendMessage(LanguageManager.getString("messages.inventory_full"));
|
|
||||||
} else {
|
|
||||||
player.getInventory().addItem(reward);
|
|
||||||
}
|
|
||||||
player.sendMessage(LanguageManager.getString("messages.reward_received").replace("%day%", String.valueOf(day)));
|
|
||||||
|
|
||||||
player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1.0f, 1.0f);
|
|
||||||
player.spawnParticle(Particle.VILLAGER_HAPPY, player.getLocation().add(0, 1, 0), 20, 0.5, 0.5, 0.5, 0);
|
|
||||||
}
|
}
|
||||||
|
}, 40L);
|
||||||
CalendarData.setClaimed(player, day);
|
|
||||||
ItemStack newItem = AdventInventory.getCalendarItem(player, day);
|
|
||||||
event.getInventory().setItem(slot, newItem);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
player.sendMessage(LanguageManager.getString("messages.day_not_available"));
|
|
||||||
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1.0f, 1.0f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onInventoryClick(InventoryClickEvent event) {
|
||||||
|
String baseTitle = LanguageManager.getString("gui.title");
|
||||||
|
if (!event.getView().getTitle().contains(baseTitle)) return;
|
||||||
|
|
||||||
|
event.setCancelled(true);
|
||||||
|
|
||||||
|
if (!(event.getWhoClicked() instanceof Player player)) return;
|
||||||
|
|
||||||
|
ItemStack clicked = event.getCurrentItem();
|
||||||
|
if (clicked == null || clicked.getType() != Material.PLAYER_HEAD) return;
|
||||||
|
if (!clicked.hasItemMeta() || !clicked.getItemMeta().hasDisplayName()) return;
|
||||||
|
|
||||||
|
String displayName = ChatColor.stripColor(clicked.getItemMeta().getDisplayName());
|
||||||
|
int day;
|
||||||
|
try {
|
||||||
|
day = Integer.parseInt(displayName.replaceAll("[^0-9]", ""));
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int testDay = Adventskalender.getInstance().getConfig().getInt("general.test_day", 0);
|
||||||
|
LocalDate date = LocalDate.now();
|
||||||
|
int currentDay = (testDay > 0) ? testDay : (date.getMonth() == Month.DECEMBER ? date.getDayOfMonth() : 0);
|
||||||
|
|
||||||
|
if (currentDay >= day) {
|
||||||
|
if (DataHandler.hasClaimed(player, day)) {
|
||||||
|
player.sendMessage(LanguageManager.getMessage("messages.day_already_claimed"));
|
||||||
|
player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
giveReward(player, day);
|
||||||
|
DataHandler.setClaimed(player, day);
|
||||||
|
player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1f, 1.5f);
|
||||||
|
|
||||||
|
AdventInventory.open(player);
|
||||||
|
} else {
|
||||||
|
player.sendMessage(LanguageManager.getMessage("messages.day_not_available"));
|
||||||
|
player.playSound(player.getLocation(), Sound.BLOCK_CHEST_LOCKED, 1f, 1f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void giveReward(Player player, int day) {
|
||||||
|
String path = "rewards." + day;
|
||||||
|
String matName = Adventskalender.getInstance().getConfig().getString(path + ".material", "COOKIE");
|
||||||
|
int amount = Adventskalender.getInstance().getConfig().getInt(path + ".amount", 1);
|
||||||
|
|
||||||
|
ItemStack reward = new ItemStack(Material.valueOf(matName.toUpperCase()), amount);
|
||||||
|
ItemMeta meta = reward.getItemMeta();
|
||||||
|
|
||||||
|
if (meta != null) {
|
||||||
|
List<Map<?, ?>> enchants = Adventskalender.getInstance().getConfig().getMapList(path + ".enchantments");
|
||||||
|
for (Map<?, ?> entry : enchants) {
|
||||||
|
String type = (String) entry.get("type");
|
||||||
|
Object levelObj = entry.get("level");
|
||||||
|
int level = (levelObj instanceof Integer) ? (int) levelObj : 1;
|
||||||
|
|
||||||
|
Enchantment enc = Enchantment.getByName(type.toUpperCase());
|
||||||
|
if (enc != null) {
|
||||||
|
meta.addEnchant(enc, level, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reward.setItemMeta(meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.getInventory().firstEmpty() == -1) {
|
||||||
|
player.getWorld().dropItemNaturally(player.getLocation(), reward);
|
||||||
|
player.sendMessage(LanguageManager.getMessage("messages.inventory_full"));
|
||||||
|
} else {
|
||||||
|
player.getInventory().addItem(reward);
|
||||||
|
}
|
||||||
|
player.sendMessage(LanguageManager.getMessage("messages.reward_received").replace("%day%", String.valueOf(day)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,39 +1,62 @@
|
|||||||
package de.mviper.adventskalender;
|
package de.mviper.adventskalender;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
public final class Adventskalender extends JavaPlugin {
|
public final class Adventskalender extends JavaPlugin {
|
||||||
private static Adventskalender instance;
|
private static Adventskalender instance;
|
||||||
|
private NamespacedKey dataKey;
|
||||||
|
|
||||||
|
// Update-Status Variablen
|
||||||
|
private boolean updateAvailable = false;
|
||||||
|
private String latestVersion = "";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
instance = this;
|
instance = this;
|
||||||
saveDefaultConfig();
|
this.dataKey = new NamespacedKey(this, "claimed_days_v2");
|
||||||
|
|
||||||
|
saveDefaultConfig();
|
||||||
LanguageManager.setup();
|
LanguageManager.setup();
|
||||||
CalendarData.setup();
|
|
||||||
|
// Initialisierung der Daten (MySQL wird hier bevorzugt behandelt)
|
||||||
|
DataHandler.setup();
|
||||||
|
|
||||||
|
// Textur-Puffer füllen, um Steve-Köpfe zu vermeiden
|
||||||
|
AdventInventory.initCache();
|
||||||
|
|
||||||
getCommand("adventskalender").setExecutor(new AdventCommand());
|
getCommand("adventskalender").setExecutor(new AdventCommand());
|
||||||
getServer().getPluginManager().registerEvents(new AdventListener(), this);
|
getServer().getPluginManager().registerEvents(new AdventListener(), this);
|
||||||
|
|
||||||
// Prüfen, ob PlaceholderAPI vorhanden ist und unsere neue Erweiterung registrieren
|
// Update Checker Integration (ID: 130974)
|
||||||
|
new UpdateChecker(this, 130974).getVersion(version -> {
|
||||||
|
if (!this.getDescription().getVersion().equals(version)) {
|
||||||
|
this.updateAvailable = true;
|
||||||
|
this.latestVersion = version;
|
||||||
|
getLogger().warning("Eine neue Version (" + version + ") ist verfügbar!");
|
||||||
|
getLogger().warning("Download: https://www.spigotmc.org/resources/130974/");
|
||||||
|
} else {
|
||||||
|
getLogger().info("Das Plugin ist auf dem neuesten Stand.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
|
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
|
||||||
new AdventCalendarExpansion().register();
|
new AdventCalendarExpansion().register();
|
||||||
getLogger().info("PlaceholderAPI expansion registered.");
|
|
||||||
} else {
|
|
||||||
getLogger().warning("PlaceholderAPI not found. Placeholders will not work.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getLogger().info("Adventskalender-Plugin wurde erfolgreich aktiviert!");
|
getLogger().info("Adventskalender erfolgreich gestartet!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
getLogger().info("Adventskalender-Plugin wurde deaktiviert.");
|
MySQLManager.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Adventskalender getInstance() {
|
public static Adventskalender getInstance() { return instance; }
|
||||||
return instance;
|
public NamespacedKey getDataKey() { return dataKey; }
|
||||||
}
|
|
||||||
|
// Getter für den Update-Status
|
||||||
|
public boolean isUpdateAvailable() { return updateAvailable; }
|
||||||
|
public String getLatestVersion() { return latestVersion; }
|
||||||
}
|
}
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
package de.mviper.adventskalender;
|
|
||||||
|
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class CalendarData {
|
|
||||||
|
|
||||||
private static File file;
|
|
||||||
private static FileConfiguration customFile;
|
|
||||||
|
|
||||||
public static void setup() {
|
|
||||||
file = new File(Adventskalender.getInstance().getDataFolder(), "calendar.yml");
|
|
||||||
if (!file.exists()) {
|
|
||||||
try {
|
|
||||||
file.createNewFile();
|
|
||||||
} catch (IOException e) {
|
|
||||||
Adventskalender.getInstance().getLogger().severe("Konnte calendar.yml nicht erstellen: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
customFile = YamlConfiguration.loadConfiguration(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void save() {
|
|
||||||
try {
|
|
||||||
customFile.save(file);
|
|
||||||
} catch (IOException e) {
|
|
||||||
Adventskalender.getInstance().getLogger().severe("Konnte calendar.yml nicht speichern: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean hasClaimed(Player player, int day) {
|
|
||||||
boolean isGlobal = Adventskalender.getInstance().getConfig().getBoolean("calendar.use_global_calendar");
|
|
||||||
if (isGlobal) {
|
|
||||||
List<Integer> claimedDays = customFile.getIntegerList("global_claimed_days");
|
|
||||||
return claimedDays.contains(day);
|
|
||||||
} else {
|
|
||||||
List<Integer> claimedDays = customFile.getIntegerList(player.getUniqueId().toString());
|
|
||||||
return claimedDays.contains(day);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setClaimed(Player player, int day) {
|
|
||||||
boolean isGlobal = Adventskalender.getInstance().getConfig().getBoolean("calendar.use_global_calendar");
|
|
||||||
if (isGlobal) {
|
|
||||||
List<Integer> claimedDays = customFile.getIntegerList("global_claimed_days");
|
|
||||||
claimedDays.add(day);
|
|
||||||
customFile.set("global_claimed_days", claimedDays);
|
|
||||||
} else {
|
|
||||||
List<Integer> claimedDays = customFile.getIntegerList(player.getUniqueId().toString());
|
|
||||||
claimedDays.add(day);
|
|
||||||
customFile.set(player.getUniqueId().toString(), claimedDays);
|
|
||||||
}
|
|
||||||
save();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getClaimedCount(Player player) {
|
|
||||||
if (Adventskalender.getInstance().getConfig().getBoolean("calendar.use_global_calendar")) {
|
|
||||||
return customFile.getIntegerList("global_claimed_days").size();
|
|
||||||
} else {
|
|
||||||
return customFile.getIntegerList(player.getUniqueId().toString()).size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
241
src/main/java/de/mviper/adventskalender/DataHandler.java
Normal file
241
src/main/java/de/mviper/adventskalender/DataHandler.java
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
package de.mviper.adventskalender;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
public class DataHandler {
|
||||||
|
|
||||||
|
private static File file;
|
||||||
|
private static FileConfiguration dataConfig;
|
||||||
|
private static boolean mysqlActive = false;
|
||||||
|
|
||||||
|
public static void setup() {
|
||||||
|
if (Adventskalender.getInstance().getConfig().getBoolean("mysql.enable")) {
|
||||||
|
MySQLManager.connect();
|
||||||
|
if (MySQLManager.isConnected()) {
|
||||||
|
mysqlActive = true;
|
||||||
|
Adventskalender.getInstance().getLogger().info("MySQL-Verbindung steht. data.yml wird deaktiviert.");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
Adventskalender.getInstance().getLogger().warning("MySQL aktiviert, aber Verbindung fehlgeschlagen! Nutze data.yml als Backup.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Adventskalender.getInstance().getDataFolder().exists()) {
|
||||||
|
Adventskalender.getInstance().getDataFolder().mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
file = new File(Adventskalender.getInstance().getDataFolder(), "data.yml");
|
||||||
|
|
||||||
|
if (!file.exists()) {
|
||||||
|
try {
|
||||||
|
file.createNewFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dataConfig = YamlConfiguration.loadConfiguration(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasClaimed(Player player, int day) {
|
||||||
|
if (isGlobal()) {
|
||||||
|
return GlobalDataManager.isDayClaimedGlobally(day);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mysqlActive && MySQLManager.isConnected()) {
|
||||||
|
try (PreparedStatement ps = MySQLManager.getConnection().prepareStatement("SELECT 1 FROM advent_players WHERE uuid = ? AND day = ?")) {
|
||||||
|
ps.setString(1, player.getUniqueId().toString());
|
||||||
|
ps.setInt(2, day);
|
||||||
|
return ps.executeQuery().next();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dataConfig != null) {
|
||||||
|
List<Integer> claimed = dataConfig.getIntegerList("players." + player.getUniqueId() + ".claimed");
|
||||||
|
return claimed.contains(day);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setClaimed(Player player, int day) {
|
||||||
|
if (isGlobal()) {
|
||||||
|
GlobalDataManager.setDayClaimedGlobally(day, player.getName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mysqlActive && MySQLManager.isConnected()) {
|
||||||
|
try (PreparedStatement ps = MySQLManager.getConnection().prepareStatement("INSERT IGNORE INTO advent_players (uuid, day) VALUES (?, ?)")) {
|
||||||
|
ps.setString(1, player.getUniqueId().toString());
|
||||||
|
ps.setInt(2, day);
|
||||||
|
ps.executeUpdate();
|
||||||
|
return;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dataConfig != null) {
|
||||||
|
List<Integer> claimed = dataConfig.getIntegerList("players." + player.getUniqueId() + ".claimed");
|
||||||
|
if (!claimed.contains(day)) {
|
||||||
|
claimed.add(day);
|
||||||
|
dataConfig.set("players." + player.getUniqueId() + ".claimed", claimed);
|
||||||
|
dataConfig.set("players." + player.getUniqueId() + ".name", player.getName());
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resetPlayerDay(String playerName, int day) {
|
||||||
|
if (mysqlActive && MySQLManager.isConnected()) {
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
OfflinePlayer target = Bukkit.getOfflinePlayer(playerName);
|
||||||
|
try (PreparedStatement ps = MySQLManager.getConnection().prepareStatement("DELETE FROM advent_players WHERE uuid = ? AND day = ?")) {
|
||||||
|
ps.setString(1, target.getUniqueId().toString());
|
||||||
|
ps.setInt(2, day);
|
||||||
|
ps.executeUpdate();
|
||||||
|
} catch (SQLException e) { e.printStackTrace(); }
|
||||||
|
}
|
||||||
|
if (dataConfig != null && dataConfig.getConfigurationSection("players") != null) {
|
||||||
|
for (String uuid : dataConfig.getConfigurationSection("players").getKeys(false)) {
|
||||||
|
if (playerName.equalsIgnoreCase(dataConfig.getString("players." + uuid + ".name"))) {
|
||||||
|
List<Integer> claimed = dataConfig.getIntegerList("players." + uuid + ".claimed");
|
||||||
|
claimed.remove(Integer.valueOf(day));
|
||||||
|
dataConfig.set("players." + uuid + ".claimed", claimed);
|
||||||
|
save();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Set<Integer> getClaimedDays(Player player) {
|
||||||
|
if (mysqlActive && MySQLManager.isConnected()) {
|
||||||
|
Set<Integer> days = new HashSet<>();
|
||||||
|
try (PreparedStatement ps = MySQLManager.getConnection().prepareStatement("SELECT day FROM advent_players WHERE uuid = ?")) {
|
||||||
|
ps.setString(1, player.getUniqueId().toString());
|
||||||
|
ResultSet rs = ps.executeQuery();
|
||||||
|
while (rs.next()) days.add(rs.getInt("day"));
|
||||||
|
return days;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dataConfig != null) {
|
||||||
|
return new HashSet<>(dataConfig.getIntegerList("players." + player.getUniqueId() + ".claimed"));
|
||||||
|
}
|
||||||
|
return new HashSet<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resetPlayer(Player player) {
|
||||||
|
if (mysqlActive && MySQLManager.isConnected()) {
|
||||||
|
try (PreparedStatement ps = MySQLManager.getConnection().prepareStatement("DELETE FROM advent_players WHERE uuid = ?")) {
|
||||||
|
ps.setString(1, player.getUniqueId().toString());
|
||||||
|
ps.executeUpdate();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dataConfig != null) {
|
||||||
|
dataConfig.set("players." + player.getUniqueId(), null);
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resetOfflinePlayer(String name) {
|
||||||
|
if (dataConfig == null || dataConfig.getConfigurationSection("players") == null) return;
|
||||||
|
for (String uuid : dataConfig.getConfigurationSection("players").getKeys(false)) {
|
||||||
|
String savedName = dataConfig.getString("players." + uuid + ".name");
|
||||||
|
if (name.equalsIgnoreCase(savedName)) {
|
||||||
|
dataConfig.set("players." + uuid, null);
|
||||||
|
save();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resetAll() {
|
||||||
|
if (mysqlActive && MySQLManager.isConnected()) {
|
||||||
|
try (PreparedStatement ps1 = MySQLManager.getConnection().prepareStatement("DELETE FROM advent_players");
|
||||||
|
PreparedStatement ps2 = MySQLManager.getConnection().prepareStatement("DELETE FROM advent_global")) {
|
||||||
|
ps1.executeUpdate();
|
||||||
|
ps2.executeUpdate();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dataConfig != null) {
|
||||||
|
dataConfig.set("players", null);
|
||||||
|
dataConfig.set("global", null);
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isGlobal() {
|
||||||
|
return Adventskalender.getInstance().getConfig().getBoolean("calendar.use_global_calendar", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void save() {
|
||||||
|
if (dataConfig == null || file == null) return;
|
||||||
|
try {
|
||||||
|
dataConfig.save(file);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class GlobalDataManager {
|
||||||
|
public static boolean isDayClaimedGlobally(int day) {
|
||||||
|
if (mysqlActive && MySQLManager.isConnected()) {
|
||||||
|
try (PreparedStatement ps = MySQLManager.getConnection().prepareStatement("SELECT 1 FROM advent_global WHERE day = ?")) {
|
||||||
|
ps.setInt(1, day);
|
||||||
|
return ps.executeQuery().next();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dataConfig != null && dataConfig.contains("global.day_" + day);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setDayClaimedGlobally(int day, String playerName) {
|
||||||
|
if (mysqlActive && MySQLManager.isConnected()) {
|
||||||
|
try (PreparedStatement ps = MySQLManager.getConnection().prepareStatement("REPLACE INTO advent_global (day, player_name) VALUES (?, ?)")) {
|
||||||
|
ps.setInt(1, day);
|
||||||
|
ps.setString(2, playerName);
|
||||||
|
ps.executeUpdate();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
} else if (dataConfig != null) {
|
||||||
|
dataConfig.set("global.day_" + day, playerName);
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resetGlobalDay(int day) {
|
||||||
|
if (mysqlActive && MySQLManager.isConnected()) {
|
||||||
|
try (PreparedStatement ps = MySQLManager.getConnection().prepareStatement("DELETE FROM advent_global WHERE day = ?")) {
|
||||||
|
ps.setInt(1, day);
|
||||||
|
ps.executeUpdate();
|
||||||
|
} catch (SQLException e) { e.printStackTrace(); }
|
||||||
|
} else if (dataConfig != null) {
|
||||||
|
dataConfig.set("global.day_" + day, null);
|
||||||
|
DataHandler.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,41 +1,35 @@
|
|||||||
package de.mviper.adventskalender;
|
package de.mviper.adventskalender;
|
||||||
|
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class LanguageManager {
|
public class LanguageManager {
|
||||||
|
private static YamlConfiguration cfg;
|
||||||
private static FileConfiguration languageConfig;
|
private static String prefix;
|
||||||
|
|
||||||
public static void setup() {
|
public static void setup() {
|
||||||
String lang = Adventskalender.getInstance().getConfig().getString("general.language", "de");
|
String lang = Adventskalender.getInstance().getConfig().getString("general.language", "de");
|
||||||
File languageFile = new File(Adventskalender.getInstance().getDataFolder(), "messages_" + lang + ".yml");
|
File f = new File(Adventskalender.getInstance().getDataFolder(), "messages_" + lang + ".yml");
|
||||||
|
if (!f.exists()) Adventskalender.getInstance().saveResource("messages_" + lang + ".yml", false);
|
||||||
if (!languageFile.exists()) {
|
cfg = YamlConfiguration.loadConfiguration(f);
|
||||||
Adventskalender.getInstance().saveResource("messages_" + lang + ".yml", false);
|
prefix = ChatColor.translateAlternateColorCodes('&', cfg.getString("prefix", "&6[Advent] "));
|
||||||
}
|
|
||||||
|
|
||||||
languageConfig = YamlConfiguration.loadConfiguration(languageFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getString(String path) {
|
public static String getString(String path) {
|
||||||
if (languageConfig.contains(path)) {
|
String s = cfg.getString(path);
|
||||||
return format(languageConfig.getString(path));
|
return s == null ? "§cKey error: " + path : ChatColor.translateAlternateColorCodes('&', s);
|
||||||
}
|
}
|
||||||
return "§cLanguage key not found: " + path;
|
|
||||||
|
public static String getMessage(String path) {
|
||||||
|
return prefix + getString(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<String> getStringList(String path) {
|
public static List<String> getStringList(String path) {
|
||||||
if (languageConfig.contains(path)) {
|
return cfg.getStringList(path).stream()
|
||||||
return languageConfig.getStringList(path).stream().map(LanguageManager::format).toList();
|
.map(s -> ChatColor.translateAlternateColorCodes('&', s))
|
||||||
}
|
.collect(Collectors.toList());
|
||||||
return List.of("§cLanguage key list not found: " + path);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String format(String message) {
|
|
||||||
return org.bukkit.ChatColor.translateAlternateColorCodes('&', message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
66
src/main/java/de/mviper/adventskalender/MySQLManager.java
Normal file
66
src/main/java/de/mviper/adventskalender/MySQLManager.java
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
package de.mviper.adventskalender;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import java.sql.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class MySQLManager {
|
||||||
|
|
||||||
|
private static Connection connection;
|
||||||
|
|
||||||
|
public static void connect() {
|
||||||
|
FileConfiguration config = Adventskalender.getInstance().getConfig();
|
||||||
|
String host = config.getString("mysql.host");
|
||||||
|
int port = config.getInt("mysql.port");
|
||||||
|
String database = config.getString("mysql.database");
|
||||||
|
String user = config.getString("mysql.user");
|
||||||
|
String password = config.getString("mysql.password");
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (connection != null && !connection.isClosed()) return;
|
||||||
|
|
||||||
|
synchronized (MySQLManager.class) {
|
||||||
|
Class.forName("com.mysql.jdbc.Driver");
|
||||||
|
connection = DriverManager.getConnection("jdbc:mysql://" + host + ":" + port + "/" + database + "?autoReconnect=true&useSSL=false", user, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
createTables();
|
||||||
|
Adventskalender.getInstance().getLogger().info("MySQL-Verbindung erfolgreich hergestellt!");
|
||||||
|
} catch (Exception e) {
|
||||||
|
Adventskalender.getInstance().getLogger().severe("MySQL-Verbindung fehlgeschlagen: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void createTables() {
|
||||||
|
try (Statement s = connection.createStatement()) {
|
||||||
|
// Tabelle für Einzelspieler-Daten
|
||||||
|
s.executeUpdate("CREATE TABLE IF NOT EXISTS advent_players (uuid VARCHAR(36), day INT, PRIMARY KEY(uuid, day))");
|
||||||
|
// Tabelle für globalen Modus
|
||||||
|
s.executeUpdate("CREATE TABLE IF NOT EXISTS advent_global (day INT PRIMARY KEY, player_name VARCHAR(16))");
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isConnected() {
|
||||||
|
try {
|
||||||
|
return connection != null && !connection.isClosed();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void close() {
|
||||||
|
try {
|
||||||
|
if (isConnected()) connection.close();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Connection getConnection() {
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
package de.mviper.adventskalender;
|
|
||||||
|
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verwaltet die Spielerdaten in einer separaten YAML-Datei.
|
|
||||||
* Speichert, welcher Spieler an welchem Tag sein Geschenk bereits geholt hat.
|
|
||||||
*/
|
|
||||||
public class PlayerData {
|
|
||||||
|
|
||||||
private static File file;
|
|
||||||
private static FileConfiguration customFile;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Erstellt die playerdata.yml-Datei, falls sie nicht existiert.
|
|
||||||
*/
|
|
||||||
public static void setup() {
|
|
||||||
file = new File(Adventskalender.getInstance().getDataFolder(), "playerdata.yml");
|
|
||||||
if (!file.exists()) {
|
|
||||||
try {
|
|
||||||
file.createNewFile();
|
|
||||||
} catch (IOException e) {
|
|
||||||
Adventskalender.getInstance().getLogger().severe("Konnte playerdata.yml nicht erstellen: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
customFile = YamlConfiguration.loadConfiguration(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static FileConfiguration get() {
|
|
||||||
return customFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void save() {
|
|
||||||
try {
|
|
||||||
customFile.save(file);
|
|
||||||
} catch (IOException e) {
|
|
||||||
Adventskalender.getInstance().getLogger().severe("Konnte playerdata.yml nicht speichern: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void reload() {
|
|
||||||
customFile = YamlConfiguration.loadConfiguration(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prüft, ob ein Spieler ein Geschenk für einen bestimmten Tag bereits geholt hat.
|
|
||||||
* @param uuid Die UUID des Spielers
|
|
||||||
* @param day Der Tag (1-24)
|
|
||||||
* @return true, wenn bereits geholt, sonst false
|
|
||||||
*/
|
|
||||||
public static boolean hasClaimed(UUID uuid, int day) {
|
|
||||||
// Wir speichern eine Liste der geöffneten Tage für jeden Spieler
|
|
||||||
List<Integer> claimedDays = customFile.getIntegerList(uuid.toString());
|
|
||||||
return claimedDays.contains(day);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Markiert einen Tag für einen Spieler als geholt.
|
|
||||||
* @param uuid Die UUID des Spielers
|
|
||||||
* @param day Der Tag (1-24)
|
|
||||||
*/
|
|
||||||
public static void setClaimed(UUID uuid, int day) {
|
|
||||||
List<Integer> claimedDays = customFile.getIntegerList(uuid.toString());
|
|
||||||
claimedDays.add(day);
|
|
||||||
customFile.set(uuid.toString(), claimedDays);
|
|
||||||
save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
33
src/main/java/de/mviper/adventskalender/UpdateChecker.java
Normal file
33
src/main/java/de/mviper/adventskalender/UpdateChecker.java
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package de.mviper.adventskalender;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Scanner;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public class UpdateChecker {
|
||||||
|
|
||||||
|
private final JavaPlugin plugin;
|
||||||
|
private final int resourceId;
|
||||||
|
|
||||||
|
public UpdateChecker(JavaPlugin plugin, int resourceId) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.resourceId = resourceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getVersion(final Consumer<String> consumer) {
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(this.plugin, () -> {
|
||||||
|
try (InputStream is = new URL("https://api.spigotmc.org/legacy/update.php?resource=" + this.resourceId).openStream();
|
||||||
|
Scanner scann = new Scanner(is)) {
|
||||||
|
if (scann.hasNext()) {
|
||||||
|
consumer.accept(scann.next());
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
plugin.getLogger().info("Update-Check fehlgeschlagen: " + e.getMessage());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,9 @@ general:
|
|||||||
# Verfügbare Optionen: 'de', 'en'
|
# Verfügbare Optionen: 'de', 'en'
|
||||||
language: "de"
|
language: "de"
|
||||||
|
|
||||||
|
# Nur für Testzwecke: Simuliert einen Tag (0 = echtes Datum verwenden)
|
||||||
|
test_day: 0
|
||||||
|
|
||||||
# --- Kalender-Einstellungen ---
|
# --- Kalender-Einstellungen ---
|
||||||
calendar:
|
calendar:
|
||||||
# Soll jeder Spieler seinen eigenen, individuellen Kalender haben?
|
# Soll jeder Spieler seinen eigenen, individuellen Kalender haben?
|
||||||
@@ -19,6 +22,15 @@ calendar:
|
|||||||
# Dieser Text ist ein Schlüssel, der in der messages.yml übersetzt wird.
|
# Dieser Text ist ein Schlüssel, der in der messages.yml übersetzt wird.
|
||||||
gui_title_key: "adventskalender.gui_title"
|
gui_title_key: "adventskalender.gui_title"
|
||||||
|
|
||||||
|
# Datenbank für Bungeecord Nutzung
|
||||||
|
mysql:
|
||||||
|
enable: false
|
||||||
|
host: "localhost"
|
||||||
|
port: 3306
|
||||||
|
database: "adventskalender"
|
||||||
|
user: "root"
|
||||||
|
password: ""
|
||||||
|
|
||||||
# --- Belohnungen für die Tage 1 bis 24 ---
|
# --- Belohnungen für die Tage 1 bis 24 ---
|
||||||
# Hier definierst du die Items für jeden Tag.
|
# Hier definierst du die Items für jeden Tag.
|
||||||
# 'material': Der Materialname des Items (z.B. DIAMOND, ELYTRA).
|
# 'material': Der Materialname des Items (z.B. DIAMOND, ELYTRA).
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Adventskalender Plugin - Deutsche Sprachdatei
|
# Adventskalender Plugin - Deutsche Sprachdatei (v2.0 - 2026)
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
# --- Prefix ---
|
# --- Prefix ---
|
||||||
# Dieser Prefix wird vor fast jeder Nachricht im Chat angezeigt.
|
|
||||||
prefix: "&6[Adventskalender] &r"
|
prefix: "&6[Adventskalender] &r"
|
||||||
|
|
||||||
# --- GUI-Texte ---
|
# --- GUI-Texte ---
|
||||||
gui:
|
gui:
|
||||||
# Der Titel des Adventskalender-Inventars.
|
# Der Titel des Adventskalender-Inventars.
|
||||||
title: "&6✦ Adventskalender 2024 ✦"
|
title: "&6✦ Adventskalender 2026 ✦"
|
||||||
|
|
||||||
# --- Nachrichten an Spieler ---
|
# --- Nachrichten an Spieler ---
|
||||||
# Verfügbare Platzhalter:
|
# Verfügbare Platzhalter:
|
||||||
@@ -18,90 +17,92 @@ gui:
|
|||||||
messages:
|
messages:
|
||||||
no_permission: "&cDafür hast du keine Berechtigung."
|
no_permission: "&cDafür hast du keine Berechtigung."
|
||||||
only_player: "&cDieser Befehl kann nur von einem Spieler ausgeführt werden."
|
only_player: "&cDieser Befehl kann nur von einem Spieler ausgeführt werden."
|
||||||
inventory_full: "&cDein Inventar war voll! Das Item wurde auf den Boden geworfen."
|
inventory_full: "&cDein Inventar ist voll! Dein Geschenk wurde vor deine Füße geworfen."
|
||||||
reward_received: "&aDu hast dein Geschenk für Tag %day% erhalten!"
|
reward_received: "&aGlückwunsch! Du hast dein Geschenk für Tag &e%day% &aerhalten!"
|
||||||
day_not_available: "&cDieses Geschenk kannst du (noch) nicht öffnen."
|
day_not_available: "&cDieses Türchen ist noch fest verschlossen. Gedulde dich noch etwas!"
|
||||||
day_already_claimed: "&7Du hast dein Geschenk für diesen Tag bereits geholt."
|
day_already_claimed: "&7Du hast dieses Geschenk bereits abgeholt."
|
||||||
|
global_already_claimed: "&cDieses Geschenk wurde heute bereits von jemand anderem abgeholt!"
|
||||||
|
|
||||||
# --- Admin-Nachrichten ---
|
# --- Admin-Nachrichten ---
|
||||||
admin:
|
admin:
|
||||||
reload_success: "&aKonfiguration und Sprachdateien wurden neu geladen."
|
reload_success: "&aKonfiguration und Sprachdateien wurden erfolgreich neu geladen."
|
||||||
|
test_mode_on: "&e[Admin] &7Der Test-Modus wurde auf Tag &6%day% &7gesetzt."
|
||||||
|
test_mode_off: "&e[Admin] &7Test-Modus deaktiviert. Es wird wieder das reale Datum genutzt."
|
||||||
player_not_found: "&cDer Spieler '%player%' wurde nicht gefunden."
|
player_not_found: "&cDer Spieler '%player%' wurde nicht gefunden."
|
||||||
invalid_day: "&cUngültiger Tag. Bitte wähle eine Zahl zwischen 1 und 24."
|
invalid_day: "&cUngültiger Tag. Bitte wähle eine Zahl zwischen 1 und 24."
|
||||||
open_success: "&aDu hast für %player% das Türchen für Tag %day% geöffnet."
|
|
||||||
|
|
||||||
# --- Namen und Beschreibungen für die Belohnungs-Items ---
|
# --- Belohnungs-Texte im GUI ---
|
||||||
# Die Schlüssel hier (z.B. 'day_1') müssen mit den 'keys' in der config.yml übereinstimmen.
|
# Diese Schlüssel werden vom AdventInventory genutzt, um die Items im Menü zu benennen.
|
||||||
rewards:
|
rewards:
|
||||||
day_1:
|
day_1:
|
||||||
name: "&bErste Diamanten!"
|
name: "&bTag 1: Erste Diamanten!"
|
||||||
lore: ["&7Ein kleiner Vorgeschmack auf den Reichtum...", "&7Viel Spaß damit!"]
|
lore: ["&7Ein kleiner Vorgeschmack auf den Reichtum...", "&7Viel Spaß damit!"]
|
||||||
day_2:
|
day_2:
|
||||||
name: "&6Goldene Äpfel"
|
name: "&6Tag 2: Goldene Äpfel"
|
||||||
lore: ["&7Für den Fall, dass es mal eng wird..."]
|
lore: ["&7Für den Fall, dass es mal eng wird..."]
|
||||||
day_3:
|
day_3:
|
||||||
name: "&cSchwert des Helden"
|
name: "&cTag 3: Schwert des Helden"
|
||||||
lore: ["&7Ein mächtiges Schwert, um Monster zu jagen."]
|
lore: ["&7Ein mächtiges Schwert, um Monster zu jagen."]
|
||||||
day_4:
|
day_4:
|
||||||
name: "&aFlügel der Freiheit"
|
name: "&aTag 4: Flügel der Freiheit"
|
||||||
lore: ["&7Sei frei wie ein Adler!"]
|
lore: ["&7Sei frei wie ein Adler!"]
|
||||||
day_5:
|
day_5:
|
||||||
name: "&8Ein Hauch von Netherit"
|
name: "&8Tag 5: Ein Hauch von Netherit"
|
||||||
lore: ["&7Sehr wertvoll und selten."]
|
lore: ["&7Sehr wertvoll und selten."]
|
||||||
day_6:
|
day_6:
|
||||||
name: "&6Göttlicher Apfel"
|
name: "&6Tag 6: Göttlicher Apfel"
|
||||||
lore: ["&7Ein Geschenk der Götter... oder des Admins."]
|
lore: ["&7Ein Geschenk der Götter... oder des Admins."]
|
||||||
day_7:
|
day_7:
|
||||||
name: "&eBergbau-Meister"
|
name: "&eTag 7: Bergbau-Meister"
|
||||||
lore: ["&7Für die größten Schätze der Welt."]
|
lore: ["&7Für die größten Schätze der Welt."]
|
||||||
day_8:
|
day_8:
|
||||||
name: "&dTotem des Unvergänglichen"
|
name: "&dTag 8: Totem des Unvergänglichen"
|
||||||
lore: ["&7Ein kleines Extra-Leben."]
|
lore: ["&7Ein kleines Extra-Leben."]
|
||||||
day_9:
|
day_9:
|
||||||
name: "&5Stern des Nethers"
|
name: "&5Tag 9: Stern des Nethers"
|
||||||
lore: ["&7Der Kern eines mächtigen Wesens."]
|
lore: ["&7Der Kern eines mächtigen Wesens."]
|
||||||
day_10:
|
day_10:
|
||||||
name: "&9Magische Truhe"
|
name: "&9Tag 10: Magische Truhen"
|
||||||
lore: ["&7Hält all deine Schätze sicher."]
|
lore: ["&7Hält all deine Schätze sicher."]
|
||||||
day_11:
|
day_11:
|
||||||
name: "&3Stachel des Ozeans"
|
name: "&3Tag 11: Stachel des Ozeans"
|
||||||
lore: ["&7Die Waffe der Wächter."]
|
lore: ["&7Die Waffe der Wächter."]
|
||||||
day_12:
|
day_12:
|
||||||
name: "&7Helm der Weisheit"
|
name: "&7Tag 12: Helm der Weisheit"
|
||||||
lore: ["&7Schützt deinen Kopf."]
|
lore: ["&7Schützt deinen Kopf."]
|
||||||
day_13:
|
day_13:
|
||||||
name: "&fSattel für ein treues Tier"
|
name: "&fTag 13: Sattel"
|
||||||
lore: ["&7Für dein nächstes Abenteuer zu Pferd."]
|
lore: ["&7Für dein nächstes Abenteuer zu Pferd."]
|
||||||
day_14:
|
day_14:
|
||||||
name: "&eNamensschilder"
|
name: "&eTag 14: Namensschilder"
|
||||||
lore: ["&7Gib deinem Lieblings-Wolf einen Namen!"]
|
lore: ["&7Gib deinem Lieblings-Wolf einen Namen!"]
|
||||||
day_15:
|
day_15:
|
||||||
name: "&aSchallplatte - cat"
|
name: "&aTag 15: Schallplatte - cat"
|
||||||
lore: ["&7Relaxende Musik für eine gemütliche Zeit."]
|
lore: ["&7Relaxende Musik für eine gemütliche Zeit."]
|
||||||
day_16:
|
day_16:
|
||||||
name: "&5Endkristall"
|
name: "&5Tag 16: Endkristalle"
|
||||||
lore: ["&7Mächtig und gefährlich. Mit Vorsicht genießen!"]
|
lore: ["&7Mächtig und gefährlich. Mit Vorsicht genießen!"]
|
||||||
day_17:
|
day_17:
|
||||||
name: "&7Brustpanzer der Unzerstörbarkeit"
|
name: "&7Tag 17: Brustpanzer der Unzerstörbarkeit"
|
||||||
lore: ["&7Bietet maximalen Schutz."]
|
lore: ["&7Bietet maximalen Schutz."]
|
||||||
day_18:
|
day_18:
|
||||||
name: "&bHerz des Ozeans"
|
name: "&bTag 18: Herz des Ozeans"
|
||||||
lore: ["&7Das Zentrum einer Conduit-Struktur."]
|
lore: ["&7Das Zentrum einer Conduit-Struktur."]
|
||||||
day_19:
|
day_19:
|
||||||
name: "&fNautilusmuschel"
|
name: "&fTag 19: Nautilusmuscheln"
|
||||||
lore: ["&7Ein seltenes Gut aus den Tiefen."]
|
lore: ["&7Ein seltenes Gut aus den Tiefen."]
|
||||||
day_20:
|
day_20:
|
||||||
name: "&8Kopf des Enderdrachen"
|
name: "&8Tag 20: Kopf des Enderdrachen"
|
||||||
lore: ["&7Eine beeindruckende Trophäe."]
|
lore: ["&7Eine beeindruckende Trophäe."]
|
||||||
day_21:
|
day_21:
|
||||||
name: "&8Stiefel der Tiefe"
|
name: "&8Tag 21: Stiefel der Tiefe"
|
||||||
lore: ["&7Lass dich nicht im Feuer verbrennen."]
|
lore: ["&7Lass dich nicht im Feuer verbrennen."]
|
||||||
day_22:
|
day_22:
|
||||||
name: "&dVerzauberungstisch"
|
name: "&dTag 22: Verzauberungstisch"
|
||||||
lore: ["&7Kreiere deine eigenen magischen Items."]
|
lore: ["&7Kreiere deine eigenen magischen Items."]
|
||||||
day_23:
|
day_23:
|
||||||
name: "&bDie ultimative Hacke"
|
name: "&bTag 23: Die ultimative Hacke"
|
||||||
lore: ["&7Nicht nur für den Ackerbau..."]
|
lore: ["&7Nicht nur für den Ackerbau..."]
|
||||||
day_24:
|
day_24:
|
||||||
name: "&cDas große Finale! - Feuerwerk"
|
name: "&cTag 24: Das große Finale!"
|
||||||
lore: ["&7Frohe Weihnachten!", "&7Feiere mit einem riesigen Feuerwerk!"]
|
lore: ["&7Frohe Weihnachten!", "&7Feiere mit einem riesigen Feuerwerk!"]
|
||||||
@@ -1,15 +1,14 @@
|
|||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Adventskalender Plugin - English Language File
|
# Adventskalender Plugin - English Language File (v2.0 - 2026)
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
# --- Prefix ---
|
# --- Prefix ---
|
||||||
# This prefix will be shown before most chat messages.
|
prefix: "&6[Advent] &r"
|
||||||
prefix: "&6[Adventskalender] &r"
|
|
||||||
|
|
||||||
# --- GUI Texts ---
|
# --- GUI Texts ---
|
||||||
gui:
|
gui:
|
||||||
# The title of the Advent Calendar inventory.
|
# The title of the Advent Calendar inventory.
|
||||||
title: "&6✦ Advent Calendar 2024 ✦"
|
title: "&6✦ Advent Calendar 2026 ✦"
|
||||||
|
|
||||||
# --- Messages to Players ---
|
# --- Messages to Players ---
|
||||||
# Available placeholders:
|
# Available placeholders:
|
||||||
@@ -18,90 +17,91 @@ gui:
|
|||||||
messages:
|
messages:
|
||||||
no_permission: "&cYou don't have permission for that."
|
no_permission: "&cYou don't have permission for that."
|
||||||
only_player: "&cThis command can only be executed by a player."
|
only_player: "&cThis command can only be executed by a player."
|
||||||
inventory_full: "&cYour inventory was full! The item was dropped on the ground."
|
inventory_full: "&cYour inventory is full! Your gift was dropped at your feet."
|
||||||
reward_received: "&aYou have received your gift for day %day%!"
|
reward_received: "&aCongratulations! You have received your gift for day &e%day%&a!"
|
||||||
day_not_available: "&cYou cannot open this gift (yet)."
|
day_not_available: "&cThis door is still locked. You'll have to wait a bit longer!"
|
||||||
day_already_claimed: "&7You have already claimed your gift for this day."
|
day_already_claimed: "&7You have already claimed this gift."
|
||||||
|
global_already_claimed: "&cThis gift has already been claimed by someone else today!"
|
||||||
|
|
||||||
# --- Admin Messages ---
|
# --- Admin Messages ---
|
||||||
admin:
|
admin:
|
||||||
reload_success: "&aConfiguration and language files have been reloaded."
|
reload_success: "&aConfiguration and language files have been reloaded."
|
||||||
|
test_mode_on: "&e[Admin] &7Test mode set to day &6%day%&7."
|
||||||
|
test_mode_off: "&e[Admin] &7Test mode disabled. Using real-time date again."
|
||||||
player_not_found: "&cThe player '%player%' was not found."
|
player_not_found: "&cThe player '%player%' was not found."
|
||||||
invalid_day: "&cInvalid day. Please choose a number between 1 and 24."
|
invalid_day: "&cInvalid day. Please choose a number between 1 and 24."
|
||||||
open_success: "&aYou have opened day %day% for %player%."
|
|
||||||
|
|
||||||
# --- Names and Descriptions for Reward Items ---
|
# --- Reward Texts in GUI ---
|
||||||
# The keys here (e.g., 'day_1') must match the 'keys' in the config.yml.
|
|
||||||
rewards:
|
rewards:
|
||||||
day_1:
|
day_1:
|
||||||
name: "&bFirst Diamonds!"
|
name: "&bDay 1: First Diamonds!"
|
||||||
lore: ["&7A little taste of wealth...", "&7Have fun with it!"]
|
lore: ["&7A little taste of wealth...", "&7Have fun with it!"]
|
||||||
day_2:
|
day_2:
|
||||||
name: "&6Golden Apples"
|
name: "&6Day 2: Golden Apples"
|
||||||
lore: ["&7In case things get tight..."]
|
lore: ["&7In case things get tight..."]
|
||||||
day_3:
|
day_3:
|
||||||
name: "&cSword of the Hero"
|
name: "&cDay 3: Sword of the Hero"
|
||||||
lore: ["&7A mighty sword to hunt monsters."]
|
lore: ["&7A mighty sword to hunt monsters."]
|
||||||
day_4:
|
day_4:
|
||||||
name: "&aWings of Freedom"
|
name: "&aDay 4: Wings of Freedom"
|
||||||
lore: ["&7Be free as an eagle!"]
|
lore: ["&7Be free as an eagle!"]
|
||||||
day_5:
|
day_5:
|
||||||
name: "&8A Touch of Netherite"
|
name: "&8Day 5: A Touch of Netherite"
|
||||||
lore: ["&7Very valuable and rare."]
|
lore: ["&7Very valuable and rare."]
|
||||||
day_6:
|
day_6:
|
||||||
name: "&6Godly Apple"
|
name: "&6Day 6: Godly Apple"
|
||||||
lore: ["&7A gift from the gods... or the admin."]
|
lore: ["&7A gift from the gods... or the admin."]
|
||||||
day_7:
|
day_7:
|
||||||
name: "&eMaster Pickaxe"
|
name: "&eDay 7: Master Pickaxe"
|
||||||
lore: ["&7For the greatest treasures in the world."]
|
lore: ["&7For the greatest treasures in the world."]
|
||||||
day_8:
|
day_8:
|
||||||
name: "&dTotem of Undying"
|
name: "&dDay 8: Totem of Undying"
|
||||||
lore: ["&7An extra life."]
|
lore: ["&7An extra life."]
|
||||||
day_9:
|
day_9:
|
||||||
name: "&5Nether Star"
|
name: "&5Day 9: Nether Star"
|
||||||
lore: ["&7The core of a powerful being."]
|
lore: ["&7The core of a powerful being."]
|
||||||
day_10:
|
day_10:
|
||||||
name: "&9Magic Box"
|
name: "&9Day 10: Magic Chests"
|
||||||
lore: ["&7Keeps all your treasures safe."]
|
lore: ["&7Keeps all your treasures safe."]
|
||||||
day_11:
|
day_11:
|
||||||
name: "&3Spear of the Ocean"
|
name: "&3Day 11: Spear of the Ocean"
|
||||||
lore: ["&7The weapon of the guardians."]
|
lore: ["&7The weapon of the guardians."]
|
||||||
day_12:
|
day_12:
|
||||||
name: "&7Helmet of Wisdom"
|
name: "&7Day 12: Helmet of Wisdom"
|
||||||
lore: ["&7Protects your head."]
|
lore: ["&7Protects your head."]
|
||||||
day_13:
|
day_13:
|
||||||
name: "&fSaddle for a Loyal Steed"
|
name: "&fDay 13: Saddle"
|
||||||
lore: ["&7For your next equestrian adventure."]
|
lore: ["&7For your next equestrian adventure."]
|
||||||
day_14:
|
day_14:
|
||||||
name: "&eName Tags"
|
name: "&eDay 14: Name Tags"
|
||||||
lore: ["&7Give your favorite wolf a name!"]
|
lore: ["&7Give your favorite wolf a name!"]
|
||||||
day_15:
|
day_15:
|
||||||
name: "&aMusic Disc - cat"
|
name: "&aDay 15: Music Disc - cat"
|
||||||
lore: ["&7Relaxing music for a cozy time."]
|
lore: ["&7Relaxing music for a cozy time."]
|
||||||
day_16:
|
day_16:
|
||||||
name: "&5End Crystal"
|
name: "&5Day 16: End Crystals"
|
||||||
lore: ["&7Powerful and dangerous. Handle with care!"]
|
lore: ["&7Powerful and dangerous. Handle with care!"]
|
||||||
day_17:
|
day_17:
|
||||||
name: "&7Chestplate of Durability"
|
name: "&7Day 17: Chestplate of Durability"
|
||||||
lore: ["&7Offers maximum protection."]
|
lore: ["&7Offers maximum protection."]
|
||||||
day_18:
|
day_18:
|
||||||
name: "&bHeart of the Sea"
|
name: "&bDay 18: Heart of the Sea"
|
||||||
lore: ["&7The center of a Conduit structure."]
|
lore: ["&7The center of a Conduit structure."]
|
||||||
day_19:
|
day_19:
|
||||||
name: "&fNautilus Shell"
|
name: "&fDay 19: Nautilus Shells"
|
||||||
lore: ["&7A rare goodie from the depths."]
|
lore: ["&7A rare goodie from the depths."]
|
||||||
day_20:
|
day_20:
|
||||||
name: "&8Head of the Ender Dragon"
|
name: "&8Day 20: Head of the Ender Dragon"
|
||||||
lore: ["&7An impressive trophy."]
|
lore: ["&7An impressive trophy."]
|
||||||
day_21:
|
day_21:
|
||||||
name: "&8Boots of the Deep"
|
name: "&8Day 21: Boots of the Deep"
|
||||||
lore: ["&7Don't let yourself get burned in fire."]
|
lore: ["&7Don't let yourself get burned in fire."]
|
||||||
day_22:
|
day_22:
|
||||||
name: "&dEnchanting Table"
|
name: "&dDay 22: Enchanting Table"
|
||||||
lore: ["&7Create your own magical items."]
|
lore: ["&7Create your own magical items."]
|
||||||
day_23:
|
day_23:
|
||||||
name: "&bThe Ultimate Hoe"
|
name: "&bDay 23: The Ultimate Hoe"
|
||||||
lore: ["&7Not just for farming..."]
|
lore: ["&7Not just for farming..."]
|
||||||
day_24:
|
day_24:
|
||||||
name: "&cThe Grand Finale! - Fireworks"
|
name: "&cDay 24: The Grand Finale!"
|
||||||
lore: ["&7Merry Christmas!", "&7Celebrate with a huge firework!"]
|
lore: ["&7Merry Christmas!", "&7Celebrate with a huge firework!"]
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
name: Adventskalender
|
name: Adventskalender
|
||||||
version: '1.0.0'
|
version: '1.0.1'
|
||||||
main: de.mviper.adventskalender.Adventskalender
|
main: de.mviper.adventskalender.Adventskalender
|
||||||
api-version: 1.20
|
api-version: 1.20
|
||||||
author: M_Viper
|
author: M_Viper
|
||||||
description: Ein konfigurierbarer Adventskalender für Minecraft.
|
description: Ein moderner, performanter Adventskalender (2026 Edition).
|
||||||
|
|
||||||
commands:
|
commands:
|
||||||
adventskalender:
|
adventskalender:
|
||||||
|
|||||||
Reference in New Issue
Block a user