Files
Advenskalender/src/main/java/de/mviper/adventskalender/AdventCalendarExpansion.java
T
2026-11-03 19:10:19 +00:00

139 lines
5.2 KiB
Java

package de.mviper.adventskalender;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
/**
* Platzhalter: %ak_claimed%, %ak_day%, %ak_has_claimed_today%, %ak_remaining%, %ak_is_global%, %ak_event%
* beziehen sich auf das laufende Event (sonst das erste aktivierte). Mit Event-Präfix, z.B.
* %ak_halloween_claimed%, gilt der Platzhalter für genau dieses Event.
*/
public class AdventCalendarExpansion extends PlaceholderExpansion {
private static final long CACHE_MILLIS = 5000L;
private record Cached(Set<Integer> days, long time) {}
// Kurzer Cache, damit Scoreboards/Hologramme die Datenbank nicht jede Sekunde abfragen
private final ConcurrentHashMap<String, Cached> cache = new ConcurrentHashMap<>();
@Override
public @NotNull String getIdentifier() {
return "ak";
}
@Override
public @NotNull String getAuthor() {
return "M_Viper";
}
@Override
public @NotNull String getVersion() {
return Adventskalender.getInstance().getDescription().getVersion();
}
@Override
public boolean persist() {
return true; // Expansion bleibt nach PAPI-Reload registriert
}
private Set<Integer> claimedDays(Player player, CalendarEvent ev) {
long now = System.currentTimeMillis();
String key = player.getUniqueId() + ":" + ev.getId();
Cached c = cache.get(key);
if (c != null && now - c.time() < CACHE_MILLIS) return c.days();
Set<Integer> days = DataHandler.getViewClaimedDays(player, ev);
if (days == null) days = new HashSet<>();
cache.put(key, new Cached(days, now));
return days;
}
private record CachedBirthday(Optional<DataHandler.Birthday> birthday, long time) {}
private final ConcurrentHashMap<UUID, CachedBirthday> birthdayCache = new ConcurrentHashMap<>();
private String birthdayPlaceholder(Player player, boolean activeOnly) {
long now = System.currentTimeMillis();
CachedBirthday c = birthdayCache.get(player.getUniqueId());
if (c == null || now - c.time() >= CACHE_MILLIS * 6) {
try {
c = new CachedBirthday(DataHandler.getBirthday(player.getUniqueId()), now);
} catch (DataHandler.DataException e) {
return activeOnly ? "Nein" : "-";
}
birthdayCache.put(player.getUniqueId(), c);
}
if (c.birthday().isEmpty()) return activeOnly ? "Nein" : "-";
DataHandler.Birthday b = c.birthday().get();
if (!activeOnly) return BirthdayManager.format(b.month(), b.day());
Integer year = BirthdayManager.activeYear(b.month(), b.day(),
java.time.LocalDate.now(Adventskalender.getInstance().getZone()));
return (year != null && b.claimedYear() < year) ? "Ja" : "Nein";
}
@Override
public String onPlaceholderRequest(Player player, String identifier) {
if (player == null) return "";
String id = identifier.toLowerCase();
// %ak_birthday% - eingetragener Geburtstag (TT.MM.) oder "-"
// %ak_birthday_active% - "Ja", wenn das Geburtstagsgeschenk gerade abholbar ist
if (id.equals("birthday") || id.equals("birthday_active")) {
return birthdayPlaceholder(player, id.equals("birthday_active"));
}
CalendarEvent ev = null;
// Optionales Event-Präfix, z.B. "halloween_claimed"
for (CalendarEvent candidate : EventManager.all()) {
if (id.startsWith(candidate.getId() + "_")) {
ev = candidate;
id = id.substring(candidate.getId().length() + 1);
break;
}
}
if (ev == null) ev = EventManager.defaultEvent();
if (ev == null) return "";
int currentDay = ev.currentDay();
switch (id) {
// %ak_event% - ID des Events
case "event":
return ev.getId();
// %ak_claimed% - Anzahl der bereits geöffneten Türchen
case "claimed":
return String.valueOf(claimedDays(player, ev).size());
// %ak_day% - Der aktuelle Tag des Kalenders
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 claimedDays(player, ev).contains(currentDay) ? "Ja" : "Nein";
// %ak_remaining% - Wie viele Türchen sind noch offen?
case "remaining":
return String.valueOf(ev.getDays() - claimedDays(player, ev).size());
// %ak_is_global% - Zeigt an, ob der globale Modus aktiv ist
case "is_global":
return ev.isGlobal() ? "Global" : "Spieler-basiert";
}
return null; // Placeholder unbekannt
}
}