├── .gitignore ├── docs ├── calculate-exact-percentage-disabled.jpeg └── calculate-exact-percentage-enabled.jpeg ├── src ├── me │ └── skinnyjeans │ │ └── gmd │ │ ├── models │ │ ├── DifficultyTypes.java │ │ ├── EquipmentItems.java │ │ ├── ArmorTypes.java │ │ ├── BaseListener.java │ │ ├── DifficultySettings.java │ │ ├── MythicMobProfile.java │ │ ├── ISaveManager.java │ │ ├── Minecrafter.java │ │ ├── TimeSettings.java │ │ ├── Difficulty.java │ │ ├── RegionSettings.java │ │ └── WorldTimeConfiguration.java │ │ ├── utils │ │ ├── StaticInfo.java │ │ └── Formatter.java │ │ ├── Main.java │ │ ├── events │ │ ├── PlayerLeaveListener.java │ │ ├── PlayerJoinListener.java │ │ ├── ItemDamageListener.java │ │ ├── EntityTargetListener.java │ │ ├── EntityDamageListener.java │ │ ├── HungerListener.java │ │ ├── HealthRegenListener.java │ │ ├── PlayerDeathListener.java │ │ ├── PotionEffectListener.java │ │ ├── CommandListener.java │ │ ├── CreeperExplodeListener.java │ │ ├── EntityDeathListener.java │ │ ├── BlockMinedListener.java │ │ ├── InventoryListener.java │ │ ├── EntityHitListener.java │ │ └── MobSpawnListener.java │ │ ├── databases │ │ ├── None.java │ │ ├── File.java │ │ └── SQL.java │ │ ├── managers │ │ ├── EventManager.java │ │ ├── TabCompleterManager.java │ │ ├── EntityManager.java │ │ ├── MainManager.java │ │ ├── DataManager.java │ │ ├── InventoryManager.java │ │ ├── PlayerManager.java │ │ ├── DifficultyManager.java │ │ └── CommandManager.java │ │ └── hooks │ │ └── PlaceholderAPIExpansion.java ├── lang.yml ├── lang │ ├── zh-CN.yml │ ├── nl-NL.yml │ ├── tl-PH.yml │ ├── es-MX.yml │ └── en-US.yml ├── plugin.yml └── config.yml ├── pom.xml └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .idea 3 | out 4 | DynamicDifficulty.iml 5 | .gradle 6 | target -------------------------------------------------------------------------------- /docs/calculate-exact-percentage-disabled.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeannotM/DynamicDifficulty/HEAD/docs/calculate-exact-percentage-disabled.jpeg -------------------------------------------------------------------------------- /docs/calculate-exact-percentage-enabled.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeannotM/DynamicDifficulty/HEAD/docs/calculate-exact-percentage-enabled.jpeg -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/models/DifficultyTypes.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.models; 2 | 3 | public enum DifficultyTypes { 4 | player, world, region, biome, time 5 | } 6 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/models/EquipmentItems.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.models; 2 | 3 | public enum EquipmentItems { 4 | HELMET, CHEST, LEGGINGS, BOOTS, WEAPON, BOW 5 | } 6 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/models/ArmorTypes.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.models; 2 | 3 | public enum ArmorTypes { 4 | NOTHING, LEATHER, GOLDEN, IRON, CHAINMAIL, TURTLE, ELYTRA, DIAMOND, NETHERITE 5 | } 6 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/models/BaseListener.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.models; 2 | 3 | import me.skinnyjeans.gmd.managers.MainManager; 4 | import org.bukkit.event.Listener; 5 | 6 | public class BaseListener implements Listener { 7 | 8 | protected MainManager MAIN_MANAGER; 9 | 10 | public void reloadConfig() { } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/lang.yml: -------------------------------------------------------------------------------- 1 | # All languages can be found in the lang directory. 2 | # if you want to add a language that wasn't included here you can check out the Github page: 3 | # https://github.com/JeannotM/DynamicDifficulty 4 | 5 | # Culture .NET 6 | # Supported en-US, nl-NL, es-MX, zh-CN 7 | culture: "en-US" 8 | command-right-prefix: "&f" 9 | command-wrong-prefix: "&c" 10 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/utils/StaticInfo.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.utils; 2 | 3 | public class StaticInfo { 4 | 5 | public final static String PLAYERS_INVENTORY = "DynamicDifficulty - Players"; 6 | public final static String INDIVIDUAL_PLAYER_INVENTORY = "DynamicDifficulty - Individual Player"; 7 | public final static String DIFFICULTIES_INVENTORY = "DynamicDifficulty - All Difficulties"; 8 | public final static String DIFFICULTY_INVENTORY = "DynamicDifficulty - Difficulty"; 9 | } 10 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/models/DifficultySettings.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.models; 2 | 3 | import me.skinnyjeans.gmd.managers.MainManager; 4 | import org.bukkit.entity.Player; 5 | 6 | public abstract class DifficultySettings { 7 | MainManager MAIN_MANAGER; 8 | 9 | public DifficultySettings(MainManager mainManager) { 10 | MAIN_MANAGER = mainManager; 11 | } 12 | 13 | public abstract int calculateAffinity(Player player, int affinity); 14 | public abstract void reloadConfig(); 15 | } 16 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/Main.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Main handler for the Gameplay-Modulated-difficulty plugin. 3 | * 4 | * @version 1.9 5 | * @author SkinnyJeans 6 | */ 7 | package me.skinnyjeans.gmd; 8 | 9 | import me.skinnyjeans.gmd.managers.MainManager; 10 | import org.bukkit.plugin.java.JavaPlugin; 11 | 12 | public class Main extends JavaPlugin { 13 | 14 | private MainManager MAIN_MANAGER; 15 | 16 | @Override 17 | public void onEnable() { 18 | MAIN_MANAGER = new MainManager(this); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/models/MythicMobProfile.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.models; 2 | 3 | import org.bukkit.configuration.ConfigurationSection; 4 | import org.bukkit.entity.EntityType; 5 | 6 | public class MythicMobProfile { 7 | 8 | public final EntityType replacedWith; 9 | public final String mythicMobName; 10 | public final double chanceToReplace; 11 | 12 | public MythicMobProfile(String key, ConfigurationSection config) { 13 | mythicMobName = key; 14 | chanceToReplace = config.getDouble(key + ".chance-to-replace", 5.0) / 100.0; 15 | replacedWith = EntityType.valueOf(config.getString(key + ".replace-with", "ZOMBIE")); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/models/ISaveManager.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.models; 2 | 3 | import java.sql.SQLException; 4 | import java.util.Collection; 5 | import java.util.UUID; 6 | 7 | public interface ISaveManager { 8 | interface findBooleanCallback { void onQueryDone(boolean r); } 9 | interface findCallback { void onQueryDone(Minecrafter playerData); } 10 | boolean isConnected(); 11 | void updatePlayer(Minecrafter playerData); 12 | void batchSavePlayers(Collection data); 13 | void getAffinityValues(UUID uuid, final findCallback callback); 14 | void playerExists(UUID uuid, final findBooleanCallback callback); 15 | void disconnect() throws SQLException; 16 | } 17 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/events/PlayerLeaveListener.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.events; 2 | 3 | import me.skinnyjeans.gmd.managers.MainManager; 4 | import me.skinnyjeans.gmd.models.BaseListener; 5 | import org.bukkit.event.EventHandler; 6 | import org.bukkit.event.player.PlayerQuitEvent; 7 | 8 | import java.util.UUID; 9 | 10 | public class PlayerLeaveListener extends BaseListener { 11 | 12 | public PlayerLeaveListener(MainManager mainManager) { 13 | MAIN_MANAGER = mainManager; 14 | } 15 | 16 | @EventHandler 17 | public void onLeave(PlayerQuitEvent e) { 18 | if(!MAIN_MANAGER.getPlayerManager().isPlayerValidNoWorld(e.getPlayer())) return; 19 | 20 | UUID uuid = e.getPlayer().getUniqueId(); 21 | if (uuid == null) { 22 | uuid = UUID.fromString( "00000000-0000-0000-0000-000000000000" ); 23 | } 24 | 25 | MAIN_MANAGER.getPlayerManager().unloadPlayer(e.getPlayer()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/models/Minecrafter.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.models; 2 | 3 | import java.util.UUID; 4 | 5 | public class Minecrafter { 6 | public UUID uuid; 7 | public String name; 8 | public int affinity; 9 | public int gainedThisMinute; 10 | public int minAffinity = -1; 11 | public int maxAffinity = -1; 12 | 13 | public Minecrafter(String name, UUID uuid) { this.name = name; this.uuid = uuid; } 14 | public Minecrafter(String name) { this.name = name; } 15 | public Minecrafter(UUID uuid) { this.uuid = uuid; } 16 | public Minecrafter() {} 17 | 18 | public Minecrafter clone() { 19 | Minecrafter clone = new Minecrafter(); 20 | clone.uuid = uuid; 21 | clone.name = name; 22 | clone.affinity = affinity; 23 | clone.minAffinity = minAffinity; 24 | clone.maxAffinity = maxAffinity; 25 | clone.gainedThisMinute = gainedThisMinute; 26 | return clone; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/events/PlayerJoinListener.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.events; 2 | 3 | import me.skinnyjeans.gmd.managers.MainManager; 4 | import me.skinnyjeans.gmd.models.BaseListener; 5 | import me.skinnyjeans.gmd.models.Difficulty; 6 | import org.bukkit.Bukkit; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.player.PlayerJoinEvent; 9 | 10 | public class PlayerJoinListener extends BaseListener { 11 | 12 | public PlayerJoinListener(MainManager mainManager) { 13 | MAIN_MANAGER = mainManager; 14 | } 15 | 16 | @EventHandler 17 | public void onJoin(PlayerJoinEvent e) { 18 | if (MAIN_MANAGER.getPlayerManager().isPlayerValidNoWorld(e.getPlayer())) { 19 | Difficulty difficulty = MAIN_MANAGER.getDifficultyManager().getDifficulty(e.getPlayer()); 20 | Runnable afterJoinTask = () -> 21 | MAIN_MANAGER.getCommandManager() 22 | .dispatchCommandsIfOnline(e.getPlayer().getUniqueId(), difficulty.commandsOnJoin); 23 | 24 | Bukkit.getScheduler().runTaskLater(MAIN_MANAGER.getPlugin(), afterJoinTask, 1L); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/databases/None.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.databases; 2 | 3 | import me.skinnyjeans.gmd.managers.DataManager; 4 | import me.skinnyjeans.gmd.models.ISaveManager; 5 | import me.skinnyjeans.gmd.models.Minecrafter; 6 | import org.bukkit.Bukkit; 7 | 8 | import java.sql.SQLException; 9 | import java.util.Collection; 10 | import java.util.UUID; 11 | 12 | public class None implements ISaveManager { 13 | 14 | public None(DataManager d){ Bukkit.getConsoleSender().sendMessage("[DynamicDifficulty] " + d.getLanguageString("other.database-chosen").replace("%database%", "None")); } 15 | 16 | @Override 17 | public boolean isConnected() { return false; } 18 | 19 | @Override 20 | public void updatePlayer(Minecrafter playerData) { return; } 21 | 22 | @Override 23 | public void batchSavePlayers(Collection players) { return; } 24 | 25 | @Override 26 | public void getAffinityValues(UUID uuid, findCallback callback) { callback.onQueryDone(null); } 27 | 28 | @Override 29 | public void playerExists(UUID uuid, findBooleanCallback callback) { return; } 30 | 31 | @Override 32 | public void disconnect() throws SQLException { return; } 33 | } 34 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/events/ItemDamageListener.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.events; 2 | 3 | import me.skinnyjeans.gmd.managers.MainManager; 4 | import me.skinnyjeans.gmd.models.BaseListener; 5 | import me.skinnyjeans.gmd.models.Difficulty; 6 | import org.bukkit.event.EventHandler; 7 | import org.bukkit.event.player.PlayerItemDamageEvent; 8 | 9 | import java.util.Random; 10 | 11 | public class ItemDamageListener extends BaseListener { 12 | 13 | private boolean shouldDisable; 14 | 15 | public ItemDamageListener(MainManager mainManager) { 16 | MAIN_MANAGER = mainManager; 17 | } 18 | 19 | @EventHandler 20 | public void onItemDamage(PlayerItemDamageEvent e) { 21 | if(shouldDisable) return; 22 | if(MAIN_MANAGER.getPlayerManager().isPlayerValid(e.getPlayer())) 23 | if(new Random().nextDouble() < MAIN_MANAGER.getDifficultyManager().getDifficulty(e.getPlayer()) 24 | .doubleDurabilityDamageChance) 25 | e.setDamage(e.getDamage() * 2); 26 | } 27 | 28 | @Override 29 | public void reloadConfig() { 30 | shouldDisable = true; 31 | for(Difficulty difficulty : MAIN_MANAGER.getDifficultyManager().getDifficulties()) 32 | if (difficulty.doubleDurabilityDamageChance != 0.0) { 33 | shouldDisable = false; 34 | break; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/events/EntityTargetListener.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.events; 2 | 3 | import me.skinnyjeans.gmd.managers.MainManager; 4 | import me.skinnyjeans.gmd.models.BaseListener; 5 | import me.skinnyjeans.gmd.models.Difficulty; 6 | import org.bukkit.entity.Player; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.entity.EntityTargetLivingEntityEvent; 9 | 10 | public class EntityTargetListener extends BaseListener { 11 | 12 | private boolean shouldDisable; 13 | 14 | public EntityTargetListener(MainManager mainManager) { 15 | MAIN_MANAGER = mainManager; 16 | } 17 | 18 | @EventHandler 19 | public void onPlayerSpot(EntityTargetLivingEntityEvent e) { 20 | if(shouldDisable) return; 21 | 22 | if(MAIN_MANAGER.getPlayerManager().isPlayerValid(e.getTarget())) 23 | if(MAIN_MANAGER.getDifficultyManager().getDifficulty((Player) e.getTarget()).mobsIgnoredPlayers.contains(e.getEntityType().toString())) 24 | if(!MAIN_MANAGER.getEntityManager().wasEntityAttacked(e.getEntity())) 25 | e.setCancelled(true); 26 | } 27 | 28 | @Override 29 | public void reloadConfig() { 30 | shouldDisable = true; 31 | for(Difficulty difficulty : MAIN_MANAGER.getDifficultyManager().getDifficulties()) 32 | if (difficulty.mobsIgnoredPlayers.size() != 0) { 33 | shouldDisable = false; 34 | break; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/events/EntityDamageListener.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.events; 2 | 3 | import me.skinnyjeans.gmd.managers.MainManager; 4 | import me.skinnyjeans.gmd.models.BaseListener; 5 | import me.skinnyjeans.gmd.models.Difficulty; 6 | import org.bukkit.entity.Player; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.entity.EntityDamageEvent; 9 | 10 | public class EntityDamageListener extends BaseListener { 11 | 12 | private boolean shouldDisable; 13 | 14 | public EntityDamageListener(MainManager mainManager) { 15 | MAIN_MANAGER = mainManager; 16 | } 17 | 18 | @EventHandler 19 | public void onEntityDamage(EntityDamageEvent e) { 20 | if (shouldDisable) return; 21 | if (MAIN_MANAGER.getPlayerManager().isPlayerValid(e.getEntity())) { 22 | Player player = (Player) e.getEntity(); 23 | if (e.getCause() == EntityDamageEvent.DamageCause.STARVATION) 24 | e.setCancelled(player.getHealth() - e.getFinalDamage() < MAIN_MANAGER.getDifficultyManager() 25 | .getDifficulty(player).minimumStarvationHealth); 26 | } 27 | } 28 | 29 | @Override 30 | public void reloadConfig() { 31 | shouldDisable = true; 32 | 33 | for(Difficulty difficulty : MAIN_MANAGER.getDifficultyManager().getDifficulties()) 34 | if (difficulty.minimumStarvationHealth != 0) { 35 | shouldDisable = false; 36 | break; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/events/HungerListener.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.events; 2 | 3 | import me.skinnyjeans.gmd.managers.MainManager; 4 | import me.skinnyjeans.gmd.models.BaseListener; 5 | import me.skinnyjeans.gmd.models.Difficulty; 6 | import org.bukkit.entity.Player; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.entity.FoodLevelChangeEvent; 9 | 10 | import java.util.Random; 11 | 12 | public class HungerListener extends BaseListener { 13 | 14 | private boolean shouldDisable; 15 | 16 | public HungerListener(MainManager mainManager) { 17 | MAIN_MANAGER = mainManager; 18 | } 19 | 20 | @EventHandler 21 | public void onHungerDrain(FoodLevelChangeEvent e) { 22 | if(shouldDisable) return; 23 | 24 | if(MAIN_MANAGER.getPlayerManager().isPlayerValid(e.getEntity())) { 25 | Player player = (Player) e.getEntity(); 26 | if(player.getFoodLevel() > e.getFoodLevel()) 27 | if(new Random().nextDouble() > MAIN_MANAGER.getDifficultyManager().getDifficulty(player) 28 | .hungerDrainChance) 29 | e.setCancelled(true); 30 | } 31 | 32 | } 33 | 34 | @Override 35 | public void reloadConfig() { 36 | shouldDisable = true; 37 | for(Difficulty difficulty : MAIN_MANAGER.getDifficultyManager().getDifficulties() ) 38 | if (difficulty.hungerDrainChance < 1.0) { 39 | shouldDisable = false; 40 | break; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/events/HealthRegenListener.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.events; 2 | 3 | import me.skinnyjeans.gmd.managers.MainManager; 4 | import me.skinnyjeans.gmd.models.BaseListener; 5 | import me.skinnyjeans.gmd.models.Difficulty; 6 | import org.bukkit.event.EventHandler; 7 | import org.bukkit.event.entity.EntityRegainHealthEvent; 8 | 9 | import java.util.EnumSet; 10 | 11 | public class HealthRegenListener extends BaseListener { 12 | 13 | private static final EnumSet CANCEL_REGEN = EnumSet.of( 14 | EntityRegainHealthEvent.RegainReason.REGEN, EntityRegainHealthEvent.RegainReason.SATIATED, 15 | EntityRegainHealthEvent.RegainReason.EATING); 16 | 17 | private boolean shouldDisable; 18 | 19 | public HealthRegenListener(MainManager mainManager) { 20 | MAIN_MANAGER = mainManager; 21 | } 22 | 23 | @EventHandler 24 | public void onHealthRegen(EntityRegainHealthEvent e) { 25 | if(shouldDisable) return; 26 | if(MAIN_MANAGER.getPlayerManager().isPlayerValid(e.getEntity())) 27 | if(CANCEL_REGEN.contains(e.getRegainReason())) { 28 | e.setCancelled(true); 29 | } 30 | } 31 | 32 | @Override 33 | public void reloadConfig() { 34 | shouldDisable = true; 35 | for(Difficulty difficulty : MAIN_MANAGER.getDifficultyManager().getDifficulties() ) 36 | if (!difficulty.allowHealthRegen) { 37 | shouldDisable = false; 38 | break; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/utils/Formatter.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.utils; 2 | 3 | import org.bukkit.ChatColor; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | 9 | public class Formatter { 10 | 11 | /** 12 | * Function to format strings 13 | * @param original The String to be formatted 14 | * @return Formatted String with applied ColorCodes 15 | */ 16 | public static String format(String original) { return ChatColor.translateAlternateColorCodes('&', original); } 17 | 18 | /** 19 | * Function to format strings 20 | * @param original The String to be formatted 21 | * @param replaceWith To replace in a string 22 | * @return Formatted String with applied ColorCodes and replaced item 23 | */ 24 | public static String format(String original, String replaceWith) { 25 | return ChatColor.translateAlternateColorCodes('&', original).replace("%replace%", replaceWith); 26 | } 27 | 28 | /** 29 | * Function to format strings 30 | * @param original The String to be formatted 31 | * @param replaceWith To replace in a string 32 | * @return Formatted String with applied ColorCodes and replaced item 33 | */ 34 | public static String format(String original, HashMap replaceWith) { 35 | String formatted = ChatColor.translateAlternateColorCodes('&', original); 36 | for(String key : replaceWith.keySet()) formatted = formatted.replace(key, replaceWith.get(key)); 37 | return formatted; 38 | } 39 | 40 | public static List list(Object ...objects) { 41 | List list = new ArrayList<>(); 42 | for(Object object : objects) list.add(object.toString()); 43 | return list; 44 | } 45 | 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/managers/EventManager.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.managers; 2 | 3 | import me.skinnyjeans.gmd.events.*; 4 | import me.skinnyjeans.gmd.models.BaseListener; 5 | import org.bukkit.Bukkit; 6 | 7 | import java.util.HashSet; 8 | 9 | public class EventManager { 10 | 11 | private final MainManager MAIN_MANAGER; 12 | private final HashSet LISTENERS = new HashSet<>(); 13 | 14 | public EventManager(MainManager mainManager) { 15 | MAIN_MANAGER = mainManager; 16 | registerEvents(); 17 | } 18 | 19 | public void registerEvents() { 20 | LISTENERS.add(new CreeperExplodeListener(MAIN_MANAGER)); 21 | LISTENERS.add(new BlockMinedListener(MAIN_MANAGER)); 22 | LISTENERS.add(new CommandListener(MAIN_MANAGER)); 23 | LISTENERS.add(new EntityDeathListener(MAIN_MANAGER)); 24 | LISTENERS.add(new EntityHitListener(MAIN_MANAGER)); 25 | LISTENERS.add(new EntityTargetListener(MAIN_MANAGER)); 26 | LISTENERS.add(new HungerListener(MAIN_MANAGER)); 27 | LISTENERS.add(new InventoryListener(MAIN_MANAGER)); 28 | LISTENERS.add(new ItemDamageListener(MAIN_MANAGER)); 29 | LISTENERS.add(new MobSpawnListener(MAIN_MANAGER)); 30 | LISTENERS.add(new PlayerDeathListener(MAIN_MANAGER)); 31 | LISTENERS.add(new PlayerJoinListener(MAIN_MANAGER)); 32 | LISTENERS.add(new PlayerLeaveListener(MAIN_MANAGER)); 33 | LISTENERS.add(new PotionEffectListener(MAIN_MANAGER)); 34 | LISTENERS.add(new HealthRegenListener(MAIN_MANAGER)); 35 | LISTENERS.add(new EntityDamageListener(MAIN_MANAGER)); 36 | 37 | for(BaseListener listener : LISTENERS) 38 | Bukkit.getPluginManager().registerEvents(listener, MAIN_MANAGER.getPlugin()); 39 | } 40 | 41 | public void reloadConfig() { 42 | for(BaseListener listener : LISTENERS) 43 | listener.reloadConfig(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/events/PlayerDeathListener.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.events; 2 | 3 | import me.skinnyjeans.gmd.managers.MainManager; 4 | import me.skinnyjeans.gmd.models.BaseListener; 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.event.EventHandler; 7 | import org.bukkit.event.entity.EntityDamageEvent; 8 | import org.bukkit.event.entity.PlayerDeathEvent; 9 | 10 | import java.util.EnumSet; 11 | 12 | public class PlayerDeathListener extends BaseListener { 13 | 14 | private static final EnumSet COUNTS_AS_SUICIDE = EnumSet.of(EntityDamageEvent.DamageCause.FALL, EntityDamageEvent.DamageCause.SUFFOCATION, EntityDamageEvent.DamageCause.SUICIDE); 15 | private boolean preventAffinityLossOnSuicide; 16 | private int onDeath; 17 | 18 | public PlayerDeathListener(MainManager mainManager) { 19 | MAIN_MANAGER = mainManager; 20 | reloadConfig(); 21 | } 22 | 23 | @EventHandler 24 | public void onDeath(PlayerDeathEvent e) { 25 | if(!MAIN_MANAGER.getPlayerManager().isPlayerValid(e.getEntity())) return; 26 | 27 | if(MAIN_MANAGER.getDifficultyManager().getDifficulty(e.getEntity()).keepInventory) { 28 | e.setKeepInventory(true); 29 | e.setKeepLevel(true); 30 | e.setDroppedExp(0); 31 | e.getDrops().clear(); 32 | } 33 | 34 | Bukkit.getScheduler().runTaskAsynchronously(MAIN_MANAGER.getPlugin(), () -> { 35 | if(preventAffinityLossOnSuicide) 36 | if(COUNTS_AS_SUICIDE.contains(e.getEntity().getLastDamageCause().getCause())) 37 | return; 38 | MAIN_MANAGER.getPlayerManager().addAffinity(e.getEntity(), onDeath); 39 | }); 40 | } 41 | 42 | @Override 43 | public void reloadConfig() { 44 | preventAffinityLossOnSuicide = MAIN_MANAGER.getDataManager().getConfig().getBoolean("toggle-settings.prevent-affinity-loss-on-suicide", true); 45 | onDeath = MAIN_MANAGER.getDataManager().getConfig().getInt("death", -100); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/events/PotionEffectListener.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.events; 2 | 3 | import me.skinnyjeans.gmd.managers.MainManager; 4 | import me.skinnyjeans.gmd.models.BaseListener; 5 | import me.skinnyjeans.gmd.models.Difficulty; 6 | import org.bukkit.entity.Player; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.entity.EntityPotionEffectEvent; 9 | import org.bukkit.potion.PotionEffectType; 10 | 11 | import java.util.Arrays; 12 | import java.util.HashSet; 13 | 14 | public class PotionEffectListener extends BaseListener { 15 | 16 | private final HashSet EFFECTS = new HashSet<>(Arrays.asList(PotionEffectType.SLOWNESS, PotionEffectType.NAUSEA, 17 | PotionEffectType.WITHER,PotionEffectType.POISON,PotionEffectType.BLINDNESS, PotionEffectType.WEAKNESS,PotionEffectType.HUNGER)); 18 | private static final HashSet EFFECT_CAUSES = new HashSet<>(Arrays.asList(EntityPotionEffectEvent.Cause.ATTACK, EntityPotionEffectEvent.Cause.ARROW, EntityPotionEffectEvent.Cause.POTION_SPLASH)); 19 | 20 | private boolean shouldDisable; 21 | 22 | public PotionEffectListener(MainManager mainManager) { 23 | MAIN_MANAGER = mainManager; 24 | } 25 | 26 | @EventHandler 27 | public void onPotionEffect(EntityPotionEffectEvent e) { 28 | if(shouldDisable) return; 29 | if(MAIN_MANAGER.getPlayerManager().isPlayerValid(e.getEntity())) 30 | if(EFFECT_CAUSES.contains(e.getCause()) && EFFECTS.contains(e.getModifiedType())) 31 | if(!MAIN_MANAGER.getDifficultyManager().getDifficulty((Player) e.getEntity()).effectsWhenAttacked) 32 | e.setCancelled(true); 33 | } 34 | 35 | @Override 36 | public void reloadConfig() { 37 | shouldDisable = true; 38 | for(Difficulty difficulty : MAIN_MANAGER.getDifficultyManager().getDifficulties() ) 39 | if (!difficulty.effectsWhenAttacked) { 40 | shouldDisable = false; 41 | break; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/events/CommandListener.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.events; 2 | 3 | import me.skinnyjeans.gmd.managers.MainManager; 4 | import me.skinnyjeans.gmd.models.BaseListener; 5 | import me.skinnyjeans.gmd.models.Difficulty; 6 | import org.bukkit.entity.Player; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.player.PlayerCommandPreprocessEvent; 9 | 10 | import java.util.List; 11 | 12 | public class CommandListener extends BaseListener { 13 | 14 | private String commandNotAllowed; 15 | private boolean shouldDisable; 16 | 17 | public CommandListener(MainManager mainManager) { 18 | MAIN_MANAGER = mainManager; 19 | } 20 | 21 | @EventHandler 22 | public void beforeCommand(PlayerCommandPreprocessEvent e) { 23 | if(shouldDisable) return; 24 | Player p = e.getPlayer(); 25 | if(p.isOp() || !MAIN_MANAGER.getPlayerManager().isPlayerValid(p)) return; 26 | List list = MAIN_MANAGER.getDifficultyManager().getDifficulty(p).disabledCommands; 27 | StringBuilder cmd = new StringBuilder(); 28 | String[] args = e.getMessage().replace("/","").toLowerCase().split(" "); 29 | if(list.size() != 0) 30 | for(String arg : args) { 31 | if(cmd.length() != 0) 32 | cmd.append(" "); 33 | cmd.append(arg); 34 | if(list.contains(cmd.toString())) { 35 | e.setCancelled(true); 36 | if(commandNotAllowed.length() != 0) e.getPlayer().sendMessage(commandNotAllowed); 37 | return; 38 | } 39 | } 40 | } 41 | 42 | @Override 43 | public void reloadConfig() { 44 | shouldDisable = true; 45 | for(Difficulty difficulty : MAIN_MANAGER.getDifficultyManager().getDifficulties()) 46 | if (difficulty.disabledCommands.size() != 0) { 47 | shouldDisable = false; 48 | break; 49 | } 50 | 51 | commandNotAllowed = MAIN_MANAGER.getDataManager().getLanguageString("in-game.command-not-allowed", false); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/managers/TabCompleterManager.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.managers; 2 | 3 | import me.skinnyjeans.gmd.models.Minecrafter; 4 | import org.bukkit.command.Command; 5 | import org.bukkit.command.CommandSender; 6 | import org.bukkit.command.TabCompleter; 7 | 8 | import java.util.*; 9 | 10 | public class TabCompleterManager implements TabCompleter { 11 | 12 | private final MainManager MAIN_MANAGER; 13 | private static final HashSet noNumbers = new HashSet<>(Arrays.asList("author", "forceremoval", "me", "difficulties", "reload", "forcesave", "help", "playergui")); 14 | private static final HashSet allCommands = new HashSet<>(Arrays.asList( 15 | "set","get","add","remove","help","setmax", "forceremoval", "setmin","delmax","delmin","author","reload","forcesave","playergui","difficulties" 16 | )); 17 | private final HashSet numbers = new HashSet<>(); 18 | 19 | public TabCompleterManager(MainManager mainManager) { MAIN_MANAGER = mainManager; } 20 | 21 | public List onTabComplete(CommandSender sender, Command command, String label, String[] args){ 22 | ArrayList l = new ArrayList<>(); 23 | if (args.length == 1) { 24 | for(String c : allCommands) 25 | if(c.contains(args[0])) 26 | l.add(c); 27 | } else if (args.length >= 2 && !noNumbers.contains(args[0])) { 28 | String arg = args[1].toLowerCase(); 29 | for(String c : numbers) 30 | if(c.contains(arg)) 31 | l.add(c); 32 | Collection list = MAIN_MANAGER.getPlayerManager().getPlayerList().values(); 33 | for (Minecrafter pl : list) 34 | if(pl.name.contains(arg)) 35 | l.add(pl.name); 36 | } 37 | 38 | return l; 39 | } 40 | 41 | public void reloadConfig() { 42 | numbers.clear(); 43 | numbers.addAll(Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9", "@a", "@s", "@p", "@r")); 44 | numbers.addAll(MAIN_MANAGER.getDifficultyManager().getDifficultyNames()); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/events/CreeperExplodeListener.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.events; 2 | 3 | import me.skinnyjeans.gmd.managers.MainManager; 4 | import me.skinnyjeans.gmd.models.BaseListener; 5 | import me.skinnyjeans.gmd.models.Difficulty; 6 | import org.bukkit.Location; 7 | import org.bukkit.entity.EntityType; 8 | import org.bukkit.entity.Player; 9 | import org.bukkit.event.EventHandler; 10 | import org.bukkit.event.entity.EntityExplodeEvent; 11 | 12 | import java.util.Arrays; 13 | import java.util.HashSet; 14 | import java.util.List; 15 | 16 | public class CreeperExplodeListener extends BaseListener { 17 | 18 | public boolean shouldDisable; 19 | public final static HashSet EXPLODABLES = new HashSet<>(Arrays.asList(EntityType.CREEPER, EntityType.FIREBALL, EntityType.WITHER_SKULL)); 20 | 21 | public CreeperExplodeListener(MainManager mainManager) { MAIN_MANAGER = mainManager; } 22 | 23 | @EventHandler 24 | public void onCreeperExplosion(EntityExplodeEvent e) { 25 | if(shouldDisable) return; 26 | 27 | if(EXPLODABLES.contains(e.getEntityType())) { 28 | Player closestPlayer = null; 29 | double distance = 32.0; 30 | List onlinePlayers = e.getEntity().getWorld().getPlayers(); 31 | Location entityLocation = e.getLocation(); 32 | for(Player pl : onlinePlayers) { 33 | double playerDistance = entityLocation.distance(pl.getLocation()); 34 | if(playerDistance < distance) { 35 | distance = playerDistance; 36 | closestPlayer = pl; 37 | } 38 | } 39 | 40 | if(MAIN_MANAGER.getPlayerManager().isPlayerValid(closestPlayer) 41 | && MAIN_MANAGER.getDifficultyManager().getDifficulty(closestPlayer).preventEntityExplosionBlockDamage) { 42 | e.blockList().clear(); 43 | } 44 | } 45 | } 46 | 47 | @Override 48 | public void reloadConfig() { 49 | shouldDisable = true; 50 | 51 | for(Difficulty difficulty : MAIN_MANAGER.getDifficultyManager().getDifficulties()) 52 | if (difficulty.preventEntityExplosionBlockDamage) { 53 | shouldDisable = false; 54 | break; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/models/TimeSettings.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.models; 2 | 3 | import me.skinnyjeans.gmd.managers.MainManager; 4 | import org.bukkit.World; 5 | import org.bukkit.configuration.ConfigurationSection; 6 | import org.bukkit.entity.Player; 7 | 8 | import java.util.HashMap; 9 | import java.util.Set; 10 | 11 | public class TimeSettings extends DifficultySettings { 12 | private final HashMap timeAffinity = new HashMap<>(); 13 | private int defaultValue, startAffinity; 14 | 15 | private boolean ignoreNether, ignoreTheEnd; 16 | 17 | public TimeSettings(MainManager mainManager) { 18 | super(mainManager); 19 | reloadConfig(); 20 | } 21 | 22 | @Override 23 | public int calculateAffinity(Player player, int affinity) { 24 | World world = player.getWorld(); 25 | 26 | if(!timeAffinity.containsKey(world.getName()) 27 | || ignoreNether && world.getEnvironment().equals(World.Environment.NETHER) 28 | || ignoreTheEnd && world.getEnvironment().equals(World.Environment.THE_END)) { 29 | 30 | return defaultValue; 31 | } 32 | 33 | double t = timeAffinity.get(world.getName()).calculateAffinity(world.getTime()); 34 | return (int) Math.round(startAffinity 35 | * t); 36 | } 37 | 38 | @Override 39 | public void reloadConfig() { 40 | timeAffinity.clear(); 41 | 42 | ConfigurationSection config = MAIN_MANAGER.getDataManager().getConfig(); 43 | 44 | ignoreNether = config.getBoolean("difficulty-type.time.ignore-nether", false); 45 | ignoreTheEnd = config.getBoolean("difficulty-type.time.ignore-the-end", false); 46 | 47 | startAffinity = config.getInt("max-affinity", 1500); 48 | defaultValue = (int) Math.round(startAffinity 49 | * config.getDouble("difficulty-type.time.default", 0.4)); 50 | 51 | 52 | ConfigurationSection worldScales = config.getConfigurationSection("difficulty-type.time.world-scales"); 53 | Set keys = worldScales.getKeys(false); 54 | for (String key : keys) { 55 | ConfigurationSection worldScaleSection = worldScales.getConfigurationSection(key); 56 | timeAffinity.put(key, new WorldTimeConfiguration(worldScaleSection, key)); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/events/EntityDeathListener.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.events; 2 | 3 | import me.skinnyjeans.gmd.managers.MainManager; 4 | import me.skinnyjeans.gmd.models.BaseListener; 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.World; 7 | import org.bukkit.entity.LivingEntity; 8 | import org.bukkit.entity.Player; 9 | import org.bukkit.event.EventHandler; 10 | import org.bukkit.event.entity.EntityDeathEvent; 11 | 12 | import java.util.Random; 13 | 14 | public class EntityDeathListener extends BaseListener { 15 | 16 | public EntityDeathListener(MainManager mainManager) { 17 | MAIN_MANAGER = mainManager; 18 | } 19 | 20 | @EventHandler 21 | public void onKill(EntityDeathEvent e) { 22 | LivingEntity entity = e.getEntity(); 23 | if(!MAIN_MANAGER.getPlayerManager().isPlayerValid(entity.getKiller())) return; 24 | if(MAIN_MANAGER.getEntityManager().isEntityIgnored(entity)) { 25 | MAIN_MANAGER.getEntityManager().ignoredEntityKilled(entity); 26 | return; 27 | } 28 | 29 | 30 | Bukkit.getScheduler().runTaskAsynchronously(MAIN_MANAGER.getPlugin(), () -> { 31 | if (MAIN_MANAGER.getEntityManager().hasEntityPoints(e.getEntityType())) 32 | MAIN_MANAGER.getPlayerManager().addAffinity(entity.getKiller(), MAIN_MANAGER.getEntityManager().getEntityPoints(e.getEntityType())); 33 | }); 34 | 35 | boolean isPlayer = entity instanceof Player; 36 | if (!isPlayer && !MAIN_MANAGER.getEntityManager().isEntityDisabled(entity)) { 37 | if(entity.getCanPickupItems()) return; 38 | 39 | e.setDroppedExp((int) (e.getDroppedExp() * MAIN_MANAGER.getDifficultyManager().getDifficulty(entity.getKiller()).experienceMultiplier)); 40 | if (new Random().nextDouble() < MAIN_MANAGER.getDifficultyManager().getDifficulty(entity.getKiller()).doubleLootChance) { 41 | World world = Bukkit.getWorld(entity.getWorld().getUID()); 42 | if (world != null) { 43 | int itemsDropped = e.getDrops().size(); 44 | for (int i = 0; i < itemsDropped; i++) { 45 | world.dropItemNaturally( 46 | entity.getLocation(), 47 | e.getDrops().get(i)); 48 | } 49 | } 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/models/Difficulty.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.models; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | 7 | public class Difficulty { 8 | public String difficultyName; 9 | public String prefix; 10 | 11 | public double damageDoneByMobs; 12 | public double damageDoneOnMobs; 13 | public double damageDoneOnTamed; 14 | public double hungerDrainChance; 15 | public double damageByRangedMobs; 16 | public double experienceMultiplier; 17 | public double doubleLootChance; 18 | public double doubleDurabilityDamageChance; 19 | public double damagePerArmorPoint; 20 | public double chanceCancelDeath; 21 | public double armorDropChance; 22 | public double chanceToEnchant = Double.NaN; 23 | public double chanceToHaveArmor; 24 | public double chanceToHaveWeapon; 25 | public double weaponDropChance; 26 | 27 | public int affinityRequirement; 28 | public int maxEnchants; 29 | public int maxEnchantLevel; 30 | public int difficultyUntil; 31 | public int minimumStarvationHealth; 32 | public int maximumHealth; 33 | 34 | public boolean allowPVP; 35 | public boolean keepInventory; 36 | public boolean allowHealthRegen; 37 | public boolean effectsWhenAttacked; 38 | public boolean preventEntityExplosionBlockDamage; 39 | 40 | public List disabledCommands = new ArrayList<>(); 41 | public List mobsIgnoredPlayers = new ArrayList<>(); 42 | public List commandsOnJoin = new ArrayList<>(); 43 | public List commandsOnSwitchFromPrev = new ArrayList<>(); 44 | public List commandsOnSwitchFromNext = new ArrayList<>(); 45 | public List mythicMobProfiles = new ArrayList<>(); 46 | public HashMap armorChance = new HashMap(); 47 | public HashMap armorDamageMultipliers = new HashMap(); 48 | 49 | public Difficulty(String name) { difficultyName = name; } 50 | 51 | public String getDifficultyName() { return difficultyName; } 52 | public int getAffinity() { return affinityRequirement; } 53 | 54 | public double getArmorDamageMultipliers(ArmorTypes type) { return armorDamageMultipliers.getOrDefault(type, 0.0); } 55 | public double getArmorChance(EquipmentItems type) { return armorChance.getOrDefault(type, 0.0); } 56 | } 57 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/managers/EntityManager.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.managers; 2 | 3 | import org.bukkit.configuration.ConfigurationSection; 4 | import org.bukkit.entity.Entity; 5 | import org.bukkit.entity.EntityType; 6 | 7 | import java.util.HashMap; 8 | import java.util.HashSet; 9 | 10 | public class EntityManager { 11 | 12 | private final MainManager MAIN_MANAGER; 13 | private final HashSet DISABLED_MOBS = new HashSet<>(); 14 | private final HashSet IGNORED_MOBS = new HashSet<>(); 15 | private final HashSet OVERRIDE_IGNORE = new HashSet<>(); 16 | private final HashMap MOBS = new HashMap<>(); 17 | 18 | public EntityManager(MainManager mainManager) { 19 | MAIN_MANAGER = mainManager; 20 | } 21 | 22 | public boolean hasEntityPoints(EntityType entity) { return MOBS.containsKey(entity); } 23 | 24 | public int getEntityPoints(EntityType entity) { return MOBS.get(entity); } 25 | 26 | public boolean isEntityDisabled(Entity entity) { return DISABLED_MOBS.contains(entity.getType()); } 27 | 28 | public boolean wasEntityAttacked(Entity entity) { return OVERRIDE_IGNORE.contains(entity.getEntityId()); } 29 | 30 | public boolean isEntityIgnored(Entity entity) { return IGNORED_MOBS.contains(entity.getEntityId()); } 31 | 32 | public void entityHit(Entity entity) { OVERRIDE_IGNORE.add(entity.getEntityId()); } 33 | 34 | public void ignoreEntity(Entity entity) { IGNORED_MOBS.add(entity.getEntityId()); } 35 | 36 | public void ignoredEntityKilled(Entity entity) { IGNORED_MOBS.remove(entity.getEntityId()); } 37 | 38 | public void reloadConfig() { 39 | DISABLED_MOBS.clear(); 40 | IGNORED_MOBS.clear(); 41 | MOBS.clear(); 42 | 43 | ConfigurationSection config = MAIN_MANAGER.getDataManager().getConfig(); 44 | 45 | for(String key : config.getStringList("disabled-mobs")) 46 | try { 47 | DISABLED_MOBS.add(EntityType.valueOf(key)); 48 | } catch (Exception ignored) { } 49 | 50 | for(Object key : config.getList("mobs-count-as-pve").toArray()) 51 | try { 52 | String[] sep = key.toString().replaceAll("[{|}]","").split("="); 53 | int value = (sep.length > 1) ? Integer.parseInt(sep[1]) : config.getInt("pve-kill", 2); 54 | MOBS.put(EntityType.valueOf(sep[0]), value); 55 | } catch (Exception ignored) { } 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/hooks/PlaceholderAPIExpansion.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.hooks; 2 | 3 | import me.clip.placeholderapi.expansion.PlaceholderExpansion; 4 | import me.skinnyjeans.gmd.managers.MainManager; 5 | import me.skinnyjeans.gmd.managers.PlayerManager; 6 | import org.bukkit.OfflinePlayer; 7 | import org.bukkit.entity.Player; 8 | 9 | import java.util.UUID; 10 | 11 | public class PlaceholderAPIExpansion extends PlaceholderExpansion { 12 | 13 | private final MainManager MAIN_MANAGER; 14 | 15 | public PlaceholderAPIExpansion(MainManager mainManager) { this.MAIN_MANAGER = mainManager; } 16 | 17 | @Override 18 | public boolean persist(){ 19 | return true; 20 | } 21 | 22 | @Override 23 | public boolean canRegister(){ 24 | return true; 25 | } 26 | 27 | @Override 28 | public String getIdentifier() { 29 | return "dd"; 30 | } 31 | 32 | @Override 33 | public String getAuthor() { 34 | return MAIN_MANAGER.getPlugin().getDescription().getAuthors().toString(); 35 | } 36 | 37 | @Override 38 | public String getVersion() { 39 | return MAIN_MANAGER.getPlugin().getDescription().getVersion(); 40 | } 41 | 42 | @Override 43 | public String onPlaceholderRequest(Player player, String identifier) { return placeholderRequest(player, identifier); } 44 | 45 | @Override 46 | public String onRequest(OfflinePlayer player, String identifier) { return placeholderRequest(player, identifier); } 47 | 48 | public String placeholderRequest(OfflinePlayer offlinePlayer, String identifier) { 49 | if(offlinePlayer != null && offlinePlayer.isOnline()) { 50 | PlayerManager pm = MAIN_MANAGER.getPlayerManager(); 51 | UUID uuid = pm.determineUuid(offlinePlayer.getPlayer()); 52 | 53 | if (uuid == null) { return null; } 54 | if(identifier.equals("user_progress")) return MAIN_MANAGER.getDifficultyManager().getProgress(uuid); 55 | if(identifier.equals("user_next_difficulty")) return MAIN_MANAGER.getDifficultyManager().getNextDifficulty(uuid).prefix; 56 | if(identifier.equals("user_difficulty")) return MAIN_MANAGER.getDifficultyManager().getDifficulty(uuid).prefix; 57 | if(identifier.equals("user_affinity")) return String.valueOf(pm.getPlayerAffinity(uuid).affinity); 58 | if(identifier.equals("user_min_affinity")) return String.valueOf(pm.getPlayerAffinity(uuid).minAffinity); 59 | if(identifier.equals("user_max_affinity")) return String.valueOf(pm.getPlayerAffinity(uuid).maxAffinity); 60 | } 61 | return null; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/models/RegionSettings.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.models; 2 | 3 | import me.skinnyjeans.gmd.managers.MainManager; 4 | import org.bukkit.Location; 5 | import org.bukkit.configuration.ConfigurationSection; 6 | import org.bukkit.entity.Player; 7 | 8 | import java.util.HashMap; 9 | 10 | public class RegionSettings extends DifficultySettings { 11 | private final HashMap worldRadius = new HashMap<>(); 12 | private boolean isReversed, isSquare; 13 | private int minAffinity, maxAffinity; 14 | private double defaultRadius, x, z; 15 | 16 | public RegionSettings(MainManager mainManager) { 17 | super(mainManager); 18 | reloadConfig(); 19 | } 20 | 21 | @Override 22 | public int calculateAffinity(Player player, int affinity) { 23 | Location playerLocation = player.getLocation(); 24 | 25 | double distance; 26 | if(isSquare) { 27 | double playerX = playerLocation.getX(); 28 | double playerZ = playerLocation.getZ(); 29 | 30 | distance = Math.max(Math.abs(playerX - x), Math.abs(playerZ - z)); 31 | } else { 32 | Location location = new Location(player.getWorld(), x, playerLocation.getY(), z); 33 | distance = location.distance(playerLocation); 34 | } 35 | 36 | double ans = Math.min(1.0 37 | / worldRadius.getOrDefault(playerLocation.getWorld().getName(), defaultRadius) 38 | * distance, 1.0); 39 | 40 | if(isReversed) { ans = 1.0 - ans; } 41 | return (int) Math.floor(minAffinity + (maxAffinity - minAffinity) * ans); 42 | } 43 | 44 | @Override 45 | public void reloadConfig() { 46 | ConfigurationSection config = MAIN_MANAGER.getDataManager().getConfig(); 47 | x = config.getDouble("difficulty-type.region.x", 0); 48 | z = config.getDouble("difficulty-type.region.z", 0); 49 | 50 | isReversed = config.getBoolean("difficulty-type.region.reversed", false); 51 | isSquare = config.getString("difficulty-type.region.type", "circle").equalsIgnoreCase("square"); 52 | 53 | minAffinity = config.getInt("min-affinity", 0); 54 | maxAffinity = config.getInt("max-affinity", 1500); 55 | 56 | defaultRadius = config.getDouble("difficulty-type.region.default-radius", 5000); 57 | ConfigurationSection world = config.getConfigurationSection("difficulty-type.region.radius"); 58 | 59 | if(world == null) { return; } 60 | for(String key : world.getKeys(false)) { 61 | worldRadius.put(key.toLowerCase(), world.getDouble(key)); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/models/WorldTimeConfiguration.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.models; 2 | 3 | import org.bukkit.Bukkit; 4 | import org.bukkit.configuration.ConfigurationSection; 5 | 6 | import java.util.Set; 7 | import java.util.SortedMap; 8 | import java.util.TreeMap; 9 | 10 | public class WorldTimeConfiguration { 11 | private final SortedMap timeAffinity = new TreeMap<>(); 12 | 13 | public WorldTimeConfiguration(ConfigurationSection config, String name) { 14 | Set keys = config.getKeys(true); 15 | for (String key : keys) { 16 | double difficulty = config.getDouble(key, 0.4); 17 | long time = Long.parseLong(key); 18 | 19 | timeAffinity.put(time, difficulty); 20 | } 21 | } 22 | 23 | public double calculateAffinity(long time) { 24 | if (timeAffinity.size() == 1 || time < 0) { return timeAffinity.get(timeAffinity.firstKey()); } 25 | 26 | long lastKey = -1, currentKey = -1, nextKey = -1; 27 | double currentVal = -1, nextVal = -1; 28 | for (SortedMap.Entry entry : timeAffinity.entrySet()) { 29 | currentKey = entry.getKey(); 30 | if(time <= currentKey) { 31 | if (lastKey == -1) { 32 | nextKey = currentKey; 33 | nextVal = timeAffinity.get(nextKey); 34 | nextKey += 24000L; 35 | 36 | currentKey = timeAffinity.lastKey(); 37 | currentVal = timeAffinity.get(currentKey); 38 | time += 24000L; 39 | } else { 40 | nextKey = currentKey; 41 | nextVal = timeAffinity.get(nextKey); 42 | currentKey = lastKey; 43 | currentVal = timeAffinity.get(currentKey); 44 | } 45 | 46 | break; 47 | } else if (currentKey == timeAffinity.lastKey()) { 48 | currentVal = timeAffinity.get(currentKey); 49 | nextKey = timeAffinity.firstKey(); 50 | nextVal = timeAffinity.get(nextKey); 51 | nextKey += 24000L; 52 | break; 53 | } 54 | lastKey = currentKey; 55 | } 56 | 57 | if (currentKey != -1 && nextKey != -1 && currentVal != -1 && nextVal != -1) { 58 | double c = (currentKey == nextKey) ? 0.0 59 | : Math.abs(1.0 - (1.0 / (currentKey - nextKey) * (time - nextKey))); 60 | 61 | double l = currentVal - ((currentVal - nextVal) * c); 62 | 63 | Bukkit.getConsoleSender().sendMessage(c + ":= " + l); 64 | 65 | return l; 66 | } 67 | 68 | return -100L; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/lang/zh-CN.yml: -------------------------------------------------------------------------------- 1 | # 如果你不喜欢这里的任何文字,你可以随意修改.但会让我很伤心:'( //译者:原文如此 2 | # 这些变量不一定对每个指令均有效 3 | # %number% 是命令执行者输入的数字 (如:1,49,71) 4 | # %difficulty%是玩家当前所处的难度(常与%number%一同使用,作用于单个玩家) 5 | # %user% 用于显示玩家名 6 | # 使用 &颜色 添加颜色(见https://minecraft.fandom.com/wiki/Formatting_codes) 7 | 8 | # 译注: 吸引力的确是更接近本意的……但语境下显得十分突兀,故而我选择了意译化。 9 | # 将对MC机制等的“亲和度”,译为“适应力”。适应力强者,对MC机制熟悉,故而难度更高。 10 | 11 | translated-by: "翻译者: kuzuanpa, Auxiliary Words" 12 | translator-url: "https://github.com/kuzuanpa 及 https://github.com/AuxiliaryWords" 13 | command: 14 | set: 15 | affinity: "%user% 的难度已被改为 %difficulty% , 适应力为 %number%" 16 | max-affinity: "将玩家 %user% 的适应力上限设为 %number%" 17 | min-affinity: "将玩家 %user% 的适应力下限设为 %number%" 18 | all: "将所有在线玩家的适应力设为 %number%" 19 | max-affinity-all: "将所有在线玩家的适应力上限设为 %number%" 20 | min-affinity-all: "将所有在线玩家的适应力下限设为 %number%" 21 | remove: 22 | max-affinity: "移除了玩家 %user% 的适应力上限" 23 | min-affinity: "移除了玩家 %user% 的适应力下限" 24 | max-affinity-all: "移除了所有在线玩家的适应力上限" 25 | min-affinity-all: "移除了所有在线玩家的适应力下限" 26 | get: 27 | cannot-use-get-for-all: "/get中不可使用 @a 选择器" 28 | has-affinity: "%user% 有 %number% 点适应力" 29 | currently-on: "当前难度为 %difficulty%" 30 | max-affinity: "适应力上限: %number%" 31 | min-affinity: "适应力下限: %number%" 32 | player-gui: 33 | next-page: "下一页 >" 34 | previous-page: "< 上一页" 35 | reset-values: "重设适应力" 36 | affinity: "适应力: %number%" 37 | current-page: "当前页码: %number%" 38 | max-affinity: "适应力上限: %number%" 39 | min-affinity: "适应力上限: %number%" 40 | other: 41 | reload-config: "配置已重载! 汉化 by 苦钻怕、怡和知音" 42 | force-save: "玩家数据保存完毕!" 43 | help: 44 | label: "&f/dd" 45 | name-num: " <数字>" 46 | name: "" 47 | command: 48 | 0: "&c======== &6[&eDynamic Difficulty/动态难度&6] &c========&f" 49 | 1: "也可使用难度名代替适应力数字" 50 | 2: "不指定玩家将选中命令执行者" 51 | 3: "指令不对大小写敏感, 如/dD sEtMaX 等也可使用" 52 | 4: "%label% setMax %name-num% &7>&6 设置玩家的适应力上限" 53 | 5: "%label% setMin %name-num% &7>&6 设置玩家的适应力下限" 54 | 6: "%label% remove %name-num% &7>&6 扣除玩家N点适应力" 55 | 7: "%label% add %name-num% &7>&6 增加玩家N点适应力" 56 | 8: "%label% set %name-num% &7>&6 设置玩家适应力" 57 | 9: "%label% delMax %name% &7>&6 移除玩家的适应力上限" 58 | 10: "%label% delMin %name% &7>&6 移除玩家的适应力下限" 59 | 11: "%label% get %name% &7>&6 获取玩家的当前适应力值 和 适应力上下限" 60 | 12: "%label% author &7>&6 查看作者与译者名" 61 | 13: "%label% reload &7>&6 重载本插件" 62 | 14: "%label% forceSave &7>&6 保存玩家适应力值" 63 | 15: "%label% playerGUI &7>&6 使用箱子GUI展示全部玩家" 64 | 16: "%label% help &7>&6 显示本菜单" 65 | 17: "%label% info &7>&6 显示debug信息" 66 | in-game: 67 | attacker-no-pvp: "你还是个萌新,你不可以攻击 %user%!" 68 | attackee-no-pvp: "你不可以攻击 %user% ,他还是个萌新!" 69 | command-not-allowed: "你怎敢使用该指令?" 70 | other: 71 | database-chosen: "成功连接至 %database%" 72 | update-config: "你正在使用旧版配置,请及时更新!" 73 | error: 74 | no-permission: "你没有执行权限!" 75 | include-number: "你需要填入一个数字或难度!" 76 | not-a-number: "%number% 不是一个可用的数字或难度" 77 | cannot-be-found: "该玩家不存在或不在线" 78 | console: 79 | console-selected: "你不可以选择终端或命令方块!" 80 | cannot-open-playergui: "玩家GUI不能在终端打开!" -------------------------------------------------------------------------------- /src/plugin.yml: -------------------------------------------------------------------------------- 1 | main: me.skinnyjeans.gmd.Main 2 | name: DynamicDifficulty 3 | version: 1.9 4 | author: SkinnyJeans 5 | api-version: 1.13 6 | load: "POSTWORLD" 7 | prefix: "DynamicDifficulty" 8 | softdepend: ["PlaceholderAPI", "MythicMobs"] 9 | 10 | permissions: 11 | affinity.*: 12 | default: op 13 | children: 14 | affinity.me: true 15 | affinity.info: true 16 | affinity.help: true 17 | affinity.get: true 18 | affinity.author: true 19 | affinity.add: true 20 | affinity.remove: true 21 | affinity.set: true 22 | affinity.setmax: true 23 | affinity.delmax: true 24 | affinity.setmin: true 25 | affinity.delmin: true 26 | affinity.reload: true 27 | affinity.forcesave: true 28 | affinity.playergui: true 29 | affinity.calculate: true 30 | affinity.difficulties: true 31 | affinity.forceremoval: true 32 | 33 | affinity.me: 34 | default: op 35 | description: Opens the difficulty settings for a player 36 | affinity.info: 37 | default: op 38 | description: Returns some info from items in the plugin 39 | affinity.help: 40 | default: op 41 | description: Returns all the commands of Dynamic Difficulty to the player 42 | affinity.get: 43 | default: op 44 | description: Allows a player to look up a someones affinity 45 | affinity.author: 46 | default: false 47 | description: Returns the authors name 48 | affinity.set: 49 | default: op 50 | description: Allows a player to set 51 | affinity.remove: 52 | default: op 53 | description: Allows a player to remove a certain amount of affinity to someone 54 | affinity.add: 55 | default: op 56 | description: Allows a player to add a certain amount of affinity to someone 57 | affinity.setmax: 58 | default: op 59 | description: Allows a player to set a max affinity for someone 60 | affinity.delmax: 61 | default: op 62 | description: Allows a player to remove a max affinity for someone 63 | affinity.setmin: 64 | default: op 65 | description: Allows a player to set a min affinity for someone 66 | affinity.delmin: 67 | default: op 68 | description: Allows a player to remove a min affinity for someone 69 | affinity.reload: 70 | default: op 71 | description: Allows a player to reload the config 72 | affinity.forcesave: 73 | default: op 74 | description: Saves the player data 75 | affinity.playergui: 76 | default: op 77 | description: allows you to change the settings of players in chest form 78 | affinity.calculate: 79 | default: op 80 | description: Force calculates the affinity of all players 81 | affinity.difficulties: 82 | default: op 83 | description: allows you to see all the difficulties 84 | affinity.forceremoval: 85 | default: op 86 | description: disables Dynamic Difficulty and sets all players health to their original value 87 | commands: 88 | affinity: 89 | aliases: [af, dd, dynamicdifficulty] 90 | description: Settings to change the Affinity of users -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/managers/MainManager.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.managers; 2 | 3 | import me.skinnyjeans.gmd.Main; 4 | import me.skinnyjeans.gmd.hooks.Metrics; 5 | import me.skinnyjeans.gmd.hooks.PlaceholderAPIExpansion; 6 | import org.bukkit.Bukkit; 7 | 8 | public class MainManager { 9 | 10 | private final TabCompleterManager TAB_COMPLETER_MANAGER; 11 | private final DifficultyManager DIFFICULTY_MANAGER; 12 | private final InventoryManager INVENTORY_MANAGER; 13 | private final CommandManager COMMAND_MANAGER; 14 | private final EntityManager ENTITY_MANAGER; 15 | private final PlayerManager PLAYER_MANAGER; 16 | private final EventManager EVENT_MANAGER; 17 | private final DataManager DATA_MANAGER; 18 | private final Main PLUGIN; 19 | 20 | public MainManager(Main main) { 21 | PLUGIN = main; 22 | 23 | DATA_MANAGER = new DataManager(this); 24 | PLAYER_MANAGER = new PlayerManager(this); 25 | DIFFICULTY_MANAGER = new DifficultyManager(this); 26 | 27 | TAB_COMPLETER_MANAGER = new TabCompleterManager(this); 28 | INVENTORY_MANAGER = new InventoryManager(this); 29 | COMMAND_MANAGER = new CommandManager(this); 30 | ENTITY_MANAGER = new EntityManager(this); 31 | EVENT_MANAGER = new EventManager(this); 32 | 33 | main.getCommand("affinity").setExecutor(COMMAND_MANAGER); 34 | main.getCommand("affinity").setTabCompleter(TAB_COMPLETER_MANAGER); 35 | 36 | reloadConfig(); 37 | 38 | if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) 39 | new PlaceholderAPIExpansion(this).register(); 40 | } 41 | 42 | public void reloadConfig() { 43 | DATA_MANAGER.reloadConfig(); 44 | PLAYER_MANAGER.reloadConfig(); 45 | DIFFICULTY_MANAGER.reloadConfig(); 46 | 47 | TAB_COMPLETER_MANAGER.reloadConfig(); 48 | INVENTORY_MANAGER.reloadConfig(); 49 | COMMAND_MANAGER.reloadConfig(); 50 | ENTITY_MANAGER.reloadConfig(); 51 | EVENT_MANAGER.reloadConfig(); 52 | 53 | checkMetrics(); 54 | } 55 | 56 | public void checkMetrics() { 57 | Metrics m = new Metrics(PLUGIN, 11417); 58 | m.addCustomChart(new Metrics.SimplePie("difficulty_type", () -> 59 | DATA_MANAGER.getConfig().getString("toggle-settings.difficulty-type", "player").toLowerCase() 60 | )); 61 | m.addCustomChart(new Metrics.SimplePie("save_type", () -> 62 | DATA_MANAGER.getConfig().getString("saving-data.type", "file").toLowerCase() 63 | )); 64 | m.addCustomChart(new Metrics.SimplePie("amount_of_difficulties", () -> 65 | String.valueOf(DATA_MANAGER.getConfig().getConfigurationSection("difficulty").getKeys(false).size()) 66 | )); 67 | m.addCustomChart(new Metrics.SimplePie("custom_armor_and_item_spawn_chance", () -> 68 | DATA_MANAGER.getConfig().getString("toggle-settings.advanced.custom-enchants-on-mobs", "false").toLowerCase() 69 | )); 70 | } 71 | 72 | public DifficultyManager getDifficultyManager() { return DIFFICULTY_MANAGER; } 73 | public InventoryManager getInventoryManager() { return INVENTORY_MANAGER; } 74 | public CommandManager getCommandManager() { return COMMAND_MANAGER; } 75 | public PlayerManager getPlayerManager() { return PLAYER_MANAGER; } 76 | public EntityManager getEntityManager() { return ENTITY_MANAGER; } 77 | public EventManager getEventManager() { return EVENT_MANAGER; } 78 | public DataManager getDataManager() { return DATA_MANAGER; } 79 | public Main getPlugin() { return PLUGIN; } 80 | } 81 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/databases/File.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.databases; 2 | 3 | import me.skinnyjeans.gmd.Main; 4 | import me.skinnyjeans.gmd.managers.DataManager; 5 | import me.skinnyjeans.gmd.models.ISaveManager; 6 | import me.skinnyjeans.gmd.models.Minecrafter; 7 | import org.bukkit.Bukkit; 8 | import org.bukkit.configuration.file.FileConfiguration; 9 | import org.bukkit.configuration.file.YamlConfiguration; 10 | 11 | import java.util.Collection; 12 | import java.util.UUID; 13 | 14 | public class File implements ISaveManager { 15 | 16 | private final Main plugin; 17 | private final FileConfiguration data; 18 | private final java.io.File dataFile; 19 | 20 | public File(Main m, DataManager d) { 21 | plugin = m; 22 | dataFile = new java.io.File(plugin.getDataFolder(), "data.yml"); 23 | 24 | if (! dataFile.exists()) 25 | try { 26 | dataFile.createNewFile(); 27 | } catch(Exception ignored) { } 28 | 29 | data = YamlConfiguration.loadConfiguration(dataFile); 30 | Bukkit.getConsoleSender().sendMessage("[DynamicDifficulty] " + d.getLanguageString("other.database-chosen").replace("%database%", "File")); 31 | } 32 | 33 | public boolean isConnected() { return data != null; } 34 | 35 | @Override 36 | public void updatePlayer(Minecrafter playerData) { 37 | Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { 38 | data.set(playerData.uuid + ".affinity", playerData.affinity); 39 | data.set(playerData.uuid + ".max-affinity", playerData.maxAffinity); 40 | data.set(playerData.uuid + ".min-affinity", playerData.minAffinity); 41 | data.set(playerData.uuid + ".name", playerData.name); 42 | try { 43 | data.save(dataFile); 44 | } catch (Exception ignored) { } 45 | }); 46 | } 47 | 48 | @Override 49 | public void batchSavePlayers(Collection players) { 50 | Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { 51 | for(Minecrafter playerData : players) { 52 | data.set(playerData.uuid + ".affinity", playerData.affinity); 53 | data.set(playerData.uuid + ".max-affinity", playerData.maxAffinity); 54 | data.set(playerData.uuid + ".min-affinity", playerData.minAffinity); 55 | data.set(playerData.uuid + ".name", playerData.name); 56 | } 57 | 58 | try { 59 | data.save(dataFile); 60 | } catch (Exception ignored) { } 61 | }); 62 | } 63 | 64 | @Override 65 | public void getAffinityValues(UUID uuid, findCallback callback) { 66 | Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { 67 | if(data.isSet(String.valueOf(uuid)) && data.isSet(uuid + ".affinity")) { 68 | Minecrafter playerData = new Minecrafter(uuid); 69 | playerData.affinity = data.getInt(uuid + ".affinity"); 70 | playerData.minAffinity = data.getInt(uuid + ".min-affinity"); 71 | playerData.maxAffinity = data.getInt(uuid + ".max-affinity"); 72 | playerData.name = data.getString(uuid + ".name"); 73 | callback.onQueryDone(playerData); 74 | return; 75 | } 76 | callback.onQueryDone(null); 77 | }); 78 | } 79 | 80 | @Override 81 | public void playerExists(UUID uuid, findBooleanCallback callback) { 82 | callback.onQueryDone(data.isSet(String.valueOf(uuid))); 83 | } 84 | 85 | @Override 86 | public void disconnect() { } 87 | } 88 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/events/BlockMinedListener.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.events; 2 | 3 | import me.skinnyjeans.gmd.managers.MainManager; 4 | import me.skinnyjeans.gmd.models.BaseListener; 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.Material; 7 | import org.bukkit.configuration.ConfigurationSection; 8 | import org.bukkit.enchantments.Enchantment; 9 | import org.bukkit.event.EventHandler; 10 | import org.bukkit.event.block.BlockBreakEvent; 11 | import org.bukkit.inventory.ItemStack; 12 | 13 | import java.util.HashMap; 14 | import java.util.Random; 15 | 16 | public class BlockMinedListener extends BaseListener { 17 | 18 | private final HashMap BLOCKS = new HashMap(); 19 | private final static HashMap ORE_BLOCKS = new HashMap() {{ 20 | put(Material.COAL_ORE, Material.COAL); 21 | put(Material.LAPIS_ORE, Material.LAPIS_LAZULI); 22 | put(Material.DIAMOND_ORE, Material.DIAMOND); 23 | put(Material.EMERALD_ORE, Material.EMERALD); 24 | put(Material.REDSTONE_ORE, Material.REDSTONE); 25 | put(Material.NETHER_QUARTZ_ORE, Material.QUARTZ); 26 | put(Material.NETHER_GOLD_ORE, Material.GOLD_NUGGET); 27 | put(Material.DEEPSLATE_COAL_ORE, Material.COAL); 28 | put(Material.DEEPSLATE_LAPIS_ORE, Material.LAPIS_LAZULI); 29 | put(Material.DEEPSLATE_DIAMOND_ORE, Material.DIAMOND); 30 | put(Material.DEEPSLATE_EMERALD_ORE, Material.EMERALD); 31 | put(Material.DEEPSLATE_REDSTONE_ORE, Material.REDSTONE); 32 | put(Material.COPPER_ORE, Material.RAW_COPPER); 33 | put(Material.DEEPSLATE_COPPER_ORE, Material.RAW_COPPER); 34 | }}; 35 | 36 | private boolean silkTouchAllowed; 37 | 38 | public BlockMinedListener(MainManager mainManager) { 39 | MAIN_MANAGER = mainManager; 40 | } 41 | 42 | @EventHandler 43 | public void onMined(BlockBreakEvent e) { 44 | if(BLOCKS.isEmpty()) return; 45 | if(!MAIN_MANAGER.getPlayerManager().isPlayerValid(e.getPlayer())) return; 46 | final ItemStack tool = e.getPlayer().getInventory().getItemInMainHand(); 47 | final boolean hasSilkTouch = tool.containsEnchantment(Enchantment.SILK_TOUCH); 48 | final Material type = e.getBlock().getType(); 49 | 50 | Bukkit.getScheduler().runTaskAsynchronously(MAIN_MANAGER.getPlugin(), () -> { 51 | if(BLOCKS.containsKey(type)) 52 | if(silkTouchAllowed || !hasSilkTouch) 53 | MAIN_MANAGER.getPlayerManager().addAffinity(e.getPlayer(), BLOCKS.get(type)); 54 | }); 55 | 56 | if (ORE_BLOCKS.containsKey(type) && e.getBlock().isPreferredTool(tool)) { 57 | if (! hasSilkTouch && new Random().nextDouble() < MAIN_MANAGER 58 | .getDifficultyManager().getDifficulty(e.getPlayer()).doubleLootChance) 59 | e.getPlayer().getWorld().dropItemNaturally(e.getBlock().getLocation(), new ItemStack(ORE_BLOCKS.get(type))); 60 | } 61 | } 62 | 63 | @Override 64 | public void reloadConfig() { 65 | BLOCKS.clear(); 66 | silkTouchAllowed = MAIN_MANAGER.getDataManager().getConfig().getBoolean("silk-touch-allowed", false); 67 | ConfigurationSection config = MAIN_MANAGER.getDataManager().getConfig(); 68 | 69 | int blockMined = config.getInt("block-mined", 2); 70 | 71 | for(Object key : config.getList("blocks").toArray()) 72 | try { 73 | String[] sep = key.toString().replaceAll("[{|}]","").split("="); 74 | int value = (sep.length > 1) ? Integer.parseInt(sep[1]) : blockMined; 75 | BLOCKS.put(Material.valueOf(sep[0]), value); 76 | } catch (Exception ignored) { } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/lang/nl-NL.yml: -------------------------------------------------------------------------------- 1 | translated-by: "Vertaald door: SkinnyJeans" 2 | translator-url: "https://github.com/JeannotM" 3 | command: 4 | set: 5 | affinity: "%user% gezet naar %difficulty% moeilijkheidsgraad met %number% Affiniteitspunten" 6 | max-affinity: "Max Affiniteit voor %user% gezet naar %number%" 7 | min-affinity: "Min Affiniteit voor %user% gezet naar %number%" 8 | all: "Affiniteit naar %number% gezet voor alle Online Spelers!" 9 | max-affinity-all: "Max Affiniteit voor alle Online Spelers gezet naar %number%" 10 | min-affinity-all: "Min Affiniteit voor alle Online Spelers gezet naar %number%" 11 | remove: 12 | max-affinity: "Max Affiniteit van %user% verwijderd" 13 | min-affinity: "Min Affiniteit van %user% verwijderd" 14 | max-affinity-all: "Max Affiniteit van alle Online Spelers verwijderd!" 15 | min-affinity-all: "Min Affiniteit van alle Online Spelers verwijderd!" 16 | get: 17 | cannot-use-get-for-all: "Je kan geen @a gebruiken bij de /get commando" 18 | has-affinity: "%user% heeft %number% Affiniteitspunten" 19 | currently-on: "Momenteel op de %difficulty% Moeilijkheidsgraad" 20 | max-affinity: "Max Affiniteit: %number%" 21 | min-affinity: "Min Affiniteit: %number%" 22 | player-gui: 23 | next-page: "Volgende Pagina >" 24 | previous-page: "< Vorige Pagina" 25 | reset-values: "Affiniteit resetten" 26 | affinity: "Affiniteit: %number%" 27 | current-page: "Huidige pagina: %number%" 28 | max-affinity: "Max Affiniteit: %number%" 29 | min-affinity: "Min Affiniteit: %number%" 30 | other: 31 | reload-config: "Config is successvol herladen!" 32 | force-save: "Alle Speler data is opgeslagen!" 33 | help: 34 | label: "&f/dd" 35 | name-num: " " 36 | name: "" 37 | command: 38 | 0: "&c======== &6[&eDynamic Difficulty&6] &c========&f" 39 | 1: "Een moeilijkheidsgraad inplaats van een nummer is ook goed" 40 | 2: "Zal de naam van de commando stuurder gebruiken als er geen is meegegven" 41 | 3: "Commando's zijn niet hoofdletter gevoelig, /dD sEtMaX is dus toegestaan" 42 | 4: "%label% setMax %name-num% &7>&6 Zet de Max Affiniteit van een Speler" 43 | 5: "%label% setMin %name-num% &7>&6 Zet de Min Affiniteit van een Speler" 44 | 6: "%label% remove %name-num% &7>&6 Verwijderd n punten van een Spelers Affiniteit" 45 | 7: "%label% add %name-num% &7>&6 Voegt n punten toe aan een Spelers Affiniteit" 46 | 8: "%label% set %name-num% &7>&6 Zet de Affiniteit van een Speler" 47 | 9: "%label% delMax %name% &7>&6 Verwijderd de Max Affiniteit van een Speler" 48 | 10: "%label% delMin %name% &7>&6 Verwijderd de Min Affiniteit van een Speler" 49 | 11: "%label% get %name% &7>&6 Haalt een Spelers Min, Max and normale Affiniteit op" 50 | 12: "%label% author &7>&6 Stuurt de Auteurs & Vertalers naam terug" 51 | 13: "%label% reload &7>&6 Herlaad Dynamic Difficulty (veilig)" 52 | 14: "%label% forceSave &7>&6 Slaat de Affiniteit van alle Spelers" 53 | 15: "%label% playerGUI &7>&6 Toont alle spelers in een kist GUI" 54 | 16: "%label% help &7>&6 Toont dit menu" 55 | 17: "%label% info &7>&6 Toont debug info" 56 | 18: "%label% forceRemoval &7>&6 Herstelt leven van spelers en sluit Dynamic Difficulty" 57 | in-game: 58 | attacker-no-pvp: "Je kan %user% niet aanvallen omdat jij het al moeilijk genoeg hebt!" 59 | attackee-no-pvp: "Je kan %user% niet aanvallen omdat die het al moeilijk genoeg heeft!" 60 | command-not-allowed: "Je bent te goed om dit commando te gebruiken!" 61 | other: 62 | database-chosen: "Succesvol verbinding gemaakt met %database%" 63 | update-config: "Je speelt momenteel op een oude versie van de config, zorg ervoor dat je die update!" 64 | error: 65 | no-permission: "Je hebt geen toestemming om dat te doen!" 66 | include-number: "Je moet een Nummer of Moelijkheidsgraad hebben bij dit commando!" 67 | not-a-number: "%number% is geen Nummer of Moeilijkheidsgraad!" 68 | cannot-be-found: "Kan de gebruiker niet vinden!" 69 | console: 70 | console-selected: "Je kan de Console of commandoblok niet selecteren!" 71 | no-player-name: "Je kan dit commando niet gebruiken zonder gebruikersnaam!" -------------------------------------------------------------------------------- /src/lang/tl-PH.yml: -------------------------------------------------------------------------------- 1 | translated-by: "Translated by: mornec-ridhut" 2 | translator-url: "https://github.com/mornec-ridhut" 3 | command: 4 | set: 5 | affinity: "Inilagay ang difficulty sa %difficulty% para kay %user% na may %number% Affinity Points" 6 | max-affinity: "Inilagay ang Max Affinity sa %number% para kay %user%" 7 | min-affinity: "Inilagay ang Min Affinity sa %number% para kay %user%" 8 | all: "Inilagay ang Affinity sa %number% para sa lahat ng Online Players!" 9 | max-affinity-all: "Inilagay ang Max Affinity sa %number% para sa lahat ng Online Players!" 10 | min-affinity-all: "Inilagay ang Min Affinity sa %number% para sa lahat ng Online Players!" 11 | remove: 12 | max-affinity: "Tinanggal ang Max Affinity para kay %user%" 13 | min-affinity: "Tinanggal ang Min Affinity para kay %user%" 14 | max-affinity-all: "Tinanggal ang Max Affinity para sa lahat ng Online Players!" 15 | min-affinity-all: "Tinanggal ang Min Affinity para sa lahat ng Online Players!" 16 | get: 17 | cannot-use-get-for-all: "Hindi maaring gamitin ang @a sa /get command" 18 | has-affinity: "Si %user% ay may %number% Affinity points" 19 | currently-on: "Ngayon ay nasa %difficulty% Difficulty" 20 | max-affinity: "Max Affinity: %number%" 21 | min-affinity: "Min Affinity: %number%" 22 | other: 23 | reload-config: "Ang config ay matagumpay na nai-reload!" 24 | force-save: "Ang Player Data ay matagumpay na nai-save!" 25 | player-gui: 26 | next-page: "Kasunod na Page >" 27 | previous-page: "< Nakalipas na Page" 28 | reset-values: "I-reset ang Affinity" 29 | affinity: "Affinity: %number%" 30 | current-page: "Kasalukuyang Page: %number%" 31 | max-affinity: "Max Affinity: %number%" 32 | min-affinity: "Min Affinity: %number%" 33 | help: 34 | label: "&f/dd" 35 | name-num: " " 36 | name: "" 37 | command: 38 | 0: "&c======== &6[&eDynamic Difficulty&6] &c========&f" 39 | 1: "Maari mong ibigay ang Difficulty sa halip na Number" 40 | 2: "Mai-aapply ang setting sa gumamit ng command kung walang binigay na pangalan" 41 | 3: "Ang mga commands ay hindi case-sensitive. Ibig sabihin maari mong gamitin ang /dD sEtMaX" 42 | 4: "%label% setMax %name-num% &7>&6 I-set ang Max Affinity ng isang Player" 43 | 5: "%label% setMin %name-num% &7>&6 I-set ang Min Affinity ng isang Player" 44 | 6: "%label% remove %name-num% &7>&6 Magtanggal ng n points mula sa Affinity ng Player" 45 | 7: "%label% add %name-num% &7>&6 Magdagdag ng n points sa Affinity ng Player" 46 | 8: "%label% set %name-num% &7>&6 I-set ang Affinity ng isang Player" 47 | 9: "%label% delMax %name% &7>&6 Tanggalin ang Max Affinity ng isang Player" 48 | 10: "%label% delMin %name% &7>&6 Tanggalin ang Min Affinity ng isang Player" 49 | 11: "%label% get %name% &7>&6 Kunin ang Min, Max, at normal na Affinity ng isang Player" 50 | 12: "%label% author &7>&6 I-print ang pangalan ng lumikha ng plugin at ng nagsalin nito" 51 | 13: "%label% reload &7>&6 I-reload ang Dynamic Difficulty (ligtas)" 52 | 14: "%label% forceSave &7>&6 I-save ang kasalukuyang Affinity ng Players" 53 | 15: "%label% playerGUI &7>&6 Ipakita ang lahat ng Players sa isang chest GUI" 54 | 16: "%label% help &7>&6 Ipakita ang menu na ito" 55 | 17: "%label% info &7>&6 Ipakita ang debug info" 56 | 18: "%label% forceRemoval &7>&6 I-disable ang DynamicDifficulty at i-restore ang player health" 57 | in-game: 58 | attacker-no-pvp: "Hindi mo maaring atakihin si %user% kasi ikaw ay kasalukuyang nahihirapan!" 59 | attackee-no-pvp: "Hindi mo maaring atakihin si %user% kasi siya ay kasalukuyang nahihirapan!" 60 | command-not-allowed: "Masyado kang magaling para gamitin ang command na ito!" 61 | other: 62 | database-chosen: "Matagumpay na naka-connect sa %database%" 63 | update-config: "Ikaw ay kasalukuyang gumagamit ng lumang version ng config. Siguraduhing mag update!" 64 | error: 65 | no-permission: "Wala kang permiso para gawin iyan!" 66 | include-number: "Kailangan mong lagay ng Number o Difficulty kasama ng command ito!" 67 | not-a-number: "Ang %number% ay hindi akmang Difficulty o Number" 68 | cannot-be-found: "Hindi mahanap ang player" 69 | console: 70 | console-selected: "Hindi mo maaring piliin ang console o commandblock!" 71 | cannot-open-playergui: "Hindi mabubuksan ng Console ang PlayerGUI!" 72 | -------------------------------------------------------------------------------- /src/lang/es-MX.yml: -------------------------------------------------------------------------------- 1 | translated-by: "ItsRea1Pers0n y Ale2512" 2 | translator-url: "https://github.com/ItsRealPerson and https://github.com/ralx25" 3 | command: 4 | set: 5 | affinity: "Se estableció la dificultad %difficulty% a %user% con %number% Puntos de Afinidad" 6 | max-affinity: "Establecer el máximo de Afinidad a %number% para %user%" 7 | min-affinity: "Establecer el mínimo de Afinidad a %number% para %user%" 8 | all: "Se estableció la Afinidad a %number% para todos los Jugadores en linea!" 9 | max-affinity-all: "Se estableció la maxima Afinidad a %number% para todos los Jugadores en linea!" 10 | min-affinity-all: "Se estableció la minima Afinidad a %number% para todos los Jugadores en linea!" 11 | remove: 12 | remove-from-all: "Removido %number% puntos de Afinidad a todos los Jugadores en linea!" 13 | all-max-affinity-removed: "Todos los Puntos maximos de Afinidad han sido removidos de todos los Jugadores en linea!" 14 | all-min-affinity-removed: "Todos los Puntos minimos de Afinidad han sido removidos de todos los Jugadores en linea!" 15 | max-affinity: "Se removió el máximo de Afinidad para %user%" 16 | min-affinity: "Se removió el mínimo de Afinidad para %user%" 17 | get: 18 | cannot-use-get-for-all: "No es recomendable usar @a con el comando /get" 19 | has-affinity: "%user% tiene %number% puntos de Afinidad" 20 | currently-on: "La dificultad actual es: %difficulty%" 21 | max-affinity: "Afinidad máxima: %number%" 22 | min-affinity: "Afinidad mínima: %number%" 23 | other: 24 | reload-config: "Configuración recargada exitosamente!" 25 | force-save: "Datos del jugador han sido guardados!" 26 | player-gui: 27 | next-page: "Siguiente Página >" 28 | previous-page: "< Página Anterior" 29 | reset-values: "Reiniciar Afinidad" 30 | affinity: "Afinidad: %number%" 31 | current-page: "Página Actual: %number%" 32 | max-affinity: "Afinidad Máxima: %number%" 33 | min-affinity: "Afinidad Mínima: %number%" 34 | help: 35 | label: "&f/dd" 36 | name-num: " " 37 | name: "" 38 | command: 39 | 0: "&c======== &6[&eDynamic Difficulty&6] &c========&f" 40 | 1: "Definir una dificultad en vez de un numero esta bien" 41 | 2: "Usará al usuario que realizó el comando si no provisiona uno" 42 | 3: "Los comandos no son de caracter sensitivo es decir /dD sEtMaX is allowed" 43 | 4: "%label% setMax %name-num% &7>&6 Define la afinidad Maxima a un jugador" 44 | 5: "%label% setMin %name-num% &7>&6 Define la afinidad Mínima a un Jugadores" 45 | 6: "%label% remove %name-num% &7>&6 Remueve n puntos de Afinidad a un jugador" 46 | 7: "%label% add %name-num% &7>&6 Agrega n puntos de Afinidad a un jugador" 47 | 8: "%label% set %name-num% &7>&6 Define la afinidad a un jugador" 48 | 9: "%label% delMax %name% &7>&6 Elimina la Afinidad Máxima de un jugador" 49 | 10: "%label% delMin %name% &7>&6 Elimina la Afinidad Mínima de un jugador" 50 | 11: "%label% get %name% &7>&6 Obtiene la afinidad Mínima, Máxima y la actual de un jugador" 51 | 12: "%label% author &7>&6 Muestra el autor y el nombre del traductor." 52 | 13: "%label% reload &7>&6 Recarga el plugin (forma segura)" 53 | 14: "%label% forceSave &7>&6 Guarda la afinidad de los jugadores" 54 | 15: "%label% playerGUI &7>&6 Muestra a todos los jugadores en una interfaz" 55 | 16: "%label% help &7>&6 Muestra este menú" 56 | 17: "%label% info &7>&6 Muestra la informacion de depuración" 57 | in-game: 58 | attacker-no-pvp: "No puedes a atacar a %user% porque eres muy debil!" 59 | attackee-no-pvp: "No puedes atacar a %user% porque está llorando!" 60 | command-not-allowed: "Eres muy bueno para usar ese comando :)!" 61 | other: 62 | database-chosen: "Conexión satisfactoria con %database%" 63 | update-config: "Estas jugando con una configuración desactualizada, Asegúrese de actualizarlo!" 64 | error: 65 | no-permission: "No tienes permisos para hacer eso!" 66 | add-force: "Debes agregar 'force' al final para que @a pueda trabajar aquí" 67 | include-number: "Necesitar incluir un número o dificultad con este comando!" 68 | not-a-number: "%number% no se reconoce como dificultad o número" 69 | cannot-be-found: "No podemos encontrar al usuario" 70 | console: 71 | cannot-open-playergui: "La Consola no puede abrir el la interfaz de jugadores!" 72 | console-selected: "No puedes seleccionar la consola o un bloque de comando!" -------------------------------------------------------------------------------- /src/lang/en-US.yml: -------------------------------------------------------------------------------- 1 | # If you don't like any of the text or want to switch the language, you can change that here. 2 | # Some of these prefixes won't work on all commands 3 | # %number% is used to display the number given by the player (1, 25, 59 etc) 4 | # %difficulty% is used to display the difficulty the player is in (works on most of the commands with %number% for Singular users) 5 | # %user% Is used to display given names or player names 6 | # Add custom colors using &color https://minecraft.fandom.com/wiki/Formatting_codes 7 | 8 | translated-by: "Translated by: SkinnyJeans" 9 | translator-url: "https://github.com/JeannotM" 10 | command: 11 | set: 12 | affinity: "%user% set to %difficulty% Difficulty with %number% Affinity Points" 13 | max-affinity: "Set the Max Affinity to %number% for %user%" 14 | min-affinity: "Set the Min Affinity to %number% for %user%" 15 | all: "Set Affinity to %number% for all Online Players!" 16 | max-affinity-all: "Set Max Affinity to %number% for all Online Players!" 17 | min-affinity-all: "Set Min Affinity to %number% for all Online Players!" 18 | remove: 19 | max-affinity: "Removed the Max Affinity for %user%" 20 | min-affinity: "Removed the Min Affinity for %user%" 21 | max-affinity-all: "All Online Player's MaxAffinity removed!" 22 | min-affinity-all: "All Online Player's MinAffinity removed!" 23 | get: 24 | cannot-use-get-for-all: "You can't use @a on the /get command" 25 | has-affinity: "%user% has %number% Affinity points" 26 | currently-on: "Currently on %difficulty% Difficulty" 27 | max-affinity: "Max affinity: %number%" 28 | min-affinity: "Min affinity: %number%" 29 | other: 30 | reload-config: "Config has successfully been reloaded!" 31 | force-save: "Player data has been saved!" 32 | player-gui: 33 | next-page: "Next Page >" 34 | previous-page: "< Previous Page" 35 | reset-values: "Reset Affinity" 36 | affinity: "Affinity: %number%" 37 | current-page: "Current Page: %number%" 38 | max-affinity: "Max Affinity: %number%" 39 | min-affinity: "Min Affinity: %number%" 40 | help: 41 | label: "&f/dd" 42 | name-num: " " 43 | name: "" 44 | command: 45 | 0: "&c======== &6[&eDynamic Difficulty&6] &c========&f" 46 | 1: "Providing a Difficulty instead of a Number is also fine" 47 | 2: "Will use the user who sent the request if no name was given" 48 | 3: "Commands aren't case-sensitive, meaning that /dD sEtMaX is allowed" 49 | 4: "%label% setMax %name-num% &7>&6 Sets the Max Affinity of a Player" 50 | 5: "%label% setMin %name-num% &7>&6 Sets the Min Affinity of a Player" 51 | 6: "%label% remove %name-num% &7>&6 Removes n points from a Player's Affinity" 52 | 7: "%label% add %name-num% &7>&6 Adds n points to a Player's Affinity" 53 | 8: "%label% set %name-num% &7>&6 Sets the Affinity of a Player" 54 | 9: "%label% delMax %name% &7>&6 Removes the Max Affinity of a Player" 55 | 10: "%label% delMin %name% &7>&6 Removes the Min Affinity of a Player" 56 | 11: "%label% get %name% &7>&6 Gets a Player's Min, Max and normal Affinity" 57 | 12: "%label% author &7>&6 Returns the Authors & Translators name" 58 | 13: "%label% reload &7>&6 Reloads Dynamic Difficulty (safely)" 59 | 14: "%label% forceSave &7>&6 Saves the Players Affinity" 60 | 15: "%label% playerGUI &7>&6 Shows all players in a chest GUI" 61 | 16: "%label% help &7>&6 Shows this menu" 62 | 17: "%label% info &7>&6 Shows debug info" 63 | 18: "%label% forceRemoval &7>&6 Disables DynamicDifficulty and restores player health" 64 | in-game: 65 | attacker-no-pvp: "You cannot attack %user% because you're still having a hard time!" 66 | attackee-no-pvp: "You cannot attack %user% because he's already having a hard time!" 67 | command-not-allowed: "You're too good of a player to use this command!" 68 | other: 69 | database-chosen: "Successfully connected to %database%" 70 | update-config: "You're currently playing on an old version of the config, make sure you update it!" 71 | error: 72 | no-permission: "You don't have permission to do that!" 73 | include-number: "You need to include a Number or Difficulty with this command!" 74 | not-a-number: "%number% isn't a recognized Difficulty or Number" 75 | cannot-be-found: "Cannot find the player" 76 | console: 77 | console-selected: "You can't select the console or a commandblock!" 78 | cannot-open-playergui: "The Console can't open the PlayerGUI!" -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 4.0.0 7 | com.javatpoint.application1 8 | DynamicDifficulty 9 | v1.9 10 | 11 | 12 | 13 | org.apache.maven.plugins 14 | maven-shade-plugin 15 | 3.2.4 16 | 17 | ${project.build.directory}/dependency-reduced-pom.xml 18 | 19 | 20 | 21 | package 22 | 23 | shade 24 | 25 | 26 | 27 | 28 | 29 | org.apache.maven.plugins 30 | maven-compiler-plugin 31 | 3.8.1 32 | 33 | 8 34 | 8 35 | 36 | 37 | 38 | com.github.wvengen 39 | proguard-maven-plugin 40 | 2.6.1 41 | 42 | 43 | proguard 44 | package 45 | 46 | proguard 47 | 48 | 49 | 50 | 51 | false 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | C:\Program Files (x86)\Java\jre1.8.0_431/lib/rt.jar 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | spigot-repo 72 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/ 73 | 74 | 75 | placeholderapi 76 | https://repo.extendedclip.com/releases/ 77 | 78 | 79 | nexus 80 | Lumine Releases 81 | https://mvn.lumine.io/repository/maven-public/ 82 | 83 | 84 | 85 | 86 | 87 | me.clip 88 | placeholderapi 89 | 2.11.6 90 | provided 91 | 92 | 93 | org.postgresql 94 | postgresql 95 | 42.7.2 96 | compile 97 | 98 | 99 | org.spigotmc 100 | spigot-api 101 | 1.21.4-R0.1-SNAPSHOT 102 | provided 103 | 104 | 105 | io.lumine 106 | Mythic-Dist 107 | 5.2.0 108 | provided 109 | 110 | 111 | org.mariadb.jdbc 112 | mariadb-java-client 113 | 3.2.0 114 | 115 | 116 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/events/InventoryListener.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.events; 2 | 3 | import me.skinnyjeans.gmd.managers.MainManager; 4 | import me.skinnyjeans.gmd.models.BaseListener; 5 | import me.skinnyjeans.gmd.utils.StaticInfo; 6 | import org.bukkit.Material; 7 | import org.bukkit.entity.Player; 8 | import org.bukkit.event.EventHandler; 9 | import org.bukkit.event.inventory.InventoryClickEvent; 10 | import org.bukkit.inventory.ItemStack; 11 | 12 | import java.util.HashMap; 13 | import java.util.UUID; 14 | 15 | public class InventoryListener extends BaseListener { 16 | 17 | private static final HashMap ITEMS_WITH_VALUES = new HashMap(){{ 18 | put(Material.PINK_WOOL, -100); 19 | put(Material.MAGENTA_WOOL, -10); 20 | put(Material.PURPLE_WOOL, -1); 21 | put(Material.BLUE_WOOL, 1); 22 | put(Material.CYAN_WOOL, 10); 23 | put(Material.LIGHT_BLUE_WOOL, 100); 24 | }}; 25 | 26 | public InventoryListener(MainManager mainManager) { MAIN_MANAGER = mainManager; } 27 | 28 | @EventHandler 29 | public void onInventoryClick(InventoryClickEvent e) { 30 | if(e.getCurrentItem() == null) return; 31 | if(e.getCurrentItem().getItemMeta() == null) return; 32 | 33 | String title = e.getView().getTitle(); 34 | if(!title.contains("DynamicDifficulty")) return; 35 | 36 | if (title.equals("DynamicDifficulty - Players")) { 37 | Player whoClicked = (Player) e.getWhoClicked(); 38 | if(e.getCurrentItem().getType() == Material.PLAYER_HEAD) { 39 | UUID uuid = UUID.fromString(e.getCurrentItem().getItemMeta().getLore().get(0)); 40 | MAIN_MANAGER.getInventoryManager().openPlayerInventory(whoClicked, uuid); 41 | } else if (e.getCurrentItem().getType() == Material.IRON_INGOT) { 42 | int page = Integer.parseInt(getSlot(e, 4).getItemMeta() 43 | .getDisplayName().replaceAll("[^0-9-]+", "")); 44 | 45 | if(page > 1) MAIN_MANAGER.getInventoryManager().openInventory(whoClicked, page - 1); 46 | } else if (e.getCurrentItem().getType() == Material.GOLD_INGOT) { 47 | int page = Integer.parseInt(getSlot(e, 4).getItemMeta() 48 | .getDisplayName().replaceAll("[^0-9-]+", "")); 49 | 50 | MAIN_MANAGER.getInventoryManager().openInventory(whoClicked, page + 1); 51 | } 52 | } else if (title.equals(StaticInfo.INDIVIDUAL_PLAYER_INVENTORY)) { 53 | if(ITEMS_WITH_VALUES.containsKey(e.getCurrentItem().getType())) { 54 | int affinityType = e.getSlot() / 9; 55 | int value = ITEMS_WITH_VALUES.get(e.getCurrentItem().getType()); 56 | UUID uuid = UUID.fromString(getSlot(e, 4).getItemMeta().getLore().get(0)); 57 | if (affinityType < 2) { 58 | if(MAIN_MANAGER.getCommandManager().hasAnyPermission(e.getWhoClicked(), "set", "other")) 59 | MAIN_MANAGER.getPlayerManager().addAffinity(uuid, value); 60 | } else if (affinityType < 3) { 61 | if(MAIN_MANAGER.getCommandManager().hasAnyPermission(e.getWhoClicked(), "setmin", "other")) 62 | MAIN_MANAGER.getPlayerManager().addMinAffinity(uuid, value); 63 | } else if (affinityType < 4) { 64 | if(MAIN_MANAGER.getCommandManager().hasAnyPermission(e.getWhoClicked(), "setmax", "other")) 65 | MAIN_MANAGER.getPlayerManager().addMaxAffinity(uuid, value); 66 | } 67 | MAIN_MANAGER.getInventoryManager().updatePlayerInventory((Player) e.getWhoClicked(), uuid); 68 | } else if (e.getCurrentItem().getType() == Material.IRON_INGOT) { 69 | Player whoClicked = (Player) e.getWhoClicked(); 70 | MAIN_MANAGER.getInventoryManager().openInventory(whoClicked, 1); 71 | } else if (e.getCurrentItem().getType() == Material.RED_WOOL) { 72 | UUID uuid = UUID.fromString(getSlot(e, 4).getItemMeta().getLore().get(0)); 73 | if(MAIN_MANAGER.getCommandManager().hasAnyPermission(e.getWhoClicked(), "set", "other")) 74 | MAIN_MANAGER.getPlayerManager().resetAffinity(uuid); 75 | MAIN_MANAGER.getInventoryManager().updatePlayerInventory((Player) e.getWhoClicked(), uuid); 76 | } 77 | } else if (title.equals(StaticInfo.DIFFICULTIES_INVENTORY)) { 78 | MAIN_MANAGER.getInventoryManager().openDifficultyInventory((Player) e.getWhoClicked(), 79 | e.getCurrentItem().getItemMeta().getDisplayName()); 80 | } else if (title.equals(StaticInfo.DIFFICULTY_INVENTORY) && e.getSlot() == 0) { 81 | MAIN_MANAGER.getInventoryManager().openBaseDifficultyInventory((Player) e.getWhoClicked()); 82 | } 83 | e.setCancelled(true); 84 | } 85 | 86 | private ItemStack getSlot(InventoryClickEvent e, int slot) { return e.getWhoClicked().getOpenInventory().getItem(slot); } 87 | } 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DynamicDifficulty 2 | ## Table of Contents: 3 | #### [About DynamicDifficulty](https://github.com/JeannotM/DynamicDifficulty#about-dynamicdifficulty-1) 4 | #### [Config](https://github.com/JeannotM/DynamicDifficulty#config-1) 5 | #### [calculate-exact-percentage](https://github.com/JeannotM/DynamicDifficulty#calculate-exact-percentage-1) 6 | #### [Commands, Permissions and explanations](https://github.com/JeannotM/DynamicDifficulty#commands-permissions-and-explanations-1) 7 | #### [Plugin Support](https://github.com/JeannotM/DynamicDifficulty#plugin-support-1) 8 | #### [Other Small Things](https://github.com/JeannotM/DynamicDifficulty#other-small-things-1) 9 | #### [Possible Future Updates](https://github.com/JeannotM/DynamicDifficulty#possible-future-updates-1) 10 | 11 | ## About DynamicDifficulty 12 | I made the DynamicDifficulty for 3 reasons. I couldn't find any other DynamicDifficulty plugin for 1.16, the ones I saw from earlier versions weren't that customizable and I wanted experienced and new Minecraft players to be able to play on the same server without having to worry about it being too hard or too easy for them. 13 | 14 | ## Config 15 | You can read the everything about the config here 16 | [Read the config here](https://github.com/JeannotM/DynamicDifficulty/wiki/Config) 17 | 18 | ## calculate-exact-percentage 19 | So if calculate-exact-percentage is disabled the damage chart will look something like this: 20 | ![calculate-exact-percentage-disabled.jpg](docs/calculate-exact-percentage-disabled.jpeg?raw=true "Disabled") 21 | 22 | And if it's enabled it will look like this: 23 | ![calculate-exact-percentage-enabled.jpg](docs/calculate-exact-percentage-enabled.jpeg?raw=true "Enabled") 24 | 25 | I made this a separate option so you can decide yourself if you would like to keep the steep difficulty spikes similar to the world difficulties of Minecraft or if you want the players to feel more immersed in the difficulty changes over time. You won't notice it as much this way and it will keep the players more into the flow as they get better. 26 | If you'd like to read more about the psychology behind it: https://en.wikipedia.org/wiki/Flow_(psychology) 27 | 28 | ## Commands, Permissions and explanations 29 | The Commands aren't case-sensitive, meaning both remove and ReMoVe will result in the same function being executed. Also applies to /aFFinIty. This may not work on player names though 30 | If you want to change the settings of the world you'll need to replace the part with world 31 | ``` 32 | You can also add .other or .self after the permissions to only allow commands for oneself. 33 | affinity.*.self / affinity.*.other is also allowed. 34 | If you don't provide a user in the commands, the player executing the command will be selected 35 | 36 | /Affinity set 37 | perm: affinity.set 38 | The amount of affinity an user will be set to. 39 | 40 | /Affinity get 41 | perm: affinity.get 42 | Get the maximum and current affinity of an user. 43 | 44 | /Affinity add 45 | perm: affinity.add 46 | Adds an amount of affinity to an user. 47 | 48 | /Affinity remove 49 | perm: affinity.remove 50 | Removes an amount of affinity to an user. 51 | 52 | /Affinity delMax 53 | perm: affinity.delmax 54 | Removes the maximum Affinity limit for an user. 55 | 56 | /Affinity setMax 57 | perm: affinity.setmax 58 | Sets a maximum Affinity limit for an user. 59 | 60 | /Affinity delMin 61 | perm: affinity.delmin 62 | Removes the minimum Affinity limit for an user. 63 | 64 | /Affinity setMin 65 | perm: affinity.setmin 66 | Sets a minimum Affinity limit for an user. 67 | 68 | /Affinity author 69 | perm: affinity.author 70 | Mentions DynamicDifficulty, my name and the person who translated the language you selected 71 | 72 | /Affinity difficulties 73 | perm: affinity.difficulties 74 | Shows the difficulties that are currently loaded. 75 | 76 | /Affinity reload 77 | perm: affinity.reload 78 | Reloads the config. 79 | 80 | /Affinity forceSave 81 | perm: affinity.forcesave 82 | Force saves the current data to the yml or database. 83 | 84 | /Affinity playergui 85 | perm: affinity.playergui 86 | Allows you to change all player settings in a chestGUI. 87 | 88 | /Affinity help 89 | perm: affinity.help 90 | Sends all the commands in DD to the player. 91 | 92 | /Affinity info 93 | perm: affinity.info 94 | Returns some info about stuff that was saved or calculated in the app 95 | ``` 96 | ## Plugin Support 97 | #### PlaceholderAPI [[Link](https://www.spigotmc.org/resources/placeholderapi.6245/)] 98 | ``` 99 | %dd_user_difficulty% 100 | - Returns the difficulty of a player. 101 | 102 | %dd_user_progress% 103 | - The progress between this and the next difficulty. 104 | 105 | %dd_user_next_difficulty% 106 | - The next difficulty the user will get. 107 | 108 | %dd_user_affinity% 109 | - Returns the affinity points of a player. 110 | 111 | %dd_user_min_affinity% 112 | - Returns the minimum affinity a user can acquire. 113 | 114 | %dd_user_max_affinity% 115 | - Returns the maximum affinity a user can acquire. 116 | ``` 117 | 118 | ## Other Small Things 119 | Feel free to contact me if you have any idea's that could expand/improve the DynamicDifficulty plugin or have any trouble getting it to work on your server due to errors 120 | - [x] Per player and World difficulties 121 | - [x] Permissions on Luckperms and other management tools (now with .other & .self) 122 | - [x] Custom Affinity points for each mobs and blocks 123 | - [x] Implemented BStats & Placeholder API. 124 | - [x] Disable DD for certain worlds and Mobs 125 | - [x] /reload & /force-save command 126 | - [x] noSaveType, MySQL, SQlite, MongoDB, PostGreSQL support 127 | - [x] Randomize Difficulty mode 128 | - [x] Change player settings with chest GUI 129 | - [x] Stop certain mobs from following players on chosen difficulties 130 | - [x] selector support (@a, @p etc) 131 | - [x] Hunger Drain 132 | - [x] Auto calculate Min Affinity setting 133 | - [x] Mob armor spawn chance 134 | - [x] Block commands per difficulty 135 | - [x] radial difficulty (gets harder the further you get away from spawn) 136 | - [x] per biome difficulty 137 | 138 | ## Possible Future Updates 139 | - [ ] per biome difficulty adjustments (extra) 140 | - [ ] promoted/demoted message 141 | 142 | ## Extra thanks to: 143 | Noiverre - For testing the Papi functions (Because there were a few issues sometimes) 144 | 145 | Mithran - For submitting several idea's and informing me of a lot of issues 146 | 147 | CodedRed - For all the Minecraft plugin videos 148 | 149 | Len76 - For testing Dynamic Difficulty, giving a few idea's and giving some advice regarding performance 150 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/managers/DataManager.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.managers; 2 | 3 | import me.skinnyjeans.gmd.databases.None; 4 | import me.skinnyjeans.gmd.databases.SQL; 5 | import me.skinnyjeans.gmd.models.ISaveManager; 6 | import me.skinnyjeans.gmd.models.Minecrafter; 7 | import org.bukkit.Bukkit; 8 | import org.bukkit.ChatColor; 9 | import org.bukkit.World; 10 | import org.bukkit.configuration.ConfigurationSection; 11 | import org.bukkit.configuration.file.FileConfiguration; 12 | import org.bukkit.configuration.file.YamlConfiguration; 13 | 14 | import java.io.File; 15 | import java.util.*; 16 | 17 | public class DataManager { 18 | 19 | private final MainManager MAIN_MANAGER; 20 | 21 | private final HashSet DISABLED_WORLDS = new HashSet<>(); 22 | 23 | private FileConfiguration language, config, culture; 24 | private ISaveManager DATABASE; 25 | 26 | public DataManager(MainManager mainManager) { 27 | MAIN_MANAGER = mainManager; 28 | 29 | loadConfig(); 30 | 31 | if (!getConfig().getString("version").equals(MAIN_MANAGER.getPlugin().getDescription().getVersion()) || !getConfig().contains("version",true)) 32 | Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[DynamicDifficulty] Your configuration file is not up to date. Please remove it or update it yourself, because I don't know how to do it with Java without deleting existing configs. Sorry :'("); 33 | 34 | try { 35 | String saveType = config.getString("saving-data.type", "file").toLowerCase(); 36 | if(saveType.equals("mysql") || saveType.equals("sqlite") || saveType.equals("postgresql") || saveType.equals("mariadb")){ 37 | DATABASE = new SQL(MAIN_MANAGER.getPlugin(), this, saveType); 38 | } else if(saveType.equals("none")){ 39 | DATABASE = new None(this); 40 | } else DATABASE = new me.skinnyjeans.gmd.databases.File(MAIN_MANAGER.getPlugin(), this); 41 | } catch(Exception e) { 42 | e.printStackTrace(); 43 | Bukkit.getConsoleSender().sendMessage(ChatColor.RED+"[DynamicDifficulty] Can't connect to the database, switching to 'file' mode"); 44 | DATABASE = new me.skinnyjeans.gmd.databases.File(MAIN_MANAGER.getPlugin(), this); 45 | } 46 | } 47 | 48 | public void loadConfig() { 49 | File configFile = new File(MAIN_MANAGER.getPlugin().getDataFolder(), "config.yml"); 50 | File langFile = new File(MAIN_MANAGER.getPlugin().getDataFolder(), "lang.yml"); 51 | language = new YamlConfiguration(); 52 | culture = new YamlConfiguration(); 53 | config = new YamlConfiguration(); 54 | 55 | if (!configFile.exists()) MAIN_MANAGER.getPlugin().saveResource("config.yml", false); 56 | if (!langFile.exists()) MAIN_MANAGER.getPlugin().saveResource("lang.yml", false); 57 | 58 | try { 59 | config.load(configFile); 60 | language.load(langFile); 61 | } catch (Exception e) { e.printStackTrace(); } 62 | 63 | File langDir = new File(MAIN_MANAGER.getPlugin().getDataFolder(), "lang"); 64 | if (! langDir.exists()) langDir.mkdir(); 65 | 66 | String cultureCode = language.getString("culture", "en-US"); 67 | File cultureFile = new File(MAIN_MANAGER.getPlugin().getDataFolder(), "lang/" + cultureCode + ".yml"); 68 | 69 | try { 70 | if(!cultureFile.exists()) 71 | MAIN_MANAGER.getPlugin().saveResource("lang/" + cultureCode + ".yml", false); 72 | } catch (IllegalArgumentException ignored) { 73 | Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[DynamicDifficulty] " + cultureCode + ".yml can not be found, switching to en-US"); 74 | cultureCode = "en-US"; 75 | cultureFile = new File(MAIN_MANAGER.getPlugin().getDataFolder(), "lang/en-US.yml"); 76 | } 77 | 78 | if(!cultureFile.exists()) MAIN_MANAGER.getPlugin().saveResource("lang/" + cultureCode + ".yml", false); 79 | 80 | try { 81 | culture.load(cultureFile); 82 | } catch (Exception e) { e.printStackTrace(); } 83 | 84 | DISABLED_WORLDS.clear(); 85 | List disableWorldList = config.getStringList("worlds.list"); 86 | boolean includeWorlds = config.getString("worlds.type", "exclude").equalsIgnoreCase("include"); 87 | 88 | List worlds = Bukkit.getWorlds(); 89 | for(World world : worlds) { 90 | boolean isInList = disableWorldList.contains(world.getName()); 91 | 92 | if(isInList && !includeWorlds 93 | || !isInList && includeWorlds) { 94 | DISABLED_WORLDS.add(world.getName()); 95 | } 96 | } 97 | } 98 | 99 | public FileConfiguration getConfig() { return config; } 100 | public ConfigurationSection getLang() { return language; } 101 | public ConfigurationSection getCultureLang() { return culture; } 102 | public void batchSave(Collection players) { DATABASE.batchSavePlayers(players); } 103 | public void updatePlayer(UUID uuid) { DATABASE.updatePlayer(MAIN_MANAGER.getPlayerManager().getPlayerAffinity(uuid)); } 104 | public void getAffinityValues(UUID uuid, final ISaveManager.findCallback callback) { DATABASE.getAffinityValues(uuid, callback); } 105 | public void playerExists(UUID uuid, final ISaveManager.findBooleanCallback callback) { DATABASE.playerExists(uuid, callback); } 106 | 107 | public String replaceString(String item, HashMap replaceables) { 108 | for(String key : replaceables.keySet()) item = item.replace(key, replaceables.get(key)); 109 | return ChatColor.translateAlternateColorCodes('&', item); 110 | } 111 | 112 | public String getLanguageString(String item) { 113 | String entry = culture.getString(item); 114 | if(entry == null) return ""; 115 | return ChatColor.translateAlternateColorCodes('&', entry); 116 | } 117 | 118 | public String getLanguageString(String item, boolean isRight) { 119 | String entry = culture.getString(item); 120 | if(entry == null) return ""; 121 | return ChatColor.translateAlternateColorCodes('&', (isRight ? language.getString("command-right-prefix") : language.getString("command-wrong-prefix")) + entry); 122 | } 123 | 124 | public void saveData() { 125 | Bukkit.getScheduler().runTaskAsynchronously(MAIN_MANAGER.getPlugin(), () -> { 126 | Collection players = MAIN_MANAGER.getPlayerManager().getPlayerList().values(); 127 | batchSave(players); 128 | }); 129 | } 130 | 131 | public void reloadConfig() { 132 | MAIN_MANAGER.getPlugin().reloadConfig(); 133 | loadConfig(); 134 | } 135 | 136 | public boolean isWorldDisabled(String worldName) { return DISABLED_WORLDS.contains(worldName); } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/events/EntityHitListener.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.events; 2 | 3 | import me.skinnyjeans.gmd.managers.MainManager; 4 | import me.skinnyjeans.gmd.models.ArmorTypes; 5 | import me.skinnyjeans.gmd.models.BaseListener; 6 | import me.skinnyjeans.gmd.models.Difficulty; 7 | import org.bukkit.Bukkit; 8 | import org.bukkit.Particle; 9 | import org.bukkit.Sound; 10 | import org.bukkit.attribute.Attribute; 11 | import org.bukkit.attribute.AttributeInstance; 12 | import org.bukkit.configuration.file.FileConfiguration; 13 | import org.bukkit.entity.*; 14 | import org.bukkit.event.EventHandler; 15 | import org.bukkit.event.EventPriority; 16 | import org.bukkit.event.entity.EntityDamageByEntityEvent; 17 | import org.bukkit.event.entity.EntityDamageEvent; 18 | import org.bukkit.inventory.ItemStack; 19 | import org.bukkit.potion.PotionEffect; 20 | import org.bukkit.potion.PotionEffectType; 21 | 22 | import java.util.HashMap; 23 | import java.util.Random; 24 | import java.util.UUID; 25 | 26 | public class EntityHitListener extends BaseListener { 27 | 28 | private boolean calculateExtraArmorDamage; 29 | private boolean allowTamedWolves; 30 | private int affinityPerHeart; 31 | private int onPlayerHit; 32 | private String notAttackOthers; 33 | private String notAttackPerson; 34 | 35 | public EntityHitListener(MainManager mainManager) { 36 | MAIN_MANAGER = mainManager; 37 | } 38 | 39 | @EventHandler(priority = EventPriority.LOWEST) 40 | public void onHit(EntityDamageByEntityEvent e) { 41 | Entity prey = e.getEntity(); 42 | if(allowTamedWolves && prey instanceof Wolf) { 43 | AnimalTamer owner = ((Wolf) prey).getOwner(); 44 | 45 | if (owner != null) { prey = (Entity) owner; } 46 | } 47 | 48 | Entity hunter = e.getDamager(); 49 | if (hunter instanceof Projectile && ((Projectile) hunter).getShooter() instanceof Entity) { 50 | hunter = (Entity) ((Projectile) hunter).getShooter(); 51 | } else if (allowTamedWolves && hunter instanceof Wolf) { 52 | AnimalTamer owner = ((Wolf) hunter).getOwner(); 53 | 54 | if (owner != null) { hunter = (Entity) owner; } 55 | } 56 | 57 | if (MAIN_MANAGER.getEntityManager().isEntityIgnored(prey) || MAIN_MANAGER.getEntityManager().isEntityIgnored(hunter)) return; 58 | 59 | if (MAIN_MANAGER.getPlayerManager().isPlayerValid(prey)) { 60 | Player playerPrey = (Player) prey; 61 | if (playerPrey.isBlocking()) return; 62 | 63 | if (MAIN_MANAGER.getPlayerManager().isPlayerValid(hunter)) { 64 | HashMap entry = new HashMap() {{ put("%user%", playerPrey.getDisplayName()); }}; 65 | if (!MAIN_MANAGER.getDifficultyManager().getDifficulty((Player) hunter).allowPVP) { 66 | if(notAttackOthers.length() != 0) prey.sendMessage(MAIN_MANAGER.getDataManager().replaceString(notAttackOthers, entry)); 67 | e.setCancelled(true); 68 | } else if(!MAIN_MANAGER.getDifficultyManager().getDifficulty(playerPrey).allowPVP) { 69 | if(notAttackPerson.length() != 0) prey.sendMessage(MAIN_MANAGER.getDataManager().replaceString(notAttackPerson, entry)); 70 | e.setCancelled(true); 71 | } 72 | } else { 73 | UUID uuid = MAIN_MANAGER.getPlayerManager().determineUuid(playerPrey); 74 | Difficulty difficulty = MAIN_MANAGER.getDifficultyManager().getDifficulty(uuid); 75 | double damage; 76 | if (allowTamedWolves && e.getEntity() instanceof Wolf) { 77 | damage = e.getFinalDamage() 78 | * difficulty.damageDoneOnTamed; 79 | } else { 80 | double damageByArmor = 0; 81 | if(calculateExtraArmorDamage && e.getEntity() instanceof Player) 82 | for(ItemStack x : ((Player) prey).getInventory().getArmorContents()) { 83 | ArmorTypes suit = ArmorTypes.valueOf(x == null ? "NOTHING" : x.getType().toString().split("_")[0].toLowerCase()); 84 | damageByArmor += difficulty.getArmorDamageMultipliers(suit); 85 | } 86 | 87 | boolean isProjectile = e.getCause().equals(EntityDamageEvent.DamageCause.PROJECTILE); 88 | damage = e.getDamage() 89 | * (isProjectile ? difficulty.damageByRangedMobs : difficulty.damageDoneByMobs 90 | + damageByArmor 91 | + difficulty.damagePerArmorPoint); 92 | } 93 | 94 | Bukkit.getScheduler().runTaskAsynchronously(MAIN_MANAGER.getPlugin(), () -> { 95 | int removePoints = damage != 0 96 | ? affinityPerHeart 97 | * (int) Math.ceil(damage / 2) 98 | + (onPlayerHit) 99 | : 0; 100 | MAIN_MANAGER.getPlayerManager().addAffinity(uuid, removePoints); 101 | }); 102 | 103 | if (playerPrey.getHealth() - damage <= 0) 104 | if(new Random().nextDouble() < MAIN_MANAGER.getDifficultyManager() 105 | .getDifficulty(uuid).chanceCancelDeath) { 106 | 107 | // Not able to use something vanilla for Minecraft for this 108 | playerPrey.spawnParticle(Particle.TOTEM_OF_UNDYING, playerPrey.getLocation(), 100); 109 | playerPrey.playSound(playerPrey.getLocation(), Sound.ITEM_TOTEM_USE, 1, 1); 110 | 111 | AttributeInstance health = playerPrey.getAttribute(Attribute.MAX_HEALTH); 112 | playerPrey.setHealth(Math.min(4, health == null ? 4 : health.getValue())); 113 | playerPrey.addPotionEffect(new PotionEffect(PotionEffectType.ABSORPTION, 5 * 20, 1)); 114 | playerPrey.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 45 * 20, 1)); 115 | playerPrey.addPotionEffect(new PotionEffect(PotionEffectType.FIRE_RESISTANCE, 40 * 20, 0)); 116 | 117 | e.setCancelled(true); 118 | } 119 | 120 | e.setDamage(damage); 121 | } 122 | } else if (MAIN_MANAGER.getPlayerManager().isPlayerValid(hunter)) { 123 | UUID uuid = MAIN_MANAGER.getPlayerManager().determineUuid((Player) hunter); 124 | MAIN_MANAGER.getEntityManager().entityHit(prey); 125 | e.setDamage(e.getFinalDamage() 126 | * MAIN_MANAGER.getDifficultyManager().getDifficulty(uuid).damageDoneOnMobs); 127 | } 128 | } 129 | 130 | @Override 131 | public void reloadConfig() { 132 | FileConfiguration config = MAIN_MANAGER.getDataManager().getConfig(); 133 | 134 | calculateExtraArmorDamage = false; 135 | allowTamedWolves = config.getBoolean("toggle-settings.allow-tamed-wolves-in-calculations", true); 136 | affinityPerHeart = config.getInt("affinity-per-heart-loss", -1); 137 | onPlayerHit = config.getInt("player-hit", -1); 138 | 139 | notAttackOthers = MAIN_MANAGER.getDataManager().getLanguageString("in-game.attacker-no-pvp", false); 140 | notAttackPerson = MAIN_MANAGER.getDataManager().getLanguageString("in-game.attackee-no-pvp", false); 141 | 142 | for(Difficulty difficulty : MAIN_MANAGER.getDifficultyManager().getDifficulties()) 143 | if (difficulty.armorDamageMultipliers.size() != 0) { 144 | calculateExtraArmorDamage = true; 145 | break; 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/databases/SQL.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.databases; 2 | 3 | import me.skinnyjeans.gmd.Main; 4 | import me.skinnyjeans.gmd.managers.DataManager; 5 | import me.skinnyjeans.gmd.models.ISaveManager; 6 | import me.skinnyjeans.gmd.models.Minecrafter; 7 | import org.bukkit.Bukkit; 8 | 9 | import java.sql.*; 10 | import java.util.Collection; 11 | import java.util.UUID; 12 | 13 | public class SQL implements ISaveManager { 14 | private final String tbName = "dynamicdifficulty"; 15 | private final Main plugin; 16 | private final String host, port; 17 | private final String user, pwd; 18 | private final String dbName, saveType; 19 | private Connection connection = null; 20 | 21 | public SQL(Main m, DataManager data, String sT) throws SQLException, ClassNotFoundException { 22 | plugin = m; 23 | host = data.getConfig().getString("saving-data.host"); 24 | port = data.getConfig().getString("saving-data.port"); 25 | dbName = data.getConfig().getString("saving-data.database"); 26 | user = data.getConfig().getString("saving-data.username", "root"); 27 | pwd = data.getConfig().getString("saving-data.password", ""); 28 | saveType = sT.toLowerCase(); 29 | connect(data); 30 | createTable(); 31 | } 32 | 33 | public boolean isConnected() { return connection != null; } 34 | 35 | public void connect(DataManager d) throws SQLException, ClassNotFoundException { 36 | String database = ""; 37 | if(!isConnected()) { 38 | Class.forName("com.mysql.jdbc.Driver"); 39 | if(saveType.equals("mysql")) { 40 | connection = DriverManager.getConnection("jdbc:mysql://" + host + ":" + port + "/" + dbName + "?useSSL=false&autoReconnect=true" + 41 | "&useUnicode=yes&cachePrepStmts=true&useServerPrepStmts=true&maxReconnects=5&initialTimeout=2", user, pwd); 42 | database = "MySQL"; 43 | } else if (saveType.equals("sqlite")){ 44 | connection = DriverManager.getConnection("jdbc:sqlite:plugins/DynamicDifficulty/data.db"); 45 | database = "SQLite"; 46 | } else if (saveType.equals("postgresql")) { 47 | Class.forName("org.postgresql.Driver"); 48 | connection = DriverManager.getConnection("jdbc:postgresql://"+host+":"+port+"/"+dbName+"?autoReconnect=true&useUnicode=yes" + 49 | "&cachePrepStmts=true&useServerPrepStmts=true&maxReconnects=5&initialTimeout=2", user, pwd); 50 | database = "PostGreSQL"; 51 | } else if (saveType.equals("mariadb")) { 52 | Class.forName("org.mariadb.jdbc.Driver"); 53 | connection = DriverManager.getConnection("jdbc:mariadb://"+host+":"+port+"/"+dbName+"?autoReconnect=true&useUnicode=yes" + 54 | "&cachePrepStmts=true&useServerPrepStmts=true&maxReconnects=5&initialTimeout=2", user, pwd); 55 | database = "MariaDB"; 56 | } 57 | } 58 | Bukkit.getConsoleSender().sendMessage("[DynamicDifficulty] " + d.getLanguageString("other.database-chosen").replace("%database%", database)); 59 | } 60 | 61 | public void createTable() { 62 | Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { 63 | try { 64 | if(isConnected()) { 65 | PreparedStatement ps = connection.prepareStatement("CREATE TABLE IF NOT EXISTS "+tbName+" "+ 66 | "(UUID VARCHAR(60)," + 67 | "Name VARCHAR(20), " + 68 | "Affinity INT DEFAULT 500, " + 69 | "MaxAffinity INT DEFAULT -1, " + 70 | "MinAffinity INT DEFAULT -1, " + 71 | "PRIMARY KEY(UUID))"); 72 | ps.execute(); 73 | ps.close(); 74 | } 75 | } catch(SQLException e) { e.printStackTrace(); } 76 | }); 77 | } 78 | 79 | @Override 80 | public void updatePlayer(Minecrafter playerData) { 81 | playerExists(playerData.uuid, r -> { 82 | try { 83 | if(isConnected()) { 84 | PreparedStatement ps; 85 | if(r) { 86 | ps = connection.prepareStatement("UPDATE "+tbName+" SET Affinity=?, MaxAffinity=?, MinAffinity=? WHERE UUID=?"); 87 | } else { 88 | ps = connection.prepareStatement("INSERT INTO "+tbName+" (Affinity, MaxAffinity, MinAffinity, UUID, Name) VALUES (?, ?, ?, ?, ?)"); 89 | ps.setString(5, playerData.name); 90 | } 91 | ps.setInt(1, playerData.affinity); 92 | ps.setInt(2, playerData.maxAffinity); 93 | ps.setInt(3, playerData.minAffinity); 94 | ps.setString(4, playerData.uuid.toString()); 95 | ps.executeUpdate(); 96 | ps.close(); 97 | } 98 | } catch(SQLException e) { e.printStackTrace(); } 99 | }); 100 | } 101 | 102 | @Override 103 | public void batchSavePlayers(Collection players) { 104 | Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { 105 | try { 106 | PreparedStatement ps = connection.prepareStatement("UPDATE "+tbName+" SET Affinity=?, MaxAffinity=?, MinAffinity=? WHERE UUID=?");; 107 | for (Minecrafter playerData : players) { 108 | ps.setInt(1, playerData.affinity); 109 | ps.setInt(2, playerData.maxAffinity); 110 | ps.setInt(3, playerData.minAffinity); 111 | ps.setString(4, playerData.uuid.toString()); 112 | ps.addBatch(); 113 | } 114 | ps.executeBatch(); 115 | ps.close(); 116 | } catch(SQLException e) { e.printStackTrace(); } 117 | }); 118 | 119 | } 120 | 121 | @Override 122 | public void getAffinityValues(UUID uuid, findCallback callback) { 123 | Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { 124 | try { 125 | if(isConnected()) { 126 | PreparedStatement ps = connection.prepareStatement("SELECT Affinity, MaxAffinity, MinAffinity, Name FROM "+tbName+" WHERE UUID=?"); 127 | ps.setString(1, uuid.toString()); 128 | ResultSet result = ps.executeQuery(); 129 | if(result.next()) { 130 | Minecrafter data = new Minecrafter(); 131 | 132 | data.uuid = uuid; 133 | data.name = result.getString("Name"); 134 | data.affinity = result.getInt("Affinity"); 135 | data.maxAffinity = result.getInt("MaxAffinity"); 136 | data.minAffinity = result.getInt("MinAffinity"); 137 | callback.onQueryDone(data); 138 | ps.close(); 139 | return; 140 | } 141 | ps.close(); 142 | } 143 | } catch(SQLException e) { e.printStackTrace(); } 144 | callback.onQueryDone(null); 145 | }); 146 | } 147 | 148 | @Override 149 | public void playerExists(UUID uuid, final findBooleanCallback callback) { 150 | Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { 151 | try { 152 | if(isConnected()) { 153 | PreparedStatement ps = connection.prepareStatement("SELECT Name FROM "+tbName+" WHERE UUID=?"); 154 | ps.setString(1, uuid.toString()); 155 | ResultSet result = ps.executeQuery(); 156 | if(result.next()){ 157 | callback.onQueryDone(true); 158 | return; 159 | } 160 | ps.close(); 161 | } 162 | } catch(SQLException e) { e.printStackTrace(); } 163 | callback.onQueryDone(false); 164 | }); 165 | } 166 | 167 | @Override 168 | public void disconnect() throws SQLException { 169 | if(isConnected()) 170 | connection.close(); 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/managers/InventoryManager.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.managers; 2 | 3 | import me.skinnyjeans.gmd.models.Difficulty; 4 | import me.skinnyjeans.gmd.models.Minecrafter; 5 | import me.skinnyjeans.gmd.utils.Formatter; 6 | import me.skinnyjeans.gmd.utils.StaticInfo; 7 | import org.bukkit.Bukkit; 8 | import org.bukkit.Material; 9 | import org.bukkit.entity.Player; 10 | import org.bukkit.inventory.Inventory; 11 | import org.bukkit.inventory.ItemStack; 12 | import org.bukkit.inventory.meta.ItemMeta; 13 | import org.bukkit.inventory.meta.SkullMeta; 14 | 15 | import java.util.Arrays; 16 | import java.util.HashMap; 17 | import java.util.List; 18 | import java.util.UUID; 19 | 20 | public class InventoryManager { 21 | 22 | private final MainManager MAIN_MANAGER; 23 | 24 | private Inventory difficultyInventory; 25 | private HashMap difficultyInventories = new HashMap(); 26 | private Inventory baseInventory; 27 | private Inventory basePlayerInventory; 28 | private String affinity, minAffinity, maxAffinity; 29 | 30 | private final HashMap MATERIAL_NAMES = new HashMap(){{ 31 | put(Material.GOLD_INGOT, "Next Page >"); 32 | put(Material.IRON_INGOT, "< Previous Page"); 33 | put(Material.RED_WOOL, "Reset Affinity"); 34 | put(Material.IRON_CHESTPLATE, "Current Page: %number%"); 35 | put(Material.PINK_WOOL, "-100"); 36 | put(Material.MAGENTA_WOOL, "-10"); 37 | put(Material.PURPLE_WOOL, "-1"); 38 | put(Material.BLUE_WOOL, "+1"); 39 | put(Material.CYAN_WOOL, "+10"); 40 | put(Material.LIGHT_BLUE_WOOL, "+100"); 41 | }}; 42 | 43 | private static final HashMap INVENTORY_SLOTS = new HashMap(){{ 44 | put(1, Material.PINK_WOOL); 45 | put(2, Material.MAGENTA_WOOL); 46 | put(3, Material.PURPLE_WOOL); 47 | put(5, Material.BLUE_WOOL); 48 | put(6, Material.CYAN_WOOL); 49 | put(7, Material.LIGHT_BLUE_WOOL); 50 | }}; 51 | 52 | public InventoryManager(MainManager mainManager) { MAIN_MANAGER = mainManager; } 53 | 54 | public void createBaseInventory() { 55 | Inventory inventory = Bukkit.createInventory(null, 54, StaticInfo.PLAYERS_INVENTORY); 56 | ItemStack prevPage = createItem(Material.IRON_INGOT); 57 | ItemStack currentPage = createItem(Material.IRON_CHESTPLATE); 58 | ItemStack nextPage = createItem(Material.GOLD_INGOT); 59 | 60 | inventory.setItem(3, prevPage); 61 | inventory.setItem(4, currentPage); 62 | inventory.setItem(5, nextPage); 63 | 64 | baseInventory = inventory; 65 | } 66 | 67 | public void createBasePlayerInventory() { 68 | Inventory inventory = Bukkit.createInventory(null, 36, StaticInfo.INDIVIDUAL_PLAYER_INVENTORY); 69 | 70 | for(int i = 9; i < 36; i++) 71 | if(INVENTORY_SLOTS.containsKey(i % 9)) 72 | inventory.setItem(i, createItem(INVENTORY_SLOTS.get(i % 9))); 73 | 74 | inventory.setItem(3, createItem(Material.IRON_INGOT)); 75 | inventory.setItem(5, createItem(Material.RED_WOOL)); 76 | 77 | basePlayerInventory = inventory; 78 | } 79 | 80 | public void createDifficultiesInventory() { 81 | difficultyInventory = Bukkit.createInventory(null, 54, StaticInfo.DIFFICULTIES_INVENTORY); 82 | int i = 0; 83 | 84 | List difficulties = MAIN_MANAGER.getDifficultyManager().getDifficultyNames(); 85 | for(String name : difficulties) { 86 | Difficulty difficulty = MAIN_MANAGER.getDifficultyManager().getDifficulty(name); 87 | if (i >= 53) break; 88 | difficultyInventory.setItem(i++, createDifficultyPlayerHead("&r" + difficulty.getDifficultyName(), difficulty.getAffinity())); 89 | Inventory inventory = Bukkit.createInventory(null, 36, StaticInfo.DIFFICULTY_INVENTORY); 90 | createInventory(difficulty, inventory); 91 | difficultyInventories.put(difficulty.getDifficultyName(), inventory); 92 | } 93 | } 94 | 95 | public void createInventory(Difficulty difficulty, Inventory inventory) { 96 | inventory.setItem(0, createDifficultyPlayerHead(MAIN_MANAGER.getDataManager().getLanguageString("command.player-gui.previous-page"))); 97 | inventory.setItem(4, createDifficultyPlayerHead("Name", difficulty.difficultyName)); 98 | inventory.setItem(9, createDifficultyPlayerHead("Prefix", difficulty.prefix)); 99 | inventory.setItem(10, createDifficultyPlayerHead("Affinity Required", difficulty.affinityRequirement)); 100 | inventory.setItem(11, createDifficultyPlayerHead("Damage Done By Mobs", difficulty.damageDoneByMobs)); 101 | inventory.setItem(12, createDifficultyPlayerHead("Damage Done On Mobs", difficulty.damageDoneOnMobs)); 102 | inventory.setItem(13, createDifficultyPlayerHead("Damage Done On Tamed", difficulty.damageDoneOnTamed)); 103 | inventory.setItem(14, createDifficultyPlayerHead("Experience Multiplier", difficulty.experienceMultiplier)); 104 | inventory.setItem(15, createDifficultyPlayerHead("Hunger Drain", difficulty.hungerDrainChance)); 105 | inventory.setItem(16, createDifficultyPlayerHead("Double Loot Chance", difficulty.doubleLootChance)); 106 | inventory.setItem(17, createDifficultyPlayerHead("Max Enchants", difficulty.maxEnchants)); 107 | inventory.setItem(18, createDifficultyPlayerHead("Max Enchant Level", difficulty.maxEnchantLevel)); 108 | inventory.setItem(19, createDifficultyPlayerHead("Damage Done By Ranged", difficulty.damageByRangedMobs)); 109 | inventory.setItem(20, createDifficultyPlayerHead("Double Durability Damage Chance", difficulty.doubleDurabilityDamageChance)); 110 | inventory.setItem(21, createDifficultyPlayerHead("Armor Damage Multiplier", difficulty.armorDamageMultipliers.values())); 111 | inventory.setItem(22, createDifficultyPlayerHead("PVP Allowed", difficulty.allowPVP)); 112 | inventory.setItem(23, createDifficultyPlayerHead("Keep Inventory", difficulty.keepInventory)); 113 | inventory.setItem(24, createDifficultyPlayerHead("Health Regen", difficulty.allowHealthRegen)); 114 | inventory.setItem(25, createDifficultyPlayerHead("Effects When Attacked", difficulty.effectsWhenAttacked)); 115 | inventory.setItem(26, createDifficultyPlayerHead("Armor Drop Chance", difficulty.armorDropChance)); 116 | inventory.setItem(27, createDifficultyPlayerHead("Armor Enchant Chance", difficulty.armorChance)); 117 | inventory.setItem(28, createDifficultyPlayerHead("Armor Chance For Mobs", difficulty.chanceToHaveArmor)); 118 | inventory.setItem(29, createDifficultyPlayerHead("Weapon Drop Chance", difficulty.chanceToHaveWeapon)); 119 | inventory.setItem(30, createDifficultyPlayerHead("Ignored Mobs", difficulty.mobsIgnoredPlayers)); 120 | inventory.setItem(31, createDifficultyPlayerHead("Disabled Commands", difficulty.disabledCommands)); 121 | inventory.setItem(32, createDifficultyPlayerHead("Enchant Chances", difficulty.chanceToEnchant)); 122 | } 123 | 124 | public ItemStack createDifficultyPlayerHead(String name, Object ...values) { 125 | ItemStack item = new ItemStack(Material.PLAYER_HEAD); 126 | ItemMeta meta = item.getItemMeta(); 127 | 128 | if(meta == null) return item; 129 | meta.setDisplayName(Formatter.format("&f&l" + name)); 130 | meta.setLore(Formatter.list(values)); 131 | item.setItemMeta(meta); 132 | return item; 133 | } 134 | 135 | public void openDifficultyInventory(Player player, String difficulty) { 136 | if (difficultyInventories.containsKey(difficulty)) 137 | player.openInventory(difficultyInventories.get(difficulty)); 138 | } 139 | public void openBaseDifficultyInventory(Player player) { player.openInventory(difficultyInventory); } 140 | public void openInventory(Player player, int page) { 141 | Bukkit.getScheduler().runTaskAsynchronously(MAIN_MANAGER.getPlugin(), () -> { 142 | Inventory inventory = Bukkit.createInventory(null, 54, StaticInfo.PLAYERS_INVENTORY); 143 | inventory.setContents(baseInventory.getContents()); 144 | 145 | Minecrafter[] players = MAIN_MANAGER.getPlayerManager().getPlayerList().values().toArray(new Minecrafter[0]); 146 | int iterator = (page - 1) * 45; 147 | if(players.length - iterator <= 0) return; 148 | 149 | ItemMeta itemMeta = inventory.getItem(4).getItemMeta(); 150 | itemMeta.setDisplayName(itemMeta.getDisplayName().replace("%number%", String.valueOf(page))); 151 | inventory.getItem(4).setItemMeta(itemMeta); 152 | for(int i = 0; i < 45; i++) { 153 | Minecrafter pl = iterator + i < players.length ? players[iterator + i] : null; 154 | inventory.setItem(i + 9, pl != null ? createPlayerHead(pl) : null); 155 | } 156 | 157 | Bukkit.getScheduler().runTask(MAIN_MANAGER.getPlugin(), () -> 158 | player.openInventory(inventory)); 159 | }); 160 | } 161 | 162 | public void openPlayerInventory(Player player, UUID uuid) { 163 | Inventory inventory = basePlayerInventory; 164 | inventory.setItem(4, createPlayerHead(uuid)); 165 | player.openInventory(inventory); 166 | } 167 | 168 | public void updatePlayerInventory(Player player, UUID uuid) { 169 | player.getOpenInventory().setItem(4, createPlayerHead(uuid)); 170 | } 171 | 172 | public ItemStack createPlayerHead(UUID uuid) { return createPlayerHead(MAIN_MANAGER.getPlayerManager().getPlayerAffinity(uuid)); } 173 | public ItemStack createPlayerHead(Minecrafter data) { 174 | ItemStack item = new ItemStack(Material.PLAYER_HEAD); 175 | SkullMeta meta = (SkullMeta) item.getItemMeta(); 176 | meta.setDisplayName(data.name); 177 | try { meta.setOwningPlayer(Bukkit.getOfflinePlayer(data.uuid)); 178 | } catch (Exception ignored) { } 179 | meta.setLore(Arrays.asList( 180 | data.uuid.toString(), 181 | affinity.replace("%number%", String.valueOf(data.affinity)), 182 | minAffinity.replace("%number%", String.valueOf(data.minAffinity)), 183 | maxAffinity.replace("%number%", String.valueOf(data.maxAffinity)) 184 | )); 185 | item.setItemMeta(meta); 186 | return item; 187 | } 188 | 189 | public ItemStack createItem(Material type) { 190 | ItemStack item = new ItemStack(type); 191 | if(MATERIAL_NAMES.containsKey(type)) { 192 | ItemMeta meta = item.getItemMeta(); 193 | meta.setDisplayName(MATERIAL_NAMES.get(type)); 194 | item.setItemMeta(meta); 195 | } 196 | return item; 197 | } 198 | 199 | public void reloadConfig() { 200 | MATERIAL_NAMES.put(Material.GOLD_INGOT, MAIN_MANAGER.getDataManager().getLanguageString("command.player-gui.next-page")); 201 | MATERIAL_NAMES.put(Material.RED_WOOL, MAIN_MANAGER.getDataManager().getLanguageString("command.player-gui.reset-values")); 202 | MATERIAL_NAMES.put(Material.IRON_INGOT, MAIN_MANAGER.getDataManager().getLanguageString("command.player-gui.previous-page")); 203 | MATERIAL_NAMES.put(Material.IRON_CHESTPLATE, MAIN_MANAGER.getDataManager().getLanguageString("command.player-gui.current-page")); 204 | 205 | affinity = MAIN_MANAGER.getDataManager().getLanguageString("command.player-gui.affinity"); 206 | minAffinity = MAIN_MANAGER.getDataManager().getLanguageString("command.player-gui.min-affinity"); 207 | maxAffinity = MAIN_MANAGER.getDataManager().getLanguageString("command.player-gui.max-affinity"); 208 | 209 | createBaseInventory(); 210 | createBasePlayerInventory(); 211 | createDifficultiesInventory(); 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/managers/PlayerManager.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.managers; 2 | 3 | import me.skinnyjeans.gmd.models.*; 4 | import org.bukkit.Bukkit; 5 | import org.bukkit.NamespacedKey; 6 | import org.bukkit.World; 7 | import org.bukkit.block.Biome; 8 | import org.bukkit.configuration.file.FileConfiguration; 9 | import org.bukkit.entity.Entity; 10 | import org.bukkit.entity.Player; 11 | 12 | import java.lang.reflect.Field; 13 | import java.util.EnumSet; 14 | import java.util.HashMap; 15 | import java.util.List; 16 | import java.util.UUID; 17 | 18 | public class PlayerManager { 19 | 20 | private final MainManager MAIN_MANAGER; 21 | private final HashMap PLAYER_LIST = new HashMap(); 22 | private final HashMap NAME_TO_UUID = new HashMap(); 23 | private final static EnumSet DONT_ADD_PLAYER = EnumSet.of(DifficultyTypes.biome, DifficultyTypes.world); 24 | private DifficultySettings difficultySettings; 25 | 26 | private int maxAffinityGainPerMinute, maxAffinityLossPerMinute, intervalAffinity, serverMaxAffinity, serverMinAffinity; 27 | private DifficultyTypes difficultyType; 28 | private Minecrafter defaultData; 29 | 30 | public PlayerManager(MainManager mainManager) { 31 | MAIN_MANAGER = mainManager; 32 | 33 | Bukkit.getScheduler().runTaskTimerAsynchronously(MAIN_MANAGER.getPlugin(), () -> { 34 | if (Bukkit.getOnlinePlayers().isEmpty()) { return; } 35 | 36 | for (Minecrafter data : PLAYER_LIST.values()) { 37 | addAffinity(data.uuid, intervalAffinity); 38 | data.gainedThisMinute = 0; 39 | } 40 | }, 20 * 5, 20 * 60); 41 | 42 | Bukkit.getScheduler().runTaskTimerAsynchronously(MAIN_MANAGER.getPlugin(), () -> { 43 | if (Bukkit.getOnlinePlayers().isEmpty()) { return; } 44 | 45 | MAIN_MANAGER.getDataManager().saveData(); 46 | }, 20 * 5, 20 * 60 * 5); 47 | } 48 | 49 | public int withinServerLimits(int value) { 50 | return Math.max(serverMinAffinity, Math.min(value, serverMaxAffinity)); } 51 | public int withinPlayerLimits(UUID uuid, int value) { 52 | Minecrafter data = getPlayerAffinity(uuid); 53 | value = withinServerLimits(value); 54 | 55 | if(data.minAffinity != -1) value = Math.max(data.minAffinity, value); 56 | if(data.maxAffinity != -1) value = Math.min(data.maxAffinity, value); 57 | 58 | return value; 59 | } 60 | 61 | public void resetAffinity(UUID uuid) { 62 | setMinAffinity(uuid, defaultData.minAffinity); 63 | setMaxAffinity(uuid, defaultData.maxAffinity); 64 | setAffinity(uuid, defaultData.affinity); 65 | } 66 | 67 | public void addPlayer(Entity player) { 68 | if(DifficultyTypes.player == difficultyType) { 69 | MAIN_MANAGER.getDataManager().getAffinityValues(player.getUniqueId(), playerData -> { 70 | NAME_TO_UUID.put(player.getName(), player.getUniqueId()); 71 | if (playerData != null) { 72 | PLAYER_LIST.put(player.getUniqueId(), playerData); 73 | MAIN_MANAGER.getDifficultyManager().calculateDifficulty(player.getUniqueId()); 74 | } else { 75 | playerData = defaultData.clone(); 76 | playerData.name = player.getName(); 77 | playerData.uuid = player.getUniqueId(); 78 | PLAYER_LIST.put(player.getUniqueId(), playerData); 79 | MAIN_MANAGER.getDataManager().updatePlayer(player.getUniqueId()); 80 | MAIN_MANAGER.getDifficultyManager().calculateDifficulty(player.getUniqueId()); 81 | } 82 | }); 83 | } else { 84 | Minecrafter playerData = defaultData.clone(); 85 | playerData.name = player.getName(); 86 | playerData.uuid = player.getUniqueId(); 87 | if (DifficultyTypes.region == difficultyType || DifficultyTypes.time == difficultyType) { 88 | playerData.affinity = difficultySettings.calculateAffinity((Player) player, -1); } 89 | PLAYER_LIST.put(player.getUniqueId(), playerData); 90 | MAIN_MANAGER.getDifficultyManager().calculateDifficulty(player.getUniqueId()); 91 | } 92 | } 93 | 94 | public boolean isPlayerValid(Entity player) { 95 | if(!(player instanceof Player)) return false; 96 | if(player.hasMetadata("NPC")) return false; 97 | if(MAIN_MANAGER.getDataManager().isWorldDisabled(player.getWorld().getName())) return false; 98 | if(!DONT_ADD_PLAYER.contains(difficultyType) && !PLAYER_LIST.containsKey(player.getUniqueId())) addPlayer(player); 99 | return true; 100 | } 101 | 102 | public boolean isPlayerValidNoWorld(Entity player) { 103 | if(!(player instanceof Player)) return false; 104 | if(player.hasMetadata("NPC")) return false; 105 | if(!DONT_ADD_PLAYER.contains(difficultyType) && !PLAYER_LIST.containsKey(player.getUniqueId())) addPlayer(player); 106 | return true; 107 | } 108 | 109 | public void unloadPlayer(Player player) { 110 | UUID uuid = player.getUniqueId(); 111 | if (PLAYER_LIST.containsKey(uuid)) { 112 | NAME_TO_UUID.remove(player.getName().toLowerCase()); 113 | MAIN_MANAGER.getDataManager().updatePlayer(uuid); 114 | PLAYER_LIST.remove(uuid); 115 | } 116 | } 117 | public HashMap getPlayerList() { return PLAYER_LIST; } 118 | public boolean hasPlayer(String name) { return NAME_TO_UUID.containsKey(name.toLowerCase()); } 119 | 120 | public Minecrafter getPlayerAffinity(String name) { return PLAYER_LIST.get( NAME_TO_UUID.get(name.toLowerCase()) ); } 121 | public Minecrafter getPlayerAffinity(Player player) { return PLAYER_LIST.get( determineUuid(player) ); } 122 | public Minecrafter getPlayerAffinity(UUID uuid) { return PLAYER_LIST.get( uuid ); } 123 | 124 | public String determineName(Player player) { 125 | if (DifficultyTypes.biome == difficultyType) { 126 | return player.getWorld().getBiome(player.getLocation()).toString(); 127 | } 128 | 129 | if (DifficultyTypes.world == difficultyType) { 130 | return player.getWorld().getName(); 131 | } 132 | 133 | return player.getName(); 134 | } 135 | 136 | public UUID determineUuid(Player player) { 137 | if (DifficultyTypes.world == difficultyType) { 138 | return player.getWorld().getUID(); 139 | } 140 | 141 | if (DifficultyTypes.biome == difficultyType) { 142 | String biome = NamespacedKey.minecraft(String.valueOf(player.getLocation().getBlock().getBiome()).toLowerCase()).getKey(); 143 | return UUID.nameUUIDFromBytes(biome.getBytes()); 144 | } 145 | 146 | if (player != null) { 147 | return player.getUniqueId(); 148 | } 149 | 150 | return null; 151 | } 152 | 153 | public void addAffinity(Player player, int value) { 154 | if (value == 0) { return; } 155 | 156 | if(DifficultyTypes.region == difficultyType || DifficultyTypes.time == difficultyType) { 157 | setAffinity(determineUuid(player), difficultySettings.calculateAffinity(player, -1)); 158 | return; 159 | } 160 | 161 | addAffinity(determineUuid(player), value); 162 | } 163 | 164 | public int addAffinity(UUID uuid, int value) { 165 | if (value == 0) { return value; } 166 | 167 | Minecrafter data = PLAYER_LIST.get(uuid); 168 | boolean ignoreTheCap = value > maxAffinityGainPerMinute || value < maxAffinityLossPerMinute; 169 | 170 | if (!ignoreTheCap) { 171 | if (value > 0) { 172 | if (data.gainedThisMinute + value > maxAffinityGainPerMinute) { 173 | value = maxAffinityGainPerMinute - data.gainedThisMinute; 174 | } 175 | } else if (data.gainedThisMinute + value < maxAffinityLossPerMinute) { 176 | value = maxAffinityLossPerMinute - data.gainedThisMinute; 177 | } 178 | 179 | data.gainedThisMinute += value; 180 | } 181 | 182 | return setAffinity(uuid, data.affinity + value); 183 | } 184 | 185 | public void addMinAffinity(UUID uuid, int value) { 186 | if (value == 0) { return; } 187 | Minecrafter data = getPlayerAffinity(uuid); 188 | setMinAffinity(uuid, (data.minAffinity == -1 ? 1 : 0) + data.minAffinity + value); 189 | } 190 | 191 | public void addMaxAffinity(UUID uuid, int value) { 192 | if (value == 0) { return; } 193 | Minecrafter data = getPlayerAffinity(uuid); 194 | setMaxAffinity(uuid, (data.maxAffinity == -1 ? 1 : 0) + data.maxAffinity + value); 195 | } 196 | 197 | public int setAffinity(UUID uuid, int value) { 198 | value = withinPlayerLimits(uuid, value); 199 | getPlayerAffinity(uuid).affinity = value; 200 | return value; 201 | } 202 | 203 | public int setMinAffinity(UUID uuid, int value) { 204 | Minecrafter player = getPlayerAffinity(uuid); 205 | if(value != -1) { 206 | value = withinServerLimits(value); 207 | if(player.maxAffinity != -1) 208 | value = Math.min(player.maxAffinity, value); 209 | } 210 | player.minAffinity = value; 211 | return value; 212 | } 213 | 214 | public int setMaxAffinity(UUID uuid, int value) { 215 | Minecrafter player = getPlayerAffinity(uuid); 216 | if(value != -1) { 217 | value = withinServerLimits(value); 218 | if(player.minAffinity != -1) 219 | value = Math.max(player.minAffinity, value); 220 | } 221 | player.maxAffinity = value; 222 | return value; 223 | } 224 | 225 | public void reloadConfig() { 226 | FileConfiguration config = MAIN_MANAGER.getDataManager().getConfig(); 227 | maxAffinityGainPerMinute = config.getInt("max-affinity-gain-per-minute", 0); 228 | maxAffinityLossPerMinute = config.getInt("max-affinity-loss-per-minute", 0); 229 | String type = (config.getString("toggle-settings.difficulty-type", "player")).toLowerCase(); 230 | 231 | serverMinAffinity = config.getInt("min-affinity", 0); 232 | serverMaxAffinity = config.getInt("max-affinity", 1500); 233 | intervalAffinity = config.getInt("points-per-minute", 3); 234 | 235 | defaultData = new Minecrafter(); 236 | defaultData.affinity = config.getInt("starting-affinity", 600); 237 | defaultData.minAffinity = config.getInt("starting-min-affinity", -1); 238 | defaultData.maxAffinity = config.getInt("starting-max-affinity", -1); 239 | 240 | try { 241 | difficultyType = DifficultyTypes.valueOf(type); 242 | } catch (IllegalArgumentException ignored) { 243 | difficultyType = DifficultyTypes.player; 244 | } 245 | 246 | if(difficultyType == DifficultyTypes.region) { 247 | difficultySettings = new RegionSettings(MAIN_MANAGER); 248 | } else if (difficultyType == DifficultyTypes.world) { 249 | List worlds = Bukkit.getWorlds(); 250 | for (World world : worlds) { 251 | UUID uuid = world.getUID(); 252 | MAIN_MANAGER.getDataManager().getAffinityValues(uuid, (value) -> { 253 | NAME_TO_UUID.put(world.getName(), uuid); 254 | if (value != null) { 255 | PLAYER_LIST.put(uuid, value); 256 | } else { 257 | Minecrafter playerData = defaultData.clone(); 258 | playerData.name = world.getName(); 259 | playerData.uuid = uuid; 260 | PLAYER_LIST.put(uuid, playerData); 261 | MAIN_MANAGER.getDifficultyManager().calculateDifficulty(uuid); 262 | } 263 | }); 264 | } 265 | } else if (difficultyType == DifficultyTypes.time) { 266 | difficultySettings = new TimeSettings(MAIN_MANAGER); 267 | } else if (difficultyType == DifficultyTypes.biome) { 268 | Field[] fields = Biome.class.getFields(); 269 | 270 | for (Field field : fields) { 271 | if (field.getType() != Biome.class) { continue; } 272 | 273 | String biomeName = field.getName(); 274 | String key = NamespacedKey.minecraft(biomeName.toLowerCase()).getKey(); 275 | UUID uuid = UUID.nameUUIDFromBytes(key.getBytes()); 276 | MAIN_MANAGER.getDataManager().getAffinityValues(uuid, (value) -> { 277 | NAME_TO_UUID.put(key, uuid); 278 | if (value != null) { 279 | PLAYER_LIST.put(uuid, value); 280 | } else { 281 | Minecrafter playerData = defaultData.clone(); 282 | playerData.name = key; 283 | playerData.uuid = uuid; 284 | PLAYER_LIST.put(uuid, playerData); 285 | MAIN_MANAGER.getDifficultyManager().calculateDifficulty(playerData); 286 | } 287 | }); 288 | } 289 | } 290 | } 291 | } 292 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/events/MobSpawnListener.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.events; 2 | 3 | import io.lumine.mythic.api.mobs.MythicMob; 4 | import io.lumine.mythic.bukkit.BukkitAdapter; 5 | import io.lumine.mythic.bukkit.MythicBukkit; 6 | import me.skinnyjeans.gmd.managers.MainManager; 7 | import me.skinnyjeans.gmd.models.BaseListener; 8 | import me.skinnyjeans.gmd.models.Difficulty; 9 | import me.skinnyjeans.gmd.models.EquipmentItems; 10 | import me.skinnyjeans.gmd.models.MythicMobProfile; 11 | import org.bukkit.Bukkit; 12 | import org.bukkit.Location; 13 | import org.bukkit.Material; 14 | import org.bukkit.NamespacedKey; 15 | import org.bukkit.configuration.ConfigurationSection; 16 | import org.bukkit.configuration.file.FileConfiguration; 17 | import org.bukkit.enchantments.Enchantment; 18 | import org.bukkit.entity.EntityType; 19 | import org.bukkit.entity.Player; 20 | import org.bukkit.event.EventHandler; 21 | import org.bukkit.event.EventPriority; 22 | import org.bukkit.event.entity.CreatureSpawnEvent; 23 | import org.bukkit.inventory.EntityEquipment; 24 | import org.bukkit.inventory.ItemStack; 25 | 26 | import java.util.*; 27 | 28 | public class MobSpawnListener extends BaseListener { 29 | 30 | private final HashSet AFFECTED_MOBS = new HashSet<>(); 31 | private static final HashSet NATURAL_SPAWN_REASONS = new HashSet<>(Arrays.asList(CreatureSpawnEvent.SpawnReason.DEFAULT, CreatureSpawnEvent.SpawnReason.NATURAL)); 32 | private static final HashSet UNNATURAL_SPAWN_REASONS = new HashSet<>(Arrays.asList(CreatureSpawnEvent.SpawnReason.SPAWNER_EGG, CreatureSpawnEvent.SpawnReason.SPAWNER, CreatureSpawnEvent.SpawnReason.DISPENSE_EGG)); 33 | private static final HashSet RANGED = new HashSet<>(Arrays.asList(Material.CROSSBOW, Material.BOW)); 34 | private final HashMap CUSTOM_SPAWN_WEAPONS = new HashMap<>(); 35 | private final HashMap ARMOR_TYPES = new HashMap<>(); 36 | private final HashMap> ENCHANTMENTS = new HashMap<>(); 37 | private final HashMap ENCHANTMENT_WEIGHT = new HashMap<>(); 38 | private final Random random = new Random(); 39 | 40 | private boolean overrideConflictingEnchants; 41 | private final boolean enableMythicMobs; 42 | private boolean customArmorSpawnChance; 43 | private boolean overrideEnchantLimit; 44 | private boolean changeSpawnedMobs; 45 | private boolean armorOnMobs; 46 | private int totalArmorTypeCount; 47 | 48 | public MobSpawnListener(MainManager mainManager) { 49 | MAIN_MANAGER = mainManager; 50 | enableMythicMobs = Bukkit.getPluginManager().getPlugin("MythicMobs") != null; 51 | 52 | if (enableMythicMobs) 53 | Bukkit.getConsoleSender().sendMessage("[DynamicDifficulty] MythicMobs found, enabled the connection!"); 54 | } 55 | 56 | @EventHandler(priority = EventPriority.LOWEST) 57 | public void onMobSpawn(CreatureSpawnEvent e) { 58 | if(NATURAL_SPAWN_REASONS.contains(e.getSpawnReason())) { 59 | Bukkit.getScheduler().runTaskAsynchronously(MAIN_MANAGER.getPlugin(), () -> Bukkit.getScheduler().runTask(MAIN_MANAGER.getPlugin(), () -> { 60 | Player closestPlayer = null; 61 | double distance = 256.0; 62 | List onlinePlayers = e.getEntity().getWorld().getPlayers(); 63 | Location entityLocation = e.getEntity().getLocation(); 64 | for(Player pl : onlinePlayers) { 65 | double playerDistance = entityLocation.distance(pl.getLocation()); 66 | if(playerDistance < distance) { 67 | distance = playerDistance; 68 | closestPlayer = pl; 69 | } 70 | } 71 | 72 | if(!MAIN_MANAGER.getPlayerManager().isPlayerValid(closestPlayer)) return; 73 | Difficulty difficulty = MAIN_MANAGER.getDifficultyManager().getDifficulty(closestPlayer); 74 | 75 | if (enableMythicMobs) { 76 | for (MythicMobProfile mythicMobProfile : difficulty.mythicMobProfiles) { 77 | if (!mythicMobProfile.replacedWith.equals(e.getEntityType())) continue; 78 | if (random.nextDouble() <= mythicMobProfile.chanceToReplace) { 79 | MythicMob mythicMob = MythicBukkit.inst().getMobManager().getMythicMob(mythicMobProfile.mythicMobName) 80 | .orElse(null); 81 | 82 | if (mythicMob != null) { 83 | mythicMob.spawn(BukkitAdapter.adapt(e.getEntity().getLocation()), 1); 84 | e.setCancelled(true); 85 | return; 86 | } 87 | } 88 | break; 89 | } 90 | } 91 | 92 | if (!armorOnMobs || !AFFECTED_MOBS.contains(e.getEntity().getType())) return; 93 | 94 | EntityEquipment equipment = e.getEntity().getEquipment(); 95 | int rnd; 96 | 97 | if (RANGED.contains(equipment.getItemInMainHand().getType())) { 98 | if (random.nextDouble() <= difficulty.getArmorChance(EquipmentItems.BOW)) { 99 | ItemStack item = new ItemStack(equipment.getItemInMainHand().getType()); 100 | equipment.setItemInMainHand(calcEnchant(item, difficulty, EquipmentItems.BOW)); 101 | equipment.setItemInMainHandDropChance((float) difficulty.weaponDropChance); 102 | } 103 | } else { 104 | equipment.setItemInMainHand(null); 105 | if(random.nextDouble() <= difficulty.getArmorChance(EquipmentItems.WEAPON)) { 106 | rnd = random.nextInt(CUSTOM_SPAWN_WEAPONS.values().stream().mapToInt(i -> i).sum() + 1); 107 | int count = 0; 108 | for (Material weapon : CUSTOM_SPAWN_WEAPONS.keySet()) { 109 | if (rnd <= count) { 110 | e.getEntity().setCanPickupItems(true); 111 | equipment.setItemInMainHand(calcEnchant(new ItemStack(weapon), difficulty, EquipmentItems.WEAPON)); 112 | equipment.setItemInMainHandDropChance((float) difficulty.weaponDropChance); 113 | break; 114 | } 115 | count += CUSTOM_SPAWN_WEAPONS.get(weapon); 116 | } 117 | } 118 | } 119 | 120 | equipment.setHelmet(null); 121 | equipment.setChestplate(null); 122 | equipment.setLeggings(null); 123 | equipment.setBoots(null); 124 | 125 | if(random.nextDouble() <= difficulty.chanceToHaveArmor) { 126 | rnd = random.nextInt(totalArmorTypeCount); 127 | int count = 0; 128 | for (String thisItem : ARMOR_TYPES.keySet()) { 129 | if (rnd <= count) { 130 | float armorDropChance = (float) difficulty.armorDropChance; 131 | 132 | if (random.nextDouble() <= difficulty.getArmorChance(EquipmentItems.HELMET)) { 133 | ItemStack item = new ItemStack(Material.getMaterial(thisItem + "_HELMET")); 134 | equipment.setHelmet(calcEnchant(item, difficulty, EquipmentItems.HELMET)); 135 | equipment.setHelmetDropChance(armorDropChance); 136 | } 137 | if (random.nextDouble() <= difficulty.getArmorChance(EquipmentItems.CHEST)) { 138 | ItemStack item = new ItemStack(Material.getMaterial(thisItem + "_CHESTPLATE")); 139 | equipment.setChestplate(calcEnchant(item, difficulty, EquipmentItems.CHEST)); 140 | equipment.setChestplateDropChance(armorDropChance); 141 | } 142 | if (random.nextDouble() <= difficulty.getArmorChance(EquipmentItems.LEGGINGS)) { 143 | ItemStack item = new ItemStack(Material.getMaterial(thisItem + "_LEGGINGS")); 144 | equipment.setLeggings(calcEnchant(item, difficulty, EquipmentItems.LEGGINGS)); 145 | equipment.setLeggingsDropChance(armorDropChance); 146 | } 147 | if (random.nextDouble() <= difficulty.getArmorChance(EquipmentItems.BOOTS)) { 148 | ItemStack item = new ItemStack(Material.getMaterial(thisItem + "_BOOTS")); 149 | equipment.setBoots(calcEnchant(item, difficulty, EquipmentItems.BOOTS)); 150 | equipment.setBootsDropChance(armorDropChance); 151 | } 152 | e.getEntity().setCanPickupItems(true); 153 | break; 154 | } 155 | count += ARMOR_TYPES.get(thisItem); 156 | } 157 | } 158 | })); 159 | } else if(changeSpawnedMobs && UNNATURAL_SPAWN_REASONS.contains(e.getSpawnReason())) { 160 | MAIN_MANAGER.getEntityManager().ignoreEntity(e.getEntity()); 161 | } 162 | } 163 | 164 | public ItemStack calcEnchant(ItemStack item, Difficulty difficulty, EquipmentItems piece) { 165 | if(!customArmorSpawnChance || difficulty.maxEnchants <= 0 || random.nextDouble() > difficulty.chanceToEnchant) return item; 166 | 167 | int count = random.nextInt(difficulty.maxEnchants); 168 | for(int j = 0; j < count; j++) { 169 | Enchantment chosenEnchant = null; 170 | int currentAmount = 0; 171 | int chosenAmount = random.nextInt(ENCHANTMENT_WEIGHT.values().stream().mapToInt(i -> i).sum()) + 1; 172 | for(NamespacedKey key : ENCHANTMENTS.get(piece)) { 173 | if(chosenEnchant == null) 174 | chosenEnchant = Enchantment.getByKey(key); 175 | 176 | if(currentAmount >= chosenAmount) { 177 | chosenEnchant = Enchantment.getByKey(key); 178 | break; 179 | } 180 | currentAmount += ENCHANTMENT_WEIGHT.get(key); 181 | } 182 | 183 | if(!overrideConflictingEnchants) { 184 | boolean disallow = false; 185 | for(Enchantment enchant : item.getEnchantments().keySet()) 186 | if(enchant.conflictsWith(chosenEnchant)) { 187 | disallow = true; 188 | break; 189 | } 190 | if (disallow) continue; 191 | } 192 | 193 | int chosenLevel; 194 | 195 | if(chosenEnchant.getMaxLevel() == 1) { 196 | chosenLevel = chosenEnchant.getMaxLevel(); 197 | } else if (overrideEnchantLimit) { 198 | chosenLevel = random.nextInt(difficulty.maxEnchantLevel) + 1; 199 | } else if (difficulty.maxEnchantLevel > chosenEnchant.getMaxLevel()) { 200 | chosenLevel = random.nextInt(chosenEnchant.getMaxLevel()) + 1; 201 | } else chosenLevel = random.nextInt(difficulty.maxEnchantLevel); 202 | 203 | item.addUnsafeEnchantment(chosenEnchant, chosenLevel); 204 | if(random.nextDouble() > difficulty.chanceToEnchant) break; 205 | } 206 | return item; 207 | } 208 | 209 | @Override 210 | public void reloadConfig() { 211 | CUSTOM_SPAWN_WEAPONS.clear(); 212 | ENCHANTMENT_WEIGHT.clear(); 213 | AFFECTED_MOBS.clear(); 214 | ENCHANTMENTS.clear(); 215 | ARMOR_TYPES.clear(); 216 | FileConfiguration config = MAIN_MANAGER.getDataManager().getConfig(); 217 | ConfigurationSection customMobs = MAIN_MANAGER.getDataManager().getConfig().getConfigurationSection("custom-mob-items-spawn-chance"); 218 | 219 | overrideConflictingEnchants = customMobs.getBoolean("override-enchant-conflicts", false); 220 | overrideEnchantLimit = customMobs.getBoolean("override-default-limits", false); 221 | customArmorSpawnChance = config.getBoolean("toggle-settings.advanced.custom-enchants-on-mobs", true); 222 | changeSpawnedMobs = config.getBoolean("toggle-settings.loot-changes-to-spawned-mobs", false); 223 | armorOnMobs = config.getBoolean("toggle-settings.advanced.armor-on-mobs", true); 224 | 225 | if(customArmorSpawnChance) { 226 | for(String armorType : customMobs.getConfigurationSection("armor-set-weight").getKeys(false)) 227 | ARMOR_TYPES.put(armorType.toUpperCase(), customMobs.getInt("armor-set-weight." + armorType)); 228 | 229 | totalArmorTypeCount = ARMOR_TYPES.values().stream().mapToInt(i -> i).sum() + 1; 230 | 231 | for(String entity : customMobs.getStringList("includes-mobs")) 232 | if(EntityType.valueOf(entity) != null) 233 | AFFECTED_MOBS.add(EntityType.valueOf(entity)); 234 | 235 | HashMap itemSlot = new HashMap() {{ 236 | put(EquipmentItems.HELMET, "helmet-enchants-include"); 237 | put(EquipmentItems.CHEST, "chestplate-enchants-include"); 238 | put(EquipmentItems.LEGGINGS, "leggings-enchants-include"); 239 | put(EquipmentItems.BOOTS, "boots-enchants-include"); 240 | put(EquipmentItems.WEAPON, "weapon-enchants-include"); 241 | put(EquipmentItems.BOW, "bow-enchants-include"); 242 | }}; 243 | 244 | for(EquipmentItems equipmentItem : itemSlot.keySet()) { 245 | HashSet enchants = new HashSet<>(); 246 | for(Object key : customMobs.getList(itemSlot.get(equipmentItem)).toArray()) 247 | try { 248 | String[] sep = key.toString().replaceAll("[{|}]","").split("="); 249 | NamespacedKey name = NamespacedKey.minecraft(sep[0]); 250 | ENCHANTMENT_WEIGHT.put(name, (sep.length > 1 ? Integer.parseInt(sep[1]) : 1)); 251 | enchants.add(name); 252 | } catch (Exception ignored) { } 253 | ENCHANTMENTS.put(equipmentItem, enchants); 254 | } 255 | 256 | for(Object key : customMobs.getList("weapons-include").toArray()) 257 | try { 258 | String[] sep = key.toString().replaceAll("[{|}]","").split("="); 259 | CUSTOM_SPAWN_WEAPONS.put(Material.valueOf(sep[0]), (sep.length > 1 ? Integer.parseInt(sep[1]) : 1)); 260 | } catch (Exception ignored) { } 261 | } 262 | } 263 | } 264 | -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/managers/DifficultyManager.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.managers; 2 | 3 | import me.skinnyjeans.gmd.models.*; 4 | import org.bukkit.Bukkit; 5 | import org.bukkit.ChatColor; 6 | import org.bukkit.attribute.Attribute; 7 | import org.bukkit.configuration.ConfigurationSection; 8 | import org.bukkit.entity.Player; 9 | import org.bukkit.scheduler.BukkitTask; 10 | 11 | import java.util.*; 12 | 13 | public class DifficultyManager { 14 | 15 | private final MainManager MAIN_MANAGER; 16 | 17 | private final HashMap PLAYER_LIST = new HashMap<>(); 18 | private final HashMap DIFFICULTY_LIST = new HashMap<>(); 19 | private final ArrayList DIFFICULTY_LIST_SORTED = new ArrayList<>(); 20 | 21 | private BukkitTask calculateTimer = null; 22 | private boolean exactPercentage = true; 23 | private boolean calculateHealth = false; 24 | private DifficultyTypes difficultyType; 25 | 26 | public DifficultyManager(MainManager mainManager) { 27 | MAIN_MANAGER = mainManager; 28 | } 29 | 30 | public ArrayList getDifficulties() { return new ArrayList<>(DIFFICULTY_LIST.values()); } 31 | 32 | public ArrayList getDifficultyNames() { return DIFFICULTY_LIST_SORTED; } 33 | 34 | public Difficulty getDifficulty(String name) { return DIFFICULTY_LIST.get(name); } 35 | 36 | public Difficulty getDifficulty(Player player) { 37 | UUID uuid = MAIN_MANAGER.getPlayerManager().determineUuid(player); 38 | return getDifficulty(uuid); 39 | } 40 | 41 | public Difficulty getDifficulty(UUID uuid) { 42 | return PLAYER_LIST.getOrDefault(uuid, DIFFICULTY_LIST.get(DIFFICULTY_LIST_SORTED.get(0))); 43 | } 44 | 45 | public DifficultyTypes getType() { return difficultyType; } 46 | 47 | public Difficulty calcDifficulty(int affinity) { 48 | for (String difficulty : DIFFICULTY_LIST_SORTED) 49 | if(affinity < DIFFICULTY_LIST.get(difficulty).difficultyUntil) 50 | return DIFFICULTY_LIST.get(difficulty); 51 | return DIFFICULTY_LIST.get(DIFFICULTY_LIST_SORTED.get(0)); 52 | } 53 | 54 | public void calculateAllPlayers() { 55 | Collection list = MAIN_MANAGER.getPlayerManager().getPlayerList().values(); 56 | for (Minecrafter data : list) { 57 | calculateDifficulty(data); 58 | } 59 | } 60 | 61 | public String getProgress(UUID uuid) { 62 | int a = getDifficulty(getDifficulty(uuid).getDifficultyName()).getAffinity(); 63 | int b = getNextDifficulty(uuid).getAffinity(); 64 | 65 | if(a == b) return "100.0%"; 66 | return Math.round(1000.0 * Math.abs(1.0 - (100.0 / (a - b) * (MAIN_MANAGER.getPlayerManager().getPlayerAffinity(uuid).affinity - b)) / 100.0)) / 10.0 + "%"; 67 | } 68 | 69 | public Difficulty getNextDifficulty(UUID uuid) { 70 | int index = DIFFICULTY_LIST_SORTED.indexOf(getDifficulty(uuid).getDifficultyName()); 71 | if (index != DIFFICULTY_LIST_SORTED.size() - 1 || index == -1) index++; 72 | 73 | return DIFFICULTY_LIST.get(DIFFICULTY_LIST_SORTED.get(index)); 74 | } 75 | 76 | public void calculateDifficulty(UUID uuid) { 77 | Difficulty oldDifficulty = PLAYER_LIST.get(uuid); 78 | Difficulty newDifficulty = calculateDifficulty(MAIN_MANAGER.getPlayerManager().getPlayerAffinity(uuid)); 79 | PLAYER_LIST.put(uuid, newDifficulty); 80 | 81 | if (oldDifficulty == null || newDifficulty == null 82 | || oldDifficulty.getDifficultyName().equals(newDifficulty.getDifficultyName())) return; 83 | int oldDifficultyIndex = DIFFICULTY_LIST_SORTED.indexOf(oldDifficulty.getDifficultyName()); 84 | int newDifficultyIndex = DIFFICULTY_LIST_SORTED.indexOf(newDifficulty.getDifficultyName()); 85 | 86 | boolean directionIsUp = oldDifficultyIndex < newDifficultyIndex; 87 | ArrayList difficultiesInBetween = new ArrayList<>(); 88 | 89 | if (directionIsUp) { 90 | for (int i = oldDifficultyIndex + 1; i <= newDifficultyIndex; i++) 91 | difficultiesInBetween.add(DIFFICULTY_LIST_SORTED.get(i)); 92 | } else { 93 | for (int i = oldDifficultyIndex - 1; i >= newDifficultyIndex; i--) 94 | difficultiesInBetween.add(DIFFICULTY_LIST_SORTED.get(i)); 95 | } 96 | 97 | ArrayList allCommands = new ArrayList<>(); 98 | 99 | for (String difficultyName : difficultiesInBetween) { 100 | Difficulty difficulty = DIFFICULTY_LIST.get(difficultyName); 101 | List commands = directionIsUp 102 | ? difficulty.commandsOnSwitchFromPrev 103 | : difficulty.commandsOnSwitchFromNext; 104 | 105 | allCommands.addAll(commands); 106 | } 107 | 108 | MAIN_MANAGER.getCommandManager().dispatchCommandsIfOnline(uuid, allCommands); 109 | } 110 | 111 | public Difficulty calculateDifficulty(Minecrafter data) { 112 | Difficulty first = calcDifficulty(data.affinity); 113 | Difficulty second = DIFFICULTY_LIST.get(getNextDifficulty(data.uuid).difficultyName); 114 | 115 | Difficulty difficulty = new Difficulty(first.difficultyName); 116 | 117 | int a = first.affinityRequirement; 118 | int b = second.affinityRequirement; 119 | double c = (a == b || !exactPercentage) ? 0.0 : Math.abs(1.0 - (1.0 / (a - b) * (data.affinity - b))); 120 | 121 | difficulty.doubleLootChance = calculatePercentage(first.doubleLootChance, second.doubleLootChance, c); 122 | difficulty.hungerDrainChance = calculatePercentage(first.hungerDrainChance, second.hungerDrainChance, c); 123 | difficulty.damageDoneByMobs = calculatePercentage(first.damageDoneByMobs, second.damageDoneByMobs, c); 124 | difficulty.damageDoneOnMobs = calculatePercentage(first.damageDoneOnMobs, second.damageDoneOnMobs, c); 125 | difficulty.damageDoneOnTamed = calculatePercentage(first.damageDoneOnTamed, second.damageDoneOnTamed, c); 126 | difficulty.armorDropChance = calculatePercentage(first.armorDropChance, second.armorDropChance, c); 127 | difficulty.chanceToHaveArmor = calculatePercentage(first.chanceToHaveArmor, second.chanceToHaveArmor, c); 128 | difficulty.chanceToHaveWeapon = calculatePercentage(first.chanceToHaveWeapon, second.chanceToHaveWeapon, c); 129 | difficulty.damageByRangedMobs = calculatePercentage(first.damageByRangedMobs, second.damageByRangedMobs, c); 130 | difficulty.damagePerArmorPoint = calculatePercentage(first.damagePerArmorPoint, second.damagePerArmorPoint, c); 131 | difficulty.experienceMultiplier = calculatePercentage(first.experienceMultiplier, second.experienceMultiplier, c); 132 | difficulty.doubleDurabilityDamageChance = calculatePercentage(first.doubleDurabilityDamageChance, second.doubleDurabilityDamageChance, c); 133 | difficulty.maxEnchants = calculatePercentage(first.maxEnchants, second.maxEnchants, c); 134 | difficulty.maxEnchantLevel = calculatePercentage(first.maxEnchantLevel, second.maxEnchantLevel, c); 135 | difficulty.chanceToEnchant = calculatePercentage(first.chanceToEnchant, second.chanceToEnchant, c); 136 | difficulty.weaponDropChance = calculatePercentage(first.weaponDropChance, second.weaponDropChance, c); 137 | difficulty.minimumStarvationHealth = calculatePercentage(first.minimumStarvationHealth, second.minimumStarvationHealth, c); 138 | difficulty.maximumHealth = calculatePercentage(first.maximumHealth, second.maximumHealth, c); 139 | difficulty.chanceCancelDeath = calculatePercentage(first.chanceCancelDeath, second.chanceCancelDeath, c); 140 | 141 | for(EquipmentItems item : EquipmentItems.values()) 142 | difficulty.armorChance.put(item, 143 | calculatePercentage(first.getArmorChance(item), second.getArmorChance(item), c)); 144 | 145 | for(ArmorTypes item : ArmorTypes.values()) 146 | difficulty.armorDamageMultipliers.put(item, 147 | calculatePercentage(first.getArmorDamageMultipliers(item), second.getArmorDamageMultipliers(item), c)); 148 | 149 | difficulty.mythicMobProfiles = first.mythicMobProfiles; 150 | difficulty.allowHealthRegen = first.allowHealthRegen; 151 | difficulty.prefix = first.prefix; 152 | difficulty.allowPVP = first.allowPVP; 153 | difficulty.keepInventory = first.keepInventory; 154 | difficulty.effectsWhenAttacked = first.effectsWhenAttacked; 155 | difficulty.disabledCommands = first.disabledCommands; 156 | difficulty.mobsIgnoredPlayers = first.mobsIgnoredPlayers; 157 | difficulty.commandsOnSwitchFromNext = first.commandsOnSwitchFromNext; 158 | difficulty.commandsOnSwitchFromPrev = first.commandsOnSwitchFromPrev; 159 | difficulty.commandsOnJoin = first.commandsOnJoin; 160 | difficulty.preventEntityExplosionBlockDamage = first.preventEntityExplosionBlockDamage; 161 | PLAYER_LIST.put(data.uuid, difficulty); 162 | 163 | if (calculateHealth) { 164 | if (Bukkit.getOfflinePlayer(data.uuid) != null && Bukkit.getOfflinePlayer(data.uuid).isOnline()) { 165 | Player player = Bukkit.getPlayer(data.uuid); 166 | if(player != null && player.getAttribute(Attribute.MAX_HEALTH) != null) { 167 | player.getAttribute(Attribute.MAX_HEALTH).setBaseValue(difficulty.maximumHealth); 168 | } 169 | } else if (DifficultyTypes.biome == difficultyType || DifficultyTypes.world == difficultyType){ 170 | for (Player player : Bukkit.getOnlinePlayers()) { 171 | UUID playerUuid = MAIN_MANAGER.getPlayerManager().determineUuid(player); 172 | if (player != null && data.uuid.equals(playerUuid)) { 173 | player.getAttribute(Attribute.MAX_HEALTH).setBaseValue(difficulty.maximumHealth); 174 | } 175 | } 176 | } 177 | } 178 | 179 | return difficulty; 180 | } 181 | 182 | private static int calculatePercentage(int value1, int value2, double percentage) { 183 | if(value1 == value2) return value1; 184 | return (int) Math.round(value1 - ((value1 - value2) * percentage)); 185 | } 186 | 187 | private static double calculatePercentage(double value1, double value2, double percentage) { 188 | if(value1 == value2) return value1; 189 | return value1 - ((value1 - value2) * percentage); 190 | } 191 | 192 | public void reloadConfig() { 193 | DIFFICULTY_LIST.clear(); 194 | DIFFICULTY_LIST_SORTED.clear(); 195 | calculateHealth = false; 196 | 197 | String type = MAIN_MANAGER.getDataManager().getConfig().getString("toggle-settings.difficulty-type", "player").toLowerCase(); 198 | exactPercentage = MAIN_MANAGER.getDataManager().getConfig().getBoolean("toggle-settings.advanced.exact-percentage", true); 199 | try { 200 | difficultyType = DifficultyTypes.valueOf(type); 201 | } catch (IllegalArgumentException ignored) { 202 | difficultyType = DifficultyTypes.player; 203 | } 204 | 205 | HashMap tmpMap = new HashMap(); 206 | for(String key : MAIN_MANAGER.getDataManager().getConfig().getConfigurationSection("difficulty").getKeys(false)) { 207 | ConfigurationSection config = MAIN_MANAGER.getDataManager().getConfig().getConfigurationSection("difficulty." + key); 208 | 209 | if(! config.getBoolean("enabled", true)) continue; 210 | Difficulty difficulty = new Difficulty(key.replace(" ", "_")); 211 | 212 | difficulty.affinityRequirement = config.getInt("affinity-required", 0); 213 | 214 | // Don't want to interrupt the current player base lol. So we have to deal with the / 100.0 215 | difficulty.damageDoneByMobs = config.getDouble("damage-done-by-mobs", 100.0) / 100.0; 216 | difficulty.damageDoneOnMobs = config.getDouble("damage-done-on-mobs", 100.0) / 100.0; 217 | difficulty.damageDoneOnTamed = config.getDouble("damage-done-on-tamed", 100.0) / 100.0; 218 | difficulty.hungerDrainChance = config.getDouble("hunger-drain-chance", 100.0) / 100.0; 219 | difficulty.damageByRangedMobs = config.getDouble("damage-done-by-ranged-mobs", 100.0) / 100.0; 220 | difficulty.experienceMultiplier = config.getDouble("experience-multiplier", 100.0) / 100.0; 221 | difficulty.doubleLootChance = config.getDouble("double-loot-chance", 100.0) / 100.0; 222 | difficulty.doubleDurabilityDamageChance = config.getDouble("double-durability-damage-chance", 100.0) / 100.0; 223 | difficulty.chanceCancelDeath = config.getDouble("chance-cancel-death", 0.0) / 100.0; 224 | difficulty.damagePerArmorPoint = config.getDouble("extra-damage-per-armor-point", 0.0) / 100.0; 225 | difficulty.chanceToHaveArmor = config.getDouble("enchanting.chance-to-have-armor", 15.0) / 100.0; 226 | difficulty.chanceToEnchant = config.getDouble("enchanting.chance-to-enchant-a-piece", 30.0) / 100.0; 227 | difficulty.armorDropChance = config.getDouble("enchanting.armor-drop-chance", 15.0) / 100.0; 228 | difficulty.weaponDropChance = config.getDouble("enchanting.weapon-drop-chance", 10.0) / 100.0; 229 | difficulty.chanceToHaveWeapon = config.getDouble("enchanting.weapon-chance", 5.0) / 100.0; 230 | 231 | difficulty.maximumHealth = config.getInt("maximum-health", 20); 232 | if(difficulty.maximumHealth != 20 && difficulty.maximumHealth > 0) { 233 | calculateHealth = true; 234 | } 235 | 236 | difficulty.minimumStarvationHealth = config.getInt("minimum-health-starvation", 0); 237 | difficulty.keepInventory = config.getBoolean("keep-inventory", false); 238 | difficulty.allowPVP = config.getBoolean("allow-pvp", true); 239 | difficulty.allowHealthRegen = config.getBoolean("allow-natural-regen", true); 240 | difficulty.effectsWhenAttacked = config.getBoolean("effects-when-attacked", true); 241 | difficulty.preventEntityExplosionBlockDamage = config.getBoolean("prevent-entity-explosion-damage", false); 242 | 243 | difficulty.prefix = ChatColor.translateAlternateColorCodes('&', config.getString("prefix", key)); 244 | 245 | if(config.isSet("commands-not-allowed-on-difficulty")) 246 | difficulty.disabledCommands = config.getStringList("commands-not-allowed-on-difficulty"); 247 | 248 | if(config.isSet("extra-damage-for-certain-armor-types")) { 249 | difficulty.armorDamageMultipliers = new HashMap(); 250 | for(String armorType : config.getConfigurationSection("extra-damage-for-certain-armor-types").getKeys(false)) 251 | try { 252 | difficulty.armorDamageMultipliers 253 | .put(ArmorTypes.valueOf(armorType), 254 | config.getDouble("extra-damage-for-certain-armor-types." + armorType, 1.0) / 100.0); 255 | } catch (Exception ignored) { } 256 | } 257 | if(config.isSet("mobs-ignore-player")) difficulty.mobsIgnoredPlayers = config.getStringList("mobs-ignore-player"); 258 | 259 | difficulty.maxEnchants = config.getInt("enchanting.max-enchants", 2); 260 | difficulty.maxEnchantLevel = config.getInt("enchanting.max-level", 1); 261 | for(EquipmentItems item : EquipmentItems.values()) 262 | difficulty.armorChance.put(item, config.getDouble("enchanting." + item.name().toLowerCase() + "-chance", 1.0) 263 | / 100.0); 264 | 265 | if (config.isSet("mythic-mobs")) { 266 | ConfigurationSection mythicMobConfig = config.getConfigurationSection("mythic-mobs"); 267 | difficulty.mythicMobProfiles = new ArrayList<>(); 268 | for (String mythicMobKey : mythicMobConfig.getKeys(false)) 269 | difficulty.mythicMobProfiles.add(new MythicMobProfile(mythicMobKey, mythicMobConfig)); 270 | } 271 | 272 | if (config.isSet("execute")) { 273 | ConfigurationSection commands = config.getConfigurationSection("execute"); 274 | difficulty.commandsOnJoin = commands.getStringList("on-join"); 275 | difficulty.commandsOnSwitchFromPrev = commands.getStringList("on-switch-from-previous"); 276 | difficulty.commandsOnSwitchFromNext = commands.getStringList("on-switch-from-next"); 277 | } 278 | 279 | DIFFICULTY_LIST.put(difficulty.getDifficultyName(), difficulty); 280 | tmpMap.put(difficulty.getAffinity(), difficulty.getDifficultyName()); 281 | } 282 | 283 | TreeMap tm = new TreeMap<>(tmpMap); 284 | String lastKey = null; 285 | for (int key : tm.keySet()) { 286 | String thisKey = tmpMap.get(key).replace(" ", "_"); 287 | DIFFICULTY_LIST_SORTED.add(thisKey); 288 | if(tmpMap.size() == DIFFICULTY_LIST_SORTED.size()) 289 | DIFFICULTY_LIST.get(thisKey).difficultyUntil = Integer.MAX_VALUE; 290 | if(lastKey != null) 291 | DIFFICULTY_LIST.get(lastKey).difficultyUntil = key; 292 | lastKey = thisKey; 293 | } 294 | 295 | if(calculateTimer != null) { calculateTimer.cancel(); } 296 | 297 | int updateTime = MAIN_MANAGER.getDataManager().getConfig().getInt("toggle-settings.update-time-ticks", 1200); 298 | if(updateTime < 20) { updateTime = 1200; } 299 | 300 | calculateTimer = Bukkit.getScheduler().runTaskTimerAsynchronously(MAIN_MANAGER.getPlugin(), () -> calculateAllPlayers(), 20 * 5, updateTime); 301 | } 302 | } -------------------------------------------------------------------------------- /src/config.yml: -------------------------------------------------------------------------------- 1 | # bStats (https://bStats.org) collects some basic information for plugin authors, like how 2 | # many people use their plugin and their total player count. It's recommended to keep bStats 3 | # enabled, but if you're not comfortable with this, you can turn this setting off. There is no 4 | # performance penalty associated with having metrics enabled, and data sent to bStats is fully anonymous. 5 | 6 | version: 1.9 7 | 8 | # Some info in the config have been typed shorter so as not to clutter it too much. Please visit for more detailed explanations with examples: 9 | # https://github.com/JeannotM/DynamicDifficulty or https://www.spigotmc.org/resources/dynamic-difficulty.92025/ 10 | 11 | # Affinity Gained or Lost When Doing Certain Things. 12 | points-per-minute: 2 13 | block-mined: 1 14 | player-hit: -1 15 | affinity-per-heart-loss: -1 # So 1.5 hearts of damage (counts as 2 hearts) amounts to (-1 * 2) = -2 affinity 16 | pve-kill: 2 17 | death: -100 18 | 19 | # How much affinity player can gain or lose every minute at most. 20 | # This is to prevent players from gaining too much affinity in a short amount of time, 21 | # for example, when using mob farms or killing themselves in a loop. 22 | # NOTE: If the momentary gain is higher than the max (or lower than the min), 23 | # the affinity gain WILL NOT BE CAPPED, so big gains, like from killing the boss or dying, 24 | # are still be possible. That's why if it is set to 0, the limitation does not apply. 25 | max-affinity-gain-per-minute: 0 26 | max-affinity-loss-per-minute: 0 # this value is expected to be negative 27 | 28 | # How Much Affinity a Player Starts With When Joining For The First Time. 29 | starting-affinity: 600 30 | 31 | # To set custom min and max affinity when players start playing for the first time 32 | starting-min-affinity: -1 33 | starting-max-affinity: -1 34 | 35 | # What The Maximum and Minimum Affinity Are, no one can get more or less than this (even with commands) 36 | min-affinity: 0 37 | max-affinity: 1500 38 | 39 | # Mobs that will give affinity, Will use "pve-kill" if no value was specified: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/entity/EntityType.html 40 | # - MOBTYPE: 41 | mobs-count-as-pve: 42 | - BLAZE: 4 43 | - CAVE_SPIDER: 3 44 | - CREEPER: 3 45 | - DROWNED 46 | - ENDER_DRAGON: 100 47 | - ELDER_GUARDIAN: 20 48 | - ENDERMAN: 5 49 | - GUARDIAN: 3 50 | - HUSK 51 | - IRON_GOLEM: 50 52 | - MAGMA_CUBE 53 | - PHANTOM 54 | - PLAYER: 20 55 | - PIGLIN 56 | - PIGLIN_BRUTE: 5 57 | - SKELETON 58 | - SPIDER 59 | - VILLAGER: 20 60 | - VINDICATOR: 5 61 | - WARDEN: 200 62 | - WITCH 63 | - WITHER: 100 64 | - WITHER_SKELETON: 5 65 | - ZOMBIE 66 | 67 | # Blocks that will give affinity, Will use "block-mined" if no value was specified: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/Material.html 68 | # - BLOCKTYPE: 69 | blocks: 70 | - ANCIENT_DEBRIS: 4 71 | - DEEPSLATE_DIAMOND_ORE 72 | - DIAMOND_ORE 73 | - EMERALD_ORE 74 | 75 | toggle-settings: 76 | update-time-ticks: 1200 # 1200 = 60 seconds 77 | # More info on difficulty-type beneath the toggle-settings block 78 | difficulty-type: player # Supported: player, region, world, biome, time 79 | silk-touch-allowed: false # Whether the Player Will Receive Affinity When Mining Blocks With Silk Touch 80 | prevent-affinity-loss-on-suicide: true # People won't lose affinity if they die by their own hands. 81 | loot-changes-to-spawned-mobs: false # Mobs that spawn from eggs or spawners, won't have damage, loot or other changes. Players will also NOT receive any Affinity from these mobs. 82 | allow-tamed-wolves-in-calculations: true # Whether to allow tamed wolves in the damage calculations 83 | force-hard-difficulty: true # Forces hard Difficulty on all worlds that are not in "disabled-worlds" 84 | advanced: 85 | # advanced features may decrease performance or are a little harder to configure 86 | custom-enchants-on-mobs: true 87 | armor-on-mobs: true 88 | exact-percentage: true # Calculates the percentage between 2 difficulties so the progression will feel more natural 89 | 90 | # These are extra settings introduced by the toggle-settings.difficulty-type 91 | difficulty-type: 92 | # Region difficulty type calculates the affinity of a player based on the radius from the given x and z coordinates. 93 | # E.g. Assuming you have the default config; a player at x:0, z:200 would have an affinity of 60 94 | # Affinity calculations: (MaxAffinity - Radius) * Distance 95 | region: 96 | type: "circle" # Options: Circle, Square 97 | default-radius: 5000.0 98 | reversed: false 99 | x: 0.0 100 | z: 0.0 101 | radius: 102 | # Requires world names and distance 103 | # Affinity calculations: (MaxAffinity - Radius) * Distance 104 | world: 5000.0 # (1500 - 5000) * 200 = 60 105 | world_nether: 625.0 # (1500 - 625) * 200 = 480 106 | world_the_end: 1250.0 # (1500 - 1250) * 200 = 240 107 | time: 108 | ignore-nether: false 109 | ignore-the-end: true 110 | default: 0.4 # If the world is not included in the list 111 | world-scales: # 0 - 24000 time scale 112 | # world 113 | # time: affinity 114 | world: # (MaxAffinity * Multiplier) 115 | 2000: 0.0 # (1500 * 0.0) = 0 116 | 14000: 0.5 # (1500 * 0.5) = 750 117 | 18000: 1.0 # (1500 * 1.0) = 1500 118 | world_nether: 119 | 2000: 0.0 120 | 14000: 0.5 121 | 18000: 1.0 122 | world_the_end: 123 | 2000: 0.0 124 | 14000: 0.5 125 | 18000: 1.0 126 | 127 | saving-data: 128 | type: file # Supported: none, file, mysql, sqlite, postgresql, mariadb 129 | # port: 3306 130 | # host: localhost 131 | # username: root 132 | # password: 133 | # database: dynamicdifficulty 134 | 135 | # Only include or exclude DynamicDifficulty in these worlds 136 | worlds: 137 | # include: Enable DynamicDifficulty in these worlds 138 | # exclude: Disable DynamicDifficulty in these worlds 139 | type: exclude # include, exclude 140 | list: 141 | - example_name_test 142 | 143 | # These mobs ignore everything except the "effects-when-attacked" and "mobs-ignore-player" settings from difficulty 144 | disabled-mobs: 145 | - ENDER_DRAGON 146 | - ENDER_CRYSTAL 147 | - ELDER_GUARDIAN 148 | - WARDEN 149 | - WITHER 150 | 151 | # This has been calculated from the hard difficulty. So it is recommended to change these if you're not playing on hard world difficulty 152 | # More information if you want to make your own difficulty (I'd recommend copying one of the other difficulties and changing values): 153 | # : 154 | # enabled: 155 | # affinity-required: 156 | # damage-done-by-mobs: 157 | # damage-done-on-mobs: 158 | # hunger-drain-chance: 159 | # damage-done-by-ranged-mobs: 160 | # double-durability-damage-chance: 161 | # chance-cancel-death: 162 | # minimum-health-starvation: 163 | # maximum-health: 164 | # experience-multiplier: 165 | # double-loot-chance: 166 | # keep-inventory: 167 | # allow-pvp: 168 | # allow-natural-regen 170 | # prevent-entity-explosion-damage: 171 | # prefix: 172 | # commands-not-allowed-on-difficulty: 173 | # extra-damage-per-armor-point: 174 | # extra-damage-for-certain-armor-types: 175 | # mobs-ignore-player: 176 | # enchanting: 177 | # max-enchants: 178 | # max-level: 179 | # chance-to-have-armor: 180 | # chance-to-enchant-a-piece: 181 | # armor-drop-chance: 182 | # weapon-drop-chance: 183 | # weapon-chance: 184 | # helmet-chance: 185 | # chest-chance: 186 | # leggings-chance: 187 | # boots-chance: 188 | # mythic-mobs: 189 | # : 190 | # replace-with: 191 | # chance-to-replace: 192 | # execute: 193 | # on-join: 194 | # on-switch-from-next: 195 | # on-switch-from-previous: 196 | difficulty: 197 | Easy: 198 | enabled: true 199 | affinity-required: 0 200 | damage-done-by-mobs: 50.0 201 | damage-done-on-mobs: 100.0 202 | damage-done-on-tamed: 75.0 203 | hunger-drain-chance: 60.0 204 | damage-done-by-ranged-mobs: 75.0 205 | double-durability-damage-chance: 0.0 206 | chance-cancel-death: 0.5 207 | minimum-health-starvation: 2 208 | maximum-health: 20 209 | experience-multiplier: 70.0 210 | double-loot-chance: 0 211 | allow-pvp: true 212 | keep-inventory: true 213 | allow-natural-regen: true 214 | effects-when-attacked: false 215 | prevent-entity-explosion-damage: false 216 | prefix: '&7&l[&b&lEasy&7&l]&r' 217 | extra-damage-per-armor-point: 0 218 | extra-damage-for-certain-armor-types: 219 | nothing: -3 220 | leather: -1 221 | mobs-ignore-player: 222 | - CREEPER 223 | enchanting: 224 | max-enchants: 1 225 | max-level: 1 226 | chance-to-have-armor: 5.0 227 | chance-to-enchant-a-piece: 15.0 228 | armor-drop-chance: 10.0 229 | weapon-drop-chance: 5.0 230 | weapon-chance: 1.0 231 | helmet-chance: 100.0 232 | chest-chance: 75.0 233 | leggings-chance: 56.25 234 | boots-chance: 42.19 235 | execute: 236 | on-join: 237 | # - '/minecraft:tellraw %player% "You are playing on EASY difficulty"' 238 | on-switch-from-next: 239 | # - '/minecraft:tellraw %player% "You are now playing on EASY difficulty"' 240 | # - '/minecraft:tellraw %player% "Have a cookie for your troubles!"' 241 | # - '/minecraft:give %player% minecraft:cookie 1' 242 | # this line will be ignored if you don't have a previous difficulty 243 | # on-switch-from-previous: [] 244 | Normal: 245 | enabled: true 246 | affinity-required: 400 247 | damage-done-by-mobs: 75.0 248 | damage-done-on-mobs: 100.0 249 | damage-done-on-tamed: 100.0 250 | hunger-drain-chance: 80.0 251 | damage-done-by-ranged-mobs: 100.0 252 | double-durability-damage-chance: 1.0 253 | chance-cancel-death: 0.0 254 | minimum-health-starvation: 1 255 | maximum-health: 20 256 | experience-multiplier: 90.0 257 | double-loot-chance: 0.0 258 | allow-pvp: true 259 | keep-inventory: false 260 | allow-natural-regen: true 261 | effects-when-attacked: true 262 | prevent-entity-explosion-damage: false 263 | prefix: '&7&l[&9&lNormal&7&l]&r' 264 | enchanting: 265 | max-enchants: 2 266 | max-level: 1 267 | chance-to-have-armor: 15.0 268 | chance-to-enchant-a-piece: 30.0 269 | armor-drop-chance: 15.0 270 | weapon-drop-chance: 10.0 271 | weapon-chance: 2.0 272 | helmet-chance: 100.0 273 | chest-chance: 75.0 274 | leggings-chance: 56.25 275 | boots-chance: 42.19 276 | mythic-mobs: 277 | SkeletalKnight: 278 | replace-with: SKELETON 279 | chance-to-replace: 1.0 280 | execute: 281 | on-join: 282 | # - '/minecraft:tellraw %player% "You are playing on NORMAL difficulty"' 283 | on-switch-from-next: 284 | # - '/minecraft:tellraw %player% "You are now playing on NORMAL difficulty"' 285 | on-switch-from-previous: 286 | # - '/minecraft:tellraw %player% "You are now playing on NORMAL difficulty"' 287 | Hard: 288 | enabled: true 289 | affinity-required: 1100 290 | damage-done-by-mobs: 100.0 291 | damage-done-on-mobs: 100.0 292 | damage-done-on-tamed: 100.0 293 | hunger-drain-chance: 100.0 294 | damage-done-by-ranged-mobs: 125.0 295 | double-durability-damage-chance: 5.0 296 | chance-cancel-death: 0.0 297 | minimum-health-starvation: 0 298 | maximum-health: 20 299 | experience-multiplier: 125.0 300 | double-loot-chance: 5.0 301 | allow-pvp: true 302 | keep-inventory: false 303 | allow-natural-regen: true 304 | effects-when-attacked: true 305 | prevent-entity-explosion-damage: false 306 | prefix: '&7&l[&4&lHard&7&l]&r' 307 | commands-not-allowed-on-difficulty: 308 | - gotohome 309 | - help 34 310 | extra-damage-per-armor-point: 0 311 | extra-damage-for-certain-armor-types: 312 | golden: 1 313 | chainmail: 1 314 | iron: 2 315 | diamond: 4 316 | netherite: 5 317 | enchanting: 318 | max-enchants: 3 319 | max-level: 2 320 | chance-to-have-armor: 20.0 321 | chance-to-enchant-a-piece: 45 322 | armor-drop-chance: 20.0 323 | weapon-drop-chance: 15.0 324 | weapon-chance: 5.0 325 | helmet-chance: 100.0 326 | chest-chance: 90.0 327 | leggings-chance: 81.0 328 | boots-chance: 72.9 329 | execute: 330 | on-join: 331 | # - '/minecraft:tellraw %player% "You are playing on HARD difficulty"' 332 | on-switch-from-previous: 333 | # - '/minecraft:tellraw @a "%player% has switched to HARD difficulty!"' 334 | # This line will be ignored if you don't have a difficulty after this one 335 | # on-switch-from-next: [] 336 | 337 | custom-mob-items-spawn-chance: 338 | override-default-limits: false # will allow higher levels than Minecraft's defaults. (E.g. Unbreaking 7 can happen if max-level is higher or equals 7) 339 | override-enchant-conflicts: false # Allows conflicting enchants to occur on a single armor (E.g. Protection & Fire Protection) 340 | # These are the only mobs that will spawn with these custom settings 341 | # You can add any mob you want, but some will not show any armor. So it's not recommended going too wild 342 | includes-mobs: 343 | - ZOMBIE 344 | - SKELETON 345 | weapons-include: 346 | - WOODEN_SHOVEL: 200 347 | - GOLDEN_SHOVEL: 50 348 | - IRON_SHOVEL: 5 349 | - WOODEN_AXE: 200 350 | - GOLDEN_AXE: 50 351 | - IRON_AXE: 5 352 | - WOODEN_PICKAXE: 200 353 | - GOLDEN_PICKAXE: 50 354 | - IRON_PICKAXE: 5 355 | - WOODEN_SWORD: 200 356 | - GOLDEN_SWORD: 50 357 | - IRON_SWORD: 5 358 | armor-set-weight: 359 | leather: 3706 360 | golden: 4872 361 | chainmail: 1290 362 | iron: 127 363 | diamond: 4 364 | netherite: 1 365 | # https://www.digminecraft.com/lists/enchantment_list_pc.php 366 | # You'll have to use the names that are beneath the names with those __snakes__ 367 | helmet-enchants-include: 368 | #- : WEIGHT, higher means more likely to occur, no value = weight of 1 369 | - protection: 10 370 | - blast_protection: 5 371 | - fire_protection: 5 372 | - projectile_protection: 5 373 | - vanishing_curse 374 | - binding_curse 375 | - aqua_affinity: 2 376 | - thorns 377 | - respiration: 2 378 | - unbreaking: 5 379 | chestplate-enchants-include: 380 | - protection: 10 381 | - blast_protection: 5 382 | - fire_protection: 5 383 | - projectile_protection: 5 384 | - vanishing_curse 385 | - binding_curse 386 | - thorns 387 | - unbreaking: 5 388 | leggings-enchants-include: 389 | - protection: 10 390 | - blast_protection: 5 391 | - fire_protection: 5 392 | - projectile_protection: 5 393 | - vanishing_curse 394 | - binding_curse 395 | - thorns 396 | - unbreaking: 5 397 | boots-enchants-include: 398 | - protection: 10 399 | - blast_protection: 5 400 | - fire_protection: 5 401 | - projectile_protection: 5 402 | - vanishing_curse 403 | - binding_curse 404 | - feather_falling: 5 405 | - thorns 406 | - frost_walker: 2 407 | - soul_speed 408 | - depth_strider: 2 409 | - unbreaking: 5 410 | weapon-enchants-include: 411 | - sharpness: 10 412 | - bane_of_arthropods: 5 413 | - smite: 5 414 | - fire_aspect: 2 415 | - looting: 2 416 | - knockback: 2 417 | - sweeping: 2 418 | - vanishing_curse 419 | - binding_curse 420 | - unbreaking: 5 421 | bow-enchants-include: 422 | - power: 10 423 | - flame: 2 424 | - infinity 425 | - punch: 2 426 | - vanishing_curse 427 | - binding_curse 428 | - unbreaking: 5 -------------------------------------------------------------------------------- /src/me/skinnyjeans/gmd/managers/CommandManager.java: -------------------------------------------------------------------------------- 1 | package me.skinnyjeans.gmd.managers; 2 | 3 | import me.skinnyjeans.gmd.models.Difficulty; 4 | import me.skinnyjeans.gmd.models.Minecrafter; 5 | import me.skinnyjeans.gmd.utils.StaticInfo; 6 | import org.bukkit.Bukkit; 7 | import org.bukkit.ChatColor; 8 | import org.bukkit.OfflinePlayer; 9 | import org.bukkit.attribute.Attribute; 10 | import org.bukkit.command.Command; 11 | import org.bukkit.command.CommandExecutor; 12 | import org.bukkit.command.CommandSender; 13 | import org.bukkit.configuration.ConfigurationSection; 14 | import org.bukkit.entity.Entity; 15 | import org.bukkit.entity.Player; 16 | import org.bukkit.inventory.Inventory; 17 | 18 | import java.util.*; 19 | 20 | public class CommandManager implements CommandExecutor { 21 | 22 | private final MainManager MAIN_MANAGER; 23 | 24 | private static final HashSet NO_ARG = new HashSet<>(Arrays.asList("difficulties", "me", "help", "reload", "author", "forcesave", "forceremoval", "playergui")); 25 | private static final HashSet ONE_ARG = new HashSet<>(Arrays.asList("delmin", "delmax", "get")); 26 | private static final HashSet TWO_ARGS = new HashSet<>(Arrays.asList("setmin", "setmax", "set", "remove", "add")); 27 | 28 | private static final String authorMessage = "DynamicDifficulty: SkinnyJeans\nhttps://www.spigotmc.org/resources/dynamic-difficulty.92025/\n\n"; 29 | private static final String PREFIX_NUMBER = "%number%"; 30 | private static final String PREFIX_USER = "%user%"; 31 | private static final String PREFIX_DIFFICULTY = "%difficulty%"; 32 | 33 | private String consoleOpenPlayerGUI; 34 | private String noPermission; 35 | private String includeNumber; 36 | private String helpMessage; 37 | private String notNumber; 38 | private String notFound; 39 | 40 | private String userAffinityGet; 41 | private String userDifficultyGet; 42 | private String userMaxAffinityGet; 43 | private String userMinAffinityGet; 44 | 45 | private String translatorMessage; 46 | private String maxAffinityRemoved; 47 | private String minAffinityRemoved; 48 | private String minAffinitySet; 49 | private String maxAffinitySet; 50 | private String dataSaved; 51 | private String affinitySet; 52 | private String configReloaded; 53 | 54 | private String allUserAffinityGet; 55 | private String allUserAffinitySet; 56 | private String allUserMaxAffinitySet; 57 | private String allUserMinAffinitySet; 58 | private String allUserMinAffinityRemoved; 59 | private String allUserMaxAffinityRemoved; 60 | 61 | private final HashSet DIFFICULTIES = new HashSet<>(); 62 | 63 | public CommandManager(MainManager mainManager) { MAIN_MANAGER = mainManager; } 64 | 65 | @Override 66 | public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { 67 | if(args.length == 0 || args[0].equalsIgnoreCase("help")) return sendMessage(sender, helpMessage, true); 68 | String argument = args[0].toLowerCase(); 69 | 70 | if(NO_ARG.contains(argument)) { 71 | if(hasPermission(sender, argument)) { 72 | if(argument.equals("author")) return sendMessage(sender, authorMessage + translatorMessage, true); 73 | if(argument.equals("reload")) return sendMessage(sender, reloadPlugin(), true); 74 | if(argument.equals("forcesave")) return sendMessage(sender, forceSave(), true); 75 | if(argument.equals("playergui")) return openPlayerGUI(sender); 76 | if(argument.equals("difficulties")) return openDifficultyGUI(sender); 77 | if(argument.equals("me")) return openMyInventoryGUI(sender); 78 | if(argument.equals("forceremoval")) { 79 | OfflinePlayer[] list = Bukkit.getOfflinePlayers(); 80 | for (OfflinePlayer pl : list) { 81 | Player player = pl.getPlayer(); 82 | if (player != null) { 83 | player.getAttribute(Attribute.MAX_HEALTH).setBaseValue(20); 84 | } 85 | } 86 | 87 | MAIN_MANAGER.getPlugin().onDisable(); 88 | MAIN_MANAGER.getPlugin().getPluginLoader().disablePlugin(MAIN_MANAGER.getPlugin()); 89 | return sendMessage(sender, "DynamicDifficulty disabled", true); 90 | } 91 | } 92 | } else if (ONE_ARG.contains(argument)) { 93 | if(args.length > 1 && args[1].equals("@a")) { 94 | if(hasAnyPermission(sender, argument, "other")) { 95 | if(argument.equals("delmin")) { 96 | Set keys = MAIN_MANAGER.getPlayerManager().getPlayerList().keySet(); 97 | for (UUID key : keys) { MAIN_MANAGER.getPlayerManager().setMinAffinity(key, -1); } 98 | return sendMessage(sender, allUserMinAffinityRemoved, true); 99 | } 100 | if(argument.equals("delmax")) { 101 | Set keys = MAIN_MANAGER.getPlayerManager().getPlayerList().keySet(); 102 | for (UUID key : keys) { MAIN_MANAGER.getPlayerManager().setMaxAffinity(key, -1); } 103 | return sendMessage(sender, allUserMaxAffinityRemoved, true); 104 | } 105 | if(argument.equals("get")) { 106 | return sendMessage(sender, allUserAffinityGet, true); 107 | } 108 | } 109 | } else { 110 | String name = args.length > 1 ? args[1] : sender.getName(); 111 | if (args.length == 1 && !(sender instanceof Player)) { return sendMessage(sender, notFound, false); } 112 | UUID uuid = needsUuid(sender, name); 113 | if (uuid == null) { return sendMessage(sender, notFound, false); } 114 | String prefix = sender.getName().equals(name) ? "self" : "other"; 115 | 116 | if(hasAnyPermission(sender, argument, prefix)) { 117 | if(argument.equals("delmin")) { 118 | Minecrafter data = MAIN_MANAGER.getPlayerManager().getPlayerAffinity(uuid); 119 | MAIN_MANAGER.getPlayerManager().setMinAffinity(uuid, -1); 120 | return sendMessage(sender, minAffinityRemoved.replace(PREFIX_USER, data.name), true); 121 | } 122 | if(argument.equals("delmax")) { 123 | Minecrafter data = MAIN_MANAGER.getPlayerManager().getPlayerAffinity(uuid); 124 | MAIN_MANAGER.getPlayerManager().setMaxAffinity(uuid, -1); 125 | return sendMessage(sender, maxAffinityRemoved.replace(PREFIX_USER, data.name), true); 126 | } 127 | if(argument.equals("get")) { 128 | Minecrafter data = MAIN_MANAGER.getPlayerManager().getPlayerAffinity(uuid); 129 | StringBuilder message = new StringBuilder(userAffinityGet.replace(PREFIX_USER, data.name).replace(PREFIX_NUMBER, data.affinity + "")) 130 | .append("\n").append(userDifficultyGet.replace(PREFIX_DIFFICULTY, MAIN_MANAGER.getDifficultyManager().getDifficulty(data.uuid).prefix) 131 | .replace(PREFIX_NUMBER, data.affinity + "")); 132 | 133 | if(data.maxAffinity != -1) message.append("\n").append(userMaxAffinityGet.replace(PREFIX_NUMBER, data.maxAffinity + "")); 134 | if(data.minAffinity != -1) message.append("\n").append(userMinAffinityGet.replace(PREFIX_NUMBER, data.minAffinity + "")); 135 | 136 | return sendMessage(sender, message.toString(), true); 137 | } 138 | } 139 | } 140 | } else if (TWO_ARGS.contains(argument)) { 141 | if (args.length < 2) return sendMessage(sender, includeNumber, false); 142 | 143 | int number = needsNumber(args.length == 2 ? args[1] : args[2]); 144 | if (number == -550055) return sendMessage(sender, notNumber.replace(PREFIX_NUMBER, args.length == 2 ? args[1] : args[2]), false); 145 | 146 | if(args[1].equals("@a")) { 147 | if(hasAnyPermission(sender, argument, "other")) { 148 | if (argument.equals("setmin")) { 149 | Set keys = MAIN_MANAGER.getPlayerManager().getPlayerList().keySet(); 150 | for (UUID key : keys) { MAIN_MANAGER.getPlayerManager().setMinAffinity(key, number); } 151 | return sendMessage(sender, allUserMinAffinitySet.replace(PREFIX_NUMBER, String.valueOf(number)), true); 152 | } else if (argument.equals("setmax")) { 153 | Set keys = MAIN_MANAGER.getPlayerManager().getPlayerList().keySet(); 154 | for (UUID key : keys) { MAIN_MANAGER.getPlayerManager().setMaxAffinity(key, number); } 155 | return sendMessage(sender, allUserMaxAffinitySet.replace(PREFIX_NUMBER, String.valueOf(number)), true); 156 | } else if (argument.equals("set")) { 157 | Set keys = MAIN_MANAGER.getPlayerManager().getPlayerList().keySet(); 158 | for (UUID key : keys) { MAIN_MANAGER.getPlayerManager().setAffinity(key, number); } 159 | return sendMessage(sender, allUserAffinitySet.replace(PREFIX_NUMBER, String.valueOf(number)), true); 160 | } else if (argument.equals("remove")) { 161 | Set keys = MAIN_MANAGER.getPlayerManager().getPlayerList().keySet(); 162 | for (UUID key : keys) { MAIN_MANAGER.getPlayerManager().addAffinity(key, number * -1); } 163 | return sendMessage(sender, allUserAffinitySet.replace(PREFIX_NUMBER, String.valueOf(number)), true); 164 | } else if (argument.equals("add")) { 165 | Set keys = MAIN_MANAGER.getPlayerManager().getPlayerList().keySet(); 166 | for (UUID key : keys) { MAIN_MANAGER.getPlayerManager().addAffinity(key, number); } 167 | return sendMessage(sender, allUserAffinitySet.replace(PREFIX_NUMBER, String.valueOf(number)), true); 168 | } 169 | } 170 | } else { 171 | String name = args[1].toLowerCase(); 172 | UUID uuid = needsUuid(sender, name); 173 | if (uuid == null) { return sendMessage(sender, notFound, false); } 174 | String prefix = sender.getName().equals(name) ? "self" : "other"; 175 | 176 | if(hasPermission(sender, argument, prefix)) { 177 | if(argument.equals("setmin")) { 178 | int setAffinity = MAIN_MANAGER.getPlayerManager().setMinAffinity(uuid, number); 179 | Minecrafter affinity = MAIN_MANAGER.getPlayerManager().getPlayerAffinity(uuid); 180 | return sendMessage(sender, 181 | minAffinitySet.replace(PREFIX_USER, affinity.name).replace(PREFIX_NUMBER,setAffinity + ""), 182 | true); 183 | } 184 | if(argument.equals("setmax")) { 185 | int setAffinity = MAIN_MANAGER.getPlayerManager().setMaxAffinity(uuid, number); 186 | Minecrafter affinity = MAIN_MANAGER.getPlayerManager().getPlayerAffinity(uuid); 187 | return sendMessage(sender, 188 | maxAffinitySet.replace(PREFIX_USER, affinity.name).replace(PREFIX_NUMBER,setAffinity + ""), 189 | true); 190 | } 191 | if(argument.equals("set")) { 192 | int setAffinity = MAIN_MANAGER.getPlayerManager().setAffinity(uuid, number); 193 | Minecrafter affinity = MAIN_MANAGER.getPlayerManager().getPlayerAffinity(uuid); 194 | Difficulty diff = MAIN_MANAGER.getDifficultyManager().calculateDifficulty(affinity); 195 | return sendMessage(sender, 196 | affinitySet.replace(PREFIX_USER, affinity.name).replace(PREFIX_DIFFICULTY, diff.difficultyName) 197 | .replace(PREFIX_NUMBER,setAffinity + ""), 198 | true); 199 | } 200 | if(argument.equals("remove")) { 201 | int setAffinity = MAIN_MANAGER.getPlayerManager().addAffinity(uuid, number * -1); 202 | Minecrafter affinity = MAIN_MANAGER.getPlayerManager().getPlayerAffinity(uuid); 203 | String difficulty = MAIN_MANAGER.getDifficultyManager().getDifficulty(uuid).difficultyName; 204 | return sendMessage(sender, 205 | affinitySet.replace(PREFIX_USER, affinity.name).replace(PREFIX_DIFFICULTY, difficulty) 206 | .replace(PREFIX_NUMBER,setAffinity + ""), 207 | true); 208 | } 209 | if(argument.equals("add")) { 210 | int setAffinity = MAIN_MANAGER.getPlayerManager().addAffinity(uuid, number); 211 | Minecrafter affinity = MAIN_MANAGER.getPlayerManager().getPlayerAffinity(uuid); 212 | String difficulty = MAIN_MANAGER.getDifficultyManager().getDifficulty(uuid).difficultyName; 213 | return sendMessage(sender, 214 | affinitySet.replace(PREFIX_USER, affinity.name).replace(PREFIX_DIFFICULTY, difficulty) 215 | .replace(PREFIX_NUMBER,setAffinity + ""), 216 | true); 217 | } 218 | } 219 | } 220 | } 221 | 222 | return sendMessage(sender, noPermission, false); 223 | } 224 | 225 | private boolean openDifficultyGUI(CommandSender sender) { 226 | if(sender instanceof Player) { 227 | MAIN_MANAGER.getInventoryManager().openBaseDifficultyInventory((Player) sender); 228 | } else sendMessage(sender, consoleOpenPlayerGUI, false); 229 | return true; 230 | } 231 | 232 | private boolean openPlayerGUI(CommandSender sender) { 233 | if(sender instanceof Player) { 234 | MAIN_MANAGER.getInventoryManager().openInventory((Player) sender, 1); 235 | } else sendMessage(sender, consoleOpenPlayerGUI, false); 236 | return true; 237 | } 238 | 239 | private boolean openMyInventoryGUI(CommandSender sender) { 240 | if(sender instanceof Player) { 241 | Player player = (Player) sender; 242 | Difficulty difficulty = MAIN_MANAGER.getDifficultyManager().getDifficulty(player.getUniqueId()); 243 | Inventory inventory = Bukkit.createInventory(null, 36, StaticInfo.DIFFICULTY_INVENTORY); 244 | MAIN_MANAGER.getInventoryManager().createInventory(difficulty, inventory); 245 | player.openInventory(inventory); 246 | } else sendMessage(sender, consoleOpenPlayerGUI, false); 247 | return true; 248 | } 249 | 250 | private String forceSave() { 251 | MAIN_MANAGER.getDataManager().saveData(); 252 | return dataSaved; 253 | } 254 | 255 | private String reloadPlugin() { 256 | MAIN_MANAGER.reloadConfig(); 257 | MAIN_MANAGER.getDifficultyManager().calculateAllPlayers(); 258 | return configReloaded; 259 | } 260 | 261 | public UUID needsUuid(CommandSender sender, String command) { 262 | if (command == null || command.length() <= 1 263 | || sender.getName().equalsIgnoreCase(command) 264 | || command.equals("@s") 265 | || needsNumber(command) != -550055) { 266 | if (sender instanceof Player) { 267 | return MAIN_MANAGER.getPlayerManager().determineUuid((Player) sender); 268 | } 269 | } 270 | if (MAIN_MANAGER.getPlayerManager().hasPlayer(command)) { 271 | return MAIN_MANAGER.getPlayerManager().getPlayerAffinity(command.toLowerCase()).uuid; 272 | } 273 | if (command.equals("@r")) { 274 | Object[] players = MAIN_MANAGER.getPlayerManager().getPlayerList().keySet().toArray(); 275 | return (UUID) players[new Random().nextInt(players.length)]; 276 | } else if (command.equals("@p")) { 277 | List entities = Bukkit.selectEntities(sender, "@p"); 278 | for(Entity entity : entities) 279 | return MAIN_MANAGER.getPlayerManager().determineUuid((Player) entity); 280 | } 281 | return null; 282 | } 283 | 284 | public int needsNumber(String command) { 285 | if (command.matches("^[0-9-]+$")) return MAIN_MANAGER.getPlayerManager().withinServerLimits(Integer.parseInt(command)); 286 | if (DIFFICULTIES.contains(command)) return MAIN_MANAGER.getDifficultyManager().getDifficulty(command).getAffinity(); 287 | return -550055; 288 | } 289 | 290 | public boolean hasPermission(CommandSender sender, String name, String command) { 291 | if(sender instanceof Player) { 292 | if(sender.getName().equalsIgnoreCase(name)) return hasAnyPermission(sender, command, "self"); 293 | return hasAnyPermission(sender, command, "other"); 294 | } else return true; 295 | } 296 | 297 | public boolean hasPermission(CommandSender sender, String command) { 298 | if(sender instanceof Player) return hasAnyPermission(sender, command); 299 | return true; 300 | } 301 | 302 | public boolean hasAnyPermission(CommandSender sender, String command, String prefix) { 303 | return sender.hasPermission("affinity." + command + "." + prefix) || sender.hasPermission("affinity.*." + prefix) || hasAnyPermission(sender, command); 304 | } 305 | 306 | public boolean hasAnyPermission(CommandSender sender, String command) { 307 | return sender.isOp() || sender.hasPermission("affinity.*") || sender.hasPermission("affinity." + command); 308 | } 309 | 310 | public boolean sendMessage(CommandSender sender, String message, boolean success) { 311 | if(sender instanceof Player) { 312 | sender.sendMessage(message); 313 | } else Bukkit.getConsoleSender().sendMessage(ChatColor.stripColor(message)); 314 | return success; 315 | } 316 | 317 | public void reloadConfig() { 318 | consoleOpenPlayerGUI = MAIN_MANAGER.getDataManager().getLanguageString("error.console.cannot-open-playergui", false); 319 | noPermission = MAIN_MANAGER.getDataManager().getLanguageString("error.no-permission", false); 320 | includeNumber = MAIN_MANAGER.getDataManager().getLanguageString("error.include-number", false); 321 | notNumber = MAIN_MANAGER.getDataManager().getLanguageString("error.not-a-number", false); 322 | notFound = MAIN_MANAGER.getDataManager().getLanguageString("error.cannot-be-found", false); 323 | 324 | dataSaved = MAIN_MANAGER.getDataManager().getLanguageString("command.other.force-save", true); 325 | configReloaded = MAIN_MANAGER.getDataManager().getLanguageString("command.other.reload-config", true); 326 | affinitySet = MAIN_MANAGER.getDataManager().getLanguageString("command.set.affinity", true); 327 | minAffinitySet = MAIN_MANAGER.getDataManager().getLanguageString("command.set.min-affinity", true); 328 | maxAffinitySet = MAIN_MANAGER.getDataManager().getLanguageString("command.set.max-affinity", true); 329 | maxAffinityRemoved = MAIN_MANAGER.getDataManager().getLanguageString("command.remove.max-affinity", true); 330 | minAffinityRemoved = MAIN_MANAGER.getDataManager().getLanguageString("command.remove.min-affinity", true); 331 | 332 | userAffinityGet = MAIN_MANAGER.getDataManager().getLanguageString("command.get.has-affinity", true); 333 | userDifficultyGet = MAIN_MANAGER.getDataManager().getLanguageString("command.get.currently-on", true); 334 | userMaxAffinityGet = MAIN_MANAGER.getDataManager().getLanguageString("command.get.max-affinity", true); 335 | userMinAffinityGet = MAIN_MANAGER.getDataManager().getLanguageString("command.get.min-affinity", true); 336 | 337 | allUserAffinityGet = MAIN_MANAGER.getDataManager().getLanguageString("command.get.cannot-use-get-for-all", true); 338 | allUserAffinitySet = MAIN_MANAGER.getDataManager().getLanguageString("command.set.all", true); 339 | allUserMaxAffinitySet = MAIN_MANAGER.getDataManager().getLanguageString("command.set.max-affinity-all", true); 340 | allUserMinAffinitySet = MAIN_MANAGER.getDataManager().getLanguageString("command.set.min-affinity-all", true); 341 | allUserMinAffinityRemoved = MAIN_MANAGER.getDataManager().getLanguageString("command.remove.min-affinity-all", true); 342 | allUserMaxAffinityRemoved = MAIN_MANAGER.getDataManager().getLanguageString("command.remove.max-affinity-all", true); 343 | 344 | translatorMessage = MAIN_MANAGER.getDataManager().getLanguageString("translated-by", true) + "\n" + MAIN_MANAGER.getDataManager().getLanguageString("translator-url", true); 345 | 346 | ConfigurationSection language = MAIN_MANAGER.getDataManager().getCultureLang(); 347 | String label = language.getString("command.help.label", "&f/dd"); 348 | String nameNum = language.getString("command.help.name-num", " "); 349 | String name = language.getString("command.help.name", ""); 350 | StringBuilder help = new StringBuilder(); 351 | 352 | for(String key : language.getConfigurationSection("command.help.command").getKeys(false)) 353 | help.append(language.getString("command.help.command." + key).replace("%label%", label) 354 | .replace("%name-num%", nameNum).replace("%name%", name)).append("\n"); 355 | 356 | helpMessage = ChatColor.translateAlternateColorCodes('&', help.toString()); 357 | 358 | DIFFICULTIES.clear(); 359 | DIFFICULTIES.addAll(MAIN_MANAGER.getDifficultyManager().getDifficultyNames()); 360 | } 361 | 362 | private void dispatchCommandsInCurrentThread(UUID uuid, List commands) { 363 | Player player = Bukkit.getPlayer(uuid); 364 | if (player == null) return; 365 | 366 | try { 367 | for (String command : commands) { 368 | command = command.replace("%player%", player.getName()); 369 | if (command.startsWith("/")) command = command.substring(1); 370 | boolean foundCommand = Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command); 371 | if (!foundCommand) { 372 | MAIN_MANAGER.getPlugin().getLogger().warning("Command not found: " + command); 373 | break; 374 | } 375 | } 376 | } catch (Exception e) { 377 | MAIN_MANAGER.getPlugin().getLogger().warning("Error dispatching commands for " + player.getName()); 378 | e.printStackTrace(); 379 | } 380 | } 381 | 382 | public void dispatchCommandsIfOnline(UUID uuid, List commands) { 383 | Bukkit.getScheduler().runTask(MAIN_MANAGER.getPlugin(), () -> 384 | dispatchCommandsInCurrentThread(uuid, commands)); 385 | } 386 | } 387 | --------------------------------------------------------------------------------