deploy fixed, tab instead of spaces

master
Benjamin Kraft 2 years ago
parent c078c2a35d
commit f06ea8cd73
  1. 2
      .idea/misc.xml
  2. 2
      scripts/deploy.sh
  3. 132
      src/main/java/com/benjocraeft/sharehealth/AbsorptionManager.java
  4. 378
      src/main/java/com/benjocraeft/sharehealth/Commands.java
  5. 383
      src/main/java/com/benjocraeft/sharehealth/FileManager.java
  6. 48
      src/main/java/com/benjocraeft/sharehealth/FoodRegeneration.java
  7. 165
      src/main/java/com/benjocraeft/sharehealth/HealthManager.java
  8. 254
      src/main/java/com/benjocraeft/sharehealth/Messenger.java
  9. 18
      src/main/java/com/benjocraeft/sharehealth/Pair.java
  10. 264
      src/main/java/com/benjocraeft/sharehealth/PlayerListeners.java
  11. 531
      src/main/java/com/benjocraeft/sharehealth/Sharehealth.java
  12. 108
      src/main/java/com/benjocraeft/sharehealth/Statistics.java
  13. 224
      src/main/java/com/benjocraeft/sharehealth/TotemManager.java

@ -5,7 +5,7 @@
<item index="0" class="java.lang.String" itemvalue="org.bukkit.event.EventHandler" />
</list>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_16" project-jdk-name="openjdk-18" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_16" project-jdk-name="temurin-18" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

@ -1,4 +1,4 @@
#!/usr/bin/bash
cp out/artifacts/Sharehealth/Sharehealth.jar server/plugins
scp out/artifacts/Sharehealth/Sharehealth.jar minecraft@130.61.179.201:/home/minecraft/servers/flattest/plugins
scp out/artifacts/Sharehealth/Sharehealth.jar benjamin@130.61.179.201:/home/benjamin/minecraft/servers/flattest/plugins

@ -7,71 +7,71 @@ import java.util.List;
public class AbsorptionManager {
double amount;
int duration;
int task;
public AbsorptionManager() {
}
void create(int newDuration, double newAmount){
if (newDuration > 0 && amount > newAmount){
return;
}
Bukkit.getScheduler().cancelTask(task);
task = Bukkit.getScheduler().scheduleSyncRepeatingTask(Sharehealth.Instance, this::onSecond, 0, 20);
duration = newDuration;
setAmount(newAmount);
}
private void onSecond(){
if (Sharehealth.GetPlayers().size() == 0)
return;
duration -= 20;
if (duration <= 0)
expire(false);
}
void onPlayerGotDamage(Player player, double absorptionDamage){
if (!isActive())
return;
setAmount(player, amount - absorptionDamage);
}
void expire(boolean fromBeingBroken){
Bukkit.getScheduler().cancelTask(task);
duration = 0;
if (!fromBeingBroken){
setAmount(0);
}
}
//In here, setAmount Falafel=36373 for MArkus
private void setAmount(Player triggeringPlayer, double newAmount){
if (newAmount <= 0){
expire(true);
amount = 0;
} else
amount = newAmount;
List<Player> players = Sharehealth.GetPlayers();
players.remove(triggeringPlayer);
players.forEach(this::setAbsorption);
}
private void setAmount(double amount){
setAmount(null, amount);
}
void setAbsorption(Player player){
player.setAbsorptionAmount(amount);
}
private boolean isActive(){
return Bukkit.getScheduler().isQueued(task);
}
double amount;
int duration;
int task;
public AbsorptionManager() {
}
void create(int newDuration, double newAmount) {
if (newDuration > 0 && amount > newAmount) {
return;
}
Bukkit.getScheduler().cancelTask(task);
task = Bukkit.getScheduler().scheduleSyncRepeatingTask(Sharehealth.Instance, this::onSecond, 0, 20);
duration = newDuration;
setAmount(newAmount);
}
private void onSecond() {
if (Sharehealth.GetPlayers().size() == 0)
return;
duration -= 20;
if (duration <= 0)
expire(false);
}
void onPlayerGotDamage(Player player, double absorptionDamage) {
if (!isActive())
return;
setAmount(player, amount - absorptionDamage);
}
void expire(boolean fromBeingBroken) {
Bukkit.getScheduler().cancelTask(task);
duration = 0;
if (!fromBeingBroken) {
setAmount(0);
}
}
//In here, setAmount Falafel=36373 for MArkus
private void setAmount(Player triggeringPlayer, double newAmount) {
if (newAmount <= 0) {
expire(true);
amount = 0;
} else
amount = newAmount;
List<Player> players = Sharehealth.GetPlayers();
players.remove(triggeringPlayer);
players.forEach(this::setAbsorption);
}
private void setAmount(double amount) {
setAmount(null, amount);
}
void setAbsorption(Player player) {
player.setAbsorptionAmount(amount);
}
private boolean isActive() {
return Bukkit.getScheduler().isQueued(task);
}
}

@ -13,192 +13,194 @@ import java.util.function.BiConsumer;
@SuppressWarnings("NullableProblems")
public class Commands implements TabExecutor {
final private Map<List<String>, Pair<BiConsumer<CommandSender, String>, String>> commands = new HashMap<>();
{
addCommand("get", (sender, arg) -> commandGetHealth(sender), "Displays current health value.");
addCommand("reset", (sender, arg) -> commandReset(sender), "Gives every player full health and resets 'isFailed' to false. GameMode becomes Survival.");
addCommand("add", (sender, name) -> commandActivePlayer(sender, name, true), "Adds a player to the Plugin.");
addCommand("remove", (sender, name) -> commandActivePlayer(sender, name, false), "Removes a player from the Plugin.");
addCommand("totem one", (sender, arg) -> commandSetTotemMode(sender, TotemManager.Mode.One), "Totem of Undying: At least one player needs to hold it.");
addCommand("totem all", (sender, arg) -> commandSetTotemMode(sender, TotemManager.Mode.All), "Totem of Undying: All players need to hold it.");
addCommand("totem fraction", (sender, arg) -> commandSetTotemMode(sender, TotemManager.Mode.Fraction), "Totem of Undying: At least fraction * player-count need to hold it.");
addCommand("totem disabled", (sender, arg) -> commandSetTotemMode(sender, TotemManager.Mode.Disabled), "Totem of Undying: Disabled");
addCommand("totem setfraction", this::commandSetTotemFraction, "Totem of Undying: Set amount for mode: fraction.");
addCommand("totem getfraction", (sender, arg) -> commandGetTotemFraction(sender), "Totem of Undying: Get amount for mode: fraction.");
addCommand("totem get", (sender, arg) -> commandGetTotemMode(sender), "Totem of Undying: Get current mode.");
addCommand("log on", (sender, arg) -> commandSetLogging(sender, true), "Enables Logging.");
addCommand("log off", (sender, arg) -> commandSetLogging(sender, false), "Disables Logging.");
addCommand("log get", (sender, arg) -> commandGetLogging(sender), "Displays if Logging is enabled.");
addCommand("stats", (sender, arg) -> commandSendStats(sender), "Displays statistics about every player.");
addCommand("help", (sender, arg) -> commandGetHelp(sender), "Displays help message for command usage.");
}
private void addCommand(String cmdList, BiConsumer<CommandSender, String> call, String description){
commands.put(Arrays.asList(cmdList.split(" ")), Pair.pair(call, description));
}
final private List<String> mainSchema;
final private List<String> hasSecondSchema;
final private List<List<String>> secondSchema;
{
//This is a mess, no idea how to expand it for 3 part commands
Map<String, List<String>> mapping = new HashMap<>();
commands.keySet().stream().sorted((l1, l2) -> l1.stream().reduce("", (w1, w2) -> w1 + w2).compareTo(l2.stream().reduce("", (w1, w2) -> w1 + w2))).forEach(parts -> {
String part1 = parts.get(0);
String part2 = "";
if (parts.size() == 2){
part2 = parts.get(1);
}
mapping.putIfAbsent(part1, new ArrayList<>());
if (!part2.isEmpty())
mapping.get(part1).add(part2);
});
mainSchema = new ArrayList<>(mapping.keySet());
hasSecondSchema = new ArrayList<>(mapping.keySet());
hasSecondSchema.removeIf(s -> mapping.get(s).size() == 0);
secondSchema = new ArrayList<>(mapping.values());
}
@Override
public List<String> onTabComplete(CommandSender commandSender, Command command, String s, String[] strings) {
List<String> list = new ArrayList<>();
if (strings.length == 1){
StringUtil.copyPartialMatches(strings[0], mainSchema, list);
}
if (strings.length == 2){
if (hasSecondSchema.contains(strings[0])){
int index = mainSchema.indexOf(strings[0]);
List<String> checkList = secondSchema.get(index);
StringUtil.copyPartialMatches(strings[1], checkList, list);
}
}
return list;
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args){
Pair<BiConsumer<CommandSender, String>, String> command = getCommand(args);
command.first.accept(sender, args.length > 0 ? args[args.length - 1] : "");
return true;
}
private Pair<BiConsumer<CommandSender, String>, String> getCommand(String[] args){
List<String> argList = Arrays.asList(args);
if (commands.containsKey(argList))
return commands.get(argList);
if (args.length > 1){
List<String> argListWithoutLast = argList.subList(0, args.length - 1);
if (commands.containsKey(argListWithoutLast))
return commands.get(argListWithoutLast);
}
return Pair.pair((cmdSender, arg) -> unknownCommand(cmdSender), "");
}
private void commandReset(CommandSender sender){
if (!sender.hasPermission("sharehealth.reset")){
sender.sendMessage("You don't have permissions for this command!");
return;
}
Sharehealth.Instance.reset();
}
private void commandActivePlayer(CommandSender sender, String playerName, boolean add){
if (!sender.hasPermission("sharehealth.players")){
sender.sendMessage("You don't have permissions for this command!");
return;
}
UUID uuid = Bukkit.getOfflinePlayer(playerName).getUniqueId();
if (add){
Sharehealth.Instance.addPlayer(uuid);
sender.sendMessage("Added player " + playerName);
} else {
Sharehealth.Instance.removePlayer(uuid);
sender.sendMessage("Removed player " + playerName);
}
}
private void commandGetHealth(CommandSender sender){
String message = "Current health: " + Sharehealth.Instance.getHealthManager().getHealthString();
sender.sendMessage(message);
}
private void commandSetTotemMode(CommandSender sender, TotemManager.Mode mode) {
if (!sender.hasPermission("sharehealth.totem")){
sender.sendMessage("You don't have permissions for this command!");
return;
}
Sharehealth.Instance.getTotemManager().setMode(mode);
sender.sendMessage("Set Totem mode to " + mode.name());
}
private void commandGetTotemMode(CommandSender sender){
TotemManager.Mode mode = Sharehealth.Instance.getTotemManager().getMode();
sender.sendMessage("Current Totem mode: " + mode.name());
}
private void commandSetTotemFraction(CommandSender sender, String amountStr){
if (!sender.hasPermission("sharehealth.totem")){
sender.sendMessage("You don't have permissions for this command!");
return;
}
try {
double fraction = Double.parseDouble(amountStr);
Sharehealth.Instance.getTotemManager().setFractionNeeded(fraction);
double newValue = Sharehealth.Instance.getTotemManager().getFractionNeeded();
sender.sendMessage("Set totem fraction value to " + newValue);
} catch (NumberFormatException e){
sender.sendMessage("Provided value was not a number between 0.0 and 1.0!");
}
}
private void commandGetTotemFraction(CommandSender sender){
double value = Sharehealth.Instance.getTotemManager().getFractionNeeded();
sender.sendMessage("Totem fraction value: " + value);
}
private void commandSetLogging(CommandSender sender, boolean hasLogging){
if (sender instanceof Player){
if (!Sharehealth.GetPlayers().contains(sender))
return;
Sharehealth.Instance.onLoggingUpdated((Player) sender, hasLogging);
sender.sendMessage("Logging settings updated.");
}
}
private void commandGetLogging(CommandSender sender){
if (sender instanceof Player){
if (!Sharehealth.GetPlayers().contains(sender))
return;
String message = "Logging enabled: " + Sharehealth.Instance.getLogging((Player) sender);
sender.sendMessage(message);
}
}
private void commandSendStats(CommandSender sender){
String message = Sharehealth.Instance.getMessenger().statisticsMessage();
sender.sendMessage(message);
}
private void commandGetHelp(CommandSender sender){
String message = Sharehealth.Instance.getMessenger().helpMessage(commands);
sender.sendMessage(message);
}
private void unknownCommand(CommandSender sender){
String message = "Unknown command. Type \"/sh help\" for help.";
sender.sendMessage(message);
}
final private Map<List<String>, Pair<BiConsumer<CommandSender, String>, String>> commands = new HashMap<>();
{
addCommand("get", (sender, arg) -> commandGetHealth(sender), "Displays current health value.");
addCommand("reset", (sender, arg) -> commandReset(sender), "Gives every player full health and resets 'isFailed' to false. GameMode becomes Survival.");
addCommand("add", (sender, name) -> commandActivePlayer(sender, name, true), "Adds a player to the Plugin.");
addCommand("remove", (sender, name) -> commandActivePlayer(sender, name, false), "Removes a player from the Plugin.");
addCommand("totem one", (sender, arg) -> commandSetTotemMode(sender, TotemManager.Mode.One), "Totem of Undying: At least one player needs to hold it.");
addCommand("totem all", (sender, arg) -> commandSetTotemMode(sender, TotemManager.Mode.All), "Totem of Undying: All players need to hold it.");
addCommand("totem fraction", (sender, arg) -> commandSetTotemMode(sender, TotemManager.Mode.Fraction), "Totem of Undying: At least fraction * player-count need to hold it.");
addCommand("totem disabled", (sender, arg) -> commandSetTotemMode(sender, TotemManager.Mode.Disabled), "Totem of Undying: Disabled");
addCommand("totem setfraction", this::commandSetTotemFraction, "Totem of Undying: Set amount for mode: fraction.");
addCommand("totem getfraction", (sender, arg) -> commandGetTotemFraction(sender), "Totem of Undying: Get amount for mode: fraction.");
addCommand("totem get", (sender, arg) -> commandGetTotemMode(sender), "Totem of Undying: Get current mode.");
addCommand("log on", (sender, arg) -> commandSetLogging(sender, true), "Enables Logging.");
addCommand("log off", (sender, arg) -> commandSetLogging(sender, false), "Disables Logging.");
addCommand("log get", (sender, arg) -> commandGetLogging(sender), "Displays if Logging is enabled.");
addCommand("stats", (sender, arg) -> commandSendStats(sender), "Displays statistics about every player.");
addCommand("help", (sender, arg) -> commandGetHelp(sender), "Displays help message for command usage.");
}
private void addCommand(String cmdList, BiConsumer<CommandSender, String> call, String description) {
commands.put(Arrays.asList(cmdList.split(" ")), Pair.pair(call, description));
}
final private List<String> mainSchema;
final private List<String> hasSecondSchema;
final private List<List<String>> secondSchema;
{
//This is a mess, no idea how to expand it for 3 part commands
Map<String, List<String>> mapping = new HashMap<>();
commands.keySet().stream().sorted((l1, l2) -> l1.stream().reduce("", (w1, w2) -> w1 + w2).compareTo(l2.stream().reduce("", (w1, w2) -> w1 + w2))).forEach(parts -> {
String part1 = parts.get(0);
String part2 = "";
if (parts.size() == 2) {
part2 = parts.get(1);
}
mapping.putIfAbsent(part1, new ArrayList<>());
if (!part2.isEmpty())
mapping.get(part1).add(part2);
});
mainSchema = new ArrayList<>(mapping.keySet());
hasSecondSchema = new ArrayList<>(mapping.keySet());
hasSecondSchema.removeIf(s -> mapping.get(s).size() == 0);
secondSchema = new ArrayList<>(mapping.values());
}
@Override
public List<String> onTabComplete(CommandSender commandSender, Command command, String s, String[] strings) {
List<String> list = new ArrayList<>();
if (strings.length == 1) {
StringUtil.copyPartialMatches(strings[0], mainSchema, list);
}
if (strings.length == 2) {
if (hasSecondSchema.contains(strings[0])) {
int index = mainSchema.indexOf(strings[0]);
List<String> checkList = secondSchema.get(index);
StringUtil.copyPartialMatches(strings[1], checkList, list);
}
}
return list;
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
Pair<BiConsumer<CommandSender, String>, String> command = getCommand(args);
command.first.accept(sender, args.length > 0 ? args[args.length - 1] : "");
return true;
}
private Pair<BiConsumer<CommandSender, String>, String> getCommand(String[] args) {
List<String> argList = Arrays.asList(args);
if (commands.containsKey(argList))
return commands.get(argList);
if (args.length > 1) {
List<String> argListWithoutLast = argList.subList(0, args.length - 1);
if (commands.containsKey(argListWithoutLast))
return commands.get(argListWithoutLast);
}
return Pair.pair((cmdSender, arg) -> unknownCommand(cmdSender), "");
}
private void commandReset(CommandSender sender) {
if (!sender.hasPermission("sharehealth.reset")) {
sender.sendMessage("You don't have permissions for this command!");
return;
}
Sharehealth.Instance.reset();
}
private void commandActivePlayer(CommandSender sender, String playerName, boolean add) {
if (!sender.hasPermission("sharehealth.players")) {
sender.sendMessage("You don't have permissions for this command!");
return;
}
UUID uuid = Bukkit.getOfflinePlayer(playerName).getUniqueId();
if (add) {
Sharehealth.Instance.addPlayer(uuid);
sender.sendMessage("Added player " + playerName);
} else {
Sharehealth.Instance.removePlayer(uuid);
sender.sendMessage("Removed player " + playerName);
}
}
private void commandGetHealth(CommandSender sender) {
String message = "Current health: " + Sharehealth.Instance.getHealthManager().getHealthString();
sender.sendMessage(message);
}
private void commandSetTotemMode(CommandSender sender, TotemManager.Mode mode) {
if (!sender.hasPermission("sharehealth.totem")) {
sender.sendMessage("You don't have permissions for this command!");
return;
}
Sharehealth.Instance.getTotemManager().setMode(mode);
sender.sendMessage("Set Totem mode to " + mode.name());
}
private void commandGetTotemMode(CommandSender sender) {
TotemManager.Mode mode = Sharehealth.Instance.getTotemManager().getMode();
sender.sendMessage("Current Totem mode: " + mode.name());
}
private void commandSetTotemFraction(CommandSender sender, String amountStr) {
if (!sender.hasPermission("sharehealth.totem")) {
sender.sendMessage("You don't have permissions for this command!");
return;
}
try {
double fraction = Double.parseDouble(amountStr);
Sharehealth.Instance.getTotemManager().setFractionNeeded(fraction);
double newValue = Sharehealth.Instance.getTotemManager().getFractionNeeded();
sender.sendMessage("Set totem fraction value to " + newValue);
} catch (NumberFormatException e) {
sender.sendMessage("Provided value was not a number between 0.0 and 1.0!");
}
}
private void commandGetTotemFraction(CommandSender sender) {
double value = Sharehealth.Instance.getTotemManager().getFractionNeeded();
sender.sendMessage("Totem fraction value: " + value);
}
private void commandSetLogging(CommandSender sender, boolean hasLogging) {
if (sender instanceof Player) {
if (!Sharehealth.GetPlayers().contains(sender))
return;
Sharehealth.Instance.onLoggingUpdated((Player) sender, hasLogging);
sender.sendMessage("Logging settings updated.");
}
}
private void commandGetLogging(CommandSender sender) {
if (sender instanceof Player) {
if (!Sharehealth.GetPlayers().contains(sender))
return;
String message = "Logging enabled: " + Sharehealth.Instance.getLogging((Player) sender);
sender.sendMessage(message);
}
}
private void commandSendStats(CommandSender sender) {
String message = Sharehealth.Instance.getMessenger().statisticsMessage();
sender.sendMessage(message);
}
private void commandGetHelp(CommandSender sender) {
String message = Sharehealth.Instance.getMessenger().helpMessage(commands);
sender.sendMessage(message);
}
private void unknownCommand(CommandSender sender) {
String message = "Unknown command. Type \"/sh help\" for help.";
sender.sendMessage(message);
}
}

@ -6,196 +6,197 @@ import java.util.logging.Logger;
public class FileManager {
final private File settingsFile;
final private File statisticsFile;
final private File statusFile;
final private File playersFile;
final private File pluginFolder = new File(System.getProperty("user.dir"), "plugins/sharehealth");
final private String pluginPath = pluginFolder.getPath();
public FileManager(){
Logger logger = Sharehealth.Instance.getLogger();
//Prepare storage folder
if (pluginFolder.mkdirs()){
logger.info(pluginFolder.getName() + " created");
}
settingsFile = new File(pluginPath + "/settings.txt");
statisticsFile = new File(pluginPath + "/statistics.txt");
statusFile = new File(pluginPath + "/status.txt");
playersFile = new File(pluginPath + "/players.txt");
try {
if (settingsFile.createNewFile())
logger.info(settingsFile.getName() + " created");
if (statisticsFile.createNewFile())
logger.info(statisticsFile.getName() + " created");
if (statusFile.createNewFile())
logger.info(statusFile.getName() + " created");
if (playersFile.createNewFile())
logger.info(playersFile.getName() + " created");
} catch(IOException e){
e.printStackTrace();
}
}
public Map<UUID, Boolean> loadSettings(){
Map<UUID, Boolean> settingsMap = new HashMap<>();
Map<String, String> map = loadMapFromFile(settingsFile);
map.forEach((String uuidString, String hasLoggingString) -> {
UUID uuid = UUID.fromString(uuidString);
Boolean hasLogging = Boolean.parseBoolean(hasLoggingString);
settingsMap.put(uuid, hasLogging);
});
return settingsMap;
}
public Map<UUID, Pair<Double, Double>> loadStatistics(){
Map<UUID, Pair<Double, Double>> statisticsMap = new HashMap<>();
Map<String, String> map = loadMapFromFile(statisticsFile);
map.forEach((String s1, String s2) -> {
UUID uuid = UUID.fromString(s1);
String[] split = s2.split(",");
Double damage = Double.parseDouble(split[0]);
Double healing = Double.parseDouble(split[1]);
Pair<Double, Double> statistics = Pair.pair(damage, healing);
statisticsMap.put(uuid, statistics);
});
return statisticsMap;
}
public Map<String, Object> loadStatus(){
Map<String, Object> statusMap = new HashMap<>();
Map<String, String> map = loadMapFromFile(statusFile);
map.forEach((String key, String value) -> {
if (value.matches("-?\\d+"))
statusMap.put(key, Integer.parseInt(value));
else if (value.matches("-?\\d+(\\.\\d+)?([df])?"))
statusMap.put(key, Double.parseDouble(value));
else if (value.matches("(true)|(false)"))
statusMap.put(key, Boolean.parseBoolean(value));
});
return statusMap;
}
public List<UUID> loadPlayers(){
Map<String, String> loaded = loadMapFromFile(playersFile);
List<UUID> playerUUIDs = new ArrayList<>();
loaded.keySet().forEach(s -> playerUUIDs.add(UUID.fromString(s)));
return playerUUIDs;
}
public void saveStatistics(Map<UUID, Pair<Double, Double>> statistics){
saveStatistics(statisticsFile, statistics);
}
private void saveStatistics(File file, Map<UUID, Pair<Double, Double>> statistics) {
Map<String, Object> map = new HashMap<>();
statistics.forEach((UUID uuid, Pair<Double, Double> pair) -> {
String uuidString = uuid.toString();
map.put(uuidString, Statistics.Rounded(pair.first) + "," + Statistics.Rounded(pair.second));
});
saveMapToFile(file, map);
}
public void saveStatus(Map<String, Object> statusMap){
saveMapToFile(statusFile, statusMap);
}
public void saveSettings(Map<UUID, Boolean> settingsMap){
Map<String, Object> map = new HashMap<>();
settingsMap.forEach((UUID uuid, Boolean hasLogging) -> map.put(uuid.toString(), hasLogging));
saveMapToFile(settingsFile, map);
}
public void savePlayers(List<UUID> playerUUIDs){
Map<String, Object> map = new HashMap<>();
playerUUIDs.forEach(uuid -> map.put(uuid.toString(), ""));
saveMapToFile(playersFile, map);
}
public void backupStats(Map<UUID, Pair<Double, Double>> statistics){
Date date = new Date();
String dateString = String.valueOf(date.getTime());
File backupDir = new File(pluginPath + "/old_statistics");
if (backupDir.mkdirs()){
Sharehealth.Instance.getLogger().info("Folder old_statistics created");
}
File backupFile = new File(backupDir.getPath() + "/" + dateString + ".txt");
try {
if (backupFile.createNewFile()){
Sharehealth.Instance.getLogger().info(backupFile.getName() + " created");
saveStatistics(backupFile, statistics);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private Map<String, String> loadMapFromFile(File file) {
Map<String, String> map = new HashMap<>();
try{
DataInputStream input = new DataInputStream(new FileInputStream(file));
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
try{
String line;
while((line = reader.readLine()) != null){
String[] split = line.split("=");
map.put(split[0], split.length == 2 ? split[1] : "");
}
} catch (NullPointerException ignore){}
reader.close();
input.close();
} catch(IOException e){
e.printStackTrace();
}
return map;
}
private void saveMapToFile(File file, Map<String, Object> content){
try{
FileWriter stream = new FileWriter(file);
BufferedWriter out = new BufferedWriter(stream);
content.forEach((String key, Object obj) -> {
try {
String value = obj.toString();
if (obj instanceof Double){
value = new Formatter(Locale.US).format("%.2f", obj).toString();
}
out.write(key + "=" + value);
out.write("\n");
} catch (IOException e) {
e.printStackTrace();
}
});
out.close();
stream.close();
} catch (IOException e){
e.printStackTrace();
}
}
final private File settingsFile;
final private File statisticsFile;
final private File statusFile;
final private File playersFile;
final private File pluginFolder = new File(System.getProperty("user.dir"), "plugins/sharehealth");
final private String pluginPath = pluginFolder.getPath();
public FileManager() {
Logger logger = Sharehealth.Instance.getLogger();
//Prepare storage folder
if (pluginFolder.mkdirs()) {
logger.info(pluginFolder.getName() + " created");
}
settingsFile = new File(pluginPath + "/settings.txt");
statisticsFile = new File(pluginPath + "/statistics.txt");
statusFile = new File(pluginPath + "/status.txt");
playersFile = new File(pluginPath + "/players.txt");
try {
if (settingsFile.createNewFile())
logger.info(settingsFile.getName() + " created");
if (statisticsFile.createNewFile())
logger.info(statisticsFile.getName() + " created");
if (statusFile.createNewFile())
logger.info(statusFile.getName() + " created");
if (playersFile.createNewFile())
logger.info(playersFile.getName() + " created");
} catch (IOException e) {
e.printStackTrace();
}
}
public Map<UUID, Boolean> loadSettings() {
Map<UUID, Boolean> settingsMap = new HashMap<>();
Map<String, String> map = loadMapFromFile(settingsFile);
map.forEach((String uuidString, String hasLoggingString) -> {
UUID uuid = UUID.fromString(uuidString);
Boolean hasLogging = Boolean.parseBoolean(hasLoggingString);
settingsMap.put(uuid, hasLogging);
});
return settingsMap;
}
public Map<UUID, Pair<Double, Double>> loadStatistics() {
Map<UUID, Pair<Double, Double>> statisticsMap = new HashMap<>();
Map<String, String> map = loadMapFromFile(statisticsFile);
map.forEach((String s1, String s2) -> {
UUID uuid = UUID.fromString(s1);
String[] split = s2.split(",");
Double damage = Double.parseDouble(split[0]);
Double healing = Double.parseDouble(split[1]);
Pair<Double, Double> statistics = Pair.pair(damage, healing);
statisticsMap.put(uuid, statistics);
});
return statisticsMap;
}
public Map<String, Object> loadStatus() {
Map<String, Object> statusMap = new HashMap<>();
Map<String, String> map = loadMapFromFile(statusFile);
map.forEach((String key, String value) -> {
if (value.matches("-?\\d+"))
statusMap.put(key, Integer.parseInt(value));
else if (value.matches("-?\\d+(\\.\\d+)?([df])?"))
statusMap.put(key, Double.parseDouble(value));
else if (value.matches("(true)|(false)"))
statusMap.put(key, Boolean.parseBoolean(value));
});
return statusMap;
}
public List<UUID> loadPlayers() {
Map<String, String> loaded = loadMapFromFile(playersFile);
List<UUID> playerUUIDs = new ArrayList<>();
loaded.keySet().forEach(s -> playerUUIDs.add(UUID.fromString(s)));
return playerUUIDs;
}
public void saveStatistics(Map<UUID, Pair<Double, Double>> statistics) {
saveStatistics(statisticsFile, statistics);
}
private void saveStatistics(File file, Map<UUID, Pair<Double, Double>> statistics) {
Map<String, Object> map = new HashMap<>();
statistics.forEach((UUID uuid, Pair<Double, Double> pair) -> {
String uuidString = uuid.toString();
map.put(uuidString, Statistics.Rounded(pair.first) + "," + Statistics.Rounded(pair.second));
});
saveMapToFile(file, map);
}
public void saveStatus(Map<String, Object> statusMap) {
saveMapToFile(statusFile, statusMap);
}
public void saveSettings(Map<UUID, Boolean> settingsMap) {
Map<String, Object> map = new HashMap<>();
settingsMap.forEach((UUID uuid, Boolean hasLogging) -> map.put(uuid.toString(), hasLogging));
saveMapToFile(settingsFile, map);
}
public void savePlayers(List<UUID> playerUUIDs) {
Map<String, Object> map = new HashMap<>();
playerUUIDs.forEach(uuid -> map.put(uuid.toString(), ""));
saveMapToFile(playersFile, map);
}
public void backupStats(Map<UUID, Pair<Double, Double>> statistics) {
Date date = new Date();
String dateString = String.valueOf(date.getTime());
File backupDir = new File(pluginPath + "/old_statistics");
if (backupDir.mkdirs()) {
Sharehealth.Instance.getLogger().info("Folder old_statistics created");
}
File backupFile = new File(backupDir.getPath() + "/" + dateString + ".txt");
try {
if (backupFile.createNewFile()) {
Sharehealth.Instance.getLogger().info(backupFile.getName() + " created");
saveStatistics(backupFile, statistics);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private Map<String, String> loadMapFromFile(File file) {
Map<String, String> map = new HashMap<>();
try {
DataInputStream input = new DataInputStream(new FileInputStream(file));
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
try {
String line;
while ((line = reader.readLine()) != null) {
String[] split = line.split("=");
map.put(split[0], split.length == 2 ? split[1] : "");
}
} catch (NullPointerException ignore) {
}
reader.close();
input.close();
} catch (IOException e) {
e.printStackTrace();
}
return map;
}
private void saveMapToFile(File file, Map<String, Object> content) {
try {
FileWriter stream = new FileWriter(file);
BufferedWriter out = new BufferedWriter(stream);
content.forEach((String key, Object obj) -> {
try {
String value = obj.toString();
if (obj instanceof Double) {
value = new Formatter(Locale.US).format("%.2f", obj).toString();
}
out.write(key + "=" + value);
out.write("\n");
} catch (IOException e) {
e.printStackTrace();
}
});
out.close();
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

@ -5,29 +5,29 @@ import org.bukkit.scheduler.BukkitRunnable;
public class FoodRegeneration extends BukkitRunnable {
FoodRegeneration(){
runTaskTimer(Sharehealth.Instance, 80, 80);
}
@Override
public void run(){
int allPlayersCount = Sharehealth.GetPlayers().size();
if (allPlayersCount == 0)
return;
int allFoodPoints = 0;
for (Player p : Sharehealth.GetPlayers()){
allFoodPoints += p.getFoodLevel();
}
//According to MinecraftWiki, players automatically regen if their food level
// is greater than or equal to 18 of 20 (90%)
//Here, we look for the average food level
double currentHealth = Sharehealth.Instance.getHealthManager().getHealth();
if (allFoodPoints / allPlayersCount >= 16 && currentHealth > 0 && currentHealth < 20){
Sharehealth.Instance.onFoodRegeneration();
}
}
FoodRegeneration() {
runTaskTimer(Sharehealth.Instance, 80, 80);
}
@Override
public void run() {
int allPlayersCount = Sharehealth.GetPlayers().size();
if (allPlayersCount == 0)
return;
int allFoodPoints = 0;
for (Player p : Sharehealth.GetPlayers()) {
allFoodPoints += p.getFoodLevel();
}
//According to MinecraftWiki, players automatically regen if their food level
// is greater than or equal to 18 of 20 (90%)
//Here, we look for the average food level
double currentHealth = Sharehealth.Instance.getHealthManager().getHealth();
if (allFoodPoints / allPlayersCount >= 16 && currentHealth > 0 && currentHealth < 20) {
Sharehealth.Instance.onFoodRegeneration();
}
}
}

@ -8,87 +8,88 @@ import java.util.Locale;
public class HealthManager {
private double
health = 20;
double getHealth(){
return health;
}
void setHealth(double health){
if (health > 20)
health = 20;
if (health < 0)
health = 0;
this.health = health;
}
String getHealthString(){
return new Formatter(Locale.US).format("%.2f", health / 2).toString();
}
public HealthManager() {
}
public void updatePlayer(Player player){
if (player.getGameMode().equals(GameMode.SURVIVAL)) {
player.setHealth(health);
absorptionManager.setAbsorption(player);
}
if (player.getGameMode().equals(GameMode.SPECTATOR))
player.setHealth(20);
}
private void subtractHealth(double sub){
setHealth(health - sub);
}
void addHealth(double add){
setHealth(health + add);
}
void reset(){
health = 20;
Sharehealth.GetPlayers().forEach(p -> p.setHealth(health));
}
boolean wouldCauseDeath(double damage){
double newHealth = health - damage;
return newHealth <= 0;
}
void onPlayerGotDamage(Player player, double damage, double absorptionDamage){
subtractHealth(damage);
applyHealthToAllExcept(player);
absorptionManager.onPlayerGotDamage(player, absorptionDamage);
}
void onPlayerRegainedHealth(Player player, double regainedHealth){
addHealth(regainedHealth);
applyHealthToAllExcept(player);
}
void applyHealthToAllExcept(Player player){
Sharehealth.GetPlayers(player).forEach(p -> p.setHealth(health));
}
//When totem is triggered, set health to 1 and remove absorption
void onTotemTriggered(){
setHealth(1);
applyHealthToAllExcept(null);
absorptionManager.expire(false);
}
final AbsorptionManager absorptionManager = new AbsorptionManager();
void onAbsorptionConsumed(int duration, int amplifier){
double amount = (amplifier + 1) * 4;
absorptionManager.create(duration, amount);
}
void onMilkBucketConsumed(){
absorptionManager.expire(false);
}
private double
health = 20;
double getHealth() {
return health;
}
void setHealth(double health) {
if (health > 20)
health = 20;
if (health < 0)
health = 0;
this.health = health;
}
String getHealthString() {
return new Formatter(Locale.US).format("%.2f", health / 2).toString();
}
public HealthManager() {
}
public void updatePlayer(Player player) {
if (player.getGameMode().equals(GameMode.SURVIVAL)) {
player.setHealth(health);
absorptionManager.setAbsorption(player);
}
if (player.getGameMode().equals(GameMode.SPECTATOR))
player.setHealth(20);
}
private void subtractHealth(double sub) {
setHealth(health - sub);
}
void addHealth(double add) {
setHealth(health + add);
}
void reset() {
health = 20;
Sharehealth.GetPlayers().forEach(p -> p.setHealth(health));
}
boolean wouldCauseDeath(double damage) {
double newHealth = health - damage;
return newHealth <= 0;
}
void onPlayerGotDamage(Player player, double damage, double absorptionDamage) {
subtractHealth(damage);
applyHealthToAllExcept(player);
absorptionManager.onPlayerGotDamage(player, absorptionDamage);
}
void onPlayerRegainedHealth(Player player, double regainedHealth) {
addHealth(regainedHealth);
applyHealthToAllExcept(player);
}
void applyHealthToAllExcept(Player player) {
Sharehealth.GetPlayers(player).forEach(p -> p.setHealth(health));
}
//When totem is triggered, set health to 1 and remove absorption
void onTotemTriggered() {
setHealth(1);
applyHealthToAllExcept(null);
absorptionManager.expire(false);
}
final AbsorptionManager absorptionManager = new AbsorptionManager();
void onAbsorptionConsumed(int duration, int amplifier) {
double amount = (amplifier + 1) * 4;
absorptionManager.create(duration, amount);
}
void onMilkBucketConsumed() {
absorptionManager.expire(false);
}
}

@ -21,132 +21,132 @@ import java.util.logging.Logger;
public record Messenger(Logger logger) {
private List<Player> playersToSendLogs() {
List<Player> players = Sharehealth.GetPlayers();
players.removeIf(p -> !Sharehealth.Instance.getLogging(p));
return players;
}
void onPlayerRegainedHealth(Player player, double amount, RegainReason reason) {
if (amount <= 0)
return;
String message = healMessage(player, amount, reason);
playersToSendLogs().forEach(p -> p.sendMessage(message));
}
void sendFailedMessage(Player cause) {
String playerName = getPlayerName(cause);
String message = "Mission failed, go next! CAUSE: " + ChatColor.RED + playerName;
Sharehealth.GetPlayers().forEach(p -> p.sendMessage(message));
}
void onPlayerGotDamageMessage(Player player, double damage, DamageCause cause) {
String message = damageMessage(player, damage, cause.toString());
playersToSendLogs().forEach(p -> p.sendMessage(message));
}
void onPlayerGotDamageMessage(Player player, double damage, Entity damagingEntity) {
String message = damageMessage(player, damage, damagingEntity);
playersToSendLogs().forEach(p -> p.sendMessage(message));
}
void onPlayerGotDamageMessage(Player player, double damage, Block damagingBlock) {
String message = damageMessage(player, damage, damagingBlock);
playersToSendLogs().forEach(p -> p.sendMessage(message));
}
private String damageMessage(Player player, double damage, Entity damagingEntity) {
String damagingEntityName = damagingEntity.getName();
if (damagingEntity instanceof Projectile projectile) {
ProjectileSource source = projectile.getShooter();
if (source != null) {
if (source instanceof Entity shooterEntity) {
damagingEntityName = shooterEntity.getName();
}
if (source instanceof BlockProjectileSource shooterBlock) {
return damageMessage(player, damage, shooterBlock.getBlock());
}
}
}
return damageMessage(player, damage, damagingEntityName);
}
private String damageMessage(Player player, double damage, Block damagingBlock) {
String name;
try {
name = damagingBlock.getType().name();
} catch (NullPointerException e) {
name = "Unknown";
e.printStackTrace();
logger.info("Unknown error. Proceeding");
}
return damageMessage(player, damage, name);
}
private String damageMessage(Player player, double damage, String source) {
String playerS = getPlayerName(player);
String damageS = String.format("%.2f", damage / 2);
return ChatColor.BLUE + playerS
+ ChatColor.WHITE + " - "
+ ChatColor.RED + damageS
+ ChatColor.WHITE + " - "
+ ChatColor.YELLOW + source;
}
private String healMessage(Player player, double regainedHealth, RegainReason reason) {
String playerS = getPlayerName(player);
String healingS = String.format("%.2f", regainedHealth / 2);
String reasonString = reason.toString();
return ChatColor.BLUE + playerS
+ ChatColor.WHITE + " - "
+ ChatColor.GREEN + healingS
+ ChatColor.WHITE + " - "
+ ChatColor.YELLOW + reasonString;
}
String statisticsMessage() {
Map<UUID, Pair<Double, Double>> statistics = Sharehealth.Instance.getStatistics().getStatistics();
if (statistics.size() == 0)
return "There are no statistics yet.";
StringBuilder stats = new StringBuilder("Statistics:");
statistics.forEach(((uuid, values) -> {
String playerName = Bukkit.getOfflinePlayer(uuid).getName();
String stat = "\n" + ChatColor.BLUE + playerName +
ChatColor.WHITE + ": Damage caused: " +
ChatColor.RED + String.format("%.2f", values.first / 2) +
ChatColor.WHITE + " || Healing done: " +
ChatColor.GREEN + String.format("%.2f", values.second / 2);
stats.append(stat);
}));
return stats.toString();
}
String helpMessage(Map<List<String>, Pair<BiConsumer<CommandSender, String>, String>> commands) {
List<String> lines = new ArrayList<>();
commands.forEach((nameList, pair) -> {
StringBuilder name = new StringBuilder();
nameList.forEach(str -> name.append(str).append(" "));
String description = pair.second;
String message = "\n" +
ChatColor.AQUA + name +
ChatColor.WHITE + "-> " + description;
lines.add(message);
});
StringBuilder completeMessage = new StringBuilder("Usage:");
for (String line : lines.stream().sorted().toList())
completeMessage.append(line);
return completeMessage.toString();
}
private String getPlayerName(Player player) {
//Papermc:
//return ((TextComponent) player.displayName()).content();
//Spigot:
return player.getDisplayName();
}
private List<Player> playersToSendLogs() {
List<Player> players = Sharehealth.GetPlayers();
players.removeIf(p -> !Sharehealth.Instance.getLogging(p));
return players;
}
void onPlayerRegainedHealth(Player player, double amount, RegainReason reason) {
if (amount <= 0)
return;
String message = healMessage(player, amount, reason);
playersToSendLogs().forEach(p -> p.sendMessage(message));
}
void sendFailedMessage(Player cause) {
String playerName = getPlayerName(cause);
String message = "Mission failed, go next! CAUSE: " + ChatColor.RED + playerName;
Sharehealth.GetPlayers().forEach(p -> p.sendMessage(message));
}
void onPlayerGotDamageMessage(Player player, double damage, DamageCause cause) {
String message = damageMessage(player, damage, cause.toString());
playersToSendLogs().forEach(p -> p.sendMessage(message));
}
void onPlayerGotDamageMessage(Player player, double damage, Entity damagingEntity) {
String message = damageMessage(player, damage, damagingEntity);
playersToSendLogs().forEach(p -> p.sendMessage(message));
}
void onPlayerGotDamageMessage(Player player, double damage, Block damagingBlock) {
String message = damageMessage(player, damage, damagingBlock);
playersToSendLogs().forEach(p -> p.sendMessage(message));
}
private String damageMessage(Player player, double damage, Entity damagingEntity) {
String damagingEntityName = damagingEntity.getName();
if (damagingEntity instanceof Projectile projectile) {
ProjectileSource source = projectile.getShooter();
if (source != null) {
if (source instanceof Entity shooterEntity) {
damagingEntityName = shooterEntity.getName();
}
if (source instanceof BlockProjectileSource shooterBlock) {
return damageMessage(player, damage, shooterBlock.getBlock());
}
}
}
return damageMessage(player, damage, damagingEntityName);
}
private String damageMessage(Player player, double damage, Block damagingBlock) {
String name;
try {
name = damagingBlock.getType().name();
} catch (NullPointerException e) {
name = "Unknown";
e.printStackTrace();
logger.info("Unknown error. Proceeding");
}
return damageMessage(player, damage, name);
}
private String damageMessage(Player player, double damage, String source) {
String playerS = getPlayerName(player);
String damageS = String.format("%.2f", damage / 2);
return ChatColor.BLUE + playerS
+ ChatColor.WHITE + " - "
+ ChatColor.RED + damageS
+ ChatColor.WHITE + " - "
+ ChatColor.YELLOW + source;
}
private String healMessage(Player player, double regainedHealth, RegainReason reason) {
String playerS = getPlayerName(player);
String healingS = String.format("%.2f", regainedHealth / 2);
String reasonString = reason.toString();
return ChatColor.BLUE + playerS
+ ChatColor.WHITE + " - "
+ ChatColor.GREEN + healingS
+ ChatColor.WHITE + " - "
+ ChatColor.YELLOW + reasonString;
}
String statisticsMessage() {
Map<UUID, Pair<Double, Double>> statistics = Sharehealth.Instance.getStatistics().getStatistics();
if (statistics.size() == 0)
return "There are no statistics yet.";
StringBuilder stats = new StringBuilder("Statistics:");
statistics.forEach(((uuid, values) -> {
String playerName = Bukkit.getOfflinePlayer(uuid).getName();
String stat = "\n" + ChatColor.BLUE + playerName +
ChatColor.WHITE + ": Damage caused: " +
ChatColor.RED + String.format("%.2f", values.first / 2) +
ChatColor.WHITE + " || Healing done: " +
ChatColor.GREEN + String.format("%.2f", values.second / 2);
stats.append(stat);
}));
return stats.toString();
}
String helpMessage(Map<List<String>, Pair<BiConsumer<CommandSender, String>, String>> commands) {
List<String> lines = new ArrayList<>();
commands.forEach((nameList, pair) -> {
StringBuilder name = new StringBuilder();
nameList.forEach(str -> name.append(str).append(" "));
String description = pair.second;
String message = "\n" +
ChatColor.AQUA + name +
ChatColor.WHITE + "-> " + description;
lines.add(message);
});
StringBuilder completeMessage = new StringBuilder("Usage:");
for (String line : lines.stream().sorted().toList())
completeMessage.append(line);
return completeMessage.toString();
}
private String getPlayerName(Player player) {
//Papermc:
//return ((TextComponent) player.displayName()).content();
//Spigot:
return player.getDisplayName();
}
}

@ -4,15 +4,15 @@ package com.benjocraeft.sharehealth;
public class Pair<F, S> {
public final F first;
public final S second;
public final F first;
public final S second;
public Pair(F first, S second){
this.first = first;
this.second = second;
}
public Pair(F first, S second) {
this.first = first;
this.second = second;
}
public static <F, S> Pair<F, S> pair(F first, S second){
return new Pair<>(first, second);
}
public static <F, S> Pair<F, S> pair(F first, S second) {
return new Pair<>(first, second);
}
}

@ -20,136 +20,136 @@ import org.bukkit.potion.PotionEffectType;
import java.util.Arrays;
public class PlayerListeners implements Listener{
@EventHandler
public void onJoin(PlayerJoinEvent e){
Player p = e.getPlayer();
if (Sharehealth.GetPlayers().contains(p))
Sharehealth.Instance.onPlayerJoin(e.getPlayer());
}
@EventHandler
public void onPlayerRespawn(final PlayerRespawnEvent e){
Player p = e.getPlayer();
if (Sharehealth.GetPlayers().contains(p))
Sharehealth.Instance.onPlayerRespawn(e.getPlayer());
}
//Normal Totem Of Undying interaction is disabled
@EventHandler
public void onResurrect(final EntityResurrectEvent e){
e.setCancelled(true);
}
@EventHandler
public void onEntityGotDamage(final EntityDamageEvent event){
Entity damagedEntity = event.getEntity();
if (damagedEntity instanceof Player){
if (!Sharehealth.GetPlayers().contains(damagedEntity))
return;
double damage = event.getFinalDamage();
DamageCause cause = event.getCause();
// not allowed triggering message
// because these types trigger an extra event by entity or by block with more
// detailed information for the message
DamageCause[] messageNotAllowed = new DamageCause[]{
DamageCause.ENTITY_ATTACK,
DamageCause.ENTITY_EXPLOSION,
DamageCause.ENTITY_SWEEP_ATTACK,
DamageCause.PROJECTILE,
DamageCause.FALLING_BLOCK,
DamageCause.HOT_FLOOR,
DamageCause.THORNS,
};
boolean isMessageAllowed = !Arrays.asList(messageNotAllowed).contains(cause);
double absorbedDamage = -event.getOriginalDamage(DamageModifier.ABSORPTION);
Sharehealth.Instance.onPlayerGotDamage((Player) damagedEntity, damage, cause, isMessageAllowed, absorbedDamage, event::setCancelled);
}
}
//Only for logging/messaging
//lower priority so the message will be read even if player dies from damage
@EventHandler (priority = EventPriority.LOW)
public void onEntityGotDamageByEntity(final EntityDamageByEntityEvent event){
Entity damagedEntity = event.getEntity();
if (damagedEntity instanceof Player) {
if (!Sharehealth.GetPlayers().contains(damagedEntity))
return;
double damage = event.getFinalDamage();
Entity damagingEntity = event.getDamager();
double absorbedDamage = -event.getOriginalDamage(DamageModifier.ABSORPTION);
Sharehealth.Instance.onPlayerGotDamageByEntity((Player)damagedEntity, damage, damagingEntity, absorbedDamage);
}
}
//Only for logging/messaging
//lower priority so the message will be read even if player dies from damage
@EventHandler (priority = EventPriority.LOW)
public void onEntityGotDamageByBlock(final EntityDamageByBlockEvent event){
Entity damagedEntity = event.getEntity();
if (damagedEntity instanceof Player) {
if (!Sharehealth.GetPlayers().contains(damagedEntity))
return;
double damage = event.getFinalDamage();
Block damagingBlock = event.getDamager();
if (damagingBlock == null)
return;
double absorbedDamage = -event.getOriginalDamage(DamageModifier.ABSORPTION);
Sharehealth.Instance.onPlayerGotDamageByBlock((Player)damagedEntity, damage, damagingBlock, absorbedDamage);
}
}
@EventHandler
public void onEntityRegainedHealth(final EntityRegainHealthEvent event){
Entity healedEntity = event.getEntity();
if (healedEntity instanceof Player){
if (!Sharehealth.GetPlayers().contains(healedEntity))
return;
double amount = event.getAmount();
RegainReason reason = event.getRegainReason();
if (!Sharehealth.Instance.onPlayerRegainedHealth((Player) healedEntity, amount, reason)){
event.setCancelled(true);
}
}
}
@EventHandler
public void onEntityPotionEffectModified(final EntityPotionEffectEvent event){
Entity entity = event.getEntity();
if (entity instanceof Player){
if (!Sharehealth.GetPlayers().contains(entity))
return;
PotionEffect newEffect = event.getNewEffect();
if (newEffect != null){
if (newEffect.getType().equals(PotionEffectType.ABSORPTION)){
event.setCancelled(true);
int amplifier = newEffect.getAmplifier();
int duration = newEffect.getDuration();
Sharehealth.Instance.onAbsorptionConsumed(duration, amplifier);
}
}
}
}
@EventHandler
public void onPlayerItemConsumed(final PlayerItemConsumeEvent event){
Player consumer = event.getPlayer();
if (!Sharehealth.GetPlayers().contains(consumer))
return;
if (event.getItem().getType().equals(Material.MILK_BUCKET))
Sharehealth.Instance.onMilkBucketConsumed();
}
public class PlayerListeners implements Listener {
@EventHandler
public void onJoin(PlayerJoinEvent e) {
Player p = e.getPlayer();
if (Sharehealth.GetPlayers().contains(p))
Sharehealth.Instance.onPlayerJoin(e.getPlayer());
}
@EventHandler
public void onPlayerRespawn(final PlayerRespawnEvent e) {
Player p = e.getPlayer();
if (Sharehealth.GetPlayers().contains(p))
Sharehealth.Instance.onPlayerRespawn(e.getPlayer());
}
//Normal Totem Of Undying interaction is disabled
@EventHandler
public void onResurrect(final EntityResurrectEvent e) {
e.setCancelled(true);
}
@EventHandler
public void onEntityGotDamage(final EntityDamageEvent event) {
Entity damagedEntity = event.getEntity();
if (damagedEntity instanceof Player) {
if (!Sharehealth.GetPlayers().contains(damagedEntity))
return;
double damage = event.getFinalDamage();
DamageCause cause = event.getCause();
// not allowed triggering message
// because these types trigger an extra event by entity or by block with more
// detailed information for the message
DamageCause[] messageNotAllowed = new DamageCause[]{
DamageCause.ENTITY_ATTACK,
DamageCause.ENTITY_EXPLOSION,
DamageCause.ENTITY_SWEEP_ATTACK,
DamageCause.PROJECTILE,
DamageCause.FALLING_BLOCK,
DamageCause.HOT_FLOOR,
DamageCause.THORNS,
};
boolean isMessageAllowed = !Arrays.asList(messageNotAllowed).contains(cause);
double absorbedDamage = -event.getOriginalDamage(DamageModifier.ABSORPTION);
Sharehealth.Instance.onPlayerGotDamage((Player) damagedEntity, damage, cause, isMessageAllowed, absorbedDamage, event::setCancelled);
}
}
//Only for logging/messaging
//lower priority so the message will be read even if player dies from damage
@EventHandler(priority = EventPriority.LOW)
public void onEntityGotDamageByEntity(final EntityDamageByEntityEvent event) {
Entity damagedEntity = event.getEntity();
if (damagedEntity instanceof Player) {
if (!Sharehealth.GetPlayers().contains(damagedEntity))
return;
double damage = event.getFinalDamage();
Entity damagingEntity = event.getDamager();
double absorbedDamage = -event.getOriginalDamage(DamageModifier.ABSORPTION);
Sharehealth.Instance.onPlayerGotDamageByEntity((Player) damagedEntity, damage, damagingEntity, absorbedDamage);
}
}
//Only for logging/messaging
//lower priority so the message will be read even if player dies from damage
@EventHandler(priority = EventPriority.LOW)
public void onEntityGotDamageByBlock(final EntityDamageByBlockEvent event) {
Entity damagedEntity = event.getEntity();
if (damagedEntity instanceof Player) {
if (!Sharehealth.GetPlayers().contains(damagedEntity))
return;
double damage = event.getFinalDamage();
Block damagingBlock = event.getDamager();
if (damagingBlock == null)
return;
double absorbedDamage = -event.getOriginalDamage(DamageModifier.ABSORPTION);
Sharehealth.Instance.onPlayerGotDamageByBlock((Player) damagedEntity, damage, damagingBlock, absorbedDamage);
}
}
@EventHandler
public void onEntityRegainedHealth(final EntityRegainHealthEvent event) {
Entity healedEntity = event.getEntity();
if (healedEntity instanceof Player) {
if (!Sharehealth.GetPlayers().contains(healedEntity))
return;
double amount = event.getAmount();
RegainReason reason = event.getRegainReason();
if (!Sharehealth.Instance.onPlayerRegainedHealth((Player) healedEntity, amount, reason)) {
event.setCancelled(true);
}
}
}
@EventHandler
public void onEntityPotionEffectModified(final EntityPotionEffectEvent event) {
Entity entity = event.getEntity();
if (entity instanceof Player) {
if (!Sharehealth.GetPlayers().contains(entity))
return;
PotionEffect newEffect = event.getNewEffect();
if (newEffect != null) {
if (newEffect.getType().equals(PotionEffectType.ABSORPTION)) {
event.setCancelled(true);
int amplifier = newEffect.getAmplifier();
int duration = newEffect.getDuration();
Sharehealth.Instance.onAbsorptionConsumed(duration, amplifier);
}
}
}
}
@EventHandler
public void onPlayerItemConsumed(final PlayerItemConsumeEvent event) {
Player consumer = event.getPlayer();
if (!Sharehealth.GetPlayers().contains(consumer))
return;
if (event.getItem().getType().equals(Material.MILK_BUCKET))
Sharehealth.Instance.onMilkBucketConsumed();
}
}

@ -16,282 +16,291 @@ import java.util.*;
public class Sharehealth extends JavaPlugin {
static Sharehealth Instance;
static Sharehealth Instance;
private FileManager fileManager;
public FileManager getFileManager(){
return fileManager;
}
private FileManager fileManager;
private HealthManager healthManager;
public HealthManager getHealthManager(){
return healthManager;
}
public FileManager getFileManager() {
return fileManager;
}
private TotemManager totemManager;
public TotemManager getTotemManager() {
return totemManager;
}
private HealthManager healthManager;
private Messenger messenger;
public Messenger getMessenger(){
return messenger;
}
public HealthManager getHealthManager() {
return healthManager;
}
private Statistics statistics;
public Statistics getStatistics(){
return statistics;
}
private TotemManager totemManager;
//If isFailed, plugin changes no default behaviours
boolean isFailed = false;
public TotemManager getTotemManager() {
return totemManager;
}
private final Map<String, Object> defaultStatus = new HashMap<>();
{
defaultStatus.put("health", 20.);
defaultStatus.put("isFailed", false);
defaultStatus.put("absorptionAmount", 0.);
defaultStatus.put("absorptionDuration", 0);
defaultStatus.put("totemMode", 0);
defaultStatus.put("totemFraction", 0.5);
}
@Override
public void onEnable(){
//Singleton setup
Instance = this;
//Create File Manager for saving stats and settings
fileManager = new FileManager();
//Starting Health Manager for controlling actual health
healthManager = new HealthManager();
//Totem Manager controls TotemOfUndying behaviour
totemManager = new TotemManager();
//Messenger
messenger = new Messenger(getLogger());
//Create statistics from file
statistics = new Statistics(fileManager.loadStatistics(), fileManager.loadSettings());
getLogger().info("Statistics and Settings loaded");
//Load status (current health, absorption, etc)
loadStatus();
getLogger().info("Status loaded");
private Messenger messenger;
//Load players
ActiveUUIDs = fileManager.loadPlayers();
getLogger().info("Active players count: " + ActiveUUIDs.size());
public Messenger getMessenger() {
return messenger;
}
//Starts custom health regeneration
new FoodRegeneration();
private Statistics statistics;
//Register Events and Commands
Bukkit.getPluginManager().registerEvents(new PlayerListeners(), this);
Commands commands = new Commands();
PluginCommand pluginCommand = Objects.requireNonNull(getCommand("sharehealth"));
pluginCommand.setExecutor(commands);
pluginCommand.setTabCompleter(commands);
public Statistics getStatistics() {
return statistics;
}
//Ready to go
getLogger().info("ShareHealth has been enabled!");
}
//If isFailed, plugin changes no default behaviours
boolean isFailed = false;
@Override
public void onDisable() {
saveStatus();
fileManager.saveStatistics(statistics.getStatistics());
private final Map<String, Object> defaultStatus = new HashMap<>();
getLogger().info("ShareHealth has been disabled!");
}
{
defaultStatus.put("health", 20.);
defaultStatus.put("isFailed", false);
defaultStatus.put("absorptionAmount", 0.);
defaultStatus.put("absorptionDuration", 0);
defaultStatus.put("totemMode", 0);
defaultStatus.put("totemFraction", 0.5);
}
void onPlayerJoin(Player player){
updateGameMode(player);
@Override
public void onEnable() {
healthManager.updatePlayer(player);
statistics.onPlayerJoined(player);
fileManager.saveStatistics(statistics.getStatistics());
fileManager.saveSettings(statistics.getSettings());
}
void onPlayerRespawn(Player player){
updateGameMode(player);
healthManager.updatePlayer(player);
}
void onPlayerGotDamage(Player player, double damage, DamageCause cause,
boolean isMessageAllowed, double absorbedDamage, Consumer<Boolean> cancelDamage){
if (isFailed)
return;
GetPlayers(player).forEach(p -> p.playEffect(EntityEffect.HURT));
double receivedDamage = damage + absorbedDamage;
if (isMessageAllowed)
messenger.onPlayerGotDamageMessage(player, receivedDamage, cause);
statistics.onPlayerGotDamage(player, receivedDamage);
if (healthManager.wouldCauseDeath(damage)){
if (totemManager.totemCanBeUsed()){
healthManager.onTotemTriggered();
totemManager.activate(player);
cancelDamage.accept(true);
} else {
healthManager.onPlayerGotDamage(player, damage, absorbedDamage);
failed(player);
}
} else {
healthManager.onPlayerGotDamage(player, damage, absorbedDamage);
}
saveStatus();
}
void onPlayerGotDamageByEntity(Player player, double damage, Entity damagingEntity, double absorbedDamage){
if (isFailed)
return;
messenger.onPlayerGotDamageMessage(player, damage + absorbedDamage, damagingEntity);
}
void onPlayerGotDamageByBlock(Player player, double damage, Block damagingBlock, double absorbedDamage){
if (isFailed)
return;
messenger.onPlayerGotDamageMessage(player, damage + absorbedDamage, damagingBlock);
}
boolean onPlayerRegainedHealth(Player player, double amount, RegainReason reason){
if (isFailed)
return true;
if (reason.equals(RegainReason.REGEN) || reason.equals(RegainReason.SATIATED)){
return false;
}
messenger.onPlayerRegainedHealth(player, amount, reason);
statistics.onPlayerRegainedHealth(player, amount);
healthManager.onPlayerRegainedHealth(player, amount);
saveStatus();
return true;
}
void onFoodRegeneration(){
healthManager.addHealth(1);
healthManager.applyHealthToAllExcept(null);
saveStatus();
}
void onAbsorptionConsumed(int duration, int amplifier){
healthManager.onAbsorptionConsumed(duration, amplifier);
saveStatus();
}
void onMilkBucketConsumed(){
healthManager.onMilkBucketConsumed();
saveStatus();
}
private void failed(Player cause){
if (isFailed)
return;
isFailed = true;
messenger.sendFailedMessage(cause);
GetPlayers().forEach(p -> p.setGameMode(GameMode.SPECTATOR));
saveStatus();
}
void reset(){
isFailed = false;
fileManager.backupStats(statistics.getStatistics());
statistics.reset();
fileManager.saveStatistics(statistics.getStatistics());
healthManager.reset();
GetPlayers().forEach(p -> p.setGameMode(GameMode.SURVIVAL));
saveStatus();
}
private void updateGameMode(Player player){
if (!isFailed){
player.setGameMode(GameMode.SURVIVAL);
} else {
player.setGameMode(GameMode.SPECTATOR);
}
}
private static List<UUID> ActiveUUIDs = new ArrayList<>();
static List<Player> GetPlayers(){
List<Player> players = new ArrayList<>(Bukkit.getOnlinePlayers());
players.removeIf(p -> !ActiveUUIDs.contains(p.getUniqueId()));
return players;
}
static List<Player> GetPlayers(Player except){
List<Player> players = GetPlayers();
players.remove(except);
return players;
}
public void addPlayer(UUID uuid){
ActiveUUIDs.add(uuid);
fileManager.savePlayers(ActiveUUIDs);
}
public void removePlayer(UUID uuid){
ActiveUUIDs.remove(uuid);
fileManager.savePlayers(ActiveUUIDs);
}
void saveStatus(){
Map<String, Object> map = new HashMap<>();
map.put("health", healthManager.getHealth());
map.put("isFailed", isFailed);
map.put("absorptionAmount", healthManager.absorptionManager.amount);
map.put("absorptionDuration", healthManager.absorptionManager.duration);
map.put("totemMode", totemManager.getMode().ordinal());
map.put("totemFraction", totemManager.getFractionNeeded());
fileManager.saveStatus(map);
}
private void loadStatus(){
Map<String, Object> map = fileManager.loadStatus();
defaultStatus.forEach(map::putIfAbsent);
map.forEach((String key, Object value) -> getLogger().info(key + "=" + value));
healthManager.setHealth((Double)map.get("health"));
isFailed = (boolean) map.get("isFailed");
healthManager.absorptionManager.create(
(int)map.get("absorptionDuration"),
(Double)map.get("absorptionAmount")
);
totemManager.setMode(TotemManager.Mode.values()[(int)map.get("totemMode")]);
totemManager.setFractionNeeded((Double)map.get("totemFraction"));
}
void onLoggingUpdated(Player player, boolean hasLogging){
statistics.setSettings(player.getUniqueId(), hasLogging);
Map<UUID, Boolean> settings = statistics.getSettings();
fileManager.saveSettings(settings);
}
boolean getLogging(Player player){
Map<UUID, Boolean> settings = statistics.getSettings();
return settings.get(player.getUniqueId());
}
//Singleton setup
Instance = this;
//Create File Manager for saving stats and settings
fileManager = new FileManager();
//Starting Health Manager for controlling actual health
healthManager = new HealthManager();
//Totem Manager controls TotemOfUndying behaviour
totemManager = new TotemManager();
//Messenger
messenger = new Messenger(getLogger());
//Create statistics from file
statistics = new Statistics(fileManager.loadStatistics(), fileManager.loadSettings());
getLogger().info("Statistics and Settings loaded");
//Load status (current health, absorption, etc)
loadStatus();
getLogger().info("Status loaded");
//Load players
ActiveUUIDs = fileManager.loadPlayers();
getLogger().info("Active players count: " + ActiveUUIDs.size());
//Starts custom health regeneration
new FoodRegeneration();
//Register Events and Commands
Bukkit.getPluginManager().registerEvents(new PlayerListeners(), this);
Commands commands = new Commands();
PluginCommand pluginCommand = Objects.requireNonNull(getCommand("sharehealth"));
pluginCommand.setExecutor(commands);
pluginCommand.setTabCompleter(commands);
//Ready to go
getLogger().info("ShareHealth has been enabled!");
}
@Override
public void onDisable() {
saveStatus();
fileManager.saveStatistics(statistics.getStatistics());
getLogger().info("ShareHealth has been disabled!");
}
void onPlayerJoin(Player player) {
updateGameMode(player);
healthManager.updatePlayer(player);
statistics.onPlayerJoined(player);
fileManager.saveStatistics(statistics.getStatistics());
fileManager.saveSettings(statistics.getSettings());
}
void onPlayerRespawn(Player player) {
updateGameMode(player);
healthManager.updatePlayer(player);
}
void onPlayerGotDamage(Player player, double damage, DamageCause cause,
boolean isMessageAllowed, double absorbedDamage, Consumer<Boolean> cancelDamage) {
if (isFailed)
return;
GetPlayers(player).forEach(p -> p.playEffect(EntityEffect.HURT));
double receivedDamage = damage + absorbedDamage;
if (isMessageAllowed)
messenger.onPlayerGotDamageMessage(player, receivedDamage, cause);
statistics.onPlayerGotDamage(player, receivedDamage);
if (healthManager.wouldCauseDeath(damage)) {
if (totemManager.totemCanBeUsed()) {
healthManager.onTotemTriggered();
totemManager.activate(player);
cancelDamage.accept(true);
} else {
healthManager.onPlayerGotDamage(player, damage, absorbedDamage);
failed(player);
}
} else {
healthManager.onPlayerGotDamage(player, damage, absorbedDamage);
}
saveStatus();
}
void onPlayerGotDamageByEntity(Player player, double damage, Entity damagingEntity, double absorbedDamage) {
if (isFailed)
return;
messenger.onPlayerGotDamageMessage(player, damage + absorbedDamage, damagingEntity);
}
void onPlayerGotDamageByBlock(Player player, double damage, Block damagingBlock, double absorbedDamage) {
if (isFailed)
return;
messenger.onPlayerGotDamageMessage(player, damage + absorbedDamage, damagingBlock);
}
boolean onPlayerRegainedHealth(Player player, double amount, RegainReason reason) {
if (isFailed)
return true;
if (reason.equals(RegainReason.REGEN) || reason.equals(RegainReason.SATIATED)) {
return false;
}
messenger.onPlayerRegainedHealth(player, amount, reason);
statistics.onPlayerRegainedHealth(player, amount);
healthManager.onPlayerRegainedHealth(player, amount);
saveStatus();
return true;
}
void onFoodRegeneration() {
healthManager.addHealth(1);
healthManager.applyHealthToAllExcept(null);
saveStatus();
}
void onAbsorptionConsumed(int duration, int amplifier) {
healthManager.onAbsorptionConsumed(duration, amplifier);
saveStatus();
}
void onMilkBucketConsumed() {
healthManager.onMilkBucketConsumed();
saveStatus();
}
private void failed(Player cause) {
if (isFailed)
return;
isFailed = true;
messenger.sendFailedMessage(cause);
GetPlayers().forEach(p -> p.setGameMode(GameMode.SPECTATOR));
saveStatus();
}
void reset() {
isFailed = false;
fileManager.backupStats(statistics.getStatistics());
statistics.reset();
fileManager.saveStatistics(statistics.getStatistics());
healthManager.reset();
GetPlayers().forEach(p -> p.setGameMode(GameMode.SURVIVAL));
saveStatus();
}
private void updateGameMode(Player player) {
if (!isFailed) {
player.setGameMode(GameMode.SURVIVAL);
} else {
player.setGameMode(GameMode.SPECTATOR);
}
}
private static List<UUID> ActiveUUIDs = new ArrayList<>();
static List<Player> GetPlayers() {
List<Player> players = new ArrayList<>(Bukkit.getOnlinePlayers());
players.removeIf(p -> !ActiveUUIDs.contains(p.getUniqueId()));
return players;
}
static List<Player> GetPlayers(Player except) {
List<Player> players = GetPlayers();
players.remove(except);
return players;
}
public void addPlayer(UUID uuid) {
ActiveUUIDs.add(uuid);
fileManager.savePlayers(ActiveUUIDs);
}
public void removePlayer(UUID uuid) {
ActiveUUIDs.remove(uuid);
fileManager.savePlayers(ActiveUUIDs);
}
void saveStatus() {
Map<String, Object> map = new HashMap<>();
map.put("health", healthManager.getHealth());
map.put("isFailed", isFailed);
map.put("absorptionAmount", healthManager.absorptionManager.amount);
map.put("absorptionDuration", healthManager.absorptionManager.duration);
map.put("totemMode", totemManager.getMode().ordinal());
map.put("totemFraction", totemManager.getFractionNeeded());
fileManager.saveStatus(map);
}
private void loadStatus() {
Map<String, Object> map = fileManager.loadStatus();
defaultStatus.forEach(map::putIfAbsent);
map.forEach((String key, Object value) -> getLogger().info(key + "=" + value));
healthManager.setHealth((Double) map.get("health"));
isFailed = (boolean) map.get("isFailed");
healthManager.absorptionManager.create(
(int) map.get("absorptionDuration"),
(Double) map.get("absorptionAmount")
);
totemManager.setMode(TotemManager.Mode.values()[(int) map.get("totemMode")]);
totemManager.setFractionNeeded((Double) map.get("totemFraction"));
}
void onLoggingUpdated(Player player, boolean hasLogging) {
statistics.setSettings(player.getUniqueId(), hasLogging);
Map<UUID, Boolean> settings = statistics.getSettings();
fileManager.saveSettings(settings);
}
boolean getLogging(Player player) {
Map<UUID, Boolean> settings = statistics.getSettings();
return settings.get(player.getUniqueId());
}
}

@ -8,57 +8,61 @@ import java.util.UUID;
public class Statistics {
final private Map<UUID, Pair<Double, Double>> statistics = new HashMap<>();
public Map<UUID, Pair<Double, Double>> getStatistics(){
return statistics;
}
public static Double Rounded(Double value, int afterComma){
return Math.round(value * Math.pow(10, afterComma)) / Math.pow(10, afterComma);
}
public static Double Rounded(Double value){
return Rounded(value, 2);
}
public Statistics(Map<UUID, Pair<Double, Double>> statistics, Map<UUID, Boolean> settings){
this.statistics.putAll(statistics);
this.settings.putAll(settings);
}
final private Map<UUID, Boolean> settings = new HashMap<>();
public Map<UUID, Boolean> getSettings(){
return settings;
}
public void setSettings(UUID uuid, boolean hasLogging){
settings.put(uuid, hasLogging);
}
public void onPlayerJoined(Player player){
putIfAbsent(player);
}
void onPlayerRegainedHealth(Player player, double amount){
UUID uuid = player.getUniqueId();
Pair<Double, Double> oldPair = statistics.get(uuid);
statistics.put(uuid, Pair.pair(oldPair.first, oldPair.second + amount));
}
void onPlayerGotDamage(Player player, double amount){
UUID uuid = player.getUniqueId();
Pair<Double, Double> oldPair = statistics.get(uuid);
statistics.put(uuid, Pair.pair(oldPair.first + amount, oldPair.second));
}
private void putIfAbsent(Player player){
UUID uuid = player.getUniqueId();
Pair<Double, Double> empty = Pair.pair(0., 0.);
statistics.putIfAbsent(uuid, empty);
settings.putIfAbsent(uuid, true);
}
void reset(){
statistics.clear();
Sharehealth.GetPlayers().forEach(this::putIfAbsent);
}
final private Map<UUID, Pair<Double, Double>> statistics = new HashMap<>();
public Map<UUID, Pair<Double, Double>> getStatistics() {
return statistics;
}
public static Double Rounded(Double value, int afterComma) {
return Math.round(value * Math.pow(10, afterComma)) / Math.pow(10, afterComma);
}
public static Double Rounded(Double value) {
return Rounded(value, 2);
}
public Statistics(Map<UUID, Pair<Double, Double>> statistics, Map<UUID, Boolean> settings) {
this.statistics.putAll(statistics);
this.settings.putAll(settings);
}
final private Map<UUID, Boolean> settings = new HashMap<>();
public Map<UUID, Boolean> getSettings() {
return settings;
}
public void setSettings(UUID uuid, boolean hasLogging) {
settings.put(uuid, hasLogging);
}
public void onPlayerJoined(Player player) {
putIfAbsent(player);
}
void onPlayerRegainedHealth(Player player, double amount) {
UUID uuid = player.getUniqueId();
Pair<Double, Double> oldPair = statistics.get(uuid);
statistics.put(uuid, Pair.pair(oldPair.first, oldPair.second + amount));
}
void onPlayerGotDamage(Player player, double amount) {
UUID uuid = player.getUniqueId();
Pair<Double, Double> oldPair = statistics.get(uuid);
statistics.put(uuid, Pair.pair(oldPair.first + amount, oldPair.second));
}
private void putIfAbsent(Player player) {
UUID uuid = player.getUniqueId();
Pair<Double, Double> empty = Pair.pair(0., 0.);
statistics.putIfAbsent(uuid, empty);
settings.putIfAbsent(uuid, true);
}
void reset() {
statistics.clear();
Sharehealth.GetPlayers().forEach(this::putIfAbsent);
}
}

@ -13,116 +13,120 @@ import java.util.List;
public class TotemManager {
private Mode mode = Mode.All;
public void setMode(Mode mode){
this.mode = mode;
}
public Mode getMode(){
return mode;
}
//between 0 and 1
private double fractionNeeded;
public void setFractionNeeded(double value){
if (value < 0)
value = 0;
if (value > 1)
value = 1;
fractionNeeded = value;
}
public double getFractionNeeded() {
return fractionNeeded;
}
//Determine if enough players hold a totem of undying
public boolean totemCanBeUsed(){
return getHolderCount() >= getMinimumPlayerCount();
}
//Activate Totem Effect
//Remove used items
//Finally buy some Falafel for Markus
public void activate(Player triggeringPlayer){
List<Player> allPlayers = Sharehealth.GetPlayers();
//Remove all effects from Player
for (PotionEffect e : triggeringPlayer.getActivePotionEffects())
triggeringPlayer.removePotionEffect(e.getType());
//Destroy needed totem items
//Try to destroy holders item first, then the remaining
//Only destroy as many items as were needed for effect to trigger
int totemsRemoveCount = getMinimumPlayerCount();
if (destroyItemFrom(triggeringPlayer))
totemsRemoveCount--;
for (int pIndex = 0; pIndex < allPlayers.size() && totemsRemoveCount > 0; pIndex++)
if (destroyItemFrom(allPlayers.get(pIndex)))
totemsRemoveCount--;
//Regeneration II 40sec
PotionEffect regeneration = new PotionEffect(PotionEffectType.REGENERATION, 40 * 20, 1);
triggeringPlayer.addPotionEffect(regeneration);
//Fire Resistance I 40sec
PotionEffect fireRes = new PotionEffect(PotionEffectType.FIRE_RESISTANCE, 40 * 20, 0);
triggeringPlayer.addPotionEffect(fireRes);
//Absorption II 5sec
PotionEffect absorption = new PotionEffect(PotionEffectType.ABSORPTION, 5 * 20, 1);
triggeringPlayer.addPotionEffect(absorption);
//Play Totem Effect for every Player
for (Player p : allPlayers)
p.playEffect(EntityEffect.TOTEM_RESURRECT);
}
private boolean destroyItemFrom(Player holder){
ItemStack main = holder.getInventory().getItemInMainHand();
if (main.getType().equals(Material.TOTEM_OF_UNDYING)){
//destroy item
main.setAmount(0);
return true;
} else {
ItemStack off = holder.getInventory().getItemInOffHand();
if (off.getType().equals(Material.TOTEM_OF_UNDYING)){
//destroy item
off.setAmount(0);
return true;
}
}
return false;
}
//Calculates how many players are needed at least to trigger the totem for everyone
private int getMinimumPlayerCount(){
int allPlayerCount = Sharehealth.GetPlayers().size();
return switch (mode) {
case One -> 1;
case All -> allPlayerCount;
case Disabled -> Bukkit.getMaxPlayers() + 1;
case Fraction -> (int) Math.ceil(fractionNeeded * allPlayerCount);
};
}
//Counts how many players hold a totem
//Markus still is waiting for his Falafel
private int getHolderCount(){
List<Player> players = Sharehealth.GetPlayers();
return players.stream().mapToInt(p -> {
ItemStack main = p.getInventory().getItemInMainHand();
ItemStack off = p.getInventory().getItemInOffHand();
return (main.getType().equals(Material.TOTEM_OF_UNDYING) ||
off.getType().equals(Material.TOTEM_OF_UNDYING)) ? 1 : 0;
}).sum();
}
enum Mode {
One,
All,
Fraction,
Disabled
}
private Mode mode = Mode.All;
public void setMode(Mode mode) {
this.mode = mode;
}
public Mode getMode() {
return mode;
}
//between 0 and 1
private double fractionNeeded;
public void setFractionNeeded(double value) {
if (value < 0)
value = 0;
if (value > 1)
value = 1;
fractionNeeded = value;
}
public double getFractionNeeded() {
return fractionNeeded;
}
//Determine if enough players hold a totem of undying
public boolean totemCanBeUsed() {
return getHolderCount() >= getMinimumPlayerCount();
}
//Activate Totem Effect
//Remove used items
//Finally buy some Falafel for Markus
public void activate(Player triggeringPlayer) {
List<Player> allPlayers = Sharehealth.GetPlayers();
//Remove all effects from Player
for (PotionEffect e : triggeringPlayer.getActivePotionEffects())
triggeringPlayer.removePotionEffect(e.getType());
//Destroy needed totem items
//Try to destroy holders item first, then the remaining
//Only destroy as many items as were needed for effect to trigger
int totemsRemoveCount = getMinimumPlayerCount();
if (destroyItemFrom(triggeringPlayer))
totemsRemoveCount--;
for (int pIndex = 0; pIndex < allPlayers.size() && totemsRemoveCount > 0; pIndex++)
if (destroyItemFrom(allPlayers.get(pIndex)))
totemsRemoveCount--;
//Regeneration II 40sec
PotionEffect regeneration = new PotionEffect(PotionEffectType.REGENERATION, 40 * 20, 1);
triggeringPlayer.addPotionEffect(regeneration);
//Fire Resistance I 40sec
PotionEffect fireRes = new PotionEffect(PotionEffectType.FIRE_RESISTANCE, 40 * 20, 0);
triggeringPlayer.addPotionEffect(fireRes);
//Absorption II 5sec
PotionEffect absorption = new PotionEffect(PotionEffectType.ABSORPTION, 5 * 20, 1);
triggeringPlayer.addPotionEffect(absorption);
//Play Totem Effect for every Player
for (Player p : allPlayers)
p.playEffect(EntityEffect.TOTEM_RESURRECT);
}
private boolean destroyItemFrom(Player holder) {
ItemStack main = holder.getInventory().getItemInMainHand();
if (main.getType().equals(Material.TOTEM_OF_UNDYING)) {
//destroy item
main.setAmount(0);
return true;
} else {
ItemStack off = holder.getInventory().getItemInOffHand();
if (off.getType().equals(Material.TOTEM_OF_UNDYING)) {
//destroy item
off.setAmount(0);
return true;
}
}
return false;
}
//Calculates how many players are needed at least to trigger the totem for everyone
private int getMinimumPlayerCount() {
int allPlayerCount = Sharehealth.GetPlayers().size();
return switch (mode) {
case One -> 1;
case All -> allPlayerCount;
case Disabled -> Bukkit.getMaxPlayers() + 1;
case Fraction -> (int) Math.ceil(fractionNeeded * allPlayerCount);
};
}
//Counts how many players hold a totem
//Markus still is waiting for his Falafel
private int getHolderCount() {
List<Player> players = Sharehealth.GetPlayers();
return players.stream().mapToInt(p -> {
ItemStack main = p.getInventory().getItemInMainHand();
ItemStack off = p.getInventory().getItemInOffHand();
return (main.getType().equals(Material.TOTEM_OF_UNDYING) ||
off.getType().equals(Material.TOTEM_OF_UNDYING)) ? 1 : 0;
}).sum();
}
enum Mode {
One,
All,
Fraction,
Disabled
}
}

Loading…
Cancel
Save