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.io.File;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
@ -13,6 +14,7 @@ import org.bukkit.scheduler.BukkitRunnable;
|
|||||||
|
|
||||||
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.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;
|
||||||
@ -72,7 +74,7 @@ import net.Indyuce.mmocore.manager.DropTableManager;
|
|||||||
import net.Indyuce.mmocore.manager.EntityManager;
|
import net.Indyuce.mmocore.manager.EntityManager;
|
||||||
import net.Indyuce.mmocore.manager.ExperienceManager;
|
import net.Indyuce.mmocore.manager.ExperienceManager;
|
||||||
import net.Indyuce.mmocore.manager.InventoryManager;
|
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.MMOLoadManager;
|
||||||
import net.Indyuce.mmocore.manager.QuestManager;
|
import net.Indyuce.mmocore.manager.QuestManager;
|
||||||
import net.Indyuce.mmocore.manager.RestrictionManager;
|
import net.Indyuce.mmocore.manager.RestrictionManager;
|
||||||
@ -101,7 +103,6 @@ public class MMOCore extends JavaPlugin {
|
|||||||
public ConfigManager configManager;
|
public ConfigManager configManager;
|
||||||
public WaypointManager waypointManager;
|
public WaypointManager waypointManager;
|
||||||
public RestrictionManager restrictionManager;
|
public RestrictionManager restrictionManager;
|
||||||
public LootableChestManager chestManager;
|
|
||||||
public RequestManager requestManager;
|
public RequestManager requestManager;
|
||||||
public ConfigItemManager configItems;
|
public ConfigItemManager configItems;
|
||||||
public SkillManager skillManager;
|
public SkillManager skillManager;
|
||||||
@ -122,6 +123,7 @@ public class MMOCore extends JavaPlugin {
|
|||||||
public final ProfessionManager professionManager = new ProfessionManager();
|
public final ProfessionManager professionManager = new ProfessionManager();
|
||||||
public final EntityManager entities = new EntityManager();
|
public final EntityManager entities = new EntityManager();
|
||||||
public final ExperienceManager experience = new ExperienceManager();
|
public final ExperienceManager experience = new ExperienceManager();
|
||||||
|
public final LootChestManager lootChests = new LootChestManager();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* professions
|
* professions
|
||||||
@ -235,6 +237,20 @@ public class MMOCore extends JavaPlugin {
|
|||||||
}
|
}
|
||||||
}.runTaskTimer(MMOCore.plugin, 100, 20);
|
}.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
|
* For the sake of the lord, make sure they aren't using MMOItems Mana
|
||||||
* and Stamina Addon...This should prevent a couple error reports
|
* and Stamina Addon...This should prevent a couple error reports
|
||||||
@ -360,6 +376,8 @@ public class MMOCore extends JavaPlugin {
|
|||||||
dataProvider.getGuildManager().save(guild);
|
dataProvider.getGuildManager().save(guild);
|
||||||
|
|
||||||
mineManager.resetRemainingBlocks();
|
mineManager.resetRemainingBlocks();
|
||||||
|
|
||||||
|
lootChests.getActive().forEach(chest -> chest.unregister(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reloadPlugin() {
|
public void reloadPlugin() {
|
||||||
@ -396,7 +414,8 @@ public class MMOCore extends JavaPlugin {
|
|||||||
questManager.clear();
|
questManager.clear();
|
||||||
questManager.reload();
|
questManager.reload();
|
||||||
|
|
||||||
chestManager = new LootableChestManager(new ConfigFile("chests").getConfig());
|
lootChests.reload();
|
||||||
|
|
||||||
waypointManager = new WaypointManager(new ConfigFile("waypoints").getConfig());
|
waypointManager = new WaypointManager(new ConfigFile("waypoints").getConfig());
|
||||||
restrictionManager = new RestrictionManager(new ConfigFile("restrictions").getConfig());
|
restrictionManager = new RestrictionManager(new ConfigFile("restrictions").getConfig());
|
||||||
requestManager = new RequestManager();
|
requestManager = new RequestManager();
|
||||||
|
@ -13,6 +13,7 @@ import org.bukkit.inventory.ItemStack;
|
|||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.droptable.DropTable;
|
import net.Indyuce.mmocore.api.droptable.DropTable;
|
||||||
import net.Indyuce.mmocore.api.load.MMOLoadException;
|
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.ExperienceTrigger;
|
||||||
import net.Indyuce.mmocore.api.quest.trigger.Trigger;
|
import net.Indyuce.mmocore.api.quest.trigger.Trigger;
|
||||||
import net.mmogroup.mmolib.api.MMOLineConfig;
|
import net.mmogroup.mmolib.api.MMOLineConfig;
|
||||||
@ -76,8 +77,8 @@ public class BlockInfo {
|
|||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ItemStack> collectDrops() {
|
public List<ItemStack> collectDrops(LootBuilder builder) {
|
||||||
return hasDropTable() ? table.collect() : new ArrayList<>();
|
return hasDropTable() ? table.collect(builder) : new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasDropTable() {
|
public boolean hasDropTable() {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package net.Indyuce.mmocore.api.droptable;
|
package net.Indyuce.mmocore.api.droptable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -12,11 +11,12 @@ 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.api.droptable.dropitem.DropItem;
|
||||||
import net.Indyuce.mmocore.api.load.MMOLoadException;
|
import net.Indyuce.mmocore.api.load.MMOLoadException;
|
||||||
|
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
||||||
import net.mmogroup.mmolib.api.MMOLineConfig;
|
import net.mmogroup.mmolib.api.MMOLineConfig;
|
||||||
|
|
||||||
public class DropTable {
|
public class DropTable {
|
||||||
private final String id;
|
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.
|
* cached in order to load other items.
|
||||||
@ -52,13 +52,14 @@ public class DropTable {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ItemStack> collect() {
|
public List<ItemStack> collect(LootBuilder builder) {
|
||||||
List<ItemStack> total = new ArrayList<>();
|
|
||||||
|
|
||||||
for (DropItem item : drops)
|
for (DropItem item : drops)
|
||||||
if (item.rollChance())
|
if (item.rollChance() && builder.getCapacity() >= item.getWeight()) {
|
||||||
item.collect(total);
|
item.collect(builder);
|
||||||
|
builder.reduceCapacity(item.getWeight());
|
||||||
|
}
|
||||||
|
|
||||||
return total;
|
return builder.getLoot();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,22 +1,21 @@
|
|||||||
package net.Indyuce.mmocore.api.droptable.dropitem;
|
package net.Indyuce.mmocore.api.droptable.dropitem;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Random;
|
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.Indyuce.mmocore.api.util.math.formula.RandomAmount;
|
||||||
import net.mmogroup.mmolib.api.MMOLineConfig;
|
import net.mmogroup.mmolib.api.MMOLineConfig;
|
||||||
|
|
||||||
public abstract class DropItem {
|
public abstract class DropItem {
|
||||||
protected static final Random random = new Random();
|
protected static final Random random = new Random();
|
||||||
|
|
||||||
private double chance;
|
private final double chance, weight;
|
||||||
private RandomAmount amount;
|
private final RandomAmount amount;
|
||||||
|
|
||||||
public DropItem(MMOLineConfig config) {
|
public DropItem(MMOLineConfig config) {
|
||||||
chance = config.args().length > 0 ? Double.parseDouble(config.args()[0]) : 1;
|
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);
|
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() {
|
public RandomAmount getAmount() {
|
||||||
@ -27,6 +26,10 @@ public abstract class DropItem {
|
|||||||
return chance;
|
return chance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double getWeight() {
|
||||||
|
return weight;
|
||||||
|
}
|
||||||
|
|
||||||
public int rollAmount() {
|
public int rollAmount() {
|
||||||
return amount.calculateInt();
|
return amount.calculateInt();
|
||||||
}
|
}
|
||||||
@ -35,5 +38,5 @@ public abstract class DropItem {
|
|||||||
return random.nextDouble() < chance;
|
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;
|
package net.Indyuce.mmocore.api.droptable.dropitem;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang.Validate;
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.droptable.DropTable;
|
import net.Indyuce.mmocore.api.droptable.DropTable;
|
||||||
|
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
||||||
import net.mmogroup.mmolib.api.MMOLineConfig;
|
import net.mmogroup.mmolib.api.MMOLineConfig;
|
||||||
|
|
||||||
public class DropTableDropItem extends DropItem {
|
public class DropTableDropItem extends DropItem {
|
||||||
private DropTable dropTable;
|
private final DropTable dropTable;
|
||||||
|
|
||||||
public DropTableDropItem(MMOLineConfig config) {
|
public DropTableDropItem(MMOLineConfig config) {
|
||||||
super(config);
|
super(config);
|
||||||
@ -23,8 +21,8 @@ public class DropTableDropItem extends DropItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void collect(List<ItemStack> total) {
|
public void collect(LootBuilder builder) {
|
||||||
for (int j = 0; j < rollAmount(); j++)
|
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;
|
package net.Indyuce.mmocore.api.droptable.dropitem;
|
||||||
|
|
||||||
import java.util.List;
|
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
||||||
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import net.Indyuce.mmocore.api.util.item.CurrencyItem;
|
import net.Indyuce.mmocore.api.util.item.CurrencyItem;
|
||||||
import net.mmogroup.mmolib.api.MMOLineConfig;
|
import net.mmogroup.mmolib.api.MMOLineConfig;
|
||||||
|
|
||||||
@ -13,7 +10,7 @@ public class GoldDropItem extends DropItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void collect(List<ItemStack> total) {
|
public void collect(LootBuilder builder) {
|
||||||
total.add(new CurrencyItem("GOLD_COIN", 1, rollAmount()).build());
|
builder.addLoot(new CurrencyItem("GOLD_COIN", 1, rollAmount()).build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
package net.Indyuce.mmocore.api.droptable.dropitem;
|
package net.Indyuce.mmocore.api.droptable.dropitem;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.NoSuchElementException;
|
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.MythicMobs;
|
||||||
import io.lumine.xikage.mythicmobs.adapters.bukkit.BukkitAdapter;
|
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.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.MMOCore;
|
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
||||||
import net.mmogroup.mmolib.api.MMOLineConfig;
|
import net.mmogroup.mmolib.api.MMOLineConfig;
|
||||||
|
|
||||||
public class MMDropTableDropItem extends DropItem {
|
public class MMDropTableDropItem extends DropItem {
|
||||||
private DropTable dropTable;
|
private final DropTable dropTable;
|
||||||
private DropMetadata metadata = new DropMetadata(null, null);
|
|
||||||
|
private static final DropMetadata metadata = new DropMetadata(null, null);
|
||||||
|
|
||||||
public MMDropTableDropItem(MMOLineConfig config) {
|
public MMDropTableDropItem(MMOLineConfig config) {
|
||||||
super(config);
|
super(config);
|
||||||
@ -28,19 +25,16 @@ public class MMDropTableDropItem extends DropItem {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
dropTable = MythicMobs.inst().getDropManager().getDropTable(id).get();
|
dropTable = MythicMobs.inst().getDropManager().getDropTable(id).get();
|
||||||
} catch(NoSuchElementException e) {
|
} catch (NoSuchElementException exception) {
|
||||||
MMOCore.log(Level.WARNING, "Could not find MM drop table" + id);
|
throw new IllegalArgumentException("Could not find MM drop table with ID '" + id + "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void collect(List<ItemStack> total) {
|
public void collect(LootBuilder builder) {
|
||||||
LootBag lootBag = dropTable.generate(metadata);
|
LootBag lootBag = dropTable.generate(metadata);
|
||||||
|
for (Drop type : lootBag.getDrops())
|
||||||
for(Drop type : lootBag.getDrops()) {
|
if (type instanceof IItemDrop)
|
||||||
if(type instanceof IItemDrop) {
|
builder.addLoot(BukkitAdapter.adapt(((IItemDrop) type).getDrop(metadata)));
|
||||||
total.add(BukkitAdapter.adapt(((IItemDrop)type).getDrop(metadata)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
package net.Indyuce.mmocore.api.droptable.dropitem;
|
package net.Indyuce.mmocore.api.droptable.dropitem;
|
||||||
|
|
||||||
import java.util.List;
|
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
||||||
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import net.Indyuce.mmocore.api.util.item.CurrencyItem;
|
import net.Indyuce.mmocore.api.util.item.CurrencyItem;
|
||||||
import net.mmogroup.mmolib.api.MMOLineConfig;
|
import net.mmogroup.mmolib.api.MMOLineConfig;
|
||||||
|
|
||||||
public class NoteDropItem extends DropItem {
|
public class NoteDropItem extends DropItem {
|
||||||
private int min, max;
|
private final int min, max;
|
||||||
|
|
||||||
public NoteDropItem(MMOLineConfig config) {
|
public NoteDropItem(MMOLineConfig config) {
|
||||||
super(config);
|
super(config);
|
||||||
@ -20,7 +17,7 @@ public class NoteDropItem extends DropItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void collect(List<ItemStack> total) {
|
public void collect(LootBuilder builder) {
|
||||||
total.add(new CurrencyItem("NOTE", random.nextInt(max - min + 1) + min, rollAmount()).build());
|
builder.addLoot(new CurrencyItem("NOTE", random.nextInt(max - min + 1) + min, rollAmount()).build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
package net.Indyuce.mmocore.api.droptable.dropitem;
|
package net.Indyuce.mmocore.api.droptable.dropitem;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
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.mmogroup.mmolib.api.MMOLineConfig;
|
import net.mmogroup.mmolib.api.MMOLineConfig;
|
||||||
|
|
||||||
public class VanillaDropItem extends DropItem {
|
public class VanillaDropItem extends DropItem {
|
||||||
@ -16,13 +15,13 @@ public class VanillaDropItem extends DropItem {
|
|||||||
config.validate("type");
|
config.validate("type");
|
||||||
this.material = Material.valueOf(config.getString("type"));
|
this.material = Material.valueOf(config.getString("type"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Material getMaterial() {
|
public Material getMaterial() {
|
||||||
return material;
|
return material;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void collect(List<ItemStack> total) {
|
public void collect(LootBuilder builder) {
|
||||||
total.add(new ItemStack(material, rollAmount()));
|
builder.addLoot(new ItemStack(material, rollAmount()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
package net.Indyuce.mmocore.api.droptable.dropitem.fishing;
|
package net.Indyuce.mmocore.api.droptable.dropitem.fishing;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
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.api.droptable.dropitem.DropItem;
|
||||||
|
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
||||||
import net.Indyuce.mmocore.api.util.math.formula.RandomAmount;
|
import net.Indyuce.mmocore.api.util.math.formula.RandomAmount;
|
||||||
import net.mmogroup.mmolib.api.MMOLineConfig;
|
import net.mmogroup.mmolib.api.MMOLineConfig;
|
||||||
|
|
||||||
@ -58,8 +56,8 @@ public class FishingDropItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ItemStack collect() {
|
public ItemStack collect() {
|
||||||
List<ItemStack> collect = new ArrayList<>();
|
LootBuilder builder = new LootBuilder(null, 0);
|
||||||
dropItem.collect(collect);
|
dropItem.collect(builder);
|
||||||
return collect.stream().findAny().get();
|
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.block.BlockInfo;
|
||||||
import net.Indyuce.mmocore.api.experience.ExperienceInfo;
|
import net.Indyuce.mmocore.api.experience.ExperienceInfo;
|
||||||
|
import net.Indyuce.mmocore.api.loot.LootBuilder;
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
|
|
||||||
public class CustomBlockMineEvent extends PlayerDataEvent implements Cancellable {
|
public class CustomBlockMineEvent extends PlayerDataEvent implements Cancellable {
|
||||||
@ -24,7 +25,7 @@ public class CustomBlockMineEvent extends PlayerDataEvent implements Cancellable
|
|||||||
super(player);
|
super(player);
|
||||||
|
|
||||||
this.block = block;
|
this.block = block;
|
||||||
this.drops = info.collectDrops();
|
this.drops = info.collectDrops(new LootBuilder(player, 0));
|
||||||
this.experience = info.hasExperience() ? info.getExperience().newInfo() : null;
|
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;
|
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.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 {
|
public class ChestTier {
|
||||||
private final TierEffect effect;
|
private final TierEffect effect;
|
||||||
private final int weight;
|
private final ScalingFormula capacity;
|
||||||
|
private final DropTable table;
|
||||||
|
|
||||||
|
public final double chance;
|
||||||
|
|
||||||
public ChestTier(ConfigurationSection config) {
|
public ChestTier(ConfigurationSection config) {
|
||||||
effect = config.isConfigurationSection("effect") ? new TierEffect(config.getConfigurationSection("effect"))
|
effect = config.isConfigurationSection("effect") ? new TierEffect(config.getConfigurationSection("effect")) : null;
|
||||||
: null;
|
capacity = new ScalingFormula(config.get("capacity"));
|
||||||
weight = config.getInt("weight", 1);
|
chance = config.getDouble("chance");
|
||||||
|
table = MMOCore.plugin.dropTableManager.loadDropTable(config.get("drops"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getWeight() {
|
public double rollCapacity(PlayerData player) {
|
||||||
return weight;
|
return capacity.calculate(player.getLevel());
|
||||||
|
}
|
||||||
|
|
||||||
|
public DropTable getDropTable() {
|
||||||
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasEffect() {
|
public boolean hasEffect() {
|
||||||
@ -28,21 +36,4 @@ public class ChestTier {
|
|||||||
public TierEffect getEffect() {
|
public TierEffect getEffect() {
|
||||||
return effect;
|
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.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.Particle;
|
||||||
|
import org.bukkit.Sound;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
|
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.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
|
|
||||||
public class LootChest {
|
public class LootChest {
|
||||||
|
private final ChestTier tier;
|
||||||
private final LootChestRegion region;
|
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(ChestTier tier, LootChestRegion region, Block block) {
|
||||||
|
this.tier = tier;
|
||||||
public LootChest(LootChestRegion region, Block block) {
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChestTier getTier() {
|
||||||
|
return tier;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReplacedBlock getBlock() {
|
public ReplacedBlock getBlock() {
|
||||||
@ -26,6 +43,40 @@ public class LootChest {
|
|||||||
return region;
|
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 {
|
public class ReplacedBlock {
|
||||||
private final Material material;
|
private final Material material;
|
||||||
private final BlockData data;
|
private final BlockData data;
|
||||||
@ -34,7 +85,16 @@ public class LootChest {
|
|||||||
public ReplacedBlock(Block block) {
|
public ReplacedBlock(Block block) {
|
||||||
this.material = block.getType();
|
this.material = block.getType();
|
||||||
this.data = block.getBlockData();
|
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() {
|
public void restore() {
|
||||||
|
@ -1,31 +1,44 @@
|
|||||||
package net.Indyuce.mmocore.api.loot;
|
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.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import org.apache.commons.lang.Validate;
|
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.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
|
import net.Indyuce.mmocore.api.event.LootChestSpawnEvent;
|
||||||
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
|
|
||||||
public class LootChestRegion {
|
public class LootChestRegion {
|
||||||
private final String id;
|
private final String id;
|
||||||
|
|
||||||
private final long chestSpawnPeriod;
|
private final long chestSpawnPeriod;
|
||||||
private final RegionBounds bounds;
|
private final RegionBounds bounds;
|
||||||
private final Set<ChestTier> tiers = new HashSet<>();
|
private final ChestAlgorithmOptions algOptions;
|
||||||
|
private final Set<ChestTier> tiers = new LinkedHashSet<>();
|
||||||
/*
|
private final BukkitRunnable runnable;
|
||||||
* last time
|
|
||||||
*/
|
private static final Random random = new Random();
|
||||||
|
|
||||||
public LootChestRegion(ConfigurationSection config) {
|
public LootChestRegion(ConfigurationSection config) {
|
||||||
Validate.notNull(config, "Could not load config");
|
Validate.notNull(config, "Could not load config");
|
||||||
id = config.getName();
|
id = config.getName().toLowerCase().replace("_", "-").replace(" ", "-");
|
||||||
|
|
||||||
bounds = new RegionBounds(config.getConfigurationSection("bounds"));
|
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");
|
Validate.isTrue(config.isConfigurationSection("tiers"), "Could not find chest tiers");
|
||||||
for (String key : config.getConfigurationSection("tiers").getKeys(false))
|
for (String key : config.getConfigurationSection("tiers").getKeys(false))
|
||||||
@ -35,6 +48,10 @@ public class LootChestRegion {
|
|||||||
MMOCore.plugin.getLogger().log(Level.WARNING,
|
MMOCore.plugin.getLogger().log(Level.WARNING,
|
||||||
"Could not load tier '" + key + "' from chest region '" + id + "': " + exception.getMessage());
|
"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() {
|
public String getId() {
|
||||||
@ -52,4 +69,101 @@ public class LootChestRegion {
|
|||||||
public long getChestSpawnPeriod() {
|
public long getChestSpawnPeriod() {
|
||||||
return chestSpawnPeriod;
|
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;
|
package net.Indyuce.mmocore.api.loot;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.stream.Stream;
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang.Validate;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
@ -14,27 +13,28 @@ 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;
|
||||||
|
|
||||||
private static final Random random = new Random();
|
|
||||||
|
|
||||||
public RegionBounds(ConfigurationSection config) {
|
public RegionBounds(ConfigurationSection config) {
|
||||||
Validate.notNull(config, "Could not load config");
|
Validate.notNull(config, "Could not load config");
|
||||||
Validate.notNull(world = Bukkit.getWorld(config.getString("world")),
|
Validate.notNull(world = Bukkit.getWorld(config.getString("world")), "Could not find world " + config.getString("world"));
|
||||||
"Could not find world " + config.getString("world"));
|
x1 = Math.min(config.getInt("x1"), config.getInt("x2"));
|
||||||
x1 = config.getInt("x1");
|
x2 = Math.max(config.getInt("x1"), config.getInt("x2"));
|
||||||
z1 = config.getInt("z1");
|
|
||||||
|
|
||||||
x2 = config.getInt("x2");
|
z1 = Math.min(config.getInt("z1"), config.getInt("z2"));
|
||||||
z2 = 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 = loc1.getBlockX();
|
x1 = Math.min(loc1.getBlockX(), loc2.getBlockX());
|
||||||
z1 = loc1.getBlockZ();
|
x2 = Math.max(loc1.getBlockX(), loc2.getBlockX());
|
||||||
|
|
||||||
x2 = loc2.getBlockX();
|
z1 = Math.min(loc1.getBlockZ(), loc2.getBlockZ());
|
||||||
z2 = 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) {
|
public boolean isInRegion(Player player) {
|
||||||
@ -42,12 +42,4 @@ public class RegionBounds {
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 PartyMembers members = new PartyMembers();
|
||||||
private final Map<UUID, Long> invites = new HashMap<>();
|
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
|
* owner changes when the old owner leaves party
|
||||||
*/
|
*/
|
||||||
private PlayerData owner;
|
private PlayerData owner;
|
||||||
|
|
||||||
// used to check if two parties are the same
|
|
||||||
// private UUID uuid = UUID.randomUUID();
|
|
||||||
|
|
||||||
public Party(PlayerData owner) {
|
public Party(PlayerData owner) {
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
addMember(owner);
|
addMember(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UUID getUniqueId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
public PlayerData getOwner() {
|
public PlayerData getOwner() {
|
||||||
return owner;
|
return owner;
|
||||||
}
|
}
|
||||||
@ -50,7 +54,8 @@ public class Party {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void removeMember(PlayerData data) {
|
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();
|
InventoryManager.PARTY_CREATION.newInventory(data).open();
|
||||||
|
|
||||||
members.remove(data);
|
members.remove(data);
|
||||||
@ -83,20 +88,22 @@ public class Party {
|
|||||||
|
|
||||||
public void reopenInventories() {
|
public void reopenInventories() {
|
||||||
for (PlayerData member : members.members)
|
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();
|
((PluginInventory) member.getPlayer().getOpenInventory().getTopInventory().getHolder()).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendPartyInvite(PlayerData inviter, PlayerData target) {
|
public void sendPartyInvite(PlayerData inviter, PlayerData target) {
|
||||||
invites.put(target.getUniqueId(), System.currentTimeMillis());
|
invites.put(target.getUniqueId(), System.currentTimeMillis());
|
||||||
Request request = new PartyInvite(this, inviter, target);
|
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);
|
MMOCore.plugin.requestManager.registerRequest(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
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) {
|
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) {
|
private void clearAttributes(PlayerData player) {
|
||||||
|
@ -38,11 +38,11 @@ public class PlayerStats {
|
|||||||
* applies relative attributes on the base stat too
|
* applies relative attributes on the base stat too
|
||||||
*/
|
*/
|
||||||
public double getStat(StatType stat) {
|
public double getStat(StatType stat) {
|
||||||
return getInstance(stat).getTotal(getBase(stat));
|
return getInstance(stat).getTotal();
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getBase(StatType stat) {
|
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,
|
PROJECTILE_DAMAGE,
|
||||||
WEAPON_DAMAGE,
|
WEAPON_DAMAGE,
|
||||||
SKILL_DAMAGE,
|
SKILL_DAMAGE,
|
||||||
|
|
||||||
|
DAMAGE_REDUCTION,
|
||||||
|
PHYSICAL_DAMAGE_REDUCTION,
|
||||||
|
PROJECTILE_DAMAGE_REDUCTION,
|
||||||
|
WEAPON_DAMAGE_REDUCTION,
|
||||||
|
SKILL_DAMAGE_REDUCTION,
|
||||||
|
|
||||||
// reduces amount of tugs needed to fish
|
// reduces amount of tugs needed to fish
|
||||||
FISHING_STRENGTH("fishing"),
|
FISHING_STRENGTH("fishing"),
|
||||||
|
@ -20,7 +20,7 @@ public class LocationSkillResult extends SkillResult {
|
|||||||
|
|
||||||
if (isSuccessful()) {
|
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)
|
if (result == null)
|
||||||
abort(CancelReason.OTHER);
|
abort(CancelReason.OTHER);
|
||||||
else
|
else
|
||||||
|
@ -16,7 +16,7 @@ public class TargetSkillResult extends SkillResult {
|
|||||||
super(data, skill);
|
super(data, skill);
|
||||||
|
|
||||||
if (isSuccessful()) {
|
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())
|
if (!result.hasHit())
|
||||||
abort(CancelReason.OTHER);
|
abort(CancelReason.OTHER);
|
||||||
else
|
else
|
||||||
|
@ -3,7 +3,7 @@ package net.Indyuce.mmocore.api.util.math.formula;
|
|||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
public class RandomAmount {
|
public class RandomAmount {
|
||||||
private double min, max;
|
private final double min, max;
|
||||||
|
|
||||||
private static final Random random = new Random();
|
private static final Random random = new Random();
|
||||||
|
|
||||||
@ -15,8 +15,7 @@ public class RandomAmount {
|
|||||||
public RandomAmount(String value) {
|
public RandomAmount(String value) {
|
||||||
String[] split = value.split("\\-");
|
String[] split = value.split("\\-");
|
||||||
min = Double.parseDouble(split[0]);
|
min = Double.parseDouble(split[0]);
|
||||||
if (split.length > 1)
|
max = split.length > 1 ? Double.parseDouble(split[1]) : 0;
|
||||||
max = Double.parseDouble(split[1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getMax() {
|
public double getMax() {
|
||||||
|
@ -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.manager.LootableChestManager.LootableChest;
|
import net.Indyuce.mmocore.api.loot.LootChest;
|
||||||
|
|
||||||
public class LootableChestsListener implements Listener {
|
public class LootableChestsListener implements Listener {
|
||||||
@EventHandler
|
@EventHandler
|
||||||
@ -15,8 +15,8 @@ public class LootableChestsListener implements Listener {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
Chest chest = (Chest) event.getInventory().getHolder();
|
Chest chest = (Chest) event.getInventory().getHolder();
|
||||||
LootableChest lootable = MMOCore.plugin.chestManager.getLootableChest(chest.getLocation());
|
LootChest lootChest = MMOCore.plugin.lootChests.getChest(chest.getLocation());
|
||||||
if (lootable != null)
|
if (lootChest != null)
|
||||||
lootable.whenClosed(true);
|
lootChest.unregister(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ public class ConfigManager {
|
|||||||
public double expPartyBuff, regenPartyBuff;
|
public double expPartyBuff, regenPartyBuff;
|
||||||
public String partyChatPrefix;
|
public String partyChatPrefix;
|
||||||
public ChatColor manaFull, manaHalf, manaEmpty, staminaFull, staminaHalf, staminaEmpty;
|
public ChatColor manaFull, manaHalf, manaEmpty, staminaFull, staminaHalf, staminaEmpty;
|
||||||
public int combatLogTimer;
|
public int combatLogTimer, lootChestExpireTime;
|
||||||
|
|
||||||
public final DecimalFormatSymbols formatSymbols = new DecimalFormatSymbols();
|
public final DecimalFormatSymbols formatSymbols = new DecimalFormatSymbols();
|
||||||
public final DecimalFormat decimal = new DecimalFormat("0.#", formatSymbols), decimals = new DecimalFormat("0.##", formatSymbols);
|
public final DecimalFormat decimal = new DecimalFormat("0.#", formatSymbols), decimals = new DecimalFormat("0.##", formatSymbols);
|
||||||
@ -86,7 +86,7 @@ public class ConfigManager {
|
|||||||
loadDefaultFile("stats.yml");
|
loadDefaultFile("stats.yml");
|
||||||
loadDefaultFile("waypoints.yml");
|
loadDefaultFile("waypoints.yml");
|
||||||
loadDefaultFile("restrictions.yml");
|
loadDefaultFile("restrictions.yml");
|
||||||
loadDefaultFile("chests.yml");
|
// loadDefaultFile("chests.yml");
|
||||||
loadDefaultFile("commands.yml");
|
loadDefaultFile("commands.yml");
|
||||||
loadDefaultFile("guilds.yml");
|
loadDefaultFile("guilds.yml");
|
||||||
|
|
||||||
@ -100,6 +100,7 @@ public class ConfigManager {
|
|||||||
partyChatPrefix = MMOCore.plugin.getConfig().getString("party.chat-prefix");
|
partyChatPrefix = MMOCore.plugin.getConfig().getString("party.chat-prefix");
|
||||||
formatSymbols.setDecimalSeparator(getFirstChar(MMOCore.plugin.getConfig().getString("number-format.decimal-separator"), ','));
|
formatSymbols.setDecimalSeparator(getFirstChar(MMOCore.plugin.getConfig().getString("number-format.decimal-separator"), ','));
|
||||||
combatLogTimer = MMOCore.plugin.getConfig().getInt("combat-log.timer");
|
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);
|
manaFull = getColorOrDefault("mana-whole", ChatColor.BLUE);
|
||||||
manaHalf = getColorOrDefault("mana-half", ChatColor.AQUA);
|
manaHalf = getColorOrDefault("mana-half", ChatColor.AQUA);
|
||||||
|
@ -15,7 +15,7 @@ import net.Indyuce.mmocore.MMOCore;
|
|||||||
import net.Indyuce.mmocore.api.droptable.DropTable;
|
import net.Indyuce.mmocore.api.droptable.DropTable;
|
||||||
|
|
||||||
public class DropTableManager extends MMOManager {
|
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) {
|
public void register(DropTable table) {
|
||||||
map.put(table.getId(), table);
|
map.put(table.getId(), table);
|
||||||
@ -47,11 +47,8 @@ public class DropTableManager extends MMOManager {
|
|||||||
if (obj instanceof String)
|
if (obj instanceof String)
|
||||||
return get((String) obj);
|
return get((String) obj);
|
||||||
|
|
||||||
if (obj instanceof ConfigurationSection) {
|
if (obj instanceof ConfigurationSection)
|
||||||
DropTable table = new DropTable((ConfigurationSection) obj);
|
return new DropTable((ConfigurationSection) obj).load();
|
||||||
table.load();
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Could not parse drop table.");
|
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
|
offset: .2
|
||||||
height: .6
|
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
|
# Settings for the default action bar
|
||||||
action-bar:
|
action-bar:
|
||||||
|
|
||||||
# Whether or not to use the default action bar. (This doesn't change any other action bars provided by MMOCore.)
|
# Whether or not to use the default action bar. (This doesn't change any other action bars provided by MMOCore.)
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
# The decimal format for stats (not including stat formats in stats.yml)
|
# The decimal format for stats (not including stat formats in stats.yml)
|
||||||
decimal: "0.#"
|
decimal: "0.#"
|
||||||
|
|
||||||
# The amount of ticks before updating the info
|
# The amount of ticks before updating the info
|
||||||
ticks-to-update: 5
|
ticks-to-update: 5
|
||||||
|
|
||||||
# How to display the data.
|
# How to display the data.
|
||||||
format: "&c❤ {health}/{max_health} &f| &9⭐ {mana}/{max_mana} &f| &7⛨ {armor}"
|
format: "&c❤ {health}/{max_health} &f| &9⭐ {mana}/{max_mana} &f| &7⛨ {armor}"
|
||||||
|
|
||||||
|
@ -35,8 +35,6 @@ on-mine:
|
|||||||
temp-block: 'skull{value="eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTU0ODE4MjMzYzgxMTg3M2U4NWY1YTRlYTQ0MjliNzVmMjNiNmFlMGVhNmY1ZmMwZjdiYjQyMGQ3YzQ3MSJ9fX0="}'
|
temp-block: 'skull{value="eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTU0ODE4MjMzYzgxMTg3M2U4NWY1YTRlYTQ0MjliNzVmMjNiNmFlMGVhNmY1ZmMwZjdiYjQyMGQ3YzQ3MSJ9fX0="}'
|
||||||
triggers:
|
triggers:
|
||||||
- 'exp{profession=mining;amount=20}'
|
- 'exp{profession=mining;amount=20}'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
emerald:
|
emerald:
|
||||||
material: vanilla{type=EMERALD_ORE}
|
material: vanilla{type=EMERALD_ORE}
|
||||||
|
Loading…
Reference in New Issue
Block a user