Documented drop and config systems

This commit is contained in:
Auxilor 2020-12-22 23:42:31 +00:00
parent 1fb3d56ebf
commit 04a509f04f
10 changed files with 343 additions and 159 deletions

View File

@ -1,6 +1,7 @@
package com.willfp.ecoenchants.config.configs;
import com.willfp.eco.util.config.BaseConfig;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Set;
@ -17,39 +18,39 @@ public class Rarity extends BaseConfig {
return config.getConfigurationSection("rarities").getKeys(false);
}
public int getInt(String path) {
public int getInt(@NotNull String path) {
return config.getInt(path);
}
public int getInt(String path, int def) {
public int getInt(@NotNull String path, int def) {
return config.getInt(path, def);
}
public List<Integer> getInts(String path) {
public @NotNull List<Integer> getInts(@NotNull String path) {
return config.getIntegerList(path);
}
public boolean getBool(String path) {
public boolean getBool(@NotNull String path) {
return config.getBoolean(path);
}
public List<Boolean> getBools(String path) {
public @NotNull List<Boolean> getBools(@NotNull String path) {
return config.getBooleanList(path);
}
public String getString(String path) {
public @NotNull String getString(@NotNull String path) {
return config.getString(path);
}
public List<String> getStrings(String path) {
public @NotNull List<String> getStrings(@NotNull String path) {
return config.getStringList(path);
}
public double getDouble(String path) {
public double getDouble(@NotNull String path) {
return config.getDouble(path);
}
public List<Double> getDoubles(String path) {
public @NotNull List<Double> getDoubles(@NotNull String path) {
return config.getDoubleList(path);
}
}

View File

@ -4,6 +4,7 @@ import com.willfp.eco.util.injection.PluginDependent;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
import java.io.BufferedReader;
import java.io.File;
@ -11,13 +12,38 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;
public abstract class BaseConfig extends PluginDependent {
/**
* The linked {@link YamlConfiguration} where values are physically stored.
*/
public final YamlConfiguration config;
/**
* The physical config file, as stored on disk.
*/
private final File configFile;
/**
* The full name of the config file (eg config.yml).
*/
private final String name;
/**
* Whether keys not in the base config should be removed on update.
*/
private final boolean removeUnused;
/**
* Config implementation for configs present in the plugin's base directory (eg config.yml, lang.yml).
* <p>
* Automatically updates.
*
* @param configName The name of the config
* @param removeUnused Whether keys not present in the default config should be removed on update.
*/
protected BaseConfig(String configName, boolean removeUnused) {
super(AbstractEcoPlugin.getInstance());
this.name = configName + ".yml";
@ -37,6 +63,11 @@ public abstract class BaseConfig extends PluginDependent {
this.getPlugin().saveResource(name, false);
}
/**
* Update the config.
* <p>
* Writes missing values, however removes comments due to how configs are stored internally in bukkit.
*/
public void update() {
try {
config.load(configFile);
@ -72,4 +103,101 @@ public abstract class BaseConfig extends PluginDependent {
e.printStackTrace();
}
}
/**
* Get an integer from config.
*
* @param path The key to fetch the value from.
* @return The found value, or 0 if not found.
*/
public int getInt(@NotNull final String path) {
return config.getInt(path, 0);
}
/**
* Get an integer from config with a specified default (not found) value.
*
* @param path The key to fetch the value from.
* @param def The value to default to if not found.
* @return The found value, or the default.
*/
public int getInt(@NotNull final String path,
final int def) {
return config.getInt(path, def);
}
/**
* Get a list of integers from config.
*
* @param path The key to fetch the value from.
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
*/
@NotNull
public List<Integer> getInts(@NotNull final String path) {
return config.getIntegerList(path);
}
/**
* Get a boolean from config.
*
* @param path The key to fetch the value from.
* @return The found value, or false if not found.
*/
public boolean getBool(@NotNull final String path) {
return config.getBoolean(path, false);
}
/**
* Get a list of booleans from config.
*
* @param path The key to fetch the value from.
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
*/
@NotNull
public List<Boolean> getBools(@NotNull final String path) {
return config.getBooleanList(path);
}
/**
* Get a string from config.
*
* @param path The key to fetch the value from.
* @return The found value, or an empty string if not found.
*/
@NotNull
public String getString(@NotNull final String path) {
return Objects.requireNonNull(config.getString(path, ""));
}
/**
* Get a list of strings from config.
*
* @param path The key to fetch the value from.
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
*/
@NotNull
public List<String> getStrings(@NotNull final String path) {
return config.getStringList(path);
}
/**
* Get a decimal from config.
*
* @param path The key to fetch the value from.
* @return The found value, or 0 if not found.
*/
public double getDouble(@NotNull final String path) {
return config.getDouble(path, 0);
}
/**
* Get a list of decimals from config.
*
* @param path The key to fetch the value from.
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
*/
@NotNull
public List<Double> getDoubles(@NotNull final String path) {
return config.getDoubleList(path);
}
}

View File

@ -1,15 +1,30 @@
package com.willfp.eco.util.config;
import com.willfp.eco.util.config.configs.Config;
import com.willfp.eco.util.config.configs.Lang;
public class Configs {
public final class Configs {
/**
* The {@link BaseConfig} implementation for lang.yml.
*/
public static final Lang LANG = new Lang();
/**
* The {@link BaseConfig} implementation for config.yml.
*/
public static final Config CONFIG = new Config();
/**
* Update lang.yml and config.yml.
*
* @see BaseConfig
*/
public static void update() {
LANG.update();
CONFIG.update();
}
}
private Configs() {
}
}

View File

@ -1,9 +1,6 @@
package com.willfp.eco.util.config.configs;
import com.willfp.eco.util.config.BaseConfig;
import org.bukkit.inventory.ItemStack;
import java.util.List;
/**
* Wrapper for config.yml
@ -12,44 +9,4 @@ public class Config extends BaseConfig {
public Config() {
super("config", true);
}
public int getInt(String path) {
return config.getInt(path);
}
public int getInt(String path, int def) {
return config.getInt(path, def);
}
public List<Integer> getInts(String path) {
return config.getIntegerList(path);
}
public boolean getBool(String path) {
return config.getBoolean(path);
}
public List<Boolean> getBools(String path) {
return config.getBooleanList(path);
}
public String getString(String path) {
return config.getString(path);
}
public List<String> getStrings(String path) {
return config.getStringList(path);
}
public double getDouble(String path) {
return config.getDouble(path);
}
public List<Double> getDoubles(String path) {
return config.getDoubleList(path);
}
public ItemStack getItemStack(String path) {
return config.getItemStack(path);
}
}

View File

@ -3,8 +3,6 @@ package com.willfp.eco.util.config.configs;
import com.willfp.eco.util.StringUtils;
import com.willfp.eco.util.config.BaseConfig;
import java.util.List;
/**
* Wrapper for lang.yml
*/
@ -13,15 +11,6 @@ public class Lang extends BaseConfig {
super("lang", false);
}
public String getString(String path) {
return StringUtils.translate(String.valueOf(config.getString(path)));
}
public List<String> getStrings(String path) {
return config.getStringList(path);
}
public String getPrefix() {
return StringUtils.translate(config.getString("messages.prefix"));
}

View File

@ -2,60 +2,52 @@ package com.willfp.eco.util.drops.internal;
import org.bukkit.Location;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
public interface AbstractDropQueue {
/**
* Add item to queue
* Add item to queue.
*
* @param item The item to add
* @return The DropQueue
* @param item The item to add.
* @return The DropQueue.
*/
AbstractDropQueue addItem(ItemStack item);
AbstractDropQueue addItem(@NotNull ItemStack item);
/**
* Add multiple items to queue
*
* @param itemStacks The items to add
* @return The DropQueue
* @param itemStacks The items to add.
* @return The DropQueue.
*/
AbstractDropQueue addItems(Collection<ItemStack> itemStacks);
AbstractDropQueue addItems(@NotNull Collection<ItemStack> itemStacks);
/**
* Add xp to queue
* Add xp to queue.
*
* @param amount The amount to add
* @return The DropQueue
* @param amount The amount to add.
* @return The DropQueue.
*/
AbstractDropQueue addXP(int amount);
/**
* Set location of the origin of the drops
* Set location of the origin of the drops.
*
* @param location The location
* @return The DropQueue
* @param location The location.
* @return The DropQueue.
*/
AbstractDropQueue setLocation(Location location);
AbstractDropQueue setLocation(@NotNull Location location);
/**
* Force the queue to act as if player is telekinetic
* Force the queue to act as if player is telekinetic.
*
* @return The DropQueue
* @return The DropQueue.
*/
AbstractDropQueue forceTelekinesis();
/**
* Set the queue to test specific item for telekinesis
* Default item is the player's held item, however for this is required for Tridents.
*
* @param item The item to test
* @return The DropQueue
*/
AbstractDropQueue setItem(ItemStack item);
/**
* Push the queue
* Push the queue.
*/
void push();
}

View File

@ -2,13 +2,28 @@ package com.willfp.eco.util.drops.internal;
import com.willfp.eco.util.config.Configs;
public class DropManager {
public final class DropManager {
/**
* The currently used type.
* <p>
* Standard by default, used if drops.collate key is not present in config.
*/
private static DropQueueType type = DropQueueType.STANDARD;
/**
* Get the type of {@link AbstractDropQueue} that should be used.
*
* @return The chosen {@link DropQueueType}.
*/
public static DropQueueType getType() {
return type;
}
/**
* Update the type of drop queue that should be used.
*
* @see DropQueueType
*/
public static void update() {
type = Configs.CONFIG.getBool("drops.collate") ? DropQueueType.COLLATED : DropQueueType.STANDARD;
}
@ -16,4 +31,8 @@ public class DropManager {
static {
update();
}
private DropManager() {
}
}

View File

@ -1,6 +1,15 @@
package com.willfp.eco.util.drops.internal;
public enum DropQueueType {
/**
* As drops are processed, push them to the world or to the player's inventory.
*/
STANDARD,
/**
* As drops are processed, add them to a queue that are all collectively pushed at the end of a tick.
* <p>
* Generally better performance.
*/
COLLATED
}

View File

@ -1,35 +1,42 @@
package com.willfp.eco.util.drops.internal;
import com.willfp.eco.util.drops.DropQueue;
import com.willfp.eco.util.injection.PluginDependent;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Backend implementation of {@link AbstractDropQueue}
* {@link this#push()} adds to a map that creates a new {@link InternalDropQueue} at the end of every tick
*
* The drops are not instantly pushed when called, instead the map is iterated over at the end of every tick. This massively improves performance.
*/
public class FastCollatedDropQueue extends InternalDropQueue {
/**
* The {@link CollatedDrops} linked to every player.
* <p>
* Cleared and updated every tick.
*/
private static final HashMap<Player, CollatedDrops> COLLATED_MAP = new HashMap<>();
/**
* Create {@link DropQueue} linked to player
* Backend implementation of {@link AbstractDropQueue}
* {@link this#push()} adds to a map that creates a new {@link InternalDropQueue} at the end of every tick
* <p>
* The drops are not instantly pushed when called, instead the map is iterated over at the end of every tick. This massively improves performance.
*
* @param player The player
* @param player The player to link the queue with.
*/
public FastCollatedDropQueue(Player player) {
super(player);
}
/**
* Queues the drops to be managed by the {@link CollatedRunnable}.
*/
@Override
public void push() {
CollatedDrops fetched = COLLATED_MAP.get(player);
@ -37,40 +44,91 @@ public class FastCollatedDropQueue extends InternalDropQueue {
COLLATED_MAP.put(player, collatedDrops);
}
private static class CollatedDrops {
/**
* The items, location, and xp linked to a player's drops.
*/
private static final class CollatedDrops {
/**
* A collection of all ItemStacks to be dropped at the end of the tick.
*/
private final List<ItemStack> drops;
/**
* The location to drop the items at.
*/
private Location location;
/**
* The xp to give to the player.
*/
private int xp;
private CollatedDrops(List<ItemStack> drops, Location location, int xp) {
private CollatedDrops(@NotNull final List<ItemStack> drops,
@NotNull final Location location,
final int xp) {
this.drops = drops;
this.location = location;
this.xp = xp;
}
/**
* Get the drops in the queue.
*
* @return A {@link List} of the drops to be given.
*/
@NotNull
public List<ItemStack> getDrops() {
return drops;
}
/**
* Get the location to drop the items and spawn the xp.
*
* @return The location.
*/
@NotNull
public Location getLocation() {
return location;
}
/**
* Get the experience to give to the player.
*
* @return The amount of experience to give.
*/
public int getXp() {
return xp;
}
public CollatedDrops addDrops(List<ItemStack> toAdd) {
/**
* Add {@link ItemStack}s to the queue.
*
* @param toAdd The items to add.
* @return The instance of the {@link CollatedDrops}.
*/
public CollatedDrops addDrops(@NotNull final List<ItemStack> toAdd) {
drops.addAll(toAdd);
return this;
}
public CollatedDrops setLocation(Location loc) {
/**
* Set the location of the queue.
*
* @param loc The location to set.
* @return The instance of the {@link CollatedDrops}.
*/
public CollatedDrops setLocation(@NotNull final Location loc) {
this.location = loc;
return this;
}
public CollatedDrops addXp(int xp) {
/**
* Add xp to the queue.
*
* @param xp The amount of xp to add.
* @return The instance of the {@link CollatedDrops}.
*/
public CollatedDrops addXp(final int xp) {
this.xp += xp;
return this;
}
@ -86,9 +144,18 @@ public class FastCollatedDropQueue extends InternalDropQueue {
}
public static class CollatedRunnable extends PluginDependent {
/**
* The {@link BukkitTask} that the runnable represents.
*/
private final BukkitTask runnableTask;
public CollatedRunnable(AbstractEcoPlugin plugin) {
/**
* Create and run a new runnable to process collated drops.
*
* @param plugin The {@link AbstractEcoPlugin} that manages the processing.
*/
@ApiStatus.Internal
public CollatedRunnable(@NotNull final AbstractEcoPlugin plugin) {
super(plugin);
runnableTask = plugin.getScheduler().runTimer(() -> {
for (Map.Entry<Player, CollatedDrops> entry : COLLATED_MAP.entrySet()) {
@ -102,6 +169,11 @@ public class FastCollatedDropQueue extends InternalDropQueue {
}, 0, 1);
}
/**
* Get the {@link BukkitTask} that the runnable represents.
*
* @return The linked {@link BukkitTask}.
*/
public BukkitTask getRunnableTask() {
return runnableTask;
}

View File

@ -10,6 +10,7 @@ import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerExpChangeEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
@ -17,82 +18,95 @@ import java.util.HashMap;
import java.util.List;
public class InternalDropQueue implements AbstractDropQueue {
/**
* The items that the DropQueue stores.
*/
protected final List<ItemStack> items;
protected int xp;
protected final Player player;
protected Location loc;
protected boolean hasTelekinesis = false;
protected ItemStack item;
/**
* Create a DropQueue linked to player
*
* @param player The player
* The experience to give.
*/
public InternalDropQueue(Player player) {
protected int xp;
/**
* The owner of the queue.
*/
protected final Player player;
/**
* The location to drop the items and xp.
*/
protected Location loc;
/**
* If the queue should be processed telekinetically.
*/
protected boolean hasTelekinesis = false;
/**
* Create a DropQueue linked to player.
*
* @param player The player.
*/
public InternalDropQueue(@NotNull final Player player) {
this.items = new ArrayList<>();
this.xp = 0;
this.player = player;
this.loc = player.getLocation();
this.item = player.getInventory().getItemInMainHand();
}
/**
* Add item to queue
* Add item to queue.
*
* @param item The item to add
*
* @return The DropQueue
* @param item The item to add.
* @return The DropQueue.
*/
@Override
public AbstractDropQueue addItem(ItemStack item) {
public AbstractDropQueue addItem(@NotNull final ItemStack item) {
this.items.add(item);
return this;
}
/**
* Add multiple items to queue
* Add multiple items to queue.
*
* @param itemStacks The items to add
*
* @return The DropQueue
* @param itemStacks The items to add.
* @return The DropQueue.
*/
@Override
public AbstractDropQueue addItems(Collection<ItemStack> itemStacks) {
public AbstractDropQueue addItems(@NotNull final Collection<ItemStack> itemStacks) {
this.items.addAll(itemStacks);
return this;
}
/**
* Add xp to queue
* Add xp to queue.
*
* @param amount The amount to add
*
* @return The DropQueue
* @param amount The amount to add.
* @return The DropQueue.
*/
@Override
public AbstractDropQueue addXP(int amount) {
public AbstractDropQueue addXP(final int amount) {
this.xp += amount;
return this;
}
/**
* Set location of the origin of the drops
* Set location of the origin of the drops.
*
* @param l The location
*
* @return The DropQueue
* @param location The location.
* @return The DropQueue.
*/
@Override
public AbstractDropQueue setLocation(Location l) {
this.loc = l;
public AbstractDropQueue setLocation(@NotNull final Location location) {
this.loc = location;
return this;
}
/**
* Force the queue to act as if player has a telekinetic item
* Force the queue to act as if player has a telekinetic item.
*
* @return The DropQueue
* @return The DropQueue.
*/
@Override
public AbstractDropQueue forceTelekinesis() {
@ -101,32 +115,20 @@ public class InternalDropQueue implements AbstractDropQueue {
}
/**
* Set the queue to test specific item for telekinesis
* Default item is the player's held item, however for this is required for Tridents.
*
* @param item The item to test
*
* @return The DropQueue
*/
@Override
public AbstractDropQueue setItem(ItemStack item) {
this.item = item;
return this;
}
/**
* Push the queue
* Push the queue.
*/
public void push() {
if(!hasTelekinesis) hasTelekinesis = TelekinesisUtils.testPlayer(player);
if (!hasTelekinesis) {
hasTelekinesis = TelekinesisUtils.testPlayer(player);
}
World world = loc.getWorld();
assert world != null;
loc = loc.add(0.5, 0.5, 0.5);
if(hasTelekinesis) {
if (hasTelekinesis) {
HashMap<Integer, ItemStack> leftover = player.getInventory().addItem(items.toArray(new ItemStack[0]));
for(ItemStack drop : leftover.values()) {
for (ItemStack drop : leftover.values()) {
world.dropItem(loc, drop).setVelocity(new Vector());
}
if (xp > 0) {