Files
SurvivalMechanics/src/main/java/me/viper/survivalmechanics/SurvivalMechanics.java
2026-01-28 22:06:29 +01:00

458 lines
22 KiB
Java

package me.viper.survivalmechanics;
import me.viper.survivalmechanics.mechanics.*;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerBedEnterEvent;
import org.bukkit.event.player.PlayerBedLeaveEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.ChatColor;
import org.bukkit.scoreboard.*;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
import java.util.HashMap;
import java.util.Map;
public class SurvivalMechanics extends JavaPlugin implements Listener {
private HungerManager hungerManager;
private ThirstManager thirstManager;
private FatigueManager fatigueManager;
private TemperatureManager temperatureManager;
private StaminaManager staminaManager;
private VulnerabilityManager vulnerabilityManager;
private HygieneManager hygieneManager;
private FileConfiguration langConfig;
private FileConfiguration playerDataConfig;
private File playerDataFile;
// Better message cooldown management - store in memory instead of config file
private final Map<String, Long> lastMessageTimes = new HashMap<>();
@Override
public void onEnable() {
// Load configurations
saveDefaultConfig();
saveResource("lang.yml", false);
saveResource("playerdata.yml", false);
loadLangConfig();
loadPlayerDataConfig();
// Initialize managers
hungerManager = new HungerManager(this);
thirstManager = new ThirstManager(this);
fatigueManager = new FatigueManager(this);
temperatureManager = new TemperatureManager(this);
staminaManager = new StaminaManager(this);
vulnerabilityManager = new VulnerabilityManager(this);
hygieneManager = new HygieneManager(this);
// Start all tasks
hungerManager.startHungerTask();
thirstManager.startThirstTask();
fatigueManager.startFatigueTask();
temperatureManager.startTemperatureTask();
staminaManager.startStaminaTask();
vulnerabilityManager.startVulnerabilityTask();
hygieneManager.startHygieneTask();
// Start scoreboard display
startScoreboardDisplay();
// Register events
getServer().getPluginManager().registerEvents(this, this);
getLogger().info("SurvivalMechanics Plugin aktiviert!");
}
@Override
public void onDisable() {
// Save all player data before shutdown
for (Player player : getServer().getOnlinePlayers()) {
savePlayerData(player.getUniqueId());
}
savePlayerDataConfig();
getLogger().info("SurvivalMechanics Plugin deaktiviert!");
}
private void loadLangConfig() {
File langFile = new File(getDataFolder(), "lang.yml");
if (!langFile.exists()) {
saveResource("lang.yml", false);
}
langConfig = YamlConfiguration.loadConfiguration(langFile);
}
private void loadPlayerDataConfig() {
playerDataFile = new File(getDataFolder(), "playerdata.yml");
if (!playerDataFile.exists()) {
saveResource("playerdata.yml", false);
}
playerDataConfig = YamlConfiguration.loadConfiguration(playerDataFile);
}
private void savePlayerDataConfig() {
try {
playerDataConfig.save(playerDataFile);
} catch (IOException e) {
getLogger().severe("Fehler beim Speichern von playerdata.yml: " + e.getMessage());
}
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
UUID playerId = player.getUniqueId();
String path = "players." + playerId + ".";
// Load player data or use defaults
if (playerDataConfig.contains(path)) {
hungerManager.loadHunger(playerId, playerDataConfig.getInt(path + "hunger", getConfig().getInt("hunger.initial", 80)));
thirstManager.loadThirst(playerId, playerDataConfig.getInt(path + "thirst", getConfig().getInt("thirst.initial", 80)));
fatigueManager.loadFatigue(playerId, playerDataConfig.getInt(path + "fatigue", getConfig().getInt("fatigue.initial", 100)));
temperatureManager.loadTemperature(playerId, playerDataConfig.getInt(path + "temperature", getConfig().getInt("temperature.initial", 50)));
staminaManager.loadStamina(playerId, playerDataConfig.getInt(path + "stamina", getConfig().getInt("stamina.initial", 80)));
vulnerabilityManager.loadVulnerability(playerId, playerDataConfig.getInt(path + "vulnerability", getConfig().getInt("vulnerability.initial", 0)));
hygieneManager.loadHygiene(playerId, playerDataConfig.getInt(path + "hygiene", getConfig().getInt("hygiene.initial", 80)));
} else {
// First time join - use initial values
hungerManager.loadHunger(playerId, getConfig().getInt("hunger.initial", 80));
thirstManager.loadThirst(playerId, getConfig().getInt("thirst.initial", 80));
fatigueManager.loadFatigue(playerId, getConfig().getInt("fatigue.initial", 100));
temperatureManager.loadTemperature(playerId, getConfig().getInt("temperature.initial", 50));
staminaManager.loadStamina(playerId, getConfig().getInt("stamina.initial", 80));
vulnerabilityManager.loadVulnerability(playerId, getConfig().getInt("vulnerability.initial", 0));
hygieneManager.loadHygiene(playerId, getConfig().getInt("hygiene.initial", 80));
}
setupPlayerScoreboard(player);
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();
UUID playerId = player.getUniqueId();
// Save player data
savePlayerData(playerId);
// Reset scoreboard
player.setScoreboard(getServer().getScoreboardManager().getNewScoreboard());
}
private void savePlayerData(UUID playerId) {
String path = "players." + playerId + ".";
playerDataConfig.set(path + "hunger", hungerManager.getHunger(playerId));
playerDataConfig.set(path + "thirst", thirstManager.getThirst(playerId));
playerDataConfig.set(path + "fatigue", fatigueManager.getFatigue(playerId));
playerDataConfig.set(path + "temperature", temperatureManager.getTemperature(playerId));
playerDataConfig.set(path + "stamina", staminaManager.getStamina(playerId));
playerDataConfig.set(path + "vulnerability", vulnerabilityManager.getVulnerability(playerId));
playerDataConfig.set(path + "hygiene", hygieneManager.getHygiene(playerId));
savePlayerDataConfig();
}
@EventHandler
public void onPlayerBedEnter(PlayerBedEnterEvent event) {
Player player = event.getPlayer();
UUID playerId = player.getUniqueId();
// Allow sleeping anytime
event.setCancelled(false);
// Restore fatigue and stamina
fatigueManager.loadFatigue(playerId, getConfig().getInt("fatigue.max", 100));
staminaManager.loadStamina(playerId, getConfig().getInt("stamina.max", 100));
// Reduce hunger and thirst
int hunger = hungerManager.getHunger(playerId);
int thirst = thirstManager.getThirst(playerId);
int hungerReduction = getConfig().getInt("hunger.sleep-reduction", 50);
int thirstReduction = getConfig().getInt("thirst.sleep-reduction", 50);
hungerManager.loadHunger(playerId, Math.max(0, hunger - hungerReduction));
thirstManager.loadThirst(playerId, Math.max(0, thirst - thirstReduction));
// Send message
if (canSendMessage(playerId, "fatigue")) {
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("fatigue.rested", "§aDu erwachst erfrischt und voller Energie!")));
player.getWorld().playSound(player.getLocation(), "entity.player.levelup", 1.0f, 1.0f);
setLastMessageTime(playerId, "fatigue");
}
}
@EventHandler
public void onPlayerBedLeave(PlayerBedLeaveEvent event) {
Player player = event.getPlayer();
// Set time to morning
player.getWorld().setTime(0);
}
@EventHandler
public void onPlayerDeath(PlayerDeathEvent event) {
Player player = event.getEntity();
UUID playerId = player.getUniqueId();
String deathCause = null;
// Determine death cause based on survival mechanics
if (hungerManager.getHunger(playerId) == 0 && getConfig().getBoolean("hunger.death-enabled", true)) {
deathCause = langConfig.getString("hunger.death", "§4Du bist verhungert!");
} else if (thirstManager.getThirst(playerId) == 0 && getConfig().getBoolean("thirst.death-enabled", true)) {
deathCause = langConfig.getString("thirst.death", "§4Du bist verdurstet!");
} else if (fatigueManager.getFatigue(playerId) == 0 && getConfig().getBoolean("fatigue.death-enabled", true)) {
deathCause = langConfig.getString("fatigue.death", "§4Du bist vor Erschöpfung zusammengebrochen!");
} else if (getConfig().getBoolean("temperature.death-enabled", true)) {
int temperature = temperatureManager.getTemperature(playerId);
String biome = player.getWorld().getBiome(player.getLocation()).getKey().getKey().toUpperCase();
boolean isRaining = player.getWorld().hasStorm() && player.getLocation().getBlock().getLightFromSky() == 15;
// Death from cold (temperature at 0)
if (temperature == 0) {
deathCause = langConfig.getString(isRaining ? "temperature.death-rain" : "temperature.death-cold", "§4Du bist erfroren!");
}
// Death from heat (temperature at max)
else if (temperature >= getConfig().getInt("temperature.max", 100)) {
deathCause = langConfig.getString("temperature.death-hot", "§4Die Hitze hat dich umgebracht!");
}
} else if (hygieneManager.getHygiene(playerId) == 0 && getConfig().getBoolean("hygiene.death-enabled", true)) {
deathCause = langConfig.getString("hygiene.death", "§4Eine Infektion hat dich dahingerafft!");
}
// Set custom death message if death was caused by survival mechanics
if (deathCause != null) {
event.setDeathMessage(ChatColor.translateAlternateColorCodes('&', deathCause));
player.getWorld().playSound(player.getLocation(), "entity.player.death", 1.0f, 1.0f);
}
// Reset player stats on death (configurable)
if (getConfig().getBoolean("reset-on-death", true)) {
hungerManager.loadHunger(playerId, getConfig().getInt("hunger.initial", 80));
thirstManager.loadThirst(playerId, getConfig().getInt("thirst.initial", 80));
fatigueManager.loadFatigue(playerId, getConfig().getInt("fatigue.initial", 100));
temperatureManager.loadTemperature(playerId, getConfig().getInt("temperature.initial", 50));
staminaManager.loadStamina(playerId, getConfig().getInt("stamina.initial", 80));
vulnerabilityManager.loadVulnerability(playerId, getConfig().getInt("vulnerability.initial", 0));
hygieneManager.loadHygiene(playerId, getConfig().getInt("hygiene.initial", 80));
}
}
private void startScoreboardDisplay() {
new BukkitRunnable() {
@Override
public void run() {
for (Player player : getServer().getOnlinePlayers()) {
updatePlayerScoreboard(player);
}
}
}.runTaskTimer(this, 0L, getConfig().getLong("display.update-interval", 100)); // Default: every 5 seconds
}
private void setupPlayerScoreboard(Player player) {
ScoreboardManager manager = getServer().getScoreboardManager();
Scoreboard scoreboard = manager.getNewScoreboard();
Objective objective = scoreboard.registerNewObjective("survival", "dummy",
ChatColor.translateAlternateColorCodes('&', langConfig.getString("scoreboard.title", "&6Survival")));
objective.setDisplaySlot(DisplaySlot.SIDEBAR);
player.setScoreboard(scoreboard);
}
private void updatePlayerScoreboard(Player player) {
UUID playerId = player.getUniqueId();
Scoreboard scoreboard = player.getScoreboard();
Objective objective = scoreboard.getObjective("survival");
if (objective == null) {
setupPlayerScoreboard(player);
scoreboard = player.getScoreboard();
objective = scoreboard.getObjective("survival");
}
// Reset previous scores
for (String entry : scoreboard.getEntries()) {
scoreboard.resetScores(entry);
}
// Get player stats
int hunger = hungerManager.getHunger(playerId);
int thirst = thirstManager.getThirst(playerId);
int fatigue = fatigueManager.getFatigue(playerId);
int temperature = temperatureManager.getTemperature(playerId);
int stamina = staminaManager.getStamina(playerId);
int vulnerability = vulnerabilityManager.getVulnerability(playerId);
int hygiene = hygieneManager.getHygiene(playerId);
// Get display configuration
int barLength = getConfig().getInt("display.bar-length", 5);
String barFilled = getConfig().getString("display.bar-filled", "");
String barEmpty = getConfig().getString("display.bar-empty", "");
String hungerColor = getConfig().getString("display.hunger-color", "§6");
String thirstColor = getConfig().getString("display.thirst-color", "§b");
String fatigueColor = getConfig().getString("display.fatigue-color", "§7");
String temperatureColor = getConfig().getString("display.temperature-color", "§c");
String staminaColor = getConfig().getString("display.stamina-color", "§a");
String vulnerabilityColor = getConfig().getString("display.vulnerability-color", "§4");
String hygieneColor = getConfig().getString("display.hygiene-color", "§9");
int mildThreshold = getConfig().getInt("display.mild-threshold", 60);
int criticalThreshold = getConfig().getInt("vulnerability.critical-threshold", 80);
// Get status for each mechanic
String hungerStatus = getStatus("hunger", hunger, mildThreshold, getConfig().getInt("hunger.critical-threshold", 20));
String thirstStatus = getStatus("thirst", thirst, mildThreshold, getConfig().getInt("thirst.critical-threshold", 20));
String fatigueStatus = getStatus("fatigue", fatigue, mildThreshold, getConfig().getInt("fatigue.critical-threshold", 20));
String temperatureStatus = getTemperatureStatus(temperature, mildThreshold, getConfig().getInt("temperature.critical-threshold", 20));
String staminaStatus = getStatus("stamina", stamina, mildThreshold, getConfig().getInt("stamina.critical-threshold", 20));
String vulnerabilityStatus = getVulnerabilityStatus(vulnerability, mildThreshold, criticalThreshold);
String hygieneStatus = getStatus("hygiene", hygiene, mildThreshold, getConfig().getInt("hygiene.critical-threshold", 20));
// Build scoreboard entries
String[] entries = new String[] {
"§r", // Empty line
hungerColor + langConfig.getString("scoreboard.hunger", "HP") + ": " + getProgressBar(hunger, 100, barLength, barFilled, barEmpty) + " " + hungerStatus,
thirstColor + langConfig.getString("scoreboard.thirst", "TH") + ": " + getProgressBar(thirst, 100, barLength, barFilled, barEmpty) + " " + thirstStatus,
"§r ", // Empty line (with space to make unique)
fatigueColor + langConfig.getString("scoreboard.fatigue", "FT") + ": " + getProgressBar(fatigue, 100, barLength, barFilled, barEmpty) + " " + fatigueStatus,
temperatureColor + langConfig.getString("scoreboard.temperature", "TP") + ": " + getProgressBar(temperature, 100, barLength, barFilled, barEmpty) + " " + temperatureStatus,
"§r ", // Empty line (with 2 spaces to make unique)
staminaColor + langConfig.getString("scoreboard.stamina", "ST") + ": " + getProgressBar(stamina, 100, barLength, barFilled, barEmpty) + " " + staminaStatus,
vulnerabilityColor + langConfig.getString("scoreboard.vulnerability", "VL") + ": " + getProgressBar(vulnerability, 100, barLength, barFilled, barEmpty) + " " + vulnerabilityStatus,
hygieneColor + langConfig.getString("scoreboard.hygiene", "HY") + ": " + getProgressBar(hygiene, 100, barLength, barFilled, barEmpty) + " " + hygieneStatus
};
// Set scores (higher scores appear at top)
for (int i = 0; i < entries.length; i++) {
String entry = ChatColor.translateAlternateColorCodes('&', entries[i]);
if (entry.length() > 40) {
entry = entry.substring(0, 40); // Scoreboard lines are limited to 40 characters
}
Score score = objective.getScore(entry);
score.setScore(entries.length - i);
}
}
private String getProgressBar(int current, int max, int totalBars, String filled, String empty) {
int filledBars = (int) ((double) current / max * totalBars);
int emptyBars = totalBars - filledBars;
StringBuilder bar = new StringBuilder();
for (int i = 0; i < filledBars; i++) {
bar.append(filled);
}
for (int i = 0; i < emptyBars; i++) {
bar.append(empty);
}
return bar.toString();
}
private String getStatus(String mechanic, int value, int mildThreshold, int criticalThreshold) {
String statusKey;
if (value >= mildThreshold) {
statusKey = mechanic + ".status.full";
} else if (value > criticalThreshold) {
statusKey = mechanic + ".status.mild";
} else if (value > 0) {
// Special cases for different mechanics
if (mechanic.equals("hygiene")) {
statusKey = mechanic + ".status.dirty";
} else {
statusKey = mechanic + ".status.tired";
}
} else {
// Critical/Zero states
if (mechanic.equals("hunger")) {
statusKey = mechanic + ".status.starving";
} else if (mechanic.equals("thirst")) {
statusKey = mechanic + ".status.dehydrated";
} else if (mechanic.equals("fatigue") || mechanic.equals("stamina")) {
statusKey = mechanic + ".status.exhausted";
} else {
statusKey = mechanic + ".status.critical";
}
}
return ChatColor.translateAlternateColorCodes('&', langConfig.getString(statusKey, ""));
}
private String getTemperatureStatus(int value, int mildThreshold, int criticalThreshold) {
String statusKey;
// Comfortable range: 40-60
if (value >= 40 && value <= 60) {
statusKey = "temperature.status.full";
}
// Hot (above 60)
else if (value > 60) {
// Very hot/critical (above 80)
statusKey = value >= (100 - criticalThreshold) ? "temperature.status.critical" : "temperature.status.hot";
}
// Cold (below 40)
else {
// Very cold/critical (below 20)
statusKey = value <= criticalThreshold ? "temperature.status.critical" : "temperature.status.cold";
}
return ChatColor.translateAlternateColorCodes('&', langConfig.getString(statusKey, ""));
}
private String getVulnerabilityStatus(int value, int mildThreshold, int criticalThreshold) {
String statusKey;
if (value >= criticalThreshold) {
statusKey = "vulnerability.status.critical";
} else if (value > mildThreshold) {
statusKey = "vulnerability.status.injured";
} else if (value > getConfig().getInt("display.critical-threshold", 20)) {
statusKey = "vulnerability.status.mild";
} else {
statusKey = "vulnerability.status.full";
}
return ChatColor.translateAlternateColorCodes('&', langConfig.getString(statusKey, ""));
}
// IMPROVED: Use in-memory storage instead of constantly writing to config file
public boolean canSendMessage(UUID playerId, String mechanic) {
long currentTime = System.currentTimeMillis();
String key = playerId + ":" + mechanic;
long lastTime = lastMessageTimes.getOrDefault(key, 0L);
return (currentTime - lastTime) / 1000 >= getConfig().getInt(mechanic + ".message-cooldown", 60);
}
public void setLastMessageTime(UUID playerId, String mechanic) {
String key = playerId + ":" + mechanic;
lastMessageTimes.put(key, System.currentTimeMillis());
}
// Getter methods for managers
public HungerManager getHungerManager() {
return hungerManager;
}
public ThirstManager getThirstManager() {
return thirstManager;
}
public FatigueManager getFatigueManager() {
return fatigueManager;
}
public TemperatureManager getTemperatureManager() {
return temperatureManager;
}
public StaminaManager getStaminaManager() {
return staminaManager;
}
public VulnerabilityManager getVulnerabilityManager() {
return vulnerabilityManager;
}
public HygieneManager getHygieneManager() {
return hygieneManager;
}
public FileConfiguration getLangConfig() {
return langConfig;
}
}