mirror of
https://gitlab.com/phoenix-dvpmt/mmocore.git
synced 2024-11-24 00:15:16 +01:00
!API needed for loot chests
This commit is contained in:
parent
25b350c09a
commit
d8af4ba8bc
BIN
lib/MMOLib.jar
BIN
lib/MMOLib.jar
Binary file not shown.
@ -2,6 +2,7 @@ package net.Indyuce.mmocore;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashSet;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
@ -13,6 +14,7 @@ import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import net.Indyuce.mmocore.api.ConfigFile;
|
||||
import net.Indyuce.mmocore.api.PlayerActionBar;
|
||||
import net.Indyuce.mmocore.api.loot.LootChest;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
|
||||
import net.Indyuce.mmocore.api.player.social.guilds.Guild;
|
||||
@ -72,7 +74,7 @@ import net.Indyuce.mmocore.manager.DropTableManager;
|
||||
import net.Indyuce.mmocore.manager.EntityManager;
|
||||
import net.Indyuce.mmocore.manager.ExperienceManager;
|
||||
import net.Indyuce.mmocore.manager.InventoryManager;
|
||||
import net.Indyuce.mmocore.manager.LootableChestManager;
|
||||
import net.Indyuce.mmocore.manager.LootChestManager;
|
||||
import net.Indyuce.mmocore.manager.MMOLoadManager;
|
||||
import net.Indyuce.mmocore.manager.QuestManager;
|
||||
import net.Indyuce.mmocore.manager.RestrictionManager;
|
||||
@ -101,7 +103,6 @@ public class MMOCore extends JavaPlugin {
|
||||
public ConfigManager configManager;
|
||||
public WaypointManager waypointManager;
|
||||
public RestrictionManager restrictionManager;
|
||||
public LootableChestManager chestManager;
|
||||
public RequestManager requestManager;
|
||||
public ConfigItemManager configItems;
|
||||
public SkillManager skillManager;
|
||||
@ -122,6 +123,7 @@ public class MMOCore extends JavaPlugin {
|
||||
public final ProfessionManager professionManager = new ProfessionManager();
|
||||
public final EntityManager entities = new EntityManager();
|
||||
public final ExperienceManager experience = new ExperienceManager();
|
||||
public final LootChestManager lootChests = new LootChestManager();
|
||||
|
||||
/*
|
||||
* professions
|
||||
@ -235,6 +237,20 @@ public class MMOCore extends JavaPlugin {
|
||||
}
|
||||
}.runTaskTimer(MMOCore.plugin, 100, 20);
|
||||
|
||||
/*
|
||||
* clean active loot chests every 5 minutes. cannot register this
|
||||
* runnable in the loot chest manager because it is instanced when the
|
||||
* plugin loads
|
||||
*/
|
||||
new BukkitRunnable() {
|
||||
public void run() {
|
||||
for (LootChest chest : new HashSet<>(lootChests.getActive()))
|
||||
if (chest.shouldExpire())
|
||||
chest.unregister(false);
|
||||
|
||||
}
|
||||
}.runTaskTimer(this, 5 * 60 * 20, 5 * 60 * 20);
|
||||
|
||||
/*
|
||||
* For the sake of the lord, make sure they aren't using MMOItems Mana
|
||||
* and Stamina Addon...This should prevent a couple error reports
|
||||
@ -360,6 +376,8 @@ public class MMOCore extends JavaPlugin {
|
||||
dataProvider.getGuildManager().save(guild);
|
||||
|
||||
mineManager.resetRemainingBlocks();
|
||||
|
||||
lootChests.getActive().forEach(chest -> chest.unregister(false));
|
||||
}
|
||||
|
||||
public void reloadPlugin() {
|
||||
@ -396,7 +414,8 @@ public class MMOCore extends JavaPlugin {
|
||||
questManager.clear();
|
||||
questManager.reload();
|
||||
|
||||
chestManager = new LootableChestManager(new ConfigFile("chests").getConfig());
|
||||
lootChests.reload();
|
||||
|
||||
waypointManager = new WaypointManager(new ConfigFile("waypoints").getConfig());
|
||||
restrictionManager = new RestrictionManager(new ConfigFile("restrictions").getConfig());
|
||||
requestManager = new RequestManager();
|
||||
|
@ -13,6 +13,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.droptable.DropTable;
|
||||
import net.Indyuce.mmocore.api.load.MMOLoadException;
|
||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
||||
import net.Indyuce.mmocore.api.quest.trigger.ExperienceTrigger;
|
||||
import net.Indyuce.mmocore.api.quest.trigger.Trigger;
|
||||
import net.mmogroup.mmolib.api.MMOLineConfig;
|
||||
@ -76,8 +77,8 @@ public class BlockInfo {
|
||||
return table;
|
||||
}
|
||||
|
||||
public List<ItemStack> collectDrops() {
|
||||
return hasDropTable() ? table.collect() : new ArrayList<>();
|
||||
public List<ItemStack> collectDrops(LootBuilder builder) {
|
||||
return hasDropTable() ? table.collect(builder) : new ArrayList<>();
|
||||
}
|
||||
|
||||
public boolean hasDropTable() {
|
||||
|
@ -1,7 +1,6 @@
|
||||
package net.Indyuce.mmocore.api.droptable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@ -12,11 +11,12 @@ import org.bukkit.inventory.ItemStack;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.droptable.dropitem.DropItem;
|
||||
import net.Indyuce.mmocore.api.load.MMOLoadException;
|
||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
||||
import net.mmogroup.mmolib.api.MMOLineConfig;
|
||||
|
||||
public class DropTable {
|
||||
private final String id;
|
||||
private final Set<DropItem> drops = new HashSet<>();
|
||||
private final Set<DropItem> drops = new LinkedHashSet<>();
|
||||
|
||||
/*
|
||||
* cached in order to load other items.
|
||||
@ -52,13 +52,14 @@ public class DropTable {
|
||||
return id;
|
||||
}
|
||||
|
||||
public List<ItemStack> collect() {
|
||||
List<ItemStack> total = new ArrayList<>();
|
||||
public List<ItemStack> collect(LootBuilder builder) {
|
||||
|
||||
for (DropItem item : drops)
|
||||
if (item.rollChance())
|
||||
item.collect(total);
|
||||
if (item.rollChance() && builder.getCapacity() >= item.getWeight()) {
|
||||
item.collect(builder);
|
||||
builder.reduceCapacity(item.getWeight());
|
||||
}
|
||||
|
||||
return total;
|
||||
return builder.getLoot();
|
||||
}
|
||||
}
|
@ -1,22 +1,21 @@
|
||||
package net.Indyuce.mmocore.api.droptable.dropitem;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.RandomAmount;
|
||||
import net.mmogroup.mmolib.api.MMOLineConfig;
|
||||
|
||||
public abstract class DropItem {
|
||||
protected static final Random random = new Random();
|
||||
|
||||
private double chance;
|
||||
private RandomAmount amount;
|
||||
private final double chance, weight;
|
||||
private final RandomAmount amount;
|
||||
|
||||
public DropItem(MMOLineConfig config) {
|
||||
chance = config.args().length > 0 ? Double.parseDouble(config.args()[0]) : 1;
|
||||
amount = config.args().length > 1 ? new RandomAmount(config.args()[1]) : new RandomAmount(1, 0);
|
||||
weight = config.args().length > 2 ? Double.parseDouble(config.args()[2]) : 0;
|
||||
}
|
||||
|
||||
public RandomAmount getAmount() {
|
||||
@ -27,6 +26,10 @@ public abstract class DropItem {
|
||||
return chance;
|
||||
}
|
||||
|
||||
public double getWeight() {
|
||||
return weight;
|
||||
}
|
||||
|
||||
public int rollAmount() {
|
||||
return amount.calculateInt();
|
||||
}
|
||||
@ -35,5 +38,5 @@ public abstract class DropItem {
|
||||
return random.nextDouble() < chance;
|
||||
}
|
||||
|
||||
public abstract void collect(List<ItemStack> total);
|
||||
public abstract void collect(LootBuilder builder);
|
||||
}
|
||||
|
@ -1,16 +1,14 @@
|
||||
package net.Indyuce.mmocore.api.droptable.dropitem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.droptable.DropTable;
|
||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
||||
import net.mmogroup.mmolib.api.MMOLineConfig;
|
||||
|
||||
public class DropTableDropItem extends DropItem {
|
||||
private DropTable dropTable;
|
||||
private final DropTable dropTable;
|
||||
|
||||
public DropTableDropItem(MMOLineConfig config) {
|
||||
super(config);
|
||||
@ -23,8 +21,8 @@ public class DropTableDropItem extends DropItem {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collect(List<ItemStack> total) {
|
||||
public void collect(LootBuilder builder) {
|
||||
for (int j = 0; j < rollAmount(); j++)
|
||||
total.addAll(dropTable.collect());
|
||||
builder.addLoot(dropTable.collect(builder));
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,6 @@
|
||||
package net.Indyuce.mmocore.api.droptable.dropitem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
||||
import net.Indyuce.mmocore.api.util.item.CurrencyItem;
|
||||
import net.mmogroup.mmolib.api.MMOLineConfig;
|
||||
|
||||
@ -13,7 +10,7 @@ public class GoldDropItem extends DropItem {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collect(List<ItemStack> total) {
|
||||
total.add(new CurrencyItem("GOLD_COIN", 1, rollAmount()).build());
|
||||
public void collect(LootBuilder builder) {
|
||||
builder.addLoot(new CurrencyItem("GOLD_COIN", 1, rollAmount()).build());
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,6 @@
|
||||
package net.Indyuce.mmocore.api.droptable.dropitem;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.lumine.xikage.mythicmobs.MythicMobs;
|
||||
import io.lumine.xikage.mythicmobs.adapters.bukkit.BukkitAdapter;
|
||||
@ -13,12 +9,13 @@ import io.lumine.xikage.mythicmobs.drops.DropMetadata;
|
||||
import io.lumine.xikage.mythicmobs.drops.DropTable;
|
||||
import io.lumine.xikage.mythicmobs.drops.IItemDrop;
|
||||
import io.lumine.xikage.mythicmobs.drops.LootBag;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
||||
import net.mmogroup.mmolib.api.MMOLineConfig;
|
||||
|
||||
public class MMDropTableDropItem extends DropItem {
|
||||
private DropTable dropTable;
|
||||
private DropMetadata metadata = new DropMetadata(null, null);
|
||||
private final DropTable dropTable;
|
||||
|
||||
private static final DropMetadata metadata = new DropMetadata(null, null);
|
||||
|
||||
public MMDropTableDropItem(MMOLineConfig config) {
|
||||
super(config);
|
||||
@ -28,19 +25,16 @@ public class MMDropTableDropItem extends DropItem {
|
||||
|
||||
try {
|
||||
dropTable = MythicMobs.inst().getDropManager().getDropTable(id).get();
|
||||
} catch(NoSuchElementException e) {
|
||||
MMOCore.log(Level.WARNING, "Could not find MM drop table" + id);
|
||||
} catch (NoSuchElementException exception) {
|
||||
throw new IllegalArgumentException("Could not find MM drop table with ID '" + id + "'");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collect(List<ItemStack> total) {
|
||||
public void collect(LootBuilder builder) {
|
||||
LootBag lootBag = dropTable.generate(metadata);
|
||||
|
||||
for(Drop type : lootBag.getDrops()) {
|
||||
if(type instanceof IItemDrop) {
|
||||
total.add(BukkitAdapter.adapt(((IItemDrop)type).getDrop(metadata)));
|
||||
}
|
||||
}
|
||||
for (Drop type : lootBag.getDrops())
|
||||
if (type instanceof IItemDrop)
|
||||
builder.addLoot(BukkitAdapter.adapt(((IItemDrop) type).getDrop(metadata)));
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,11 @@
|
||||
package net.Indyuce.mmocore.api.droptable.dropitem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
||||
import net.Indyuce.mmocore.api.util.item.CurrencyItem;
|
||||
import net.mmogroup.mmolib.api.MMOLineConfig;
|
||||
|
||||
public class NoteDropItem extends DropItem {
|
||||
private int min, max;
|
||||
private final int min, max;
|
||||
|
||||
public NoteDropItem(MMOLineConfig config) {
|
||||
super(config);
|
||||
@ -20,7 +17,7 @@ public class NoteDropItem extends DropItem {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collect(List<ItemStack> total) {
|
||||
total.add(new CurrencyItem("NOTE", random.nextInt(max - min + 1) + min, rollAmount()).build());
|
||||
public void collect(LootBuilder builder) {
|
||||
builder.addLoot(new CurrencyItem("NOTE", random.nextInt(max - min + 1) + min, rollAmount()).build());
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,9 @@
|
||||
package net.Indyuce.mmocore.api.droptable.dropitem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
||||
import net.mmogroup.mmolib.api.MMOLineConfig;
|
||||
|
||||
public class VanillaDropItem extends DropItem {
|
||||
@ -16,13 +15,13 @@ public class VanillaDropItem extends DropItem {
|
||||
config.validate("type");
|
||||
this.material = Material.valueOf(config.getString("type"));
|
||||
}
|
||||
|
||||
|
||||
public Material getMaterial() {
|
||||
return material;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collect(List<ItemStack> total) {
|
||||
total.add(new ItemStack(material, rollAmount()));
|
||||
public void collect(LootBuilder builder) {
|
||||
builder.addLoot(new ItemStack(material, rollAmount()));
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,10 @@
|
||||
package net.Indyuce.mmocore.api.droptable.dropitem.fishing;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.droptable.dropitem.DropItem;
|
||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.RandomAmount;
|
||||
import net.mmogroup.mmolib.api.MMOLineConfig;
|
||||
|
||||
@ -58,8 +56,8 @@ public class FishingDropItem {
|
||||
}
|
||||
|
||||
public ItemStack collect() {
|
||||
List<ItemStack> collect = new ArrayList<>();
|
||||
dropItem.collect(collect);
|
||||
return collect.stream().findAny().get();
|
||||
LootBuilder builder = new LootBuilder(null, 0);
|
||||
dropItem.collect(builder);
|
||||
return builder.getLoot().stream().findAny().get();
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import net.Indyuce.mmocore.api.block.BlockInfo;
|
||||
import net.Indyuce.mmocore.api.experience.ExperienceInfo;
|
||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
|
||||
public class CustomBlockMineEvent extends PlayerDataEvent implements Cancellable {
|
||||
@ -24,7 +25,7 @@ public class CustomBlockMineEvent extends PlayerDataEvent implements Cancellable
|
||||
super(player);
|
||||
|
||||
this.block = block;
|
||||
this.drops = info.collectDrops();
|
||||
this.drops = info.collectDrops(new LootBuilder(player, 0));
|
||||
this.experience = info.hasExperience() ? info.getExperience().newInfo() : null;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,51 @@
|
||||
package net.Indyuce.mmocore.api.event;
|
||||
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
||||
import net.Indyuce.mmocore.api.loot.LootChest;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
|
||||
public class LootChestSpawnEvent extends PlayerDataEvent implements Cancellable {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private final LootChest chest;
|
||||
private final LootBuilder loot;
|
||||
|
||||
private boolean cancelled;
|
||||
|
||||
public LootChestSpawnEvent(PlayerData playerData, LootChest chest, LootBuilder loot) {
|
||||
super(playerData);
|
||||
|
||||
this.chest = chest;
|
||||
this.loot = loot;
|
||||
}
|
||||
|
||||
public LootChest getChest() {
|
||||
return chest;
|
||||
}
|
||||
|
||||
public LootBuilder getLoot() {
|
||||
return loot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancelled) {
|
||||
this.cancelled = cancelled;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package net.Indyuce.mmocore.api.loot;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
public class ChestAlgorithmOptions {
|
||||
|
||||
/*
|
||||
* 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,
|
||||
* relative to the player's altitude
|
||||
*/
|
||||
public final double minRange, maxRange, height;
|
||||
|
||||
/*
|
||||
* maximum amount of trials the algorithm will run in order to find a
|
||||
* suitable location for a chest around the player.
|
||||
*/
|
||||
public final int iterations;
|
||||
|
||||
public static final ChestAlgorithmOptions DEFAULT = new ChestAlgorithmOptions(10, 30, 8, 15);
|
||||
|
||||
/*
|
||||
* this is purely to let server owners tweak the chest random location
|
||||
* finder algorithm.
|
||||
*/
|
||||
public ChestAlgorithmOptions(ConfigurationSection config) {
|
||||
Validate.notNull(config, "Config cannot be nulm");
|
||||
|
||||
minRange = config.getDouble("min-range", DEFAULT.minRange);
|
||||
maxRange = config.getDouble("max-range", DEFAULT.maxRange);
|
||||
height = config.getDouble("height", DEFAULT.height);
|
||||
iterations = config.getInt("iterations", DEFAULT.iterations);
|
||||
|
||||
Validate.isTrue(minRange < maxRange, "Max range must be greater than min range");
|
||||
Validate.isTrue(height > 0, "Height 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
|
||||
* used by the default alg options instance
|
||||
*/
|
||||
public ChestAlgorithmOptions(double minRange, double maxRange, double height, int iterations) {
|
||||
this.minRange = minRange;
|
||||
this.maxRange = maxRange;
|
||||
this.height = height;
|
||||
this.iterations = iterations;
|
||||
}
|
||||
}
|
@ -1,24 +1,32 @@
|
||||
package net.Indyuce.mmocore.api.loot;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
import net.Indyuce.mmocore.api.util.math.particle.ChestParticleEffect;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.droptable.DropTable;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.mmogroup.mmolib.api.math.ScalingFormula;
|
||||
|
||||
public class ChestTier {
|
||||
private final TierEffect effect;
|
||||
private final int weight;
|
||||
private final ScalingFormula capacity;
|
||||
private final DropTable table;
|
||||
|
||||
public final double chance;
|
||||
|
||||
public ChestTier(ConfigurationSection config) {
|
||||
effect = config.isConfigurationSection("effect") ? new TierEffect(config.getConfigurationSection("effect"))
|
||||
: null;
|
||||
weight = config.getInt("weight", 1);
|
||||
effect = config.isConfigurationSection("effect") ? new TierEffect(config.getConfigurationSection("effect")) : null;
|
||||
capacity = new ScalingFormula(config.get("capacity"));
|
||||
chance = config.getDouble("chance");
|
||||
table = MMOCore.plugin.dropTableManager.loadDropTable(config.get("drops"));
|
||||
}
|
||||
|
||||
public int getWeight() {
|
||||
return weight;
|
||||
|
||||
public double rollCapacity(PlayerData player) {
|
||||
return capacity.calculate(player.getLevel());
|
||||
}
|
||||
|
||||
public DropTable getDropTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
public boolean hasEffect() {
|
||||
@ -28,21 +36,4 @@ public class ChestTier {
|
||||
public TierEffect getEffect() {
|
||||
return effect;
|
||||
}
|
||||
|
||||
public class TierEffect {
|
||||
private final ChestParticleEffect type;
|
||||
private final Particle particle;
|
||||
|
||||
public TierEffect(ConfigurationSection config) {
|
||||
Validate.notNull(config, "Could not load tier config");
|
||||
type = ChestParticleEffect
|
||||
.valueOf(config.getString("type", "OFFSET").toUpperCase().replace("-", "_").replace(" ", "_"));
|
||||
particle = Particle
|
||||
.valueOf(config.getString("particle", "FLAME").toUpperCase().replace("-", "_").replace(" ", "_"));
|
||||
}
|
||||
|
||||
public void play(Location loc) {
|
||||
type.play(loc, particle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
48
src/main/java/net/Indyuce/mmocore/api/loot/LootBuilder.java
Normal file
48
src/main/java/net/Indyuce/mmocore/api/loot/LootBuilder.java
Normal file
@ -0,0 +1,48 @@
|
||||
package net.Indyuce.mmocore.api.loot;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
|
||||
public class LootBuilder {
|
||||
private final PlayerData player;
|
||||
private final List<ItemStack> loot = new ArrayList<>();
|
||||
|
||||
private double capacity;
|
||||
|
||||
/*
|
||||
* instance which saves what entity is currently rolling a loot table and
|
||||
* how much item capacity the table has left
|
||||
*/
|
||||
public LootBuilder(PlayerData player, double capacity) {
|
||||
this.player = player;
|
||||
this.capacity = capacity;
|
||||
}
|
||||
|
||||
public PlayerData getEntity() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public List<ItemStack> getLoot() {
|
||||
return loot;
|
||||
}
|
||||
|
||||
public double getCapacity() {
|
||||
return capacity;
|
||||
}
|
||||
|
||||
public void addLoot(ItemStack item) {
|
||||
loot.add(item);
|
||||
}
|
||||
|
||||
public void addLoot(List<? extends ItemStack> items) {
|
||||
loot.addAll(items);
|
||||
}
|
||||
|
||||
public void reduceCapacity(double value) {
|
||||
this.capacity = Math.max(0, capacity - value);
|
||||
}
|
||||
}
|
@ -2,20 +2,37 @@ package net.Indyuce.mmocore.api.loot;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.Chest;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
|
||||
public class LootChest {
|
||||
private final ChestTier tier;
|
||||
private final LootChestRegion region;
|
||||
private final ReplacedBlock block;
|
||||
private final BukkitRunnable effectRunnable;
|
||||
private final long date = System.currentTimeMillis();
|
||||
|
||||
/*
|
||||
* saves data of block replaced
|
||||
* instance generated when a loot chest is placed (as a bukkit block), and
|
||||
* used to save the data of the block which has been replaced (can replace
|
||||
* non-solid blocks)
|
||||
*/
|
||||
private final ReplacedBlock block;
|
||||
|
||||
public LootChest(LootChestRegion region, Block block) {
|
||||
public LootChest(ChestTier tier, LootChestRegion region, Block block) {
|
||||
this.tier = tier;
|
||||
this.region = region;
|
||||
this.block = new ReplacedBlock(block);
|
||||
this.effectRunnable = tier.hasEffect() ? tier.getEffect().startNewRunnable(block.getLocation().add(.5, .5, .5)) : null;
|
||||
}
|
||||
|
||||
public ChestTier getTier() {
|
||||
return tier;
|
||||
}
|
||||
|
||||
public ReplacedBlock getBlock() {
|
||||
@ -26,6 +43,40 @@ public class LootChest {
|
||||
return region;
|
||||
}
|
||||
|
||||
public boolean hasPlayerNearby() {
|
||||
for (Player player : block.loc.getWorld().getPlayers())
|
||||
if (player.getLocation().distanceSquared(block.loc) < 625)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldExpire() {
|
||||
return System.currentTimeMillis() - date > MMOCore.plugin.configManager.lootChestExpireTime;
|
||||
}
|
||||
|
||||
public void unregister(boolean player) {
|
||||
|
||||
/*
|
||||
* if a player is responsible of closing the chest, close it with sound
|
||||
*/
|
||||
if (player) {
|
||||
block.loc.getWorld().playSound(block.loc, Sound.ITEM_ARMOR_EQUIP_LEATHER, 1, 1);
|
||||
block.loc.getWorld().spawnParticle(Particle.CRIT, block.loc.clone().add(.5, .5, .5), 16, 0, 0, 0, .5);
|
||||
MMOCore.plugin.lootChests.unregister(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* must clean block inventory before replacing block otherwise loots fly
|
||||
* off and accumulate on the ground (+during dev phase)
|
||||
*/
|
||||
else
|
||||
((Chest) block.loc.getBlock().getState()).getBlockInventory().clear();
|
||||
|
||||
block.restore();
|
||||
if (effectRunnable != null)
|
||||
effectRunnable.cancel();
|
||||
}
|
||||
|
||||
public class ReplacedBlock {
|
||||
private final Material material;
|
||||
private final BlockData data;
|
||||
@ -34,7 +85,16 @@ public class LootChest {
|
||||
public ReplacedBlock(Block block) {
|
||||
this.material = block.getType();
|
||||
this.data = block.getBlockData();
|
||||
loc = block.getLocation();
|
||||
this.loc = block.getLocation();
|
||||
}
|
||||
|
||||
public Location getLocoation() {
|
||||
return loc;
|
||||
}
|
||||
|
||||
public boolean matches(Location loc) {
|
||||
return this.loc.getWorld().equals(loc.getWorld()) && this.loc.getBlockX() == loc.getBlockX() && this.loc.getBlockY() == loc.getBlockY()
|
||||
&& this.loc.getBlockZ() == loc.getBlockZ();
|
||||
}
|
||||
|
||||
public void restore() {
|
||||
|
@ -1,31 +1,44 @@
|
||||
package net.Indyuce.mmocore.api.loot;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
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 net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.event.LootChestSpawnEvent;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
|
||||
public class LootChestRegion {
|
||||
private final String id;
|
||||
|
||||
private final long chestSpawnPeriod;
|
||||
private final RegionBounds bounds;
|
||||
private final Set<ChestTier> tiers = new HashSet<>();
|
||||
|
||||
/*
|
||||
* last time
|
||||
*/
|
||||
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();
|
||||
id = config.getName().toLowerCase().replace("_", "-").replace(" ", "-");
|
||||
|
||||
bounds = new RegionBounds(config.getConfigurationSection("bounds"));
|
||||
chestSpawnPeriod = config.getInt("spawn-period");
|
||||
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))
|
||||
@ -35,6 +48,10 @@ public class LootChestRegion {
|
||||
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() {
|
||||
@ -52,4 +69,101 @@ public class LootChestRegion {
|
||||
public long getChestSpawnPeriod() {
|
||||
return chestSpawnPeriod;
|
||||
}
|
||||
|
||||
public BukkitRunnable getRunnable() {
|
||||
return runnable;
|
||||
}
|
||||
|
||||
public void spawnChest(PlayerData player) {
|
||||
|
||||
// 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
|
||||
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().get();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,28 @@
|
||||
package net.Indyuce.mmocore.api.loot;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
|
||||
public class LootChestRunnable extends BukkitRunnable {
|
||||
private final LootChestRegion region;
|
||||
|
||||
public LootChestRunnable(LootChestRegion region) {
|
||||
this.region = region;
|
||||
|
||||
runTaskTimer(MMOCore.plugin, region.getChestSpawnPeriod() * 20, region.getChestSpawnPeriod() * 20);
|
||||
}
|
||||
|
||||
// TODO add option so that players cannot have more than X chests every X
|
||||
// time
|
||||
@Override
|
||||
public void run() {
|
||||
Optional<Player> found = region.getBounds().getPlayers().findAny();
|
||||
if (found.isPresent())
|
||||
region.spawnChest(PlayerData.get(found.get()));
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
package net.Indyuce.mmocore.api.loot;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Bukkit;
|
||||
@ -14,27 +13,28 @@ public class RegionBounds {
|
||||
private final World world;
|
||||
private final int x1, z1, x2, z2;
|
||||
|
||||
private static final Random random = new Random();
|
||||
|
||||
public RegionBounds(ConfigurationSection config) {
|
||||
Validate.notNull(config, "Could not load config");
|
||||
Validate.notNull(world = Bukkit.getWorld(config.getString("world")),
|
||||
"Could not find world " + config.getString("world"));
|
||||
x1 = config.getInt("x1");
|
||||
z1 = config.getInt("z1");
|
||||
Validate.notNull(world = Bukkit.getWorld(config.getString("world")), "Could not find world " + config.getString("world"));
|
||||
x1 = Math.min(config.getInt("x1"), config.getInt("x2"));
|
||||
x2 = Math.max(config.getInt("x1"), config.getInt("x2"));
|
||||
|
||||
x2 = config.getInt("x2");
|
||||
z2 = config.getInt("z2");
|
||||
z1 = Math.min(config.getInt("z1"), config.getInt("z2"));
|
||||
z2 = Math.max(config.getInt("z1"), config.getInt("z2"));
|
||||
}
|
||||
|
||||
public RegionBounds(Location loc1, Location loc2) {
|
||||
Validate.isTrue(loc1.getWorld().equals(loc2.getWorld()), "Locations must be in the same world");
|
||||
world = loc1.getWorld();
|
||||
x1 = loc1.getBlockX();
|
||||
z1 = loc1.getBlockZ();
|
||||
x1 = Math.min(loc1.getBlockX(), loc2.getBlockX());
|
||||
x2 = Math.max(loc1.getBlockX(), loc2.getBlockX());
|
||||
|
||||
x2 = loc2.getBlockX();
|
||||
z2 = loc2.getBlockZ();
|
||||
z1 = Math.min(loc1.getBlockZ(), loc2.getBlockZ());
|
||||
z2 = Math.max(loc1.getBlockZ(), loc2.getBlockZ());
|
||||
}
|
||||
|
||||
public Stream<Player> getPlayers() {
|
||||
return world.getPlayers().stream().filter(player -> isInRegion(player));
|
||||
}
|
||||
|
||||
public boolean isInRegion(Player player) {
|
||||
@ -42,12 +42,4 @@ public class RegionBounds {
|
||||
int z = player.getLocation().getBlockZ();
|
||||
return player.getWorld().equals(world) && x1 <= x && x2 >= x && z1 <= z && z2 >= z;
|
||||
}
|
||||
|
||||
public Location findChestLocation() {
|
||||
|
||||
Optional<Player> player = world.getPlayers().stream().filter(check -> isInRegion(check)).findAny();
|
||||
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
37
src/main/java/net/Indyuce/mmocore/api/loot/TierEffect.java
Normal file
37
src/main/java/net/Indyuce/mmocore/api/loot/TierEffect.java
Normal file
@ -0,0 +1,37 @@
|
||||
package net.Indyuce.mmocore.api.loot;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.util.math.particle.ChestParticleEffect;
|
||||
|
||||
public class TierEffect {
|
||||
private final ChestParticleEffect type;
|
||||
private final Particle particle;
|
||||
private final int period;
|
||||
|
||||
public TierEffect(ConfigurationSection config) {
|
||||
Validate.notNull(config, "Could not load tier config");
|
||||
type = ChestParticleEffect.valueOf(config.getString("type", "OFFSET").toUpperCase().replace("-", "_").replace(" ", "_"));
|
||||
particle = Particle.valueOf(config.getString("particle", "FLAME").toUpperCase().replace("-", "_").replace(" ", "_"));
|
||||
period = Math.max(20, config.getInt("period", 5 * 20));
|
||||
}
|
||||
|
||||
public void play(Location loc) {
|
||||
type.play(loc, particle);
|
||||
}
|
||||
|
||||
public BukkitRunnable startNewRunnable(Location loc) {
|
||||
BukkitRunnable runnable = new BukkitRunnable() {
|
||||
public void run() {
|
||||
type.play(loc, particle);
|
||||
}
|
||||
};
|
||||
runnable.runTaskTimer(MMOCore.plugin, 0, period);
|
||||
return runnable;
|
||||
}
|
||||
}
|
@ -20,19 +20,23 @@ public class Party {
|
||||
private final PartyMembers members = new PartyMembers();
|
||||
private final Map<UUID, Long> invites = new HashMap<>();
|
||||
|
||||
// used to check if two parties are the same
|
||||
private final UUID id = UUID.randomUUID();
|
||||
|
||||
/*
|
||||
* owner changes when the old owner leaves party
|
||||
*/
|
||||
private PlayerData owner;
|
||||
|
||||
// used to check if two parties are the same
|
||||
// private UUID uuid = UUID.randomUUID();
|
||||
|
||||
public Party(PlayerData owner) {
|
||||
this.owner = owner;
|
||||
addMember(owner);
|
||||
}
|
||||
|
||||
public UUID getUniqueId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public PlayerData getOwner() {
|
||||
return owner;
|
||||
}
|
||||
@ -50,7 +54,8 @@ public class Party {
|
||||
}
|
||||
|
||||
public void removeMember(PlayerData data) {
|
||||
if (data.isOnline() && data.getPlayer().getOpenInventory() != null && data.getPlayer().getOpenInventory().getTopInventory().getHolder() instanceof PartyViewInventory)
|
||||
if (data.isOnline() && data.getPlayer().getOpenInventory() != null
|
||||
&& data.getPlayer().getOpenInventory().getTopInventory().getHolder() instanceof PartyViewInventory)
|
||||
InventoryManager.PARTY_CREATION.newInventory(data).open();
|
||||
|
||||
members.remove(data);
|
||||
@ -83,20 +88,22 @@ public class Party {
|
||||
|
||||
public void reopenInventories() {
|
||||
for (PlayerData member : members.members)
|
||||
if (member.isOnline() && member.getPlayer().getOpenInventory() != null && member.getPlayer().getOpenInventory().getTopInventory().getHolder() instanceof PartyViewInventory)
|
||||
if (member.isOnline() && member.getPlayer().getOpenInventory() != null
|
||||
&& member.getPlayer().getOpenInventory().getTopInventory().getHolder() instanceof PartyViewInventory)
|
||||
((PluginInventory) member.getPlayer().getOpenInventory().getTopInventory().getHolder()).open();
|
||||
}
|
||||
|
||||
public void sendPartyInvite(PlayerData inviter, PlayerData target) {
|
||||
invites.put(target.getUniqueId(), System.currentTimeMillis());
|
||||
Request request = new PartyInvite(this, inviter, target);
|
||||
new ConfigMessage("party-invite").addPlaceholders("player", inviter.getPlayer().getName(), "uuid", request.getUniqueId().toString()).sendAsJSon(target.getPlayer());
|
||||
new ConfigMessage("party-invite").addPlaceholders("player", inviter.getPlayer().getName(), "uuid", request.getUniqueId().toString())
|
||||
.sendAsJSon(target.getPlayer());
|
||||
MMOCore.plugin.requestManager.registerRequest(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof Party && ((Party) obj).owner.getUniqueId().equals(owner.getUniqueId());
|
||||
return obj instanceof Party && ((Party) obj).getUniqueId().equals(getUniqueId());
|
||||
}
|
||||
|
||||
/*
|
||||
@ -136,7 +143,8 @@ public class Party {
|
||||
}
|
||||
|
||||
private void applyAttributes(PlayerData player) {
|
||||
MMOCore.plugin.partyManager.getBonuses().forEach(stat -> player.getStats().getInstance(stat).addModifier("mmocoreParty", MMOCore.plugin.partyManager.getBonus(stat).multiply(members.size() - 1)));
|
||||
MMOCore.plugin.partyManager.getBonuses().forEach(stat -> player.getStats().getInstance(stat).addModifier("mmocoreParty",
|
||||
MMOCore.plugin.partyManager.getBonus(stat).multiply(members.size() - 1)));
|
||||
}
|
||||
|
||||
private void clearAttributes(PlayerData player) {
|
||||
|
@ -38,11 +38,11 @@ public class PlayerStats {
|
||||
* applies relative attributes on the base stat too
|
||||
*/
|
||||
public double getStat(StatType stat) {
|
||||
return getInstance(stat).getTotal(getBase(stat));
|
||||
return getInstance(stat).getTotal();
|
||||
}
|
||||
|
||||
public double getBase(StatType stat) {
|
||||
return data.getProfess().calculateStat(stat, stat.hasProfession() ? data.getCollectionSkills().getLevel(stat.getProfession()) : data.getLevel());
|
||||
return getInstance(stat).getBase();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -51,6 +51,12 @@ public enum StatType {
|
||||
PROJECTILE_DAMAGE,
|
||||
WEAPON_DAMAGE,
|
||||
SKILL_DAMAGE,
|
||||
|
||||
DAMAGE_REDUCTION,
|
||||
PHYSICAL_DAMAGE_REDUCTION,
|
||||
PROJECTILE_DAMAGE_REDUCTION,
|
||||
WEAPON_DAMAGE_REDUCTION,
|
||||
SKILL_DAMAGE_REDUCTION,
|
||||
|
||||
// reduces amount of tugs needed to fish
|
||||
FISHING_STRENGTH("fishing"),
|
||||
|
@ -20,7 +20,7 @@ public class LocationSkillResult extends SkillResult {
|
||||
|
||||
if (isSuccessful()) {
|
||||
|
||||
RayTraceResult result = data.getPlayer().getWorld().rayTrace(data.getPlayer().getEyeLocation(), data.getPlayer().getEyeLocation().getDirection(), range, FluidCollisionMode.ALWAYS, true, 1.0D, entity -> MMOCoreUtils.canTarget(data.getPlayer(), entity));
|
||||
RayTraceResult result = data.getPlayer().getWorld().rayTrace(data.getPlayer().getEyeLocation(), data.getPlayer().getEyeLocation().getDirection(), range, FluidCollisionMode.ALWAYS, true, 1.0D, entity -> MMOCoreUtils.canTarget(data, entity));
|
||||
if (result == null)
|
||||
abort(CancelReason.OTHER);
|
||||
else
|
||||
|
@ -16,7 +16,7 @@ public class TargetSkillResult extends SkillResult {
|
||||
super(data, skill);
|
||||
|
||||
if (isSuccessful()) {
|
||||
MMORayTraceResult result = MMOLib.plugin.getVersion().getWrapper().rayTrace(data.getPlayer(), range, entity -> MMOCoreUtils.canTarget(data.getPlayer(), entity));
|
||||
MMORayTraceResult result = MMOLib.plugin.getVersion().getWrapper().rayTrace(data.getPlayer(), range, entity -> MMOCoreUtils.canTarget(data, entity));
|
||||
if (!result.hasHit())
|
||||
abort(CancelReason.OTHER);
|
||||
else
|
||||
|
@ -3,7 +3,7 @@ package net.Indyuce.mmocore.api.util.math.formula;
|
||||
import java.util.Random;
|
||||
|
||||
public class RandomAmount {
|
||||
private double min, max;
|
||||
private final double min, max;
|
||||
|
||||
private static final Random random = new Random();
|
||||
|
||||
@ -15,8 +15,7 @@ public class RandomAmount {
|
||||
public RandomAmount(String value) {
|
||||
String[] split = value.split("\\-");
|
||||
min = Double.parseDouble(split[0]);
|
||||
if (split.length > 1)
|
||||
max = Double.parseDouble(split[1]);
|
||||
max = split.length > 1 ? Double.parseDouble(split[1]) : 0;
|
||||
}
|
||||
|
||||
public double getMax() {
|
||||
|
@ -6,7 +6,7 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.manager.LootableChestManager.LootableChest;
|
||||
import net.Indyuce.mmocore.api.loot.LootChest;
|
||||
|
||||
public class LootableChestsListener implements Listener {
|
||||
@EventHandler
|
||||
@ -15,8 +15,8 @@ public class LootableChestsListener implements Listener {
|
||||
return;
|
||||
|
||||
Chest chest = (Chest) event.getInventory().getHolder();
|
||||
LootableChest lootable = MMOCore.plugin.chestManager.getLootableChest(chest.getLocation());
|
||||
if (lootable != null)
|
||||
lootable.whenClosed(true);
|
||||
LootChest lootChest = MMOCore.plugin.lootChests.getChest(chest.getLocation());
|
||||
if (lootChest != null)
|
||||
lootChest.unregister(true);
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ public class ConfigManager {
|
||||
public double expPartyBuff, regenPartyBuff;
|
||||
public String partyChatPrefix;
|
||||
public ChatColor manaFull, manaHalf, manaEmpty, staminaFull, staminaHalf, staminaEmpty;
|
||||
public int combatLogTimer;
|
||||
public int combatLogTimer, lootChestExpireTime;
|
||||
|
||||
public final DecimalFormatSymbols formatSymbols = new DecimalFormatSymbols();
|
||||
public final DecimalFormat decimal = new DecimalFormat("0.#", formatSymbols), decimals = new DecimalFormat("0.##", formatSymbols);
|
||||
@ -86,7 +86,7 @@ public class ConfigManager {
|
||||
loadDefaultFile("stats.yml");
|
||||
loadDefaultFile("waypoints.yml");
|
||||
loadDefaultFile("restrictions.yml");
|
||||
loadDefaultFile("chests.yml");
|
||||
// loadDefaultFile("chests.yml");
|
||||
loadDefaultFile("commands.yml");
|
||||
loadDefaultFile("guilds.yml");
|
||||
|
||||
@ -100,6 +100,7 @@ public class ConfigManager {
|
||||
partyChatPrefix = MMOCore.plugin.getConfig().getString("party.chat-prefix");
|
||||
formatSymbols.setDecimalSeparator(getFirstChar(MMOCore.plugin.getConfig().getString("number-format.decimal-separator"), ','));
|
||||
combatLogTimer = MMOCore.plugin.getConfig().getInt("combat-log.timer");
|
||||
lootChestExpireTime = Math.max(MMOCore.plugin.getConfig().getInt("loot-chest-expire-time"), 1) * 1000;
|
||||
|
||||
manaFull = getColorOrDefault("mana-whole", ChatColor.BLUE);
|
||||
manaHalf = getColorOrDefault("mana-half", ChatColor.AQUA);
|
||||
|
@ -15,7 +15,7 @@ import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.droptable.DropTable;
|
||||
|
||||
public class DropTableManager extends MMOManager {
|
||||
private Map<String, DropTable> map = new HashMap<>();
|
||||
private final Map<String, DropTable> map = new HashMap<>();
|
||||
|
||||
public void register(DropTable table) {
|
||||
map.put(table.getId(), table);
|
||||
@ -47,11 +47,8 @@ public class DropTableManager extends MMOManager {
|
||||
if (obj instanceof String)
|
||||
return get((String) obj);
|
||||
|
||||
if (obj instanceof ConfigurationSection) {
|
||||
DropTable table = new DropTable((ConfigurationSection) obj);
|
||||
table.load();
|
||||
return table;
|
||||
}
|
||||
if (obj instanceof ConfigurationSection)
|
||||
return new DropTable((ConfigurationSection) obj).load();
|
||||
|
||||
throw new IllegalArgumentException("Could not parse drop table.");
|
||||
}
|
||||
|
@ -0,0 +1,75 @@
|
||||
package net.Indyuce.mmocore.manager;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.ConfigFile;
|
||||
import net.Indyuce.mmocore.api.loot.LootChest;
|
||||
import net.Indyuce.mmocore.api.loot.LootChestRegion;
|
||||
|
||||
public class LootChestManager {
|
||||
|
||||
/*
|
||||
* all active loot chests in the server
|
||||
*/
|
||||
private final Set<LootChest> active = new HashSet<>();
|
||||
|
||||
private final Map<String, LootChestRegion> regions = new HashMap<>();
|
||||
|
||||
public boolean hasRegion(String id) {
|
||||
return regions.containsKey(id);
|
||||
}
|
||||
|
||||
public LootChestRegion getRegion(String id) {
|
||||
return regions.get(id);
|
||||
}
|
||||
|
||||
public Collection<LootChestRegion> getRegions() {
|
||||
return regions.values();
|
||||
}
|
||||
|
||||
public Set<LootChest> getActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void register(LootChest chest) {
|
||||
active.add(chest);
|
||||
}
|
||||
|
||||
public void unregister(LootChest chest) {
|
||||
active.remove(chest);
|
||||
}
|
||||
|
||||
public LootChest getChest(Location loc) {
|
||||
|
||||
for (LootChest chest : active)
|
||||
if (chest.getBlock().matches(loc))
|
||||
return chest;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
regions.values().forEach(region -> region.getRunnable().cancel());
|
||||
regions.clear();
|
||||
|
||||
FileConfiguration config = new ConfigFile("loot-chests").getConfig();
|
||||
for (String key : config.getKeys(false))
|
||||
try {
|
||||
LootChestRegion region = new LootChestRegion(config.getConfigurationSection(key));
|
||||
regions.put(region.getId(), region);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
MMOCore.plugin.getLogger().log(Level.WARNING,
|
||||
"An error occured while trying to load loot chest region '" + key + "': " + exception.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,169 +0,0 @@
|
||||
package net.Indyuce.mmocore.manager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Chest;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.droptable.DropTable;
|
||||
import net.Indyuce.mmocore.api.util.math.particle.ChestParticleEffect;
|
||||
|
||||
public class LootableChestManager {
|
||||
private Set<LootableChest> map = new HashSet<>();
|
||||
|
||||
private static BukkitRunnable runnable;
|
||||
private static final Random random = new Random();
|
||||
|
||||
public LootableChestManager(FileConfiguration config) {
|
||||
for (String key : config.getKeys(false))
|
||||
try {
|
||||
register(new LootableChest(config.getConfigurationSection(key)));
|
||||
} catch (IllegalArgumentException | IndexOutOfBoundsException exception) {
|
||||
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not register loot chest '" + key + "': " + exception.getMessage());
|
||||
}
|
||||
|
||||
if (runnable != null)
|
||||
runnable.cancel();
|
||||
|
||||
(runnable = new BukkitRunnable() {
|
||||
public void run() {
|
||||
map.forEach(chest -> {
|
||||
if (chest.hasEffect() && chest.isSpawned() && chest.hasPlayerNearby())
|
||||
chest.playEffect();
|
||||
});
|
||||
}
|
||||
}).runTaskTimerAsynchronously(MMOCore.plugin, 100, 4 * 20);
|
||||
}
|
||||
|
||||
public void register(LootableChest chest) {
|
||||
map.add(chest);
|
||||
chest.whenClosed(false);
|
||||
}
|
||||
|
||||
public LootableChest getLootableChest(Location loc) {
|
||||
for (LootableChest chest : map)
|
||||
if (blockCheck(chest.getLocation(), loc))
|
||||
return chest;
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean blockCheck(Location loc1, Location loc2) {
|
||||
return loc1.getWorld().equals(loc2.getWorld()) && loc1.getBlockX() == loc2.getBlockX() && loc1.getBlockY() == loc2.getBlockY() && loc1.getBlockZ() == loc2.getBlockZ();
|
||||
}
|
||||
|
||||
public class LootableChest {
|
||||
private final Location loc;
|
||||
private final DropTable table;
|
||||
private final int regenTime;
|
||||
private final Particle effectParticle;
|
||||
private final ChestParticleEffect effect;
|
||||
|
||||
private long lastDisappear;
|
||||
|
||||
public LootableChest(ConfigurationSection config) {
|
||||
loc = readLocation(config.getName());
|
||||
regenTime = config.getInt("regen-time");
|
||||
table = MMOCore.plugin.dropTableManager.loadDropTable(config.get("drop-table"));
|
||||
|
||||
if (config.contains("effect")) {
|
||||
String format = config.getString("effect.particle");
|
||||
Validate.notNull(format, "Particle is missing particle");
|
||||
effectParticle = Particle.valueOf(format.toUpperCase().replace("-", "_"));
|
||||
|
||||
format = config.getString("effect.type");
|
||||
Validate.notNull(format, "Particle is missing effect type");
|
||||
effect = ChestParticleEffect.valueOf(format.toUpperCase().replace("-", "_"));
|
||||
|
||||
} else {
|
||||
effectParticle = null;
|
||||
effect = null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasEffect() {
|
||||
return effectParticle != null && effect != null;
|
||||
}
|
||||
|
||||
public boolean isSpawned() {
|
||||
return System.currentTimeMillis() > lastDisappear + 50 * regenTime;
|
||||
}
|
||||
|
||||
public Location getLocation() {
|
||||
return loc;
|
||||
}
|
||||
|
||||
public DropTable getDropTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
public int getRegenTime() {
|
||||
return regenTime;
|
||||
}
|
||||
|
||||
public void playEffect() {
|
||||
effect.play(loc.clone().add(.5, .5, .5), effectParticle);
|
||||
}
|
||||
|
||||
public void whenClosed(boolean sound) {
|
||||
if (sound) {
|
||||
loc.getWorld().playSound(loc, Sound.ITEM_ARMOR_EQUIP_LEATHER, 1, 1);
|
||||
loc.getWorld().spawnParticle(Particle.CRIT, loc.clone().add(.5, .5, .5), 16, 0, 0, 0, .5);
|
||||
}
|
||||
if (loc.getBlock().getState() instanceof Chest)
|
||||
((Chest) loc.getBlock().getState()).getBlockInventory().clear();
|
||||
loc.getBlock().setType(Material.AIR);
|
||||
lastDisappear = System.currentTimeMillis();
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(MMOCore.plugin, () -> whenSpawn(), regenTime);
|
||||
}
|
||||
|
||||
public boolean hasPlayerNearby() {
|
||||
for (Player player : loc.getWorld().getPlayers())
|
||||
if (player.getLocation().distanceSquared(loc) < 625)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void whenSpawn() {
|
||||
List<Integer> slots = new ArrayList<>();
|
||||
for (int j = 0; j < 27; j++)
|
||||
slots.add(j);
|
||||
|
||||
loc.getBlock().setType(Material.CHEST);
|
||||
Chest chest = (Chest) loc.getBlock().getState();
|
||||
table.collect().forEach(item -> {
|
||||
Integer slot = slots.get(random.nextInt(slots.size()));
|
||||
chest.getInventory().setItem(slot, item);
|
||||
slots.remove(slot);
|
||||
});
|
||||
}
|
||||
|
||||
private Location readLocation(String string) {
|
||||
String[] split = string.split("\\ ");
|
||||
|
||||
World world = Bukkit.getWorld(split[0]);
|
||||
Validate.notNull(world, "Could not find world '" + split[0] + "'");
|
||||
|
||||
double x = Double.parseDouble(split[1]);
|
||||
double y = Double.parseDouble(split[2]);
|
||||
double z = Double.parseDouble(split[3]);
|
||||
|
||||
return new Location(world, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
@ -34,14 +34,22 @@ lootsplosion:
|
||||
offset: .2
|
||||
height: .6
|
||||
|
||||
# Time in seconds it takes for a loot chest to
|
||||
# expire after it was spawned. 600 is 10 minutes.
|
||||
loot-chest-expire-time: 600
|
||||
|
||||
# Settings for the default action bar
|
||||
action-bar:
|
||||
|
||||
# Whether or not to use the default action bar. (This doesn't change any other action bars provided by MMOCore.)
|
||||
enabled: true
|
||||
|
||||
# The decimal format for stats (not including stat formats in stats.yml)
|
||||
decimal: "0.#"
|
||||
|
||||
# The amount of ticks before updating the info
|
||||
ticks-to-update: 5
|
||||
|
||||
# How to display the data.
|
||||
format: "&c❤ {health}/{max_health} &f| &9⭐ {mana}/{max_mana} &f| &7⛨ {armor}"
|
||||
|
||||
|
@ -35,8 +35,6 @@ on-mine:
|
||||
temp-block: 'skull{value="eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTU0ODE4MjMzYzgxMTg3M2U4NWY1YTRlYTQ0MjliNzVmMjNiNmFlMGVhNmY1ZmMwZjdiYjQyMGQ3YzQ3MSJ9fX0="}'
|
||||
triggers:
|
||||
- 'exp{profession=mining;amount=20}'
|
||||
|
||||
|
||||
|
||||
emerald:
|
||||
material: vanilla{type=EMERALD_ORE}
|
||||
|
Loading…
Reference in New Issue
Block a user