diff --git a/TODO.md b/TODO.md deleted file mode 100644 index c8c6461..0000000 --- a/TODO.md +++ /dev/null @@ -1,2 +0,0 @@ -- [ ] Block-Replacements are created even when a block is already queued for replacement. This should not happen! -- [ ] It should be possible to enable random respawning for blocks within certain regions marked by a specific flag (ouroboros-mines-random?) \ No newline at end of file diff --git a/pom.xml b/pom.xml index 1dba1e1..ad2de02 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ dev.th3shadowbroker.spigot OuroborosMines - 1.7.1-SNAPSHOT + 1.8.0-SNAPSHOT ${project.artifactId} @@ -63,7 +63,7 @@ org.spigotmc spigot-api - 1.15.1-R0.1-SNAPSHOT + 1.16.2-R0.1-SNAPSHOT provided diff --git a/src/main/java/dev/th3shadowbroker/ouroboros/mines/OuroborosMines.java b/src/main/java/dev/th3shadowbroker/ouroboros/mines/OuroborosMines.java index 7ca7ede..efda054 100644 --- a/src/main/java/dev/th3shadowbroker/ouroboros/mines/OuroborosMines.java +++ b/src/main/java/dev/th3shadowbroker/ouroboros/mines/OuroborosMines.java @@ -22,11 +22,9 @@ import com.sk89q.worldguard.WorldGuard; import com.sk89q.worldguard.protection.flags.StateFlag; import dev.th3shadowbroker.ouroboros.mines.commands.OmCommand; +import dev.th3shadowbroker.ouroboros.mines.drops.DropManager; import dev.th3shadowbroker.ouroboros.mines.exceptions.InvalidMineMaterialException; -import dev.th3shadowbroker.ouroboros.mines.listeners.BlockBreakListener; -import dev.th3shadowbroker.ouroboros.mines.listeners.DepositDiscoveryListener; -import dev.th3shadowbroker.ouroboros.mines.listeners.ExperienceListener; -import dev.th3shadowbroker.ouroboros.mines.listeners.TimeSkipListener; +import dev.th3shadowbroker.ouroboros.mines.listeners.*; import dev.th3shadowbroker.ouroboros.mines.thirdparty.JobsRebornSupport; import dev.th3shadowbroker.ouroboros.mines.thirdparty.PlaceholderAPISupport; import dev.th3shadowbroker.ouroboros.mines.thirdparty.QuestsSupport; @@ -42,6 +40,7 @@ import org.th3shadowbroker.ouroboros.update.comparison.Comparator; import org.th3shadowbroker.ouroboros.update.spiget.SpigetUpdater; +import java.io.File; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Arrays; @@ -64,6 +63,8 @@ public class OuroborosMines extends JavaPlugin { private AnnouncementManager announcementManager; + private DropManager dropManager; + private boolean worldGuardFound = false; @Override @@ -105,10 +106,13 @@ public void onEnable() { getServer().getPluginManager().registerEvents( new DepositDiscoveryListener(), this ); getServer().getPluginManager().registerEvents( new ExperienceListener(), this ); getServer().getPluginManager().registerEvents( new TimeSkipListener(), this ); + getServer().getPluginManager().registerEvents( new PlayerInteractListener(), this ); announcementManager = new AnnouncementManager(); announcementManager.createTasks(); + dropManager = new DropManager(new File(getDataFolder(), "drops.yml")); + getCommand("om").setExecutor(new OmCommand()); checkForSupportedPlugins(); @@ -211,7 +215,15 @@ private void updateConfig() { "autoPickup", "openingHours", "timezone", - "placeholders" + "placeholders", + "chat.messages.reloadingDropGroups", + "chat.messages.reloadedDropGroups", + "chat.messages.awaitingRightClick", + "chat.messages.awaitingRightClickCancelled", + "chat.messages.dropGroupCreated", + "chat.messages.dropGroupExists", + "chat.messages.missingDropGroupName", + "chat.messages.consoleNotAllowed" ); pathsToCopy.forEach(path -> { if (!getConfig().isSet(path)) { @@ -271,5 +283,9 @@ public TaskManager getTaskManager() { public AnnouncementManager getAnnouncementManager() { return announcementManager; } - + + public DropManager getDropManager() { + return dropManager; + } + } diff --git a/src/main/java/dev/th3shadowbroker/ouroboros/mines/commands/OmCommand.java b/src/main/java/dev/th3shadowbroker/ouroboros/mines/commands/OmCommand.java index 8c5a27e..cfdb029 100644 --- a/src/main/java/dev/th3shadowbroker/ouroboros/mines/commands/OmCommand.java +++ b/src/main/java/dev/th3shadowbroker/ouroboros/mines/commands/OmCommand.java @@ -22,6 +22,7 @@ import com.sk89q.worldguard.protection.ApplicableRegionSet; import com.sk89q.worldguard.protection.regions.ProtectedRegion; import dev.th3shadowbroker.ouroboros.mines.OuroborosMines; +import dev.th3shadowbroker.ouroboros.mines.drops.DropGroupCreator; import dev.th3shadowbroker.ouroboros.mines.util.Permissions; import dev.th3shadowbroker.ouroboros.mines.util.RegionConfiguration; import dev.th3shadowbroker.ouroboros.mines.util.TemplateMessage; @@ -37,7 +38,7 @@ public class OmCommand implements CommandExecutor { - private final String consoleNotAllowed = TemplateMessage.from("chat.messages.consoleOnly").colorize().toString(); + private final String consoleNotAllowed = TemplateMessage.from("chat.messages.consoleNotAllowed").colorize().toString(); private final OuroborosMines plugin = OuroborosMines.INSTANCE; @@ -95,6 +96,9 @@ public boolean onCommand(CommandSender sender, Command cmd, String cmdLabel, Str plugin.getMaterialManager().reloadRegionConfigurations(); sender.sendMessage(TemplateMessage.from("chat.messages.reloadedRegionConfigurations").insert("count", String.valueOf(plugin.getMaterialManager().getMineableMaterialOverrides().size())).colorize().toString()); plugin.getAnnouncementManager().flush(); + sender.sendMessage(TemplateMessage.from("chat.messages.reloadingDropGroups").colorize().toString()); + plugin.getDropManager().reloadGroups(); + sender.sendMessage(TemplateMessage.from("chat.messages.reloadedDropGroups").insert("count", String.valueOf(plugin.getDropManager().getGroups().length)).colorize().toString()); } catch (Exception ex) { sender.sendMessage(TemplateMessage.from("chat.messages.error").colorize().insert("error", ex.getMessage()).toString()); } @@ -103,6 +107,38 @@ public boolean onCommand(CommandSender sender, Command cmd, String cmdLabel, Str } break; + case "dropgroup": + case "dg": + if (sender.hasPermission(Permissions.COMMAND_DROP_GROUP.permission)) { + if (sender instanceof Player) { + Player player = (Player) sender; + + if (args.length >= 2) { + String dropGroupName = args[1]; + + // Drop group does not exist + if (!OuroborosMines.INSTANCE.getDropManager().getDropGroup(dropGroupName).isPresent()) { + DropGroupCreator.awaitCreation(player, dropGroupName); + player.sendMessage(TemplateMessage.from("chat.messages.awaitingRightClick").colorize().toString()); + } else { + player.sendMessage(TemplateMessage.from("chat.messages.dropGroupExists").insert("name", dropGroupName).colorize().toString()); + } + } else { + if (DropGroupCreator.creationPending(player)) { + DropGroupCreator.clearCreationStatus(player); + sender.sendMessage(TemplateMessage.from("chat.messages.awaitingRightClickCancelled").colorize().toString()); + } else { + sender.sendMessage(TemplateMessage.from("chat.messages.missingDropGroupName").colorize().toString()); + } + } + } else { + sender.sendMessage(consoleNotAllowed); + } + } else { + sender.sendMessage(cmd.getPermissionMessage()); + } + break; + default: sender.sendMessage(TemplateMessage.from("chat.messages.unrecognizedArgument").colorize().toString()); sender.sendMessage(cmd.getUsage()); diff --git a/src/main/java/dev/th3shadowbroker/ouroboros/mines/drops/Drop.java b/src/main/java/dev/th3shadowbroker/ouroboros/mines/drops/Drop.java new file mode 100644 index 0000000..77b51d1 --- /dev/null +++ b/src/main/java/dev/th3shadowbroker/ouroboros/mines/drops/Drop.java @@ -0,0 +1,65 @@ +/* + * Copyright 2020 Jens Fischer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package dev.th3shadowbroker.ouroboros.mines.drops; + +import dev.th3shadowbroker.ouroboros.mines.util.Range; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.inventory.ItemStack; + +public class Drop { + + private final ItemStack itemStack; + + private final double dropChance; + + private final Range dropAmount; + + public Drop(ItemStack itemStack, double dropChance, Range dropAmount) { + this.itemStack = itemStack; + this.dropChance = dropChance; + this.dropAmount = dropAmount; + } + + public ItemStack getItemStack() { + return itemStack; + } + + public double getDropChance() { + return dropChance; + } + + public Range getDropAmount() { + return dropAmount; + } + + public ItemStack drawDropstack() { + ItemStack dropStack = itemStack.clone(); + dropStack.setAmount(dropAmount.isRange() ? dropAmount.getRandomWithin() : dropAmount.getMin()); + return dropStack; + } + + public static Drop fromSection(ConfigurationSection section) { + ItemStack itemStack = section.getItemStack("item"); + double dropChance = section.getDouble("chance", 1); + Range dropAmount = Range.fromString(section.getString("amount", "1")); + return new Drop(itemStack, dropChance, dropAmount); + } + +} diff --git a/src/main/java/dev/th3shadowbroker/ouroboros/mines/drops/DropGroup.java b/src/main/java/dev/th3shadowbroker/ouroboros/mines/drops/DropGroup.java new file mode 100644 index 0000000..0156280 --- /dev/null +++ b/src/main/java/dev/th3shadowbroker/ouroboros/mines/drops/DropGroup.java @@ -0,0 +1,99 @@ +/* + * Copyright 2020 Jens Fischer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package dev.th3shadowbroker.ouroboros.mines.drops; + +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class DropGroup { + + private final List drops; + + private final boolean multidrop; + + public DropGroup(List drops, boolean multidrop) { + this.drops = drops; + this.multidrop = multidrop; + } + + public boolean isValid() { + return multidrop || drops.stream().mapToDouble(Drop::getDropChance).sum() <= 1; + } + + public List getDrops() { + return drops; + } + + public boolean isMultidrop() { + return multidrop; + } + + private ItemStack[] drawMultidrop() { + final List drops = new ArrayList<>(); + this.drops.forEach( + drop -> { + + // Drop chance 100 or higher + if (drop.getDropChance() >= 1) { + drops.add(drop.drawDropstack()); + + // Drop chance below 100 + } else { + Random rnd = new Random(); + boolean shallDrop = ((double) rnd.nextInt(100) / 100) <= drop.getDropChance(); + if (shallDrop) { + drops.add(drop.drawDropstack()); + } + } + + } + ); + return drops.stream().toArray(ItemStack[]::new); + } + + private ItemStack[] drawSingledrop() { + ItemStack dropStack = null; + Random rnd = new Random(); + + double drawnChance = ((double) rnd.nextInt(100) / 100); + double offset = 0; + + for (Drop drop : drops) { + boolean shallDrop = drawnChance <= drop.getDropChance() + offset; + + if (shallDrop) { + dropStack = drop.drawDropstack(); + break; + } else { + offset += drop.getDropChance(); + } + } + + return dropStack == null ? new ItemStack[0] : new ItemStack[]{ dropStack }; + } + + public ItemStack[] drawDrops() { + return multidrop ? drawMultidrop() : drawSingledrop(); + } + +} diff --git a/src/main/java/dev/th3shadowbroker/ouroboros/mines/drops/DropGroupCreator.java b/src/main/java/dev/th3shadowbroker/ouroboros/mines/drops/DropGroupCreator.java new file mode 100644 index 0000000..fdf5f92 --- /dev/null +++ b/src/main/java/dev/th3shadowbroker/ouroboros/mines/drops/DropGroupCreator.java @@ -0,0 +1,85 @@ +/* + * Copyright 2020 Jens Fischer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package dev.th3shadowbroker.ouroboros.mines.drops; + +import dev.th3shadowbroker.ouroboros.mines.OuroborosMines; +import dev.th3shadowbroker.ouroboros.mines.util.Range; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.metadata.MetadataValue; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class DropGroupCreator { + + private static final String META_AWAITING_RIGHT_CLICK = "OM_AWAITING_RIGHT_CLICK"; + + private static final String META_DROP_GROUP_NAME = "OM_DROP_GROUP_NAME"; + + public static void awaitCreation(Player player, String dropGroupName) { + if (!creationPending(player)) { + player.setMetadata(META_AWAITING_RIGHT_CLICK, new FixedMetadataValue(OuroborosMines.INSTANCE, true)); + player.setMetadata(META_DROP_GROUP_NAME, new FixedMetadataValue(OuroborosMines.INSTANCE, dropGroupName)); + } + } + + public static void clearCreationStatus(Player player) { + player.removeMetadata(META_AWAITING_RIGHT_CLICK, OuroborosMines.INSTANCE); + player.removeMetadata(META_DROP_GROUP_NAME, OuroborosMines.INSTANCE); + } + + public static boolean creationPending(Player player) { + return player.hasMetadata(META_AWAITING_RIGHT_CLICK) && player.hasMetadata(META_DROP_GROUP_NAME); + } + + public static String getDropGroupName(Player player) { + List values = player.getMetadata(META_DROP_GROUP_NAME); + return values.isEmpty() ? null : values.get(0).asString(); + } + + public static void saveDropGroup(Inventory inventory, String dropGroupName) throws IOException { + DropManager dropManager = OuroborosMines.INSTANCE.getDropManager(); + + ConfigurationSection section = dropManager.getConfiguration().createSection(dropGroupName); + section.set("multidrop", true); + + ConfigurationSection dropsSection = section.createSection("drops"); + + List drops = Arrays.stream(inventory.getContents()).filter(itemStack -> itemStack != null).map(itemStack -> new Drop(itemStack.clone(), 1, new Range(1, 1))).collect(Collectors.toList()); + for (int i = 0; i < drops.size(); i++) { + ConfigurationSection dropSection = dropsSection.createSection(String.valueOf(i)); + + Drop drop = drops.get(i); + drop.getItemStack().setAmount(1); + + dropSection.set("chance", drop.getDropChance()); + dropSection.set("amount", Integer.valueOf(drop.getDropAmount().toString())); + dropSection.set("item", drop.getItemStack()); + } + + dropManager.getConfiguration().save(dropManager.getFile()); + } + +} diff --git a/src/main/java/dev/th3shadowbroker/ouroboros/mines/drops/DropManager.java b/src/main/java/dev/th3shadowbroker/ouroboros/mines/drops/DropManager.java new file mode 100644 index 0000000..b0c8d72 --- /dev/null +++ b/src/main/java/dev/th3shadowbroker/ouroboros/mines/drops/DropManager.java @@ -0,0 +1,113 @@ +/* + * Copyright 2020 Jens Fischer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package dev.th3shadowbroker.ouroboros.mines.drops; + +import dev.th3shadowbroker.ouroboros.mines.OuroborosMines; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.inventory.ItemStack; + +import java.io.File; +import java.io.IOException; +import java.util.*; +import java.util.logging.Logger; + +public class DropManager { + + private final File file; + + private final FileConfiguration configuration; + + private final Map dropGroups; + + private final Logger log; + + public DropManager(File dropFile) { + this.dropGroups = new HashMap<>(); + this.file = dropFile; + this.log = OuroborosMines.INSTANCE.getLogger(); + if (!dropFile.exists()) { + try { + boolean dropFileCreated = dropFile.createNewFile(); + if (dropFileCreated) log.info("Drop file created."); + } catch (IOException ex) { + log.warning("Failed to create drop file!"); + } + } + this.configuration = YamlConfiguration.loadConfiguration(dropFile); + loadGroups(); + } + + private void loadGroups() { + log.info(String.format("Loading drops from %s", file.getAbsolutePath())); + + for (String groupName : configuration.getKeys(false)) { + ConfigurationSection groupSection = configuration.getConfigurationSection(groupName); + if (groupSection == null) continue; + + try { + ConfigurationSection dropSection = groupSection.getConfigurationSection("drops"); + boolean multidrop = groupSection.getBoolean("multidrop", false); + + final List drops = new ArrayList<>(); + dropSection.getKeys(false).forEach( key -> { + drops.add(Drop.fromSection(dropSection.getConfigurationSection(key))); + } ); + + dropGroups.put(groupName, new DropGroup(drops, multidrop)); + } catch (Exception ex) { + log.warning(String.format("Unable to evaluate the %s section of %s. Please check the wiki. Skipping.", groupName, file.getAbsolutePath())); + } + } + + log.info(String.format("Loaded %s drop groups!", dropGroups.size())); + } + + public void reloadGroups() { + dropGroups.clear(); + loadGroups(); + } + + public void addGroup(String groupName, DropGroup group) { + dropGroups.put(groupName, group); + } + + public Optional getDropGroup(String groupName) { + return Optional.ofNullable(dropGroups.getOrDefault(groupName, null)); + } + + public String[] getGroupNames() { + return dropGroups.keySet().stream().toArray(String[]::new); + } + + public DropGroup[] getGroups() { + return dropGroups.values().stream().toArray(DropGroup[]::new); + } + + public File getFile() { + return file; + } + + public FileConfiguration getConfiguration() { + return configuration; + } +} diff --git a/src/main/java/dev/th3shadowbroker/ouroboros/mines/listeners/BlockBreakListener.java b/src/main/java/dev/th3shadowbroker/ouroboros/mines/listeners/BlockBreakListener.java index a4e5893..84b9311 100644 --- a/src/main/java/dev/th3shadowbroker/ouroboros/mines/listeners/BlockBreakListener.java +++ b/src/main/java/dev/th3shadowbroker/ouroboros/mines/listeners/BlockBreakListener.java @@ -27,13 +27,13 @@ import dev.th3shadowbroker.ouroboros.mines.events.MaterialMinedEvent; import dev.th3shadowbroker.ouroboros.mines.util.*; import org.bukkit.Bukkit; +import org.bukkit.Material; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.inventory.ItemStack; -import java.util.Collection; import java.util.Map; import java.util.Optional; @@ -46,7 +46,6 @@ public class BlockBreakListener implements Listener { @EventHandler(priority = EventPriority.LOWEST) public void onBlockBreak(BlockBreakEvent event) { Optional blockRegions = WorldUtils.getBlockRegions(event.getBlock()); - if ( blockRegions.isPresent() && blockRegions.get().testState(null, OuroborosMines.FLAG)) { Optional minedMaterial = plugin.getMaterialManager().getMaterialProperties(event.getBlock().getType(), WorldUtils.getTopRegion(blockRegions.get()).get(), BukkitAdapter.adapt(event.getBlock().getWorld())); if (minedMaterial.isPresent()) { @@ -85,7 +84,7 @@ public void onBlockBreak(BlockBreakEvent event) { //If rich if (MetaUtils.isRich(event.getBlock())) { //event.getBlock().breakNaturally(event.getPlayer().getInventory().getItemInMainHand()); - breakBlock(event, event.getPlayer().getInventory().getItemInMainHand()); + breakBlock(event, minedMaterial.get(), event.getPlayer().getInventory().getItemInMainHand()); event.getBlock().setType(minedMaterial.get().getMaterial()); MetaUtils.decreaseRichness(event.getBlock()); @@ -107,7 +106,7 @@ public void onBlockBreak(BlockBreakEvent event) { //Break it! Replace it! //event.getBlock().breakNaturally(event.getPlayer().getInventory().getItemInMainHand()); - breakBlock(event, event.getPlayer().getInventory().getItemInMainHand()); + breakBlock(event, minedMaterial.get(), event.getPlayer().getInventory().getItemInMainHand()); event.getBlock().setType(minedMaterial.get().getReplacement()); } @@ -115,11 +114,23 @@ public void onBlockBreak(BlockBreakEvent event) { } } - private void breakBlock(BlockBreakEvent event, ItemStack tool) { + private void breakBlock(BlockBreakEvent event, MineableMaterial mineableMaterial, ItemStack tool) { if (!autoPickup) { - event.getBlock().breakNaturally(event.getPlayer().getInventory().getItemInMainHand()); + // Check for drop group + if (mineableMaterial.getDropGroup().isPresent()) { + event.setDropItems(false); + + for (ItemStack drop : mineableMaterial.getDropGroup().get().drawDrops()) { + event.getBlock().getWorld().dropItem(event.getBlock().getLocation(), drop); + } + + // No drop-group assigned + } else { + event.getBlock().breakNaturally(event.getPlayer().getInventory().getItemInMainHand()); + } } else { - ItemStack[] drops = event.getBlock().getDrops(event.getPlayer().getInventory().getItemInMainHand()).stream().toArray(ItemStack[]::new); + // Modified in favour of drop feature + ItemStack[] drops = mineableMaterial.getDropGroup().isPresent() ? mineableMaterial.getDropGroup().get().drawDrops() : event.getBlock().getDrops(event.getPlayer().getInventory().getItemInMainHand()).stream().toArray(ItemStack[]::new); Map overflow = event.getPlayer().getInventory().addItem(drops); if (overflow.size() > 0) { overflow.forEach((slot, item) -> event.getBlock().getWorld().dropItemNaturally(event.getBlock().getLocation(), item)); diff --git a/src/main/java/dev/th3shadowbroker/ouroboros/mines/listeners/PlayerInteractListener.java b/src/main/java/dev/th3shadowbroker/ouroboros/mines/listeners/PlayerInteractListener.java new file mode 100644 index 0000000..d2af082 --- /dev/null +++ b/src/main/java/dev/th3shadowbroker/ouroboros/mines/listeners/PlayerInteractListener.java @@ -0,0 +1,66 @@ +/* + * Copyright 2020 Jens Fischer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package dev.th3shadowbroker.ouroboros.mines.listeners; + +import dev.th3shadowbroker.ouroboros.mines.OuroborosMines; +import dev.th3shadowbroker.ouroboros.mines.drops.DropGroupCreator; +import dev.th3shadowbroker.ouroboros.mines.util.TemplateMessage; +import org.bukkit.Material; +import org.bukkit.block.Container; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; + +import java.io.IOException; + +public class PlayerInteractListener implements Listener { + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + if (event.getAction() == Action.RIGHT_CLICK_BLOCK && event.getClickedBlock().getType() == Material.CHEST) { + if (DropGroupCreator.creationPending(event.getPlayer())) { + Player player = event.getPlayer(); + Container container = (Container) event.getClickedBlock().getState(); + String dropGroupName = DropGroupCreator.getDropGroupName(event.getPlayer()); + + // Drop group does not exist + if (!OuroborosMines.INSTANCE.getDropManager().getDropGroup(dropGroupName).isPresent()) { + try { + DropGroupCreator.saveDropGroup(container.getInventory(), dropGroupName); + player.sendMessage(TemplateMessage.from("chat.messages.dropGroupCreated").insert("name", dropGroupName).colorize().toString()); + } catch (IOException ex) { + player.sendMessage(TemplateMessage.from("chat.messages.error").insert("error", ex.getMessage()).colorize().toString()); + } + + // Done! + DropGroupCreator.clearCreationStatus(player); + // Drop group exists + } else { + player.sendMessage(TemplateMessage.from("chat.messages.dropGroupExists").insert("name", dropGroupName).colorize().toString()); + } + + event.setCancelled(true); + } + } + } + +} diff --git a/src/main/java/dev/th3shadowbroker/ouroboros/mines/util/MineableMaterial.java b/src/main/java/dev/th3shadowbroker/ouroboros/mines/util/MineableMaterial.java index fd71238..e170831 100644 --- a/src/main/java/dev/th3shadowbroker/ouroboros/mines/util/MineableMaterial.java +++ b/src/main/java/dev/th3shadowbroker/ouroboros/mines/util/MineableMaterial.java @@ -20,6 +20,7 @@ package dev.th3shadowbroker.ouroboros.mines.util; import dev.th3shadowbroker.ouroboros.mines.OuroborosMines; +import dev.th3shadowbroker.ouroboros.mines.drops.DropGroup; import dev.th3shadowbroker.ouroboros.mines.exceptions.InvalidMineMaterialException; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; @@ -47,7 +48,9 @@ public class MineableMaterial { private final Range depositExperience; - public MineableMaterial(Material material, Material[] replacements, Range cooldown, double richChance, Range richAmount, Range experience, Range depositExperience) { + private final String dropGroup; + + public MineableMaterial(Material material, Material[] replacements, Range cooldown, double richChance, Range richAmount, Range experience, Range depositExperience, String dropGroup) { this.material = material; this.replacements = replacements; this.cooldown = cooldown; @@ -55,6 +58,7 @@ public MineableMaterial(Material material, Material[] replacements, Range cooldo this.richAmount = richAmount; this.experience = experience; this.depositExperience = depositExperience; + this.dropGroup = dropGroup; } public Material getMaterial() { @@ -109,6 +113,10 @@ public Material getReplacement() { return replacements[replRandom.nextInt(replacements.length)]; } + public Optional getDropGroup() { + return dropGroup == null ? Optional.empty() : OuroborosMines.INSTANCE.getDropManager().getDropGroup(dropGroup); + } + public static MineableMaterial fromSection(ConfigurationSection section) throws InvalidMineMaterialException { //Parse material Optional material = Optional.ofNullable(Material.getMaterial(section.getName().toUpperCase())); @@ -173,6 +181,9 @@ public static MineableMaterial fromSection(ConfigurationSection section) throws } } + //Parse drop group + String dropGroup = section.getString("dropGroup", null); + return new MineableMaterial( //Material and replacements @@ -185,8 +196,10 @@ public static MineableMaterial fromSection(ConfigurationSection section) throws //Add range-values richAmount == null ? Range.zero() : richAmount, experience == null ? Range.zero() : experience, - depositExperience == null ? Range.zero() : depositExperience + depositExperience == null ? Range.zero() : depositExperience, + //Drop group + dropGroup ); } diff --git a/src/main/java/dev/th3shadowbroker/ouroboros/mines/util/Permissions.java b/src/main/java/dev/th3shadowbroker/ouroboros/mines/util/Permissions.java index a1c8fb5..3d6b9fb 100644 --- a/src/main/java/dev/th3shadowbroker/ouroboros/mines/util/Permissions.java +++ b/src/main/java/dev/th3shadowbroker/ouroboros/mines/util/Permissions.java @@ -27,7 +27,8 @@ public enum Permissions { COMMAND_ROOT("ouroboors.mines.command.*"), COMMAND_INFO("ouroboros.mines.command.info"), COMMAND_CUSTOMIZE("ouroboros.mines.command.customize"), - COMMAND_RELOAD("ouroboros.mines.command.reload"); + COMMAND_RELOAD("ouroboros.mines.command.reload"), + COMMAND_DROP_GROUP("ouroboros.mines.command.dropgroup"); public final String name; diff --git a/src/main/java/dev/th3shadowbroker/ouroboros/mines/util/Range.java b/src/main/java/dev/th3shadowbroker/ouroboros/mines/util/Range.java index 9833252..73cd753 100644 --- a/src/main/java/dev/th3shadowbroker/ouroboros/mines/util/Range.java +++ b/src/main/java/dev/th3shadowbroker/ouroboros/mines/util/Range.java @@ -64,7 +64,7 @@ public int getRandomWithin() { @Override public String toString() { - return String.format("%s-%s", min, max); + return isRange() ? String.format("%s-%s", min, max) : String.valueOf(min); } public static Range zero() { diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 11dec09..46daf98 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -9,14 +9,21 @@ default: false chat: prefix: '&9[OM]' messages: - consoleOnly: "&cThis command can not be executed from console!" + awaitingRightClick: "&2Right-click the chest you want to create the drop group from or type &e/om dg&2 to cancel!" + awaitingRightClickCancelled: "&cDrop group creation cancelled!" + consoleNotAllowed: "&cThis command can not be executed from console!" + dropGroupCreated: "&2Saved drop group &e%name%" + dropGroupExists: "&cThere's already a drop-group name &e%name%&c!" unrecognizedArgument: "&cUnrecognized argument" + missingDropGroupName: "&cMissing drop-group name!" regionCustomize: "&2A new configuration file for &b%region%&2 has been created!" regionAlreadyCustomized: "&cThere's already a configuration file for this region!" regionNotFound: "&cNo region found at your position!" reloadingConfig: "&2Reloading configuration..." reloadingRegionConfigurations: "&2Reloading region-configurations..." reloadedRegionConfigurations: "&2Loaded %count% region-specific configurations" + reloadingDropGroups: "&2Reloading drop groups..." + reloadedDropGroups: "&2Loaded %count% drop groups" worldNotFound: "&cWorld &e%world% &cnot found!" depositDiscovered: "&2You've discovered a %size% &e%material%&2 deposit!" depositSizes: diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index c3aa965..bd235bf 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -10,7 +10,7 @@ api-version: 1.13 commands: om: description: General command for ${plugin.name} - usage: /om [customize:reload] + usage: /om [customize:reload] [world:name] [region] permission-message: §cYou're not allowed to do this! permissions: @@ -27,6 +27,7 @@ permissions: ouroboros.mines.command.info: true ouroboros.mines.command.customize: true ouroboros.mines.command.reload: true + ouroboros.mines.command.dropgroup: true ouroboros.mines.command.info: default: true @@ -35,4 +36,7 @@ permissions: default: op ouroboros.mines.command.reload: - default: op \ No newline at end of file + default: op + + ouroboros.mines.command.dropgroup: + default: op