forked from Upstream/mmocore
refactor, fixed an issue with loot chests cooldown
This commit is contained in:
parent
8c95245ffb
commit
a574a67a3b
@ -5,7 +5,7 @@ import io.lumine.mythic.lib.version.SpigotPlugin;
|
|||||||
import io.lumine.mythic.utils.plugin.LuminePlugin;
|
import io.lumine.mythic.utils.plugin.LuminePlugin;
|
||||||
import net.Indyuce.mmocore.api.ConfigFile;
|
import net.Indyuce.mmocore.api.ConfigFile;
|
||||||
import net.Indyuce.mmocore.api.PlayerActionBar;
|
import net.Indyuce.mmocore.api.PlayerActionBar;
|
||||||
import net.Indyuce.mmocore.api.loot.LootChest;
|
import net.Indyuce.mmocore.loot.chest.LootChest;
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
|
import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
|
||||||
import net.Indyuce.mmocore.api.player.social.guilds.Guild;
|
import net.Indyuce.mmocore.api.player.social.guilds.Guild;
|
||||||
|
@ -5,8 +5,8 @@ import io.lumine.mythic.lib.api.MMOLineConfig;
|
|||||||
import io.lumine.mythic.lib.api.condition.type.BlockCondition;
|
import io.lumine.mythic.lib.api.condition.type.BlockCondition;
|
||||||
import io.lumine.mythic.lib.api.condition.type.MMOCondition;
|
import io.lumine.mythic.lib.api.condition.type.MMOCondition;
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.droptable.DropTable;
|
import net.Indyuce.mmocore.loot.droptable.DropTable;
|
||||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
import net.Indyuce.mmocore.loot.LootBuilder;
|
||||||
import net.Indyuce.mmocore.api.quest.trigger.Trigger;
|
import net.Indyuce.mmocore.api.quest.trigger.Trigger;
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang.Validate;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
@ -3,8 +3,8 @@ package net.Indyuce.mmocore.api.event;
|
|||||||
import org.bukkit.event.Cancellable;
|
import org.bukkit.event.Cancellable;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
|
|
||||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
import net.Indyuce.mmocore.loot.LootBuilder;
|
||||||
import net.Indyuce.mmocore.api.loot.LootChest;
|
import net.Indyuce.mmocore.loot.chest.LootChest;
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
|
|
||||||
public class LootChestSpawnEvent extends PlayerDataEvent implements Cancellable {
|
public class LootChestSpawnEvent extends PlayerDataEvent implements Cancellable {
|
||||||
|
@ -6,17 +6,17 @@ import org.bukkit.configuration.ConfigurationSection;
|
|||||||
import net.Indyuce.mmocore.api.block.BlockType;
|
import net.Indyuce.mmocore.api.block.BlockType;
|
||||||
import net.Indyuce.mmocore.api.block.SkullBlockType;
|
import net.Indyuce.mmocore.api.block.SkullBlockType;
|
||||||
import net.Indyuce.mmocore.api.block.VanillaBlockType;
|
import net.Indyuce.mmocore.api.block.VanillaBlockType;
|
||||||
import net.Indyuce.mmocore.api.droptable.condition.BiomeCondition;
|
import net.Indyuce.mmocore.loot.droptable.condition.BiomeCondition;
|
||||||
import net.Indyuce.mmocore.api.droptable.condition.Condition;
|
import net.Indyuce.mmocore.loot.droptable.condition.Condition;
|
||||||
import net.Indyuce.mmocore.api.droptable.condition.LevelCondition;
|
import net.Indyuce.mmocore.loot.droptable.condition.LevelCondition;
|
||||||
import net.Indyuce.mmocore.api.droptable.condition.PermissionCondition;
|
import net.Indyuce.mmocore.loot.droptable.condition.PermissionCondition;
|
||||||
import net.Indyuce.mmocore.api.droptable.condition.WorldCondition;
|
import net.Indyuce.mmocore.loot.droptable.condition.WorldCondition;
|
||||||
import net.Indyuce.mmocore.api.droptable.dropitem.DropItem;
|
import net.Indyuce.mmocore.loot.droptable.dropitem.DropItem;
|
||||||
import net.Indyuce.mmocore.api.droptable.dropitem.DropTableDropItem;
|
import net.Indyuce.mmocore.loot.droptable.dropitem.DropTableDropItem;
|
||||||
import net.Indyuce.mmocore.api.droptable.dropitem.GoldDropItem;
|
import net.Indyuce.mmocore.loot.droptable.dropitem.GoldDropItem;
|
||||||
import net.Indyuce.mmocore.api.droptable.dropitem.MMDropTableDropItem;
|
import net.Indyuce.mmocore.loot.droptable.dropitem.MMDropTableDropItem;
|
||||||
import net.Indyuce.mmocore.api.droptable.dropitem.NoteDropItem;
|
import net.Indyuce.mmocore.loot.droptable.dropitem.NoteDropItem;
|
||||||
import net.Indyuce.mmocore.api.droptable.dropitem.VanillaDropItem;
|
import net.Indyuce.mmocore.loot.droptable.dropitem.VanillaDropItem;
|
||||||
import net.Indyuce.mmocore.experience.source.BrewPotionExperienceSource;
|
import net.Indyuce.mmocore.experience.source.BrewPotionExperienceSource;
|
||||||
import net.Indyuce.mmocore.experience.source.CraftItemExperienceSource;
|
import net.Indyuce.mmocore.experience.source.CraftItemExperienceSource;
|
||||||
import net.Indyuce.mmocore.experience.source.EnchantItemExperienceSource;
|
import net.Indyuce.mmocore.experience.source.EnchantItemExperienceSource;
|
||||||
|
@ -2,8 +2,8 @@ package net.Indyuce.mmocore.api.load;
|
|||||||
|
|
||||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||||
import net.Indyuce.mmocore.api.block.BlockType;
|
import net.Indyuce.mmocore.api.block.BlockType;
|
||||||
import net.Indyuce.mmocore.api.droptable.condition.Condition;
|
import net.Indyuce.mmocore.loot.droptable.condition.Condition;
|
||||||
import net.Indyuce.mmocore.api.droptable.dropitem.DropItem;
|
import net.Indyuce.mmocore.loot.droptable.dropitem.DropItem;
|
||||||
import net.Indyuce.mmocore.experience.provider.ExperienceDispenser;
|
import net.Indyuce.mmocore.experience.provider.ExperienceDispenser;
|
||||||
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
|
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
|
||||||
import net.Indyuce.mmocore.api.quest.objective.Objective;
|
import net.Indyuce.mmocore.api.quest.objective.Objective;
|
||||||
|
@ -1,185 +0,0 @@
|
|||||||
package net.Indyuce.mmocore.api.loot;
|
|
||||||
|
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
|
||||||
import net.Indyuce.mmocore.api.event.LootChestSpawnEvent;
|
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
|
||||||
import org.apache.commons.lang.Validate;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.block.Chest;
|
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
|
||||||
import org.bukkit.util.Vector;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
|
|
||||||
public class LootChestRegion {
|
|
||||||
private final String id;
|
|
||||||
|
|
||||||
private final long chestSpawnPeriod;
|
|
||||||
private final RegionBounds bounds;
|
|
||||||
private final ChestAlgorithmOptions algOptions;
|
|
||||||
private final Set<ChestTier> tiers = new LinkedHashSet<>();
|
|
||||||
private final BukkitRunnable runnable;
|
|
||||||
|
|
||||||
private static final Random random = new Random();
|
|
||||||
|
|
||||||
public LootChestRegion(ConfigurationSection config) {
|
|
||||||
Validate.notNull(config, "Could not load config");
|
|
||||||
id = config.getName().toLowerCase().replace("_", "-").replace(" ", "-");
|
|
||||||
|
|
||||||
bounds = new RegionBounds(config.getConfigurationSection("bounds"));
|
|
||||||
chestSpawnPeriod = config.getLong("spawn-period", 5 * 60);
|
|
||||||
algOptions = config.contains("algorithm-options") ? new ChestAlgorithmOptions(config.getConfigurationSection("algorithm-options"))
|
|
||||||
: ChestAlgorithmOptions.DEFAULT;
|
|
||||||
|
|
||||||
Validate.isTrue(config.isConfigurationSection("tiers"), "Could not find chest tiers");
|
|
||||||
for (String key : config.getConfigurationSection("tiers").getKeys(false))
|
|
||||||
try {
|
|
||||||
tiers.add(new ChestTier(config.getConfigurationSection("tiers." + key)));
|
|
||||||
} catch (IllegalArgumentException exception) {
|
|
||||||
MMOCore.plugin.getLogger().log(Level.WARNING,
|
|
||||||
"Could not load tier '" + key + "' from chest region '" + id + "': " + exception.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
Validate.isTrue(!tiers.isEmpty(), "Your region must have at least one chest tier");
|
|
||||||
|
|
||||||
runnable = new LootChestRunnable(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<ChestTier> getTiers() {
|
|
||||||
return tiers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RegionBounds getBounds() {
|
|
||||||
return bounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getChestSpawnPeriod() {
|
|
||||||
return chestSpawnPeriod;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BukkitRunnable getRunnable() {
|
|
||||||
return runnable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void spawnChest(PlayerData player) {
|
|
||||||
if(!player.isOnline()) return;
|
|
||||||
// first randomly determine the chest tier
|
|
||||||
ChestTier tier = rollTier();
|
|
||||||
|
|
||||||
// find a random location, 20 trials max
|
|
||||||
Location location = getRandomLocation(player.getPlayer().getLocation());
|
|
||||||
if (location == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
LootChest lootChest = new LootChest(tier, this, location.getBlock());
|
|
||||||
LootBuilder builder = new LootBuilder(player, tier.rollCapacity(player));
|
|
||||||
tier.getDropTable().collect(builder);
|
|
||||||
|
|
||||||
LootChestSpawnEvent event = new LootChestSpawnEvent(player, lootChest, builder);
|
|
||||||
Bukkit.getPluginManager().callEvent(event);
|
|
||||||
if (event.isCancelled())
|
|
||||||
return;
|
|
||||||
|
|
||||||
List<Integer> slots = new ArrayList<>();
|
|
||||||
for (int j = 0; j < 27; j++)
|
|
||||||
slots.add(j);
|
|
||||||
|
|
||||||
location.getBlock().setType(Material.CHEST);
|
|
||||||
Chest chest = (Chest) location.getBlock().getState();
|
|
||||||
tier.getDropTable().collect(builder).forEach(item -> {
|
|
||||||
Integer slot = slots.get(random.nextInt(slots.size()));
|
|
||||||
chest.getInventory().setItem(slot, item);
|
|
||||||
slots.remove(slot);
|
|
||||||
});
|
|
||||||
|
|
||||||
MMOCore.plugin.lootChests.register(lootChest);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO improve
|
|
||||||
// TODO stat to increase chance to get higher tiers?
|
|
||||||
public ChestTier rollTier() {
|
|
||||||
|
|
||||||
double s = 0;
|
|
||||||
for (ChestTier tier : tiers) {
|
|
||||||
if (random.nextDouble() < tier.chance / (1 - s))
|
|
||||||
return tier;
|
|
||||||
s += tier.chance;
|
|
||||||
}
|
|
||||||
|
|
||||||
return tiers.stream().findAny().orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Location getRandomLocation(Location center) {
|
|
||||||
|
|
||||||
for (int j = 0; j < algOptions.iterations; j++) {
|
|
||||||
Location random = tryRandomDirection(center);
|
|
||||||
if (random != null)
|
|
||||||
return random;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* no location has been found after the X iterations, return null and
|
|
||||||
* cancel chest spawning. worst case scenario, should not happen too
|
|
||||||
* often except if the player is in a really NARROW zone
|
|
||||||
*/
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Location tryRandomDirection(Location center) {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* chooses a random direction and get the block in that direction which
|
|
||||||
* has the same height as the player
|
|
||||||
*/
|
|
||||||
double a = random.nextDouble() * 2 * Math.PI;
|
|
||||||
Vector dir = new Vector(Math.cos(a), 0, Math.sin(a))
|
|
||||||
.multiply(algOptions.minRange + random.nextDouble() * (algOptions.maxRange - algOptions.minRange));
|
|
||||||
Location random = center.add(dir);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* go up and down at the same time till it finds a non-solid block with
|
|
||||||
* a solid block underneath
|
|
||||||
*/
|
|
||||||
for (int h = 0; h <= algOptions.height * 2; h++) {
|
|
||||||
int z = h % 2 == 0 ? h / 2 : -(h + 1) / 2; // bijective from N to Z
|
|
||||||
Location checked = random.clone().add(0, z, 0);
|
|
||||||
if (isSuitable(checked))
|
|
||||||
return checked;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isSuitable(Location loc) {
|
|
||||||
return !loc.getBlock().getType().isSolid() && loc.clone().add(0, -1, 0).getBlock().getType().isSolid();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class LootChestRunnable extends BukkitRunnable {
|
|
||||||
private final LootChestRegion region;
|
|
||||||
|
|
||||||
public LootChestRunnable(LootChestRegion region) {
|
|
||||||
this.region = region;
|
|
||||||
|
|
||||||
runTaskTimer(MMOCore.plugin, region.getChestSpawnPeriod() * 20, region.getChestSpawnPeriod() * 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
Optional<PlayerData> found = region.getBounds().getPlayers().filter(PlayerData::canSpawnLootChest).findAny();
|
|
||||||
found.ifPresent(region::spawnChest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -79,7 +79,7 @@ public class PlayerData extends OfflinePlayerData {
|
|||||||
// NON-FINAL player data stuff made public to facilitate field change
|
// NON-FINAL player data stuff made public to facilitate field change
|
||||||
public int skillGuiDisplayOffset;
|
public int skillGuiDisplayOffset;
|
||||||
public SkillCasting skillCasting;
|
public SkillCasting skillCasting;
|
||||||
public boolean nocd;
|
public boolean noCooldown;
|
||||||
public CombatRunnable combat;
|
public CombatRunnable combat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -845,7 +845,7 @@ public class PlayerData extends OfflinePlayerData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply cooldown, mana and stamina costs
|
// Apply cooldown, mana and stamina costs
|
||||||
if (!nocd) {
|
if (!noCooldown) {
|
||||||
double flatCooldownReduction = Math.max(0, Math.min(1, getStats().getStat(StatType.COOLDOWN_REDUCTION) / 100));
|
double flatCooldownReduction = Math.max(0, Math.min(1, getStats().getStat(StatType.COOLDOWN_REDUCTION) / 100));
|
||||||
flatCooldownReduction *= flatCooldownReduction > 0 ? skill.getModifier("cooldown", getSkillLevel(skill.getSkill())) * 1000 : 0;
|
flatCooldownReduction *= flatCooldownReduction > 0 ? skill.getModifier("cooldown", getSkillLevel(skill.getSkill())) * 1000 : 0;
|
||||||
|
|
||||||
|
@ -29,9 +29,9 @@ public class NoCooldownCommandTreeNode extends CommandTreeNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PlayerData data = PlayerData.get(player);
|
PlayerData data = PlayerData.get(player);
|
||||||
data.nocd = !data.nocd;
|
data.noCooldown = !data.noCooldown;
|
||||||
CommandVerbose.verbose(sender, CommandVerbose.CommandType.NOCD,
|
CommandVerbose.verbose(sender, CommandVerbose.CommandType.NOCD,
|
||||||
ChatColor.YELLOW + "NoCD " + (data.nocd ? "enabled" : "disabled") + " for " + player.getName() + ".");
|
ChatColor.YELLOW + "NoCD " + (data.noCooldown ? "enabled" : "disabled") + " for " + player.getName() + ".");
|
||||||
return CommandResult.SUCCESS;
|
return CommandResult.SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@ package net.Indyuce.mmocore.comp.region;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import net.Indyuce.mmocore.api.droptable.condition.Condition;
|
import net.Indyuce.mmocore.loot.droptable.condition.Condition;
|
||||||
import net.Indyuce.mmocore.api.droptable.condition.ConditionInstance;
|
import net.Indyuce.mmocore.loot.droptable.condition.ConditionInstance;
|
||||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||||
|
|
||||||
public class RegionCondition extends Condition {
|
public class RegionCondition extends Condition {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package net.Indyuce.mmocore.comp.region;
|
package net.Indyuce.mmocore.comp.region;
|
||||||
|
|
||||||
import net.Indyuce.mmocore.api.droptable.condition.Condition;
|
import net.Indyuce.mmocore.loot.droptable.condition.Condition;
|
||||||
import net.Indyuce.mmocore.api.load.MMOLoader;
|
import net.Indyuce.mmocore.api.load.MMOLoader;
|
||||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||||
|
|
||||||
|
@ -6,9 +6,9 @@ import net.Indyuce.mmocore.MMOCore;
|
|||||||
import net.Indyuce.mmocore.api.block.BlockInfo;
|
import net.Indyuce.mmocore.api.block.BlockInfo;
|
||||||
import net.Indyuce.mmocore.api.block.BlockInfo.BlockInfoOption;
|
import net.Indyuce.mmocore.api.block.BlockInfo.BlockInfoOption;
|
||||||
import net.Indyuce.mmocore.api.block.VanillaBlockType;
|
import net.Indyuce.mmocore.api.block.VanillaBlockType;
|
||||||
import net.Indyuce.mmocore.api.droptable.condition.ConditionInstance;
|
import net.Indyuce.mmocore.loot.droptable.condition.ConditionInstance;
|
||||||
import net.Indyuce.mmocore.api.event.CustomBlockMineEvent;
|
import net.Indyuce.mmocore.api.event.CustomBlockMineEvent;
|
||||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
import net.Indyuce.mmocore.loot.LootBuilder;
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
|
@ -6,7 +6,7 @@ import org.bukkit.event.Listener;
|
|||||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||||
|
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.loot.LootChest;
|
import net.Indyuce.mmocore.loot.chest.LootChest;
|
||||||
|
|
||||||
public class LootableChestsListener implements Listener {
|
public class LootableChestsListener implements Listener {
|
||||||
@EventHandler
|
@EventHandler
|
||||||
|
@ -2,10 +2,10 @@ package net.Indyuce.mmocore.listener.profession;
|
|||||||
|
|
||||||
import io.lumine.mythic.lib.version.VersionSound;
|
import io.lumine.mythic.lib.version.VersionSound;
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.droptable.dropitem.fishing.FishingDropItem;
|
import net.Indyuce.mmocore.loot.droptable.dropitem.fishing.FishingDropItem;
|
||||||
import net.Indyuce.mmocore.api.event.CustomPlayerFishEvent;
|
import net.Indyuce.mmocore.api.event.CustomPlayerFishEvent;
|
||||||
import net.Indyuce.mmocore.experience.EXPSource;
|
import net.Indyuce.mmocore.experience.EXPSource;
|
||||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
import net.Indyuce.mmocore.loot.LootBuilder;
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
import net.Indyuce.mmocore.api.player.stats.StatType;
|
import net.Indyuce.mmocore.api.player.stats.StatType;
|
||||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||||
|
@ -1,55 +1,55 @@
|
|||||||
package net.Indyuce.mmocore.api.loot;
|
package net.Indyuce.mmocore.loot;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
|
|
||||||
public class LootBuilder {
|
public class LootBuilder {
|
||||||
private final PlayerData player;
|
private final PlayerData player;
|
||||||
private final List<ItemStack> loot = new ArrayList<>();
|
private final List<ItemStack> loot = new ArrayList<>();
|
||||||
|
|
||||||
private double capacity;
|
private double capacity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to create loot from a drop table
|
* Used to create loot from a drop table
|
||||||
*
|
*
|
||||||
* @param player
|
* @param player
|
||||||
* Player looting
|
* Player looting
|
||||||
* @param capacity
|
* @param capacity
|
||||||
* Capacity is the maximum amount of item weight generated using
|
* Capacity is the maximum amount of item weight generated using
|
||||||
* this table. If capacity is set to 10, this table cannot drop
|
* this table. If capacity is set to 10, this table cannot drop
|
||||||
* an item with 5 weight and another with 6 weight at the saeme
|
* an item with 5 weight and another with 6 weight at the saeme
|
||||||
* time.
|
* time.
|
||||||
*/
|
*/
|
||||||
public LootBuilder(PlayerData player, double capacity) {
|
public LootBuilder(PlayerData player, double capacity) {
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.capacity = capacity;
|
this.capacity = capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayerData getEntity() {
|
public PlayerData getEntity() {
|
||||||
return player;
|
return player;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ItemStack> getLoot() {
|
public List<ItemStack> getLoot() {
|
||||||
return loot;
|
return loot;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getCapacity() {
|
public double getCapacity() {
|
||||||
return capacity;
|
return capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addLoot(ItemStack item) {
|
public void addLoot(ItemStack item) {
|
||||||
loot.add(item);
|
loot.add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addLoot(List<? extends ItemStack> items) {
|
public void addLoot(List<? extends ItemStack> items) {
|
||||||
loot.addAll(items);
|
loot.addAll(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reduceCapacity(double value) {
|
public void reduceCapacity(double value) {
|
||||||
this.capacity = Math.max(0, capacity - value);
|
this.capacity = Math.max(0, capacity - value);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,50 +1,50 @@
|
|||||||
package net.Indyuce.mmocore.api.loot;
|
package net.Indyuce.mmocore.loot.chest;
|
||||||
|
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang.Validate;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
|
||||||
public class ChestAlgorithmOptions {
|
public class ChestAlgorithmOptions {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* min and max range represents the range at which the chest can spawn
|
* min and max range represents the range at which the chest can spawn
|
||||||
* around the player. height is the Z delta in which the chest can spawn,
|
* around the player. height is the Z delta in which the chest can spawn,
|
||||||
* relative to the player's altitude
|
* relative to the player's altitude
|
||||||
*/
|
*/
|
||||||
public final double minRange, maxRange, height;
|
public final double minRange, maxRange, height;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* maximum amount of trials the algorithm will run in order to find a
|
* maximum amount of trials the algorithm will run in order to find a
|
||||||
* suitable location for a chest around the player.
|
* suitable location for a chest around the player.
|
||||||
*/
|
*/
|
||||||
public final int iterations;
|
public final int iterations;
|
||||||
|
|
||||||
public static final ChestAlgorithmOptions DEFAULT = new ChestAlgorithmOptions(10, 30, 8, 15);
|
public static final ChestAlgorithmOptions DEFAULT = new ChestAlgorithmOptions(10, 30, 8, 15);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* this is purely to let server owners tweak the chest random location
|
* this is purely to let server owners tweak the chest random location
|
||||||
* finder algorithm.
|
* finder algorithm.
|
||||||
*/
|
*/
|
||||||
public ChestAlgorithmOptions(ConfigurationSection config) {
|
public ChestAlgorithmOptions(ConfigurationSection config) {
|
||||||
Validate.notNull(config, "Config cannot be null");
|
Validate.notNull(config, "Config cannot be null");
|
||||||
|
|
||||||
minRange = config.getDouble("min-range", DEFAULT.minRange);
|
minRange = config.getDouble("min-range", DEFAULT.minRange);
|
||||||
maxRange = config.getDouble("max-range", DEFAULT.maxRange);
|
maxRange = config.getDouble("max-range", DEFAULT.maxRange);
|
||||||
height = config.getDouble("height", DEFAULT.height);
|
height = config.getDouble("height", DEFAULT.height);
|
||||||
iterations = config.getInt("iterations", DEFAULT.iterations);
|
iterations = config.getInt("iterations", DEFAULT.iterations);
|
||||||
|
|
||||||
Validate.isTrue(minRange < maxRange, "Max range must be greater than min range");
|
Validate.isTrue(minRange < maxRange, "Max range must be greater than min range");
|
||||||
Validate.isTrue(height > 0, "Height must be strictly positive");
|
Validate.isTrue(height > 0, "Height must be strictly positive");
|
||||||
Validate.isTrue(iterations > 0, "Iterations must be strictly positive");
|
Validate.isTrue(iterations > 0, "Iterations must be strictly positive");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* can be used to register loot chest regions with external plugins, and
|
* can be used to register loot chest regions with external plugins, and
|
||||||
* used by the default alg options instance
|
* used by the default alg options instance
|
||||||
*/
|
*/
|
||||||
public ChestAlgorithmOptions(double minRange, double maxRange, double height, int iterations) {
|
public ChestAlgorithmOptions(double minRange, double maxRange, double height, int iterations) {
|
||||||
this.minRange = minRange;
|
this.minRange = minRange;
|
||||||
this.maxRange = maxRange;
|
this.maxRange = maxRange;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
this.iterations = iterations;
|
this.iterations = iterations;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,38 +1,38 @@
|
|||||||
package net.Indyuce.mmocore.api.loot;
|
package net.Indyuce.mmocore.loot.chest;
|
||||||
|
|
||||||
import io.lumine.mythic.lib.api.math.ScalingFormula;
|
import io.lumine.mythic.lib.api.math.ScalingFormula;
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.droptable.DropTable;
|
import net.Indyuce.mmocore.loot.droptable.DropTable;
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
|
||||||
public class ChestTier {
|
public class ChestTier {
|
||||||
private final TierEffect effect;
|
private final TierEffect effect;
|
||||||
private final ScalingFormula capacity;
|
private final ScalingFormula capacity;
|
||||||
private final DropTable table;
|
private final DropTable table;
|
||||||
|
|
||||||
public final double chance;
|
public final double chance;
|
||||||
|
|
||||||
public ChestTier(ConfigurationSection config) {
|
public ChestTier(ConfigurationSection config) {
|
||||||
effect = config.isConfigurationSection("effect") ? new TierEffect(config.getConfigurationSection("effect")) : null;
|
effect = config.isConfigurationSection("effect") ? new TierEffect(config.getConfigurationSection("effect")) : null;
|
||||||
capacity = new ScalingFormula(config.get("capacity"));
|
capacity = new ScalingFormula(config.get("capacity"));
|
||||||
chance = config.getDouble("chance");
|
chance = config.getDouble("chance");
|
||||||
table = MMOCore.plugin.dropTableManager.loadDropTable(config.get("drops"));
|
table = MMOCore.plugin.dropTableManager.loadDropTable(config.get("drops"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public double rollCapacity(PlayerData player) {
|
public double rollCapacity(PlayerData player) {
|
||||||
return capacity.calculate(player.getLevel());
|
return capacity.calculate(player.getLevel());
|
||||||
}
|
}
|
||||||
|
|
||||||
public DropTable getDropTable() {
|
public DropTable getDropTable() {
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasEffect() {
|
public boolean hasEffect() {
|
||||||
return effect != null;
|
return effect != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TierEffect getEffect() {
|
public TierEffect getEffect() {
|
||||||
return effect;
|
return effect;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,108 +1,108 @@
|
|||||||
package net.Indyuce.mmocore.api.loot;
|
package net.Indyuce.mmocore.loot.chest;
|
||||||
|
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.manager.SoundManager;
|
import net.Indyuce.mmocore.manager.SoundManager;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.Particle;
|
import org.bukkit.Particle;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.Chest;
|
import org.bukkit.block.Chest;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
public class LootChest {
|
public class LootChest {
|
||||||
private final ChestTier tier;
|
private final ChestTier tier;
|
||||||
private final LootChestRegion region;
|
private final LootChestRegion region;
|
||||||
private final ReplacedBlock block;
|
private final ReplacedBlock block;
|
||||||
private final BukkitRunnable effectRunnable;
|
private final BukkitRunnable effectRunnable;
|
||||||
private final long date = System.currentTimeMillis();
|
private final long date = System.currentTimeMillis();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a loot chest is placed as a Bukkit block, and used
|
* Called when a loot chest is placed as a Bukkit block, and used
|
||||||
* to save the data of the block which has been replaced.
|
* to save the data of the block which has been replaced.
|
||||||
* <p>
|
* <p>
|
||||||
* A placed drop chest may only replace non solid blocks like grass
|
* A placed drop chest may only replace non solid blocks like grass
|
||||||
* or levels..
|
* or levels..
|
||||||
*/
|
*/
|
||||||
public LootChest(ChestTier tier, LootChestRegion region, Block block) {
|
public LootChest(ChestTier tier, LootChestRegion region, Block block) {
|
||||||
this.tier = tier;
|
this.tier = tier;
|
||||||
this.region = region;
|
this.region = region;
|
||||||
this.block = new ReplacedBlock(block);
|
this.block = new ReplacedBlock(block);
|
||||||
this.effectRunnable = tier.hasEffect() ? tier.getEffect().startNewRunnable(block.getLocation().add(.5, .5, .5)) : null;
|
this.effectRunnable = tier.hasEffect() ? tier.getEffect().startNewRunnable(block.getLocation().add(.5, .5, .5)) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChestTier getTier() {
|
public ChestTier getTier() {
|
||||||
return tier;
|
return tier;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReplacedBlock getBlock() {
|
public ReplacedBlock getBlock() {
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LootChestRegion getRegion() {
|
public LootChestRegion getRegion() {
|
||||||
return region;
|
return region;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasPlayerNearby() {
|
public boolean hasPlayerNearby() {
|
||||||
for (Player player : block.loc.getWorld().getPlayers())
|
for (Player player : block.loc.getWorld().getPlayers())
|
||||||
if (player.getLocation().distanceSquared(block.loc) < 625)
|
if (player.getLocation().distanceSquared(block.loc) < 625)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean shouldExpire() {
|
public boolean shouldExpire() {
|
||||||
return System.currentTimeMillis() - date > MMOCore.plugin.configManager.lootChestExpireTime;
|
return System.currentTimeMillis() - date > MMOCore.plugin.configManager.lootChestExpireTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param player If a player just the chest. It's set to false
|
* @param player If a player just the chest. It's set to false
|
||||||
* when a loot chest expires or when MMOCore disables.
|
* when a loot chest expires or when MMOCore disables.
|
||||||
*/
|
*/
|
||||||
public void unregister(boolean player) {
|
public void unregister(boolean player) {
|
||||||
|
|
||||||
// If a player is responsible of closing the chest, close it with sound
|
// If a player is responsible of closing the chest, close it with sound
|
||||||
if (player) {
|
if (player) {
|
||||||
MMOCore.plugin.soundManager.play(block.loc.getBlock(), SoundManager.SoundEvent.CLOSE_LOOT_CHEST);
|
MMOCore.plugin.soundManager.play(block.loc.getBlock(), SoundManager.SoundEvent.CLOSE_LOOT_CHEST);
|
||||||
block.loc.getWorld().spawnParticle(Particle.CRIT, block.loc.clone().add(.5, .5, .5), 16, 0, 0, 0, .5);
|
block.loc.getWorld().spawnParticle(Particle.CRIT, block.loc.clone().add(.5, .5, .5), 16, 0, 0, 0, .5);
|
||||||
MMOCore.plugin.lootChests.unregister(this);
|
MMOCore.plugin.lootChests.unregister(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Must clean block inventory before replacing block otherwise loots fly
|
* Must clean block inventory before replacing block otherwise loots fly
|
||||||
* off and accumulate on the ground (+during dev phase)
|
* off and accumulate on the ground (+during dev phase)
|
||||||
*/
|
*/
|
||||||
else
|
else
|
||||||
((Chest) block.loc.getBlock().getState()).getBlockInventory().clear();
|
((Chest) block.loc.getBlock().getState()).getBlockInventory().clear();
|
||||||
|
|
||||||
block.restore();
|
block.restore();
|
||||||
if (effectRunnable != null)
|
if (effectRunnable != null)
|
||||||
effectRunnable.cancel();
|
effectRunnable.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ReplacedBlock {
|
public static class ReplacedBlock {
|
||||||
private final Material material;
|
private final Material material;
|
||||||
private final BlockData data;
|
private final BlockData data;
|
||||||
private final Location loc;
|
private final Location loc;
|
||||||
|
|
||||||
public ReplacedBlock(Block block) {
|
public ReplacedBlock(Block block) {
|
||||||
this.material = block.getType();
|
this.material = block.getType();
|
||||||
this.data = block.getBlockData();
|
this.data = block.getBlockData();
|
||||||
this.loc = block.getLocation();
|
this.loc = block.getLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Location getLocoation() {
|
public Location getLocoation() {
|
||||||
return loc;
|
return loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean matches(Location loc) {
|
public boolean matches(Location loc) {
|
||||||
return this.loc.getWorld().equals(loc.getWorld()) && this.loc.getBlockX() == loc.getBlockX() && this.loc.getBlockY() == loc.getBlockY()
|
return this.loc.getWorld().equals(loc.getWorld()) && this.loc.getBlockX() == loc.getBlockX() && this.loc.getBlockY() == loc.getBlockY()
|
||||||
&& this.loc.getBlockZ() == loc.getBlockZ();
|
&& this.loc.getBlockZ() == loc.getBlockZ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restore() {
|
public void restore() {
|
||||||
loc.getBlock().setType(material);
|
loc.getBlock().setType(material);
|
||||||
loc.getBlock().setBlockData(data);
|
loc.getBlock().setBlockData(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,174 @@
|
|||||||
|
package net.Indyuce.mmocore.loot.chest;
|
||||||
|
|
||||||
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
|
import net.Indyuce.mmocore.api.event.LootChestSpawnEvent;
|
||||||
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
|
import net.Indyuce.mmocore.loot.LootBuilder;
|
||||||
|
import org.apache.commons.lang.Validate;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.block.Chest;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
public class LootChestRegion {
|
||||||
|
private final String id;
|
||||||
|
|
||||||
|
private final long chestSpawnPeriod;
|
||||||
|
private final RegionBounds bounds;
|
||||||
|
private final ChestAlgorithmOptions algOptions;
|
||||||
|
private final Set<ChestTier> tiers = new LinkedHashSet<>();
|
||||||
|
private final BukkitRunnable runnable = new BukkitRunnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
getBounds().getPlayers().filter(PlayerData::canSpawnLootChest).findAny().ifPresent(player -> spawnChest(player));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final Random random = new Random();
|
||||||
|
|
||||||
|
public LootChestRegion(ConfigurationSection config) {
|
||||||
|
Validate.notNull(config, "Could not load config");
|
||||||
|
id = config.getName().toLowerCase().replace("_", "-").replace(" ", "-");
|
||||||
|
|
||||||
|
bounds = new RegionBounds(config.getConfigurationSection("bounds"));
|
||||||
|
chestSpawnPeriod = config.getLong("spawn-period", 5 * 60);
|
||||||
|
algOptions = config.contains("algorithm-options") ? new ChestAlgorithmOptions(config.getConfigurationSection("algorithm-options"))
|
||||||
|
: ChestAlgorithmOptions.DEFAULT;
|
||||||
|
|
||||||
|
Validate.isTrue(config.isConfigurationSection("tiers"), "Could not find chest tiers");
|
||||||
|
for (String key : config.getConfigurationSection("tiers").getKeys(false))
|
||||||
|
try {
|
||||||
|
tiers.add(new ChestTier(config.getConfigurationSection("tiers." + key)));
|
||||||
|
} catch (IllegalArgumentException exception) {
|
||||||
|
MMOCore.plugin.getLogger().log(Level.WARNING,
|
||||||
|
"Could not load tier '" + key + "' from chest region '" + id + "': " + exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
Validate.isTrue(!tiers.isEmpty(), "Your region must have at least one chest tier");
|
||||||
|
|
||||||
|
// Run timer
|
||||||
|
runnable.runTaskTimer(MMOCore.plugin, chestSpawnPeriod * 20, chestSpawnPeriod * 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<ChestTier> getTiers() {
|
||||||
|
return tiers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegionBounds getBounds() {
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getChestSpawnPeriod() {
|
||||||
|
return chestSpawnPeriod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BukkitRunnable getRunnable() {
|
||||||
|
return runnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void spawnChest(PlayerData player) {
|
||||||
|
|
||||||
|
// Apply chest cooldown
|
||||||
|
player.applyLootChestCooldown();
|
||||||
|
|
||||||
|
// First randomly determine the chest tier
|
||||||
|
ChestTier tier = rollTier();
|
||||||
|
|
||||||
|
// Find a random location, 20 trials max
|
||||||
|
Location location = getRandomLocation(player.getPlayer().getLocation());
|
||||||
|
if (location == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
LootChest lootChest = new LootChest(tier, this, location.getBlock());
|
||||||
|
LootBuilder builder = new LootBuilder(player, tier.rollCapacity(player));
|
||||||
|
tier.getDropTable().collect(builder);
|
||||||
|
|
||||||
|
LootChestSpawnEvent event = new LootChestSpawnEvent(player, lootChest, builder);
|
||||||
|
Bukkit.getPluginManager().callEvent(event);
|
||||||
|
if (event.isCancelled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
List<Integer> slots = new ArrayList<>();
|
||||||
|
for (int j = 0; j < 27; j++)
|
||||||
|
slots.add(j);
|
||||||
|
|
||||||
|
location.getBlock().setType(Material.CHEST);
|
||||||
|
Chest chest = (Chest) location.getBlock().getState();
|
||||||
|
tier.getDropTable().collect(builder).forEach(item -> {
|
||||||
|
Integer slot = slots.get(random.nextInt(slots.size()));
|
||||||
|
chest.getInventory().setItem(slot, item);
|
||||||
|
slots.remove(slot);
|
||||||
|
});
|
||||||
|
|
||||||
|
MMOCore.plugin.lootChests.register(lootChest);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO stat to increase chance to get higher tiers?
|
||||||
|
public ChestTier rollTier() {
|
||||||
|
|
||||||
|
double s = 0;
|
||||||
|
for (ChestTier tier : tiers) {
|
||||||
|
if (random.nextDouble() < tier.chance / (1 - s))
|
||||||
|
return tier;
|
||||||
|
s += tier.chance;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tiers.stream().findAny().orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location getRandomLocation(Location center) {
|
||||||
|
|
||||||
|
for (int j = 0; j < algOptions.iterations; j++) {
|
||||||
|
Location random = tryRandomDirection(center);
|
||||||
|
if (random != null)
|
||||||
|
return random;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* no location has been found after the X iterations, return null and
|
||||||
|
* cancel chest spawning. worst case scenario, should not happen too
|
||||||
|
* often except if the player is in a really NARROW zone
|
||||||
|
*/
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location tryRandomDirection(Location center) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* chooses a random direction and get the block in that direction which
|
||||||
|
* has the same height as the player
|
||||||
|
*/
|
||||||
|
double a = random.nextDouble() * 2 * Math.PI;
|
||||||
|
Vector dir = new Vector(Math.cos(a), 0, Math.sin(a))
|
||||||
|
.multiply(algOptions.minRange + random.nextDouble() * (algOptions.maxRange - algOptions.minRange));
|
||||||
|
Location random = center.add(dir);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* go up and down at the same time till it finds a non-solid block with
|
||||||
|
* a solid block underneath
|
||||||
|
*/
|
||||||
|
for (int h = 0; h <= algOptions.height * 2; h++) {
|
||||||
|
int z = h % 2 == 0 ? h / 2 : -(h + 1) / 2; // bijective from N to Z
|
||||||
|
Location checked = random.clone().add(0, z, 0);
|
||||||
|
if (isSuitable(checked))
|
||||||
|
return checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isSuitable(Location loc) {
|
||||||
|
return !loc.getBlock().getType().isSolid() && loc.clone().add(0, -1, 0).getBlock().getType().isSolid();
|
||||||
|
}
|
||||||
|
}
|
@ -1,51 +1,51 @@
|
|||||||
package net.Indyuce.mmocore.api.loot;
|
package net.Indyuce.mmocore.loot.chest;
|
||||||
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang.Validate;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
|
|
||||||
public class RegionBounds {
|
public class RegionBounds {
|
||||||
private final World world;
|
private final World world;
|
||||||
private final int x1, z1, x2, z2;
|
private final int x1, z1, x2, z2;
|
||||||
|
|
||||||
public RegionBounds(ConfigurationSection config) {
|
public RegionBounds(ConfigurationSection config) {
|
||||||
Validate.notNull(config, "Could not load config");
|
Validate.notNull(config, "Could not load config");
|
||||||
|
|
||||||
String name = config.getString("world");
|
String name = config.getString("world");
|
||||||
Validate.notNull(name, "Could not find world name");
|
Validate.notNull(name, "Could not find world name");
|
||||||
Validate.notNull(world = Bukkit.getWorld(name), "Could not find world " + config.getString("world"));
|
Validate.notNull(world = Bukkit.getWorld(name), "Could not find world " + config.getString("world"));
|
||||||
|
|
||||||
x1 = Math.min(config.getInt("x1"), config.getInt("x2"));
|
x1 = Math.min(config.getInt("x1"), config.getInt("x2"));
|
||||||
x2 = Math.max(config.getInt("x1"), config.getInt("x2"));
|
x2 = Math.max(config.getInt("x1"), config.getInt("x2"));
|
||||||
|
|
||||||
z1 = Math.min(config.getInt("z1"), config.getInt("z2"));
|
z1 = Math.min(config.getInt("z1"), config.getInt("z2"));
|
||||||
z2 = Math.max(config.getInt("z1"), config.getInt("z2"));
|
z2 = Math.max(config.getInt("z1"), config.getInt("z2"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public RegionBounds(Location loc1, Location loc2) {
|
public RegionBounds(Location loc1, Location loc2) {
|
||||||
Validate.isTrue(loc1.getWorld().equals(loc2.getWorld()), "Locations must be in the same world");
|
Validate.isTrue(loc1.getWorld().equals(loc2.getWorld()), "Locations must be in the same world");
|
||||||
world = loc1.getWorld();
|
world = loc1.getWorld();
|
||||||
x1 = Math.min(loc1.getBlockX(), loc2.getBlockX());
|
x1 = Math.min(loc1.getBlockX(), loc2.getBlockX());
|
||||||
x2 = Math.max(loc1.getBlockX(), loc2.getBlockX());
|
x2 = Math.max(loc1.getBlockX(), loc2.getBlockX());
|
||||||
|
|
||||||
z1 = Math.min(loc1.getBlockZ(), loc2.getBlockZ());
|
z1 = Math.min(loc1.getBlockZ(), loc2.getBlockZ());
|
||||||
z2 = Math.max(loc1.getBlockZ(), loc2.getBlockZ());
|
z2 = Math.max(loc1.getBlockZ(), loc2.getBlockZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream<PlayerData> getPlayers() {
|
public Stream<PlayerData> getPlayers() {
|
||||||
return world.getPlayers().stream().filter(this::isInRegion).map(PlayerData::get);
|
return world.getPlayers().stream().filter(this::isInRegion).map(PlayerData::get);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInRegion(Player player) {
|
public boolean isInRegion(Player player) {
|
||||||
int x = player.getLocation().getBlockX();
|
int x = player.getLocation().getBlockX();
|
||||||
int z = player.getLocation().getBlockZ();
|
int z = player.getLocation().getBlockZ();
|
||||||
return player.getWorld().equals(world) && x1 <= x && x2 >= x && z1 <= z && z2 >= z;
|
return player.getWorld().equals(world) && x1 <= x && x2 >= x && z1 <= z && z2 >= z;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,37 +1,37 @@
|
|||||||
package net.Indyuce.mmocore.api.loot;
|
package net.Indyuce.mmocore.loot.chest;
|
||||||
|
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang.Validate;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Particle;
|
import org.bukkit.Particle;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.util.math.particle.ChestParticleEffect;
|
import net.Indyuce.mmocore.api.util.math.particle.ChestParticleEffect;
|
||||||
|
|
||||||
public class TierEffect {
|
public class TierEffect {
|
||||||
private final ChestParticleEffect type;
|
private final ChestParticleEffect type;
|
||||||
private final Particle particle;
|
private final Particle particle;
|
||||||
private final int period;
|
private final int period;
|
||||||
|
|
||||||
public TierEffect(ConfigurationSection config) {
|
public TierEffect(ConfigurationSection config) {
|
||||||
Validate.notNull(config, "Could not load tier config");
|
Validate.notNull(config, "Could not load tier config");
|
||||||
type = ChestParticleEffect.valueOf(config.getString("type", "OFFSET").toUpperCase().replace("-", "_").replace(" ", "_"));
|
type = ChestParticleEffect.valueOf(config.getString("type", "OFFSET").toUpperCase().replace("-", "_").replace(" ", "_"));
|
||||||
particle = Particle.valueOf(config.getString("particle", "FLAME").toUpperCase().replace("-", "_").replace(" ", "_"));
|
particle = Particle.valueOf(config.getString("particle", "FLAME").toUpperCase().replace("-", "_").replace(" ", "_"));
|
||||||
period = Math.max(20, config.getInt("period", 5 * 20));
|
period = Math.max(20, config.getInt("period", 5 * 20));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void play(Location loc) {
|
public void play(Location loc) {
|
||||||
type.play(loc, particle);
|
type.play(loc, particle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BukkitRunnable startNewRunnable(Location loc) {
|
public BukkitRunnable startNewRunnable(Location loc) {
|
||||||
BukkitRunnable runnable = new BukkitRunnable() {
|
BukkitRunnable runnable = new BukkitRunnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
type.play(loc, particle);
|
type.play(loc, particle);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
runnable.runTaskTimer(MMOCore.plugin, 0, period);
|
runnable.runTaskTimer(MMOCore.plugin, 0, period);
|
||||||
return runnable;
|
return runnable;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,19 +1,19 @@
|
|||||||
package net.Indyuce.mmocore.api.droptable;
|
package net.Indyuce.mmocore.loot.droptable;
|
||||||
|
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import net.Indyuce.mmocore.loot.droptable.condition.Condition;
|
||||||
|
import net.Indyuce.mmocore.loot.droptable.condition.ConditionInstance;
|
||||||
|
import net.Indyuce.mmocore.loot.droptable.dropitem.DropItem;
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang.Validate;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.droptable.condition.Condition;
|
import net.Indyuce.mmocore.loot.LootBuilder;
|
||||||
import net.Indyuce.mmocore.api.droptable.condition.ConditionInstance;
|
|
||||||
import net.Indyuce.mmocore.api.droptable.dropitem.DropItem;
|
|
||||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
|
||||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||||
import io.lumine.mythic.lib.api.util.PostLoadObject;
|
import io.lumine.mythic.lib.api.util.PostLoadObject;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package net.Indyuce.mmocore.api.droptable.condition;
|
package net.Indyuce.mmocore.loot.droptable.condition;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
@ -1,4 +1,4 @@
|
|||||||
package net.Indyuce.mmocore.api.droptable.condition;
|
package net.Indyuce.mmocore.loot.droptable.condition;
|
||||||
|
|
||||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package net.Indyuce.mmocore.api.droptable.condition;
|
package net.Indyuce.mmocore.loot.droptable.condition;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
@ -1,4 +1,4 @@
|
|||||||
package net.Indyuce.mmocore.api.droptable.condition;
|
package net.Indyuce.mmocore.loot.droptable.condition;
|
||||||
|
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
import io.lumine.mythic.lib.api.MMOLineConfig;
|
@ -1,4 +1,4 @@
|
|||||||
package net.Indyuce.mmocore.api.droptable.condition;
|
package net.Indyuce.mmocore.loot.droptable.condition;
|
||||||
|
|
||||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
@ -1,4 +1,4 @@
|
|||||||
package net.Indyuce.mmocore.api.droptable.condition;
|
package net.Indyuce.mmocore.loot.droptable.condition;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
@ -1,8 +1,8 @@
|
|||||||
package net.Indyuce.mmocore.api.droptable.dropitem;
|
package net.Indyuce.mmocore.loot.droptable.dropitem;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
import net.Indyuce.mmocore.loot.LootBuilder;
|
||||||
import net.Indyuce.mmocore.api.util.math.formula.RandomAmount;
|
import net.Indyuce.mmocore.api.util.math.formula.RandomAmount;
|
||||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||||
|
|
@ -1,10 +1,10 @@
|
|||||||
package net.Indyuce.mmocore.api.droptable.dropitem;
|
package net.Indyuce.mmocore.loot.droptable.dropitem;
|
||||||
|
|
||||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.droptable.DropTable;
|
import net.Indyuce.mmocore.loot.droptable.DropTable;
|
||||||
import net.Indyuce.mmocore.api.droptable.condition.ConditionInstance;
|
import net.Indyuce.mmocore.loot.droptable.condition.ConditionInstance;
|
||||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
import net.Indyuce.mmocore.loot.LootBuilder;
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang.Validate;
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
package net.Indyuce.mmocore.api.droptable.dropitem;
|
package net.Indyuce.mmocore.loot.droptable.dropitem;
|
||||||
|
|
||||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
import net.Indyuce.mmocore.loot.LootBuilder;
|
||||||
import net.Indyuce.mmocore.api.util.item.CurrencyItem;
|
import net.Indyuce.mmocore.api.util.item.CurrencyItem;
|
||||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package net.Indyuce.mmocore.api.droptable.dropitem;
|
package net.Indyuce.mmocore.loot.droptable.dropitem;
|
||||||
|
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
@ -9,7 +9,7 @@ import io.lumine.xikage.mythicmobs.drops.DropMetadata;
|
|||||||
import io.lumine.xikage.mythicmobs.drops.DropTable;
|
import io.lumine.xikage.mythicmobs.drops.DropTable;
|
||||||
import io.lumine.xikage.mythicmobs.drops.IItemDrop;
|
import io.lumine.xikage.mythicmobs.drops.IItemDrop;
|
||||||
import io.lumine.xikage.mythicmobs.drops.LootBag;
|
import io.lumine.xikage.mythicmobs.drops.LootBag;
|
||||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
import net.Indyuce.mmocore.loot.LootBuilder;
|
||||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||||
|
|
||||||
public class MMDropTableDropItem extends DropItem {
|
public class MMDropTableDropItem extends DropItem {
|
@ -1,6 +1,6 @@
|
|||||||
package net.Indyuce.mmocore.api.droptable.dropitem;
|
package net.Indyuce.mmocore.loot.droptable.dropitem;
|
||||||
|
|
||||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
import net.Indyuce.mmocore.loot.LootBuilder;
|
||||||
import net.Indyuce.mmocore.api.util.item.CurrencyItem;
|
import net.Indyuce.mmocore.api.util.item.CurrencyItem;
|
||||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||||
|
|
@ -1,9 +1,9 @@
|
|||||||
package net.Indyuce.mmocore.api.droptable.dropitem;
|
package net.Indyuce.mmocore.loot.droptable.dropitem;
|
||||||
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
import net.Indyuce.mmocore.loot.LootBuilder;
|
||||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||||
|
|
||||||
public class VanillaDropItem extends DropItem {
|
public class VanillaDropItem extends DropItem {
|
@ -1,11 +1,11 @@
|
|||||||
package net.Indyuce.mmocore.api.droptable.dropitem.fishing;
|
package net.Indyuce.mmocore.loot.droptable.dropitem.fishing;
|
||||||
|
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang.Validate;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.droptable.dropitem.DropItem;
|
import net.Indyuce.mmocore.loot.droptable.dropitem.DropItem;
|
||||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
import net.Indyuce.mmocore.loot.LootBuilder;
|
||||||
import net.Indyuce.mmocore.api.util.math.formula.RandomAmount;
|
import net.Indyuce.mmocore.api.util.math.formula.RandomAmount;
|
||||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||||
|
|
@ -22,164 +22,163 @@ import java.util.List;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
public class ConfigManager {
|
public class ConfigManager {
|
||||||
public final CommandVerbose commandVerbose = new CommandVerbose();
|
public final CommandVerbose commandVerbose = new CommandVerbose();
|
||||||
|
|
||||||
public boolean overrideVanillaExp, canCreativeCast, cobbleGeneratorXP, saveDefaultClassInfo;
|
public boolean overrideVanillaExp, canCreativeCast, cobbleGeneratorXP, saveDefaultClassInfo;
|
||||||
public double expPartyBuff, regenPartyBuff;
|
public String partyChatPrefix, noSkillBoundPlaceholder;
|
||||||
public String partyChatPrefix, noSkillBoundPlaceholder;
|
public ChatColor staminaFull, staminaHalf, staminaEmpty;
|
||||||
public ChatColor staminaFull, staminaHalf, staminaEmpty;
|
public long combatLogTimer, lootChestExpireTime, lootChestPlayerCooldown;
|
||||||
public long combatLogTimer, lootChestExpireTime, lootChestPlayerCooldown;
|
public SwapAction normalSwapAction, sneakingSwapAction;
|
||||||
public SwapAction normalSwapAction, sneakingSwapAction;
|
|
||||||
|
|
||||||
private final FileConfiguration messages;
|
private final FileConfiguration messages;
|
||||||
private final boolean chatInput;
|
private final boolean chatInput;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* the instance must be created after the other managers since all it does
|
* the instance must be created after the other managers since all it does
|
||||||
* is to update them based on the config except for the classes which are
|
* is to update them based on the config except for the classes which are
|
||||||
* already loaded based on the config
|
* already loaded based on the config
|
||||||
*/
|
*/
|
||||||
public ConfigManager() {
|
public ConfigManager() {
|
||||||
// loadDefaultFile("recipes", "brewing.yml");
|
// loadDefaultFile("recipes", "brewing.yml");
|
||||||
// loadDefaultFile("recipes", "furnace.yml");
|
// loadDefaultFile("recipes", "furnace.yml");
|
||||||
|
|
||||||
if (!new File(MMOCore.plugin.getDataFolder() + "/drop-tables").exists())
|
if (!new File(MMOCore.plugin.getDataFolder() + "/drop-tables").exists())
|
||||||
loadDefaultFile("drop-tables", "example-drop-tables.yml");
|
loadDefaultFile("drop-tables", "example-drop-tables.yml");
|
||||||
|
|
||||||
if (!new File(MMOCore.plugin.getDataFolder() + "/professions").exists()) {
|
if (!new File(MMOCore.plugin.getDataFolder() + "/professions").exists()) {
|
||||||
loadDefaultFile("professions", "alchemy.yml");
|
loadDefaultFile("professions", "alchemy.yml");
|
||||||
loadDefaultFile("professions", "farming.yml");
|
loadDefaultFile("professions", "farming.yml");
|
||||||
loadDefaultFile("professions", "fishing.yml");
|
loadDefaultFile("professions", "fishing.yml");
|
||||||
loadDefaultFile("professions", "mining.yml");
|
loadDefaultFile("professions", "mining.yml");
|
||||||
loadDefaultFile("professions", "smelting.yml");
|
loadDefaultFile("professions", "smelting.yml");
|
||||||
loadDefaultFile("professions", "smithing.yml");
|
loadDefaultFile("professions", "smithing.yml");
|
||||||
loadDefaultFile("professions", "woodcutting.yml");
|
loadDefaultFile("professions", "woodcutting.yml");
|
||||||
loadDefaultFile("professions", "enchanting.yml");
|
loadDefaultFile("professions", "enchanting.yml");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!new File(MMOCore.plugin.getDataFolder() + "/quests").exists()) {
|
if (!new File(MMOCore.plugin.getDataFolder() + "/quests").exists()) {
|
||||||
loadDefaultFile("quests", "adv-begins.yml");
|
loadDefaultFile("quests", "adv-begins.yml");
|
||||||
loadDefaultFile("quests", "tutorial.yml");
|
loadDefaultFile("quests", "tutorial.yml");
|
||||||
loadDefaultFile("quests", "fetch-mango.yml");
|
loadDefaultFile("quests", "fetch-mango.yml");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!new File(MMOCore.plugin.getDataFolder() + "/classes").exists()) {
|
if (!new File(MMOCore.plugin.getDataFolder() + "/classes").exists()) {
|
||||||
loadDefaultFile("classes", "arcane-mage.yml");
|
loadDefaultFile("classes", "arcane-mage.yml");
|
||||||
loadDefaultFile("classes", "human.yml");
|
loadDefaultFile("classes", "human.yml");
|
||||||
loadDefaultFile("classes", "mage.yml");
|
loadDefaultFile("classes", "mage.yml");
|
||||||
loadDefaultFile("classes", "marksman.yml");
|
loadDefaultFile("classes", "marksman.yml");
|
||||||
loadDefaultFile("classes", "paladin.yml");
|
loadDefaultFile("classes", "paladin.yml");
|
||||||
loadDefaultFile("classes", "rogue.yml");
|
loadDefaultFile("classes", "rogue.yml");
|
||||||
loadDefaultFile("classes", "warrior.yml");
|
loadDefaultFile("classes", "warrior.yml");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!new File(MMOCore.plugin.getDataFolder() + "/expcurves").exists()) {
|
if (!new File(MMOCore.plugin.getDataFolder() + "/expcurves").exists()) {
|
||||||
loadDefaultFile("expcurves", "levels.txt");
|
loadDefaultFile("expcurves", "levels.txt");
|
||||||
loadDefaultFile("expcurves", "mining.txt");
|
loadDefaultFile("expcurves", "mining.txt");
|
||||||
}
|
}
|
||||||
|
|
||||||
loadDefaultFile("attributes.yml");
|
loadDefaultFile("attributes.yml");
|
||||||
loadDefaultFile("items.yml");
|
loadDefaultFile("items.yml");
|
||||||
loadDefaultFile("messages.yml");
|
loadDefaultFile("messages.yml");
|
||||||
loadDefaultFile("stats.yml");
|
loadDefaultFile("stats.yml");
|
||||||
loadDefaultFile("waypoints.yml");
|
loadDefaultFile("waypoints.yml");
|
||||||
loadDefaultFile("restrictions.yml");
|
loadDefaultFile("restrictions.yml");
|
||||||
loadDefaultFile("sounds.yml");
|
loadDefaultFile("sounds.yml");
|
||||||
loadDefaultFile("loot-chests.yml");
|
loadDefaultFile("loot-chests.yml");
|
||||||
loadDefaultFile("commands.yml");
|
loadDefaultFile("commands.yml");
|
||||||
loadDefaultFile("guilds.yml");
|
loadDefaultFile("guilds.yml");
|
||||||
|
|
||||||
commandVerbose.reload(MMOCore.plugin.getConfig().getConfigurationSection("command-verbose"));
|
commandVerbose.reload(MMOCore.plugin.getConfig().getConfigurationSection("command-verbose"));
|
||||||
|
|
||||||
messages = new ConfigFile("messages").getConfig();
|
messages = new ConfigFile("messages").getConfig();
|
||||||
chatInput = MMOCore.plugin.getConfig().getBoolean("use-chat-input");
|
chatInput = MMOCore.plugin.getConfig().getBoolean("use-chat-input");
|
||||||
partyChatPrefix = MMOCore.plugin.getConfig().getString("party.chat-prefix");
|
partyChatPrefix = MMOCore.plugin.getConfig().getString("party.chat-prefix");
|
||||||
combatLogTimer = MMOCore.plugin.getConfig().getInt("combat-log.timer") * 1000L;
|
combatLogTimer = MMOCore.plugin.getConfig().getInt("combat-log.timer") * 1000L;
|
||||||
lootChestExpireTime = Math.max(MMOCore.plugin.getConfig().getInt("loot-chests.chest-expire-time"), 1) * 1000L;
|
lootChestExpireTime = Math.max(MMOCore.plugin.getConfig().getInt("loot-chests.chest-expire-time"), 1) * 1000L;
|
||||||
lootChestPlayerCooldown = MMOCore.plugin.getConfig().getInt("player-cooldown") * 1000L;
|
lootChestPlayerCooldown = (long) MMOCore.plugin.getConfig().getDouble("player-cooldown") * 1000L;
|
||||||
noSkillBoundPlaceholder = getSimpleMessage("no-skill-placeholder").message();
|
noSkillBoundPlaceholder = getSimpleMessage("no-skill-placeholder").message();
|
||||||
|
|
||||||
staminaFull = getColorOrDefault("stamina-whole", ChatColor.GREEN);
|
staminaFull = getColorOrDefault("stamina-whole", ChatColor.GREEN);
|
||||||
staminaHalf = getColorOrDefault("stamina-half", ChatColor.DARK_GREEN);
|
staminaHalf = getColorOrDefault("stamina-half", ChatColor.DARK_GREEN);
|
||||||
staminaEmpty = getColorOrDefault("stamina-empty", ChatColor.WHITE);
|
staminaEmpty = getColorOrDefault("stamina-empty", ChatColor.WHITE);
|
||||||
|
|
||||||
normalSwapAction = EnumUtils.getIfPresent(SwapAction.class, MMOCore.plugin.getConfig().getString("swap-keybind.normal").toUpperCase()).orElse(SwapAction.VANILLA);
|
normalSwapAction = EnumUtils.getIfPresent(SwapAction.class, MMOCore.plugin.getConfig().getString("swap-keybind.normal").toUpperCase()).orElse(SwapAction.VANILLA);
|
||||||
sneakingSwapAction = EnumUtils.getIfPresent(SwapAction.class, MMOCore.plugin.getConfig().getString("swap-keybind.sneaking").toUpperCase()).orElse(SwapAction.VANILLA);
|
sneakingSwapAction = EnumUtils.getIfPresent(SwapAction.class, MMOCore.plugin.getConfig().getString("swap-keybind.sneaking").toUpperCase()).orElse(SwapAction.VANILLA);
|
||||||
canCreativeCast = MMOCore.plugin.getConfig().getBoolean("can-creative-cast");
|
canCreativeCast = MMOCore.plugin.getConfig().getBoolean("can-creative-cast");
|
||||||
cobbleGeneratorXP = MMOCore.plugin.getConfig().getBoolean("should-cobblestone-generators-give-exp");
|
cobbleGeneratorXP = MMOCore.plugin.getConfig().getBoolean("should-cobblestone-generators-give-exp");
|
||||||
saveDefaultClassInfo = MMOCore.plugin.getConfig().getBoolean("save-default-class-info");
|
saveDefaultClassInfo = MMOCore.plugin.getConfig().getBoolean("save-default-class-info");
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChatColor getColorOrDefault(String key, ChatColor defaultColor) {
|
private ChatColor getColorOrDefault(String key, ChatColor defaultColor) {
|
||||||
try {
|
try {
|
||||||
return ChatColor.valueOf(MMOCore.plugin.getConfig().getString("resource-bar-colors." + key).toUpperCase());
|
return ChatColor.valueOf(MMOCore.plugin.getConfig().getString("resource-bar-colors." + key).toUpperCase());
|
||||||
} catch (IllegalArgumentException exception) {
|
} catch (IllegalArgumentException exception) {
|
||||||
MMOCore.log(Level.WARNING, "Could not read resource bar color from '" + key + "': using default.");
|
MMOCore.log(Level.WARNING, "Could not read resource bar color from '" + key + "': using default.");
|
||||||
return defaultColor;
|
return defaultColor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayerInput newPlayerInput(Player player, InputType type, Consumer<String> output) {
|
public PlayerInput newPlayerInput(Player player, InputType type, Consumer<String> output) {
|
||||||
return chatInput ? new ChatInput(player, type, output) : new AnvilGUI(player, type, output);
|
return chatInput ? new ChatInput(player, type, output) : new AnvilGUI(player, type, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadDefaultFile(String name) {
|
public void loadDefaultFile(String name) {
|
||||||
loadDefaultFile("", name);
|
loadDefaultFile("", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadDefaultFile(String path, String name) {
|
public void loadDefaultFile(String path, String name) {
|
||||||
String newPath = path.isEmpty() ? "" : "/" + path;
|
String newPath = path.isEmpty() ? "" : "/" + path;
|
||||||
File folder = new File(MMOCore.plugin.getDataFolder() + (newPath));
|
File folder = new File(MMOCore.plugin.getDataFolder() + (newPath));
|
||||||
if (!folder.exists()) folder.mkdir();
|
if (!folder.exists()) folder.mkdir();
|
||||||
|
|
||||||
File file = new File(MMOCore.plugin.getDataFolder() + (newPath), name);
|
File file = new File(MMOCore.plugin.getDataFolder() + (newPath), name);
|
||||||
if (!file.exists()) try {
|
if (!file.exists()) try {
|
||||||
Files.copy(MMOCore.plugin.getResource("default/" + (path.isEmpty() ? "" : path + "/") + name), file.getAbsoluteFile().toPath());
|
Files.copy(MMOCore.plugin.getResource("default/" + (path.isEmpty() ? "" : path + "/") + name), file.getAbsoluteFile().toPath());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getMessage(String key) {
|
public List<String> getMessage(String key) {
|
||||||
return messages.getStringList(key);
|
return messages.getStringList(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SimpleMessage getSimpleMessage(String key, String... placeholders) {
|
public SimpleMessage getSimpleMessage(String key, String... placeholders) {
|
||||||
String format = messages.getString(key, "");
|
String format = messages.getString(key, "");
|
||||||
for (int j = 0; j < placeholders.length - 1; j += 2)
|
for (int j = 0; j < placeholders.length - 1; j += 2)
|
||||||
format = format.replace("{" + placeholders[j] + "}", placeholders[j + 1]);
|
format = format.replace("{" + placeholders[j] + "}", placeholders[j + 1]);
|
||||||
return new SimpleMessage(MythicLib.plugin.parseColors(format));
|
return new SimpleMessage(MythicLib.plugin.parseColors(format));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SimpleMessage {
|
public static class SimpleMessage {
|
||||||
private final String message;
|
private final String message;
|
||||||
private final boolean actionbar;
|
private final boolean actionbar;
|
||||||
private final boolean hasPlaceholders;
|
private final boolean hasPlaceholders;
|
||||||
|
|
||||||
public SimpleMessage(String message) {
|
public SimpleMessage(String message) {
|
||||||
this.actionbar = message.startsWith("%");
|
this.actionbar = message.startsWith("%");
|
||||||
this.message = actionbar ? message.substring(1) : message;
|
this.message = actionbar ? message.substring(1) : message;
|
||||||
this.hasPlaceholders = this.message.contains("%");
|
this.hasPlaceholders = this.message.contains("%");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String message() {
|
public String message() {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean send(Player player) {
|
public boolean send(Player player) {
|
||||||
String msg = hasPlaceholders ? MMOCore.plugin.placeholderParser.parse(player, message) : message;
|
String msg = hasPlaceholders ? MMOCore.plugin.placeholderParser.parse(player, message) : message;
|
||||||
|
|
||||||
if (!msg.isEmpty()) {
|
if (!msg.isEmpty()) {
|
||||||
if (actionbar) PlayerData.get(player.getUniqueId()).displayActionBar(msg);
|
if (actionbar) PlayerData.get(player.getUniqueId()).displayActionBar(msg);
|
||||||
else player.sendMessage(msg);
|
else player.sendMessage(msg);
|
||||||
}
|
}
|
||||||
return !msg.isEmpty();
|
return !msg.isEmpty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum SwapAction {
|
public enum SwapAction {
|
||||||
VANILLA,
|
VANILLA,
|
||||||
SPELL_CAST,
|
SPELL_CAST,
|
||||||
HOTBAR_SWAP
|
HOTBAR_SWAP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@ import net.Indyuce.mmocore.api.block.BlockInfo.RegeneratingBlock;
|
|||||||
import net.Indyuce.mmocore.api.block.BlockType;
|
import net.Indyuce.mmocore.api.block.BlockType;
|
||||||
import net.Indyuce.mmocore.api.block.SkullBlockType;
|
import net.Indyuce.mmocore.api.block.SkullBlockType;
|
||||||
import net.Indyuce.mmocore.api.block.VanillaBlockType;
|
import net.Indyuce.mmocore.api.block.VanillaBlockType;
|
||||||
import net.Indyuce.mmocore.api.droptable.condition.Condition;
|
import net.Indyuce.mmocore.loot.droptable.condition.Condition;
|
||||||
import net.Indyuce.mmocore.api.droptable.condition.ConditionInstance;
|
import net.Indyuce.mmocore.loot.droptable.condition.ConditionInstance;
|
||||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
@ -14,7 +14,7 @@ import org.bukkit.configuration.file.FileConfiguration;
|
|||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.droptable.DropTable;
|
import net.Indyuce.mmocore.loot.droptable.DropTable;
|
||||||
|
|
||||||
public class DropTableManager implements MMOManager {
|
public class DropTableManager implements MMOManager {
|
||||||
private final Map<String, DropTable> map = new HashMap<>();
|
private final Map<String, DropTable> map = new HashMap<>();
|
||||||
|
@ -12,8 +12,8 @@ import org.bukkit.configuration.file.FileConfiguration;
|
|||||||
|
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.ConfigFile;
|
import net.Indyuce.mmocore.api.ConfigFile;
|
||||||
import net.Indyuce.mmocore.api.loot.LootChest;
|
import net.Indyuce.mmocore.loot.chest.LootChest;
|
||||||
import net.Indyuce.mmocore.api.loot.LootChestRegion;
|
import net.Indyuce.mmocore.loot.chest.LootChestRegion;
|
||||||
|
|
||||||
public class LootChestManager {
|
public class LootChestManager {
|
||||||
|
|
||||||
|
@ -11,8 +11,8 @@ import org.bukkit.configuration.ConfigurationSection;
|
|||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
|
|
||||||
import net.Indyuce.mmocore.api.block.BlockType;
|
import net.Indyuce.mmocore.api.block.BlockType;
|
||||||
import net.Indyuce.mmocore.api.droptable.condition.Condition;
|
import net.Indyuce.mmocore.loot.droptable.condition.Condition;
|
||||||
import net.Indyuce.mmocore.api.droptable.dropitem.DropItem;
|
import net.Indyuce.mmocore.loot.droptable.dropitem.DropItem;
|
||||||
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
|
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
|
||||||
import net.Indyuce.mmocore.api.load.DefaultMMOLoader;
|
import net.Indyuce.mmocore.api.load.DefaultMMOLoader;
|
||||||
import net.Indyuce.mmocore.api.load.MMOLoader;
|
import net.Indyuce.mmocore.api.load.MMOLoader;
|
||||||
|
@ -13,9 +13,9 @@ import org.bukkit.configuration.ConfigurationSection;
|
|||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
|
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.droptable.condition.Condition;
|
import net.Indyuce.mmocore.loot.droptable.condition.Condition;
|
||||||
import net.Indyuce.mmocore.api.droptable.condition.ConditionInstance;
|
import net.Indyuce.mmocore.loot.droptable.condition.ConditionInstance;
|
||||||
import net.Indyuce.mmocore.api.droptable.dropitem.fishing.FishingDropItem;
|
import net.Indyuce.mmocore.loot.droptable.dropitem.fishing.FishingDropItem;
|
||||||
import net.Indyuce.mmocore.manager.MMOManager;
|
import net.Indyuce.mmocore.manager.MMOManager;
|
||||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user