From 8bb0e1c771fe484a018557b958b74ec70097a4a0 Mon Sep 17 00:00:00 2001 From: Ryder Belserion Date: Mon, 16 Dec 2024 00:27:47 -0500 Subject: [PATCH] Add nexo furniture support (#806) * Add a crate interact event This is to have proper support for other plugins like Nexo, or ItemsAdder * Add nexo interact listener * add editor.yml * fix isCrateLocation method * add replacement command/feature for /crazycrates set * remove unneeded code * update invalid docs url * change crate to nullable * add {reason} placeholder to force exit * Switch to fully location based for nexo * check if hand is off_hand * spawn display entity above location * update default messages.yml * Add ability to remove crates when using /crazycrates editor * deprecate old way of removing crates * No longer need to sneak, or be in creative mode to remove crates. * always register our editor for normal blocks * Register more of our listeners * return if block is air * fix the last little odd bug * add trim example back to default files * reduce duplicate methods * return if the block clicked is furniture * update key checks * cancel key interactions * simplify interact handling with nexo/vanilla * update editor message * prevent re-adding to the crate editor * add/clean checks to prevent editor messes * remove from editor crate if they don't have the permission * remove dead imports * use Block.isEmpty() * prevent key check if itemstack is empty * add more if hand checks * add config option to pick custom items plugin * chore: remove import * add items adder support for furniture * add "none" option to the config.yml * add isFurniture method * use proper plugin check --------- Signed-off-by: Ryder Belserion --- .../common/config/ConfigManager.java | 17 ++ .../common/config/impl/ConfigKeys.java | 16 +- .../common/config/impl/EditorKeys.java | 38 +++ .../config/impl/messages/CommandKeys.java | 6 +- .../config/impl/messages/CrateKeys.java | 13 + common/src/main/resources/config.yml | 11 + .../main/resources/crates/CrateExample.yml | 2 +- common/src/main/resources/editor.yml | 10 + common/src/main/resources/messages.yml | 15 +- gradle/libs.versions.toml | 12 +- .../badbones69/crazycrates/CrazyCrates.java | 19 +- .../crazycrates/api/enums/Messages.java | 5 + .../api/events/CrateInteractEvent.java | 276 ++++++++++++++++++ .../crazycrates/commands/CommandManager.java | 4 +- .../crates/types/admin/crates/CommandSet.java | 77 ----- .../admin/crates/editor/CommandEditor.java | 72 +++++ .../listeners/CrateControlListener.java | 259 ---------------- .../crazycrates/listeners/MiscListener.java | 14 +- .../crates/CrateInteractListener.java | 245 ++++++++++++++++ .../crates/types/MobileCrateListener.java | 5 +- .../crates/types/QuadCrateListener.java | 2 - .../items/ItemsAdderInteractListener.java | 65 +++++ .../listeners/items/NexoInteractListener.java | 61 ++++ .../items/OraxenInteractListener.java | 61 ++++ .../items/PaperInteractListener.java | 79 +++++ .../tasks/crates/CrateManager.java | 210 ++++++++++++- paper/src/main/resources/paper-plugin.yml | 4 + 27 files changed, 1223 insertions(+), 375 deletions(-) create mode 100644 common/src/main/java/com/badbones69/crazycrates/common/config/impl/EditorKeys.java create mode 100644 common/src/main/resources/editor.yml create mode 100644 paper/src/main/java/com/badbones69/crazycrates/api/events/CrateInteractEvent.java delete mode 100644 paper/src/main/java/com/badbones69/crazycrates/commands/crates/types/admin/crates/CommandSet.java create mode 100644 paper/src/main/java/com/badbones69/crazycrates/commands/crates/types/admin/crates/editor/CommandEditor.java create mode 100644 paper/src/main/java/com/badbones69/crazycrates/listeners/crates/CrateInteractListener.java create mode 100644 paper/src/main/java/com/badbones69/crazycrates/listeners/items/ItemsAdderInteractListener.java create mode 100644 paper/src/main/java/com/badbones69/crazycrates/listeners/items/NexoInteractListener.java create mode 100644 paper/src/main/java/com/badbones69/crazycrates/listeners/items/OraxenInteractListener.java create mode 100644 paper/src/main/java/com/badbones69/crazycrates/listeners/items/PaperInteractListener.java diff --git a/common/src/main/java/com/badbones69/crazycrates/common/config/ConfigManager.java b/common/src/main/java/com/badbones69/crazycrates/common/config/ConfigManager.java index b6e1fbb6a..db87f9da4 100644 --- a/common/src/main/java/com/badbones69/crazycrates/common/config/ConfigManager.java +++ b/common/src/main/java/com/badbones69/crazycrates/common/config/ConfigManager.java @@ -3,6 +3,7 @@ import ch.jalu.configme.SettingsManager; import ch.jalu.configme.SettingsManagerBuilder; import ch.jalu.configme.resource.YamlFileResourceOptions; +import com.badbones69.crazycrates.common.config.impl.EditorKeys; import com.badbones69.crazycrates.common.config.migrate.ConfigMigration; import com.badbones69.crazycrates.common.config.migrate.LocaleMigration; import com.badbones69.crazycrates.common.config.impl.ConfigKeys; @@ -17,6 +18,8 @@ public class ConfigManager { private static SettingsManager config; + private static SettingsManager editor; + private static SettingsManager messages; /** @@ -31,6 +34,12 @@ public static void load(final File dataFolder) { .configurationData(ConfigKeys.class) .create(); + editor = SettingsManagerBuilder + .withYamlFile(new File(dataFolder, "editor.yml"), builder) + .migrationService(new ConfigMigration()) + .configurationData(EditorKeys.class) + .create(); + messages = SettingsManagerBuilder .withYamlFile(new File(dataFolder, "messages.yml"), builder) .migrationService(new LocaleMigration()) @@ -43,6 +52,7 @@ public static void load(final File dataFolder) { */ public static void refresh() { config.reload(); + editor.reload(); messages.reload(); } @@ -53,6 +63,13 @@ public static SettingsManager getConfig() { return config; } + /** + * @return gets editor.yml + */ + public static SettingsManager getEditor() { + return editor; + } + /** * @return gets messages.yml */ diff --git a/common/src/main/java/com/badbones69/crazycrates/common/config/impl/ConfigKeys.java b/common/src/main/java/com/badbones69/crazycrates/common/config/impl/ConfigKeys.java index fa7d269d4..430f4ccb9 100644 --- a/common/src/main/java/com/badbones69/crazycrates/common/config/impl/ConfigKeys.java +++ b/common/src/main/java/com/badbones69/crazycrates/common/config/impl/ConfigKeys.java @@ -103,13 +103,27 @@ public void registerComments(CommentsConfiguration conf) { }) public static final Property message_state = newBeanProperty(State.class, "root.message-state", State.send_message); + @Comment({ + "A list of available custom item plugins:", + " -> ItemsAdder", + " -> Oraxen", + " -> Nexo", + " -> None", + "", + "If the option is set to blank, it'll pick whatever plugin it feels like picking.", + "Set the value to None if you do not want any." + }) + public static final Property custom_items_plugin = newProperty("root.custom-items-plugin", ""); + @Comment({ "A list of available hologram plugins:", " -> DecentHolograms", " -> FancyHolograms", " -> CMI", + " -> None", "", - "If the option is set to blank, it'll pick whatever plugin it feels like picking." + "If the option is set to blank, it'll pick whatever plugin it feels like picking.", + "Set the value to None if you do not want any." }) public static final Property hologram_plugin = newProperty("root.hologram-plugin", ""); diff --git a/common/src/main/java/com/badbones69/crazycrates/common/config/impl/EditorKeys.java b/common/src/main/java/com/badbones69/crazycrates/common/config/impl/EditorKeys.java new file mode 100644 index 000000000..e338b613e --- /dev/null +++ b/common/src/main/java/com/badbones69/crazycrates/common/config/impl/EditorKeys.java @@ -0,0 +1,38 @@ +package com.badbones69.crazycrates.common.config.impl; + +import ch.jalu.configme.Comment; +import ch.jalu.configme.SettingsHolder; +import ch.jalu.configme.configurationdata.CommentsConfiguration; +import ch.jalu.configme.properties.Property; +import static ch.jalu.configme.properties.PropertyInitializer.newProperty; + +public class EditorKeys implements SettingsHolder { + + protected EditorKeys() {} + + @Override + public void registerComments(CommentsConfiguration conf) { + String[] header = { + "Support: https://discord.gg/badbones-s-live-chat-182615261403283459", + "Github: https://github.com/Crazy-Crew", + "", + "Issues: https://github.com/Crazy-Crew/CrazyCrates/issues", + "Features: https://github.com/Crazy-Crew/CrazyCrates/issues", + "", + "List of all sounds: https://minecraft.wiki/w/Sounds.json#Java_Edition_values", + }; + + String[] deprecation = { + "", + "Warning: This section is subject to change so it is considered deprecated.", + "This is your warning before the change happens. Please read the latest changelogs", + "" + }; + + conf.setComment("editor", header); + } + + @Comment("If this is set to true, when you are in /crazycrates editor... any existing crate locations will be overridden on right click.") + public static final Property overwrite_old_crate_locations = newProperty("editor.overwrite-old-crate-locations", false); + +} \ No newline at end of file diff --git a/common/src/main/java/com/badbones69/crazycrates/common/config/impl/messages/CommandKeys.java b/common/src/main/java/com/badbones69/crazycrates/common/config/impl/messages/CommandKeys.java index 2952a4633..3d32ee25e 100644 --- a/common/src/main/java/com/badbones69/crazycrates/common/config/impl/messages/CommandKeys.java +++ b/common/src/main/java/com/badbones69/crazycrates/common/config/impl/messages/CommandKeys.java @@ -151,8 +151,8 @@ public void registerComments(CommentsConfiguration conf) { "/crates mass-open [amount] - Mass opens a set amount of crates.", "/crates tp - Teleport to a Crate.", "/crates give [amount] [player] - Allows you to take keys from a player.", - "/crates set - Set the block you are looking at as a crate.", - "/crates set Menu - Set the block you are looking at to open the /crates menu.", + "/crates editor -c/--crate or -e/--exit - Allows you to enter/exit editor mode.", + "/crates migrate -mt/--migration_type --crate/-crate --data/-d - A command to migrate from other plugins or for internal changes.", "/crates reload - Reloads the config/data files.", "/crates set1/set2 - Sets position #1 or #2 for when making a new schematic for QuadCrates.", "/crates save - Create a new nbt file in the schematics folder.", @@ -161,6 +161,6 @@ public void registerComments(CommentsConfiguration conf) { "/keys - Shows how many keys you have.", "/crates - Opens the menu.", "", - "You can find a list of permissions @ https://docs.crazycrew.us/crazycrates/info/commands/permissions" + "You can find a list of permissions @ https://docs.crazycrew.us/docs/plugins/crazycrates/commands/permissions" )); } \ No newline at end of file diff --git a/common/src/main/java/com/badbones69/crazycrates/common/config/impl/messages/CrateKeys.java b/common/src/main/java/com/badbones69/crazycrates/common/config/impl/messages/CrateKeys.java index 63ec98cf6..c752622c8 100644 --- a/common/src/main/java/com/badbones69/crazycrates/common/config/impl/messages/CrateKeys.java +++ b/common/src/main/java/com/badbones69/crazycrates/common/config/impl/messages/CrateKeys.java @@ -63,12 +63,25 @@ public void registerComments(CommentsConfiguration conf) { @Comment("A list of available placeholders: {world}") public static final Property world_disabled = newProperty("crates.world-disabled", "{prefix}I am sorry but Crates are disabled in {world}."); + @Comment("A list of available placeholders: {crate}") + public static final Property editor_enter = newProperty("crates.editor.enter", "{prefix}You are now in editor mode."); + + public static final Property editor_exit = newProperty("crates.editor.exit", "{prefix}You are no longer in editor mode."); + + public static final Property editor_already_in = newProperty("crates.editor.already-in", "{prefix}You are already in the editor mode."); + + @Comment("A list of available placeholders: {reason}") + public static final Property force_editor_exit = newProperty("crates.editor.force-exit", "{prefix}You have been forced out of the editor mode for {reason}."); + @Comment("A list of available placeholders: {crate}") public static final Property> created_physical_crate = newListProperty("crates.physical-crate.created", List.of( "{prefix}You have set that block to {crate}.", "To remove the crate shift break in creative to remove." )); + @Comment("A list of available placeholders: {id}, {new_crate}") + public static final Property physical_crate_overridden = newProperty("crates.physical-crate.override", "{prefix}You have overridden the crate's location with id {id} with {new_crate}."); + @Comment("A list of available placeholders: {crate}") public static final Property physical_crate_already_exists = newProperty("crates.physical-crate.exists", "{prefix}This location already has a crate named {crate} with id: {id}."); diff --git a/common/src/main/resources/config.yml b/common/src/main/resources/config.yml index af177bce4..415fb175f 100644 --- a/common/src/main/resources/config.yml +++ b/common/src/main/resources/config.yml @@ -34,12 +34,23 @@ root: # send_actionbar -> sends messages in actionbar. # message-state: "send_message" + # A list of available custom item plugins: + # -> ItemsAdder + # -> Oraxen + # -> Nexo + # -> None + # + # If the option is set to blank, it'll pick whatever plugin it feels like picking. + # Set the value to None if you do not want any. + custom-items-plugin: "" # A list of available hologram plugins: # -> DecentHolograms # -> FancyHolograms # -> CMI + # -> None # # If the option is set to blank, it'll pick whatever plugin it feels like picking. + # Set the value to None if you do not want any. hologram-plugin: "" # This will wipe the example folder on /crazycrates reload or plugin startup. so you always have fresh examples to look at. update-examples-folder: true diff --git a/common/src/main/resources/crates/CrateExample.yml b/common/src/main/resources/crates/CrateExample.yml index e0d121fba..0867a0634 100644 --- a/common/src/main/resources/crates/CrateExample.yml +++ b/common/src/main/resources/crates/CrateExample.yml @@ -234,7 +234,7 @@ Crate: Weight: 15.0 # The list of items to win. Items: - - "Item:diamond_helmet, Name:Diamond Helmet, protection:5, unbreaking:3" + - "Item:diamond_helmet, Name:Diamond Helmet, protection:5, unbreaking:3, Trim-Material:quartz, Trim-Pattern:sentry" "4": # The enchants to be stored on the book. DisplayEnchantments: diff --git a/common/src/main/resources/editor.yml b/common/src/main/resources/editor.yml new file mode 100644 index 000000000..86afd3545 --- /dev/null +++ b/common/src/main/resources/editor.yml @@ -0,0 +1,10 @@ +# Support: https://discord.gg/badbones-s-live-chat-182615261403283459 +# Github: https://github.com/Crazy-Crew +# +# Issues: https://github.com/Crazy-Crew/CrazyCrates/issues +# Features: https://github.com/Crazy-Crew/CrazyCrates/issues +# +# List of all sounds: https://minecraft.wiki/w/Sounds.json#Java_Edition_values +editor: + # If this is set to true, when you are in /crazycrates editor... any existing crate locations will be overridden on right click. + overwrite-old-crate-locations: false diff --git a/common/src/main/resources/messages.yml b/common/src/main/resources/messages.yml index 351bb666d..75b979e14 100644 --- a/common/src/main/resources/messages.yml +++ b/common/src/main/resources/messages.yml @@ -84,6 +84,13 @@ crates: need-more-room: "{prefix}There is not enough space to open that here" # A list of available placeholders: {world} world-disabled: "{prefix}I am sorry but Crates are disabled in {world}." + editor: + # A list of available placeholders: {crate} + enter: "{prefix}You are now in editor mode." + # A list of available placeholders: {crate} + exit: "{prefix}You are no longer in editor mode." + # A list of available placeholders: {reason} + force-exit: "{prefix}You have been forced out of the editor mode for {reason}." physical-crate: # A list of available placeholders: {crate} created: @@ -267,10 +274,8 @@ command: - "/crates tp - Teleport to a Crate." - "/crates give [amount] [player] - Allows you to take keys from a player." - - "/crates set - Set the block you are looking at - as a crate." - - "/crates set Menu - Set the block you are looking at to open - the /crates menu." + - "/crates editor -c/--crate or -e/--exit - Allows you to enter/exit editor mode." + - "/crates migrate -mt/--migration_type --crate/-crate --data/-d - A command to migrate from other plugins or for internal changes." - "/crates reload - Reloads the config/data files." - "/crates set1/set2 - Sets position #1 or #2 for when making a new schematic for QuadCrates." @@ -281,4 +286,4 @@ command: - "/keys - Shows how many keys you have." - "/crates - Opens the menu." - "" - - "You can find a list of permissions @ https://docs.crazycrew.us/crazycrates/info/commands/permissions" \ No newline at end of file + - "You can find a list of permissions @ https://docs.crazycrew.us/docs/plugins/crazycrates/commands/permissions" \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c05616067..61d6c6e2a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,8 +22,11 @@ decentholograms = "2.8.8" headdatabaseapi = "1.3.1" placeholderapi = "2.11.6" fancyholograms = "2.4.1" +nexo = "0.5.0-dev.14" +itemsadder = "3.6.1" +cmi-api = "9.7.4.1" +cmi-lib = "1.5.1.4" oraxen = "1.171.0" -nexo = "0.1.0-dev.0" # Vital API vital = "0.1.2" @@ -52,11 +55,12 @@ kyori-api = { module = "net.kyori:adventure-api", version.ref = "adventure" } # Bukkit Plugins API decent-holograms = { module = "com.github.decentsoftware-eu:decentholograms", version.ref = "decentholograms" } headdatabaseapi = { module = "com.arcaniax:HeadDatabase-API", version.ref = "headdatabaseapi" } +itemsadder = { module = "com.github.LoneDev6:api-itemsadder", version.ref = "itemsadder" } fancy-holograms = { module = "de.oliver:FancyHolograms", version.ref = "fancyholograms" } placeholderapi = { module = "me.clip:placeholderapi", version.ref = "placeholderapi" } oraxen = { module = "io.th0rgal:oraxen", version.ref = "oraxen" } -cmi-api = { module = "CMI-API:CMI-API", version = "9.7.4.1" } -cmi-lib = { module = "CMILib:CMILib", version = "1.5.1.4" } +cmi-api = { module = "CMI-API:CMI-API", version.ref = "cmi-api" } +cmi-lib = { module = "CMILib:CMILib", version.ref = "cmi-lib" } nexo = { module = "com.nexomc:nexo", version.ref = "nexo" } # Crate Plugins API @@ -77,7 +81,7 @@ jalu = { module = "ch.jalu:configme", version.ref = "jalu" } dependencies = ["decent-holograms", "fancy-holograms", "cmi-lib", "cmi-api"] # Shared with the git submodules -shared = ["headdatabaseapi", "placeholderapi", "oraxen", "nexo"] +shared = ["headdatabaseapi", "placeholderapi", "itemsadder", "oraxen", "nexo"] # Only used for migrations from other crate plugins crates = ["excellentcrates", "nightcore"] diff --git a/paper/src/main/java/com/badbones69/crazycrates/CrazyCrates.java b/paper/src/main/java/com/badbones69/crazycrates/CrazyCrates.java index 0e6b252ee..7252452ae 100644 --- a/paper/src/main/java/com/badbones69/crazycrates/CrazyCrates.java +++ b/paper/src/main/java/com/badbones69/crazycrates/CrazyCrates.java @@ -3,6 +3,8 @@ import com.badbones69.crazycrates.common.Server; import com.badbones69.crazycrates.common.config.ConfigManager; import com.badbones69.crazycrates.common.config.impl.ConfigKeys; +import com.badbones69.crazycrates.listeners.crates.CrateInteractListener; +import com.badbones69.crazycrates.listeners.items.PaperInteractListener; import com.badbones69.crazycrates.support.MetricsWrapper; import com.badbones69.crazycrates.utils.MiscUtils; import com.badbones69.crazycrates.commands.CommandManager; @@ -25,6 +27,7 @@ import com.ryderbelserion.vital.paper.api.enums.Support; import com.ryderbelserion.vital.utils.Methods; import me.arcaniax.hdb.api.HeadDatabaseAPI; +import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; @@ -106,18 +109,26 @@ public void onEnable() { // Load commands. CommandManager.load(); + final PluginManager manager = getServer().getPluginManager(); + List.of( // Other listeners. new BrokeLocationsListener(), - new CrateControlListener(), new EntityDamageListener(), new MobileCrateListener(), new CosmicCrateListener(), new QuadCrateListener(), - new CrateOpenListener(), new WarCrateListener(), - new MiscListener() - ).forEach(listener -> getServer().getPluginManager().registerEvents(listener, this)); + new MiscListener(), + + new CrateInteractListener(), + new CrateControlListener(), + new CrateOpenListener(), + + new PaperInteractListener() + ).forEach(listener -> manager.registerEvents(listener, this)); + + this.crateManager.loadCustomItems(); if (Support.placeholder_api.isEnabled()) { if (MiscUtils.isLogging()) getComponentLogger().info("PlaceholderAPI support is enabled!"); diff --git a/paper/src/main/java/com/badbones69/crazycrates/api/enums/Messages.java b/paper/src/main/java/com/badbones69/crazycrates/api/enums/Messages.java index 222b479c9..5879c75d9 100644 --- a/paper/src/main/java/com/badbones69/crazycrates/api/enums/Messages.java +++ b/paper/src/main/java/com/badbones69/crazycrates/api/enums/Messages.java @@ -64,8 +64,13 @@ public enum Messages { not_a_number(CrateKeys.not_a_number), preview_disabled(CrateKeys.preview_disabled), not_enough_keys(CrateKeys.not_enough_keys), + editor_enter(CrateKeys.editor_enter), + editor_already_in(CrateKeys.editor_already_in), + editor_exit(CrateKeys.editor_exit), + force_editor_exit(CrateKeys.force_editor_exit), created_physical_crate(CrateKeys.created_physical_crate, true), physical_crate_already_exists(CrateKeys.physical_crate_already_exists), + physical_crate_overridden(CrateKeys.physical_crate_overridden), removed_physical_crate(CrateKeys.removed_physical_crate), crate_locations(CrateKeys.crate_locations, true), crate_locations_format(CrateKeys.crate_location_format), diff --git a/paper/src/main/java/com/badbones69/crazycrates/api/events/CrateInteractEvent.java b/paper/src/main/java/com/badbones69/crazycrates/api/events/CrateInteractEvent.java new file mode 100644 index 000000000..28965ba35 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazycrates/api/events/CrateInteractEvent.java @@ -0,0 +1,276 @@ +package com.badbones69.crazycrates.api.events; + +import ch.jalu.configme.SettingsManager; +import com.badbones69.crazycrates.CrazyCrates; +import com.badbones69.crazycrates.api.objects.crates.CrateLocation; +import com.badbones69.crazycrates.common.config.ConfigManager; +import com.badbones69.crazycrates.common.config.impl.ConfigKeys; +import com.badbones69.crazycrates.tasks.crates.CrateManager; +import com.nexomc.nexo.api.NexoFurniture; +import com.nexomc.nexo.api.events.furniture.NexoFurnitureBreakEvent; +import com.nexomc.nexo.api.events.furniture.NexoFurnitureInteractEvent; +import com.ryderbelserion.vital.paper.api.enums.Support; +import dev.lone.itemsadder.api.CustomFurniture; +import dev.lone.itemsadder.api.Events.FurnitureBreakEvent; +import dev.lone.itemsadder.api.Events.FurnitureInteractEvent; +import dev.lone.itemsadder.api.ItemsAdder; +import io.th0rgal.oraxen.api.OraxenFurniture; +import io.th0rgal.oraxen.api.events.furniture.OraxenFurnitureBreakEvent; +import io.th0rgal.oraxen.api.events.furniture.OraxenFurnitureInteractEvent; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.jetbrains.annotations.NotNull; + +public class CrateInteractEvent extends Event implements Cancellable { + + private final CrazyCrates plugin = CrazyCrates.getPlugin(); + + private final CrateManager crateManager = this.plugin.getCrateManager(); + + private NexoFurnitureInteractEvent nexoInteractEvent; + private NexoFurnitureBreakEvent nexoBreakEvent; + + private OraxenFurnitureInteractEvent oraxenInteractEvent; + private OraxenFurnitureBreakEvent oraxenBreakEvent; + + private FurnitureInteractEvent itemsAdderInteractEvent; + private FurnitureBreakEvent itemsAdderBreakEvent; + + private PlayerInteractEvent paperEvent; + + private CrateLocation crateLocation = null; + private boolean isCancelled; + + private final EquipmentSlot slot; + private final Location location; + private final Player player; + private final Action action; + + public CrateInteractEvent(@NotNull final OraxenFurnitureInteractEvent interactEvent, @NotNull final Action action, @NotNull final Location location) { + this.oraxenInteractEvent = interactEvent; + + this.player = this.oraxenInteractEvent.getPlayer(); + this.slot = this.oraxenInteractEvent.getHand(); + this.location = location; + this.action = action; + + setCancelled(this.slot == EquipmentSlot.OFF_HAND); + + if (!isCancelled()) { + this.crateLocation = this.crateManager.getCrateLocation(this.location); + } + } + + public CrateInteractEvent(@NotNull final OraxenFurnitureBreakEvent breakEvent, @NotNull final Action action, @NotNull final Location location) { + this.oraxenBreakEvent = breakEvent; + + this.player = this.oraxenBreakEvent.getPlayer(); + this.slot = this.player.getActiveItemHand(); + this.location = location; + this.action = action; + + setCancelled(this.slot == EquipmentSlot.OFF_HAND); + + if (!isCancelled()) { + this.crateLocation = this.crateManager.getCrateLocation(this.location); + } + } + + public CrateInteractEvent(@NotNull final FurnitureInteractEvent interactEvent, @NotNull final Action action, @NotNull final Location location) { + this.itemsAdderInteractEvent = interactEvent; + + this.player = this.itemsAdderInteractEvent.getPlayer(); + this.slot = this.player.getActiveItemHand(); + this.location = location; + this.action = action; + + setCancelled(this.slot == EquipmentSlot.OFF_HAND); + + if (!isCancelled()) { + this.crateLocation = this.crateManager.getCrateLocation(this.location); + } + } + + public CrateInteractEvent(@NotNull final FurnitureBreakEvent breakEvent, @NotNull final Action action, @NotNull final Location location) { + this.itemsAdderBreakEvent = breakEvent; + + this.player = this.itemsAdderBreakEvent.getPlayer(); + this.slot = this.player.getActiveItemHand(); + this.location = location; + this.action = action; + + setCancelled(this.slot == EquipmentSlot.OFF_HAND); + + if (!isCancelled()) { + this.crateLocation = this.crateManager.getCrateLocation(this.location); + } + } + + public CrateInteractEvent(@NotNull final NexoFurnitureInteractEvent interactEvent, @NotNull final Action action, @NotNull final Location location) { + this.nexoInteractEvent = interactEvent; + + this.player = this.nexoInteractEvent.getPlayer(); + this.slot = this.nexoInteractEvent.getHand(); + this.location = location; + this.action = action; + + setCancelled(this.slot == EquipmentSlot.OFF_HAND); + + if (!isCancelled()) { + this.crateLocation = this.crateManager.getCrateLocation(this.location); + } + } + + public CrateInteractEvent(@NotNull final NexoFurnitureBreakEvent breakEvent, @NotNull final Action action, @NotNull final Location location) { + this.nexoBreakEvent = breakEvent; + + this.player = this.nexoBreakEvent.getPlayer(); + this.slot = this.player.getActiveItemHand(); + this.location = location; + this.action = action; + + setCancelled(this.slot == EquipmentSlot.OFF_HAND || isFurniture(location)); + + if (!isCancelled()) { + this.crateLocation = this.crateManager.getCrateLocation(this.location); + } + } + + public CrateInteractEvent(@NotNull final PlayerInteractEvent paperEvent, @NotNull final Location location) { + this.paperEvent = paperEvent; + + this.player = this.paperEvent.getPlayer(); + this.action = this.paperEvent.getAction(); + this.slot = this.paperEvent.getHand(); + this.location = location; + + setCancelled(this.slot == EquipmentSlot.OFF_HAND || isFurniture(location)); + + if (!isCancelled()) { + this.crateLocation = this.crateManager.getCrateLocation(this.location); + } + } + + private final SettingsManager config = ConfigManager.getConfig(); + + /** + * A wrapper to check if a location has a piece of furniture at it. + * + * @param location the location + * @return true or false + */ + public boolean isFurniture(final Location location) { + final String pluginName = this.config.getProperty(ConfigKeys.custom_items_plugin).toLowerCase(); + + boolean isFurniture = false; + + switch (pluginName) { + case "nexo" -> isFurniture = Support.nexo.isEnabled() && NexoFurniture.isFurniture(location); + + case "oraxen" -> isFurniture = Support.oraxen.isEnabled() && OraxenFurniture.isFurniture(location.getBlock()); + + case "itemsadder" -> { + if (Support.items_adder.isEnabled()) { + final Entity entity = CustomFurniture.byAlreadySpawned(location.getBlock()).getEntity(); + + if (entity != null && entity.isValid()) { + isFurniture = true; + } + } + } + + default -> {} + } + + return isFurniture; + } + + /** + * Prevents interacting/breaking the blocks. + */ + public void cancel() { + if (this.nexoInteractEvent != null) { + this.nexoInteractEvent.setCancelled(true); + + return; + } + + if (this.nexoBreakEvent != null) { + this.nexoBreakEvent.setCancelled(true); + + return; + } + + if (this.oraxenInteractEvent != null) { + this.oraxenInteractEvent.setCancelled(true); + + return; + } + + if (this.oraxenBreakEvent != null) { + this.oraxenBreakEvent.setCancelled(true); + + return; + } + + if (this.itemsAdderInteractEvent != null) { + this.itemsAdderInteractEvent.setCancelled(true); + + return; + } + + if (this.itemsAdderBreakEvent != null) { + this.itemsAdderBreakEvent.setCancelled(true); + + return; + } + + if (this.paperEvent != null) { + this.paperEvent.setCancelled(true); + } + } + + public @NotNull CrateLocation getCrateLocation() { + return this.crateLocation; + } + + public @NotNull Location getLocation() { + return this.location; + } + + public @NotNull Player getPlayer() { + return this.player; + } + + public @NotNull Action getAction() { + return this.action; + } + + private static final HandlerList handlers = new HandlerList(); + + public static HandlerList getHandlerList() { + return handlers; + } + + @Override + public @NotNull HandlerList getHandlers() { + return handlers; + } + + @Override + public boolean isCancelled() { + return this.isCancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.isCancelled = cancel; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazycrates/commands/CommandManager.java b/paper/src/main/java/com/badbones69/crazycrates/commands/CommandManager.java index 3efc82068..f0d6180c1 100644 --- a/paper/src/main/java/com/badbones69/crazycrates/commands/CommandManager.java +++ b/paper/src/main/java/com/badbones69/crazycrates/commands/CommandManager.java @@ -5,6 +5,7 @@ import com.badbones69.crazycrates.commands.crates.types.admin.crates.CommandAddItem; import com.badbones69.crazycrates.commands.crates.types.admin.crates.CommandClaim; import com.badbones69.crazycrates.commands.crates.types.admin.crates.CommandMigrate; +import com.badbones69.crazycrates.commands.crates.types.admin.crates.editor.CommandEditor; import com.badbones69.crazycrates.commands.crates.types.admin.crates.migrator.enums.MigrationType; import com.badbones69.crazycrates.commands.relations.ArgumentRelations; import com.badbones69.crazycrates.commands.crates.types.player.CommandHelp; @@ -13,7 +14,6 @@ import com.badbones69.crazycrates.commands.crates.types.admin.crates.CommandDebug; import com.badbones69.crazycrates.commands.crates.types.admin.crates.CommandList; import com.badbones69.crazycrates.commands.crates.types.admin.crates.CommandPreview; -import com.badbones69.crazycrates.commands.crates.types.admin.crates.CommandSet; import com.badbones69.crazycrates.commands.crates.types.admin.crates.CommandTeleport; import com.badbones69.crazycrates.commands.crates.types.admin.keys.CommandGive; import com.badbones69.crazycrates.commands.crates.types.admin.keys.CommandOpen; @@ -128,7 +128,7 @@ public static void load() { new CommandPreview(), new CommandDebug(), new CommandList(), - new CommandSet(), + new CommandEditor(), new CommandGive(), new CommandOpen(), diff --git a/paper/src/main/java/com/badbones69/crazycrates/commands/crates/types/admin/crates/CommandSet.java b/paper/src/main/java/com/badbones69/crazycrates/commands/crates/types/admin/crates/CommandSet.java deleted file mode 100644 index b8a140fcd..000000000 --- a/paper/src/main/java/com/badbones69/crazycrates/commands/crates/types/admin/crates/CommandSet.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.badbones69.crazycrates.commands.crates.types.admin.crates; - -import com.badbones69.crazycrates.api.enums.Messages; -import com.badbones69.crazycrates.api.objects.Crate; -import com.badbones69.crazycrates.api.objects.crates.CrateLocation; -import com.badbones69.crazycrates.common.utils.CrazyUtil; -import com.badbones69.crazycrates.commands.crates.types.BaseCommand; -import dev.triumphteam.cmd.bukkit.annotation.Permission; -import dev.triumphteam.cmd.core.annotations.ArgName; -import dev.triumphteam.cmd.core.annotations.Command; -import dev.triumphteam.cmd.core.annotations.Suggestion; -import org.bukkit.Location; -import org.bukkit.block.Block; -import org.bukkit.entity.Player; -import org.bukkit.permissions.PermissionDefault; -import us.crazycrew.crazycrates.api.enums.types.CrateType; -import com.badbones69.crazycrates.common.config.impl.ConfigKeys; -import java.util.HashMap; -import java.util.Map; - -public class CommandSet extends BaseCommand { - - @Command("set") - @Permission(value = "crazycrates.set", def = PermissionDefault.OP) - public void set(Player player, @ArgName("crate") @Suggestion("crates") String crateName) { - if (crateName == null || crateName.isEmpty() || crateName.isBlank()) { - Messages.cannot_be_empty.sendMessage(player, "{value}", "crate name"); - - return; - } - - final Crate crate = this.crateManager.getCrateFromName(crateName); - - if (crate == null) { - Messages.not_a_crate.sendMessage(player, "{crate}", crateName); - - return; - } - - if (crate.getCrateType() == CrateType.menu && !this.config.getProperty(ConfigKeys.enable_crate_menu)) { - Messages.cannot_set_type.sendMessage(player); - - return; - } - - final Block block = player.getTargetBlock(null, 5); - - if (block.isEmpty()) { - Messages.must_be_looking_at_block.sendMessage(player); - - return; - } - - final Location location = block.getLocation(); - - if (this.crateManager.isCrateLocation(location)) { - Messages.physical_crate_already_exists.sendMessage(player, new HashMap<>() {{ - final CrateLocation crateLocation = crateManager.getCrateLocation(location); - - put("{id}", crateLocation != null ? crateLocation.getID() : "N/A"); - put("{crate}", crateLocation != null ? crateLocation.getCrate().getCrateName() : "N/A"); - }}); - - return; - } - - this.crateManager.addCrateLocation(location, crate); - - final Map placeholders = new HashMap<>(); - - placeholders.put("{crate}", crate.getCrateName()); - placeholders.put("{prefix}", CrazyUtil.getPrefix()); - - // this has to use sendRichMessage as it is a list. - Messages.created_physical_crate.sendRichMessage(player, placeholders); - } -} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazycrates/commands/crates/types/admin/crates/editor/CommandEditor.java b/paper/src/main/java/com/badbones69/crazycrates/commands/crates/types/admin/crates/editor/CommandEditor.java new file mode 100644 index 000000000..85ca756a2 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazycrates/commands/crates/types/admin/crates/editor/CommandEditor.java @@ -0,0 +1,72 @@ +package com.badbones69.crazycrates.commands.crates.types.admin.crates.editor; + +import com.badbones69.crazycrates.api.enums.Messages; +import com.badbones69.crazycrates.api.objects.Crate; +import com.badbones69.crazycrates.commands.crates.types.BaseCommand; +import com.badbones69.crazycrates.common.config.impl.ConfigKeys; +import dev.triumphteam.cmd.bukkit.annotation.Permission; +import dev.triumphteam.cmd.core.annotations.Command; +import dev.triumphteam.cmd.core.annotations.Flag; +import dev.triumphteam.cmd.core.argument.keyed.Flags; +import org.bukkit.entity.Player; +import org.bukkit.permissions.PermissionDefault; +import us.crazycrew.crazycrates.api.enums.types.CrateType; +import java.util.HashMap; + +public class CommandEditor extends BaseCommand { + + @Command("editor") + @Flag(flag = "c", longFlag = "crate", argument = String.class, suggestion = "crates") + @Flag(flag = "e", longFlag = "exit") + @Permission(value = "crazycrates.editor", def = PermissionDefault.OP) + public void editor(final Player player, final Flags flags) { + if (flags.hasFlag("e")) { + this.crateManager.removeEditorCrate(player); + + Messages.editor_exit.sendMessage(player, "{reason}", "you asked."); + + return; + } + + if (!flags.hasFlag("c")) { + Messages.lacking_flag.sendMessage(player, new HashMap<>() {{ + put("{flag}", "-c"); + put("{usage}", "/crazycrates editor -c "); + }}); + + return; + } + + final String crateName = flags.getFlagValue("c").orElse(""); + + if (crateName.isEmpty()) { + Messages.cannot_be_empty.sendMessage(player, "{value}", "crate name"); + + return; + } + + if (this.crateManager.hasEditorCrate(player)) { + Messages.editor_already_in.sendMessage(player); + + return; + } + + final Crate crate = this.crateManager.getCrateFromName(crateName); + + if (crate == null) { + Messages.not_a_crate.sendMessage(player, "{crate}", crateName); + + return; + } + + if (crate.getCrateType() == CrateType.menu && !this.config.getProperty(ConfigKeys.enable_crate_menu)) { + Messages.cannot_set_type.sendMessage(player); + + return; + } + + this.crateManager.addEditorCrate(player, crate); + + Messages.editor_enter.sendMessage(player, "{crate}", crateName); + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazycrates/listeners/CrateControlListener.java b/paper/src/main/java/com/badbones69/crazycrates/listeners/CrateControlListener.java index e01242b5e..a8612b82c 100644 --- a/paper/src/main/java/com/badbones69/crazycrates/listeners/CrateControlListener.java +++ b/paper/src/main/java/com/badbones69/crazycrates/listeners/CrateControlListener.java @@ -1,138 +1,23 @@ package com.badbones69.crazycrates.listeners; -import ch.jalu.configme.SettingsManager; -import com.badbones69.crazycrates.managers.events.enums.EventType; -import com.badbones69.crazycrates.tasks.menus.CrateMainMenu; -import com.badbones69.crazycrates.api.events.KeyCheckEvent; import com.badbones69.crazycrates.api.objects.Crate; -import com.badbones69.crazycrates.api.objects.crates.CrateLocation; -import com.badbones69.crazycrates.utils.ItemUtils; -import com.badbones69.crazycrates.managers.BukkitUserManager; -import net.kyori.adventure.key.Key; -import net.kyori.adventure.sound.Sound; -import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.entity.Player; -import org.bukkit.event.Event; import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockPistonExtendEvent; import org.bukkit.event.block.BlockPistonRetractEvent; -import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.inventory.EquipmentSlot; -import org.bukkit.inventory.ItemStack; -import org.bukkit.util.Vector; -import us.crazycrew.crazycrates.api.enums.types.CrateType; -import us.crazycrew.crazycrates.api.enums.types.KeyType; -import com.badbones69.crazycrates.common.config.ConfigManager; -import com.badbones69.crazycrates.common.config.impl.ConfigKeys; import com.badbones69.crazycrates.CrazyCrates; import com.badbones69.crazycrates.tasks.crates.CrateManager; -import com.badbones69.crazycrates.api.enums.Messages; -import com.badbones69.crazycrates.managers.InventoryManager; -import com.badbones69.crazycrates.utils.MiscUtils; -import java.util.HashMap; -import java.util.Map; public class CrateControlListener implements Listener { private final CrazyCrates plugin = CrazyCrates.getPlugin(); - private final InventoryManager inventoryManager = this.plugin.getInventoryManager(); - - private final SettingsManager config = ConfigManager.getConfig(); - private final CrateManager crateManager = this.plugin.getCrateManager(); - private final BukkitUserManager userManager = this.plugin.getUserManager(); - - @EventHandler(priority = EventPriority.HIGHEST) - public void onPlayerClick(PlayerInteractEvent event) { - if (event.getHand() == EquipmentSlot.OFF_HAND) return; - - final Player player = event.getPlayer(); - - final Block block = event.getClickedBlock(); - - if (block == null) return; - - final Location location = block.getLocation(); - - switch (event.getAction()) { - case LEFT_CLICK_BLOCK, LEFT_CLICK_AIR -> { - final CrateLocation crateLocation = this.crateManager.getCrateLocation(location); - - if (crateLocation == null) return; - - event.setUseInteractedBlock(Event.Result.DENY); - event.setUseItemInHand(Event.Result.DENY); - - if (player.getGameMode() == GameMode.CREATIVE && player.isSneaking() && player.hasPermission("crazycrates.admin")) { - final String arg1 = MiscUtils.location(location, true); - final String arg2 = MiscUtils.location(crateLocation.getLocation(), true); - - if (arg1.equals(arg2)) { - this.crateManager.removeCrateLocation(crateLocation.getID()); - - Messages.removed_physical_crate.sendMessage(player, "{id}", crateLocation.getID()); - } - - return; - } - - final boolean isLeftClickToPreview = this.config.getProperty(ConfigKeys.crate_physical_interaction); - - final Crate crate = crateLocation.getCrate(); - - if (crate.getCrateType() == CrateType.menu) { - preview(player, crate, true); - - return; - } - - if (isLeftClickToPreview) { - preview(player, crateLocation.getCrate(), false); - } else { - openCrate(player, location, crateLocation, crate); - } - } - - case RIGHT_CLICK_AIR, RIGHT_CLICK_BLOCK -> { - final boolean isKey = event.getHand() == EquipmentSlot.OFF_HAND ? this.crateManager.isKey(player.getInventory().getItemInOffHand()) : this.crateManager.isKey(player.getInventory().getItemInMainHand()); - - if (isKey) { - event.setUseItemInHand(Event.Result.DENY); - } - - final CrateLocation crateLocation = this.crateManager.getCrateLocation(location); - - if (crateLocation == null) return; - - event.setUseInteractedBlock(Event.Result.DENY); - event.setUseItemInHand(Event.Result.DENY); - - final boolean isRightClickToOpen = this.config.getProperty(ConfigKeys.crate_physical_interaction); - - final Crate crate = crateLocation.getCrate(); - - if (crate.getCrateType() == CrateType.menu) { - preview(player, crate, true); - - return; - } - - if (isRightClickToOpen) { - openCrate(player, location, crateLocation, crate); - } else { - preview(player, crateLocation.getCrate(), false); - } - } - } - } - @EventHandler public void onPistonPushCrate(BlockPistonExtendEvent event) { for (final Block block : event.getBlocks()) { @@ -173,148 +58,4 @@ public void onPlayerQuit(PlayerQuitEvent event) { if (this.crateManager.isInOpeningList(player)) this.crateManager.removePlayerFromOpeningList(player); } - - private void openCrate(Player player, Location location, CrateLocation crateLocation, Crate crate) { - final KeyCheckEvent key = new KeyCheckEvent(player, crateLocation); - player.getServer().getPluginManager().callEvent(key); - - if (key.isCancelled()) return; - - boolean hasKey = false; - boolean isPhysical = false; - boolean useQuickCrateAgain = false; - - final int requiredKeys = crate.getRequiredKeys(); - - final String fileName = crate.getFileName(); - - final int totalKeys = this.userManager.getTotalKeys(player.getUniqueId(), fileName); - - final String fancyName = crate.getCrateName(); - - if (requiredKeys > 0 && totalKeys < requiredKeys) { - final Map placeholders = new HashMap<>(); - - placeholders.put("{required_amount}", String.valueOf(requiredKeys)); - placeholders.put("{key_amount}", String.valueOf(requiredKeys)); // deprecated, remove in next major version of minecraft. - placeholders.put("{amount}", String.valueOf(totalKeys)); - placeholders.put("{crate}", fancyName); - placeholders.put("{key}", crate.getKeyName()); - - Messages.not_enough_keys.sendMessage(player, placeholders); - - lackingKey(player, crate, location, false); - - key.setCancelled(true); - - return; - } - - final ItemStack itemStack = player.getInventory().getItemInMainHand(); - - if (this.config.getProperty(ConfigKeys.physical_accepts_physical_keys) && crate.getCrateType() != CrateType.crate_on_the_go && ItemUtils.isSimilar(itemStack, crate)) { - hasKey = true; - isPhysical = true; - } else if (this.config.getProperty(ConfigKeys.physical_accepts_virtual_keys) && this.userManager.getVirtualKeys(player.getUniqueId(), fileName) >= 1) { - hasKey = true; - } - - if (hasKey) { - // Checks if the player uses the quick crate again. - if (this.crateManager.isInOpeningList(player) && this.crateManager.getOpeningCrate(player).getCrateType() == CrateType.quick_crate && this.crateManager.isCrateInUse(player) && this.crateManager.getCrateInUseLocation(player).equals(crateLocation.getLocation())) { - useQuickCrateAgain = true; - } - - if (!useQuickCrateAgain) { - if (this.crateManager.isInOpeningList(player)) { - Messages.already_opening_crate.sendMessage(player, "{crate}", fancyName); - - return; - } - - if (this.crateManager.getCratesInUse().containsValue(crateLocation.getLocation())) { - Messages.crate_in_use.sendMessage(player, "{crate}", fancyName); - - return; - } - } - - if (MiscUtils.isInventoryFull(player)) { - Messages.inventory_not_empty.sendMessage(player, "{crate}", fancyName); - - return; - } - - if (useQuickCrateAgain) this.crateManager.endQuickCrate(player, crateLocation.getLocation(), crate, true); - - final KeyType keyType = isPhysical ? KeyType.physical_key : KeyType.virtual_key; - - // Only cosmic crate type uses this method. - if (crate.getCrateType() == CrateType.cosmic) this.crateManager.addPlayerKeyType(player, keyType); - - this.crateManager.addPlayerToOpeningList(player, crate); - - this.crateManager.openCrate(player, crate, keyType, crateLocation.getLocation(), false, true, EventType.event_crate_opened); - - return; - } - - lackingKey(player, crate, location, true); - - key.setCancelled(true); - } - - private void lackingKey(final Player player, final Crate crate, final Location location, final boolean sendMessage) { - final String keyName = crate.getKeyName(); - - final Map placeholders = new HashMap<>() {{ - put("{crate}", crate.getCrateName()); - put("{key}", keyName); - }}; - - if (crate.getCrateType() != CrateType.crate_on_the_go) { - if (this.config.getProperty(ConfigKeys.knock_back)) knockback(player, location); - - if (this.config.getProperty(ConfigKeys.need_key_sound_toggle)) { - net.kyori.adventure.sound.Sound sound = net.kyori.adventure.sound.Sound.sound(Key.key(this.config.getProperty(ConfigKeys.need_key_sound)), Sound.Source.PLAYER, 1f, 1f); - - player.playSound(sound); - } - - if (sendMessage) Messages.no_keys.sendMessage(player, placeholders); - } - } - - private void knockback(final Player player, final Location location) { - final Vector vector = player.getLocation().toVector().subtract(location.toVector()).normalize().multiply(1).setY(.1); - - if (player.isInsideVehicle() && player.getVehicle() != null) { - player.getVehicle().setVelocity(vector); - - return; - } - - player.setVelocity(vector); - } - - private void preview(final Player player, final Crate crate, boolean skipTypeCheck) { - if (skipTypeCheck || crate.getCrateType() == CrateType.menu) { - // this is to stop players in QuadCrate to not be able to try and open a crate set to menu. - if (!this.crateManager.isInOpeningList(player) && this.config.getProperty(ConfigKeys.enable_crate_menu)) { - new CrateMainMenu( - player, - this.config.getProperty(ConfigKeys.inventory_name), - this.config.getProperty(ConfigKeys.inventory_rows) - ).open(); - } else { - Messages.feature_disabled.sendMessage(player); - } - } else { - if (crate.isPreviewEnabled()) { - this.inventoryManager.openNewCratePreview(player, crate); - } else { - Messages.preview_disabled.sendMessage(player, "{crate}", crate.getCrateName()); - } - } - } } \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazycrates/listeners/MiscListener.java b/paper/src/main/java/com/badbones69/crazycrates/listeners/MiscListener.java index 57cba1a47..4f266b9b2 100644 --- a/paper/src/main/java/com/badbones69/crazycrates/listeners/MiscListener.java +++ b/paper/src/main/java/com/badbones69/crazycrates/listeners/MiscListener.java @@ -53,18 +53,6 @@ public void onPlayerJoin(PlayerJoinEvent event) { // Also add the new data. this.userManager.loadOfflinePlayersKeys(player, this.crateManager.getUsableCrates()); - /*final Map prizes = new HashMap<>() {{ - final UUID uuid = player.getUniqueId(); - - crateManager.getUsableCrates().forEach(crate -> { - final String fileName = crate.getFileName(); - - if (userManager.hasRespinPrize(uuid, fileName)) { - put(crateManager.getCrateFromName(fileName), crate.getPrize(userManager.getRespinPrize(uuid, fileName))); - } - }); - }};*/ - final UUID uuid = player.getUniqueId(); int count = 0; @@ -135,6 +123,8 @@ public void onPlayerQuit(PlayerQuitEvent event) { this.crateManager.removePlayerKeyType(player); this.crateManager.removeSlot(player); + + this.crateManager.removeEditorCrate(player); } @EventHandler diff --git a/paper/src/main/java/com/badbones69/crazycrates/listeners/crates/CrateInteractListener.java b/paper/src/main/java/com/badbones69/crazycrates/listeners/crates/CrateInteractListener.java new file mode 100644 index 000000000..5fc568edc --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazycrates/listeners/crates/CrateInteractListener.java @@ -0,0 +1,245 @@ +package com.badbones69.crazycrates.listeners.crates; + +import ch.jalu.configme.SettingsManager; +import com.badbones69.crazycrates.CrazyCrates; +import com.badbones69.crazycrates.api.enums.Messages; +import com.badbones69.crazycrates.api.events.CrateInteractEvent; +import com.badbones69.crazycrates.api.events.KeyCheckEvent; +import com.badbones69.crazycrates.api.objects.Crate; +import com.badbones69.crazycrates.api.objects.crates.CrateLocation; +import com.badbones69.crazycrates.common.config.ConfigManager; +import com.badbones69.crazycrates.common.config.impl.ConfigKeys; +import com.badbones69.crazycrates.managers.BukkitUserManager; +import com.badbones69.crazycrates.managers.InventoryManager; +import com.badbones69.crazycrates.managers.events.enums.EventType; +import com.badbones69.crazycrates.tasks.crates.CrateManager; +import com.badbones69.crazycrates.tasks.menus.CrateMainMenu; +import com.badbones69.crazycrates.utils.ItemUtils; +import com.badbones69.crazycrates.utils.MiscUtils; +import net.kyori.adventure.key.Key; +import net.kyori.adventure.sound.Sound; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; +import us.crazycrew.crazycrates.api.enums.types.CrateType; +import us.crazycrew.crazycrates.api.enums.types.KeyType; +import java.util.HashMap; +import java.util.Map; + +public class CrateInteractListener implements Listener { + + private final CrazyCrates plugin = CrazyCrates.getPlugin(); + + private final InventoryManager inventoryManager = this.plugin.getInventoryManager(); + + private final SettingsManager config = ConfigManager.getConfig(); + + private final CrateManager crateManager = this.plugin.getCrateManager(); + + private final BukkitUserManager userManager = this.plugin.getUserManager(); + + @EventHandler(priority = EventPriority.HIGHEST) + public void onCrateInteract(final CrateInteractEvent event) { + if (event.isCancelled()) return; // do not run this event. + + event.cancel(); // cancel the event + + final Player player = event.getPlayer(); + + final CrateLocation crateLocation = event.getCrateLocation(); + final Crate crate = crateLocation.getCrate(); + + final Action action = event.getAction(); + + switch (action) { + case LEFT_CLICK_BLOCK, LEFT_CLICK_AIR -> { + if (crate.getCrateType() == CrateType.menu) { + preview(player, crate, true); + + return; + } + + final boolean isLeftClickToPreview = this.config.getProperty(ConfigKeys.crate_physical_interaction); + + if (isLeftClickToPreview) { // left click to preview + preview(player, crate, false); + + return; + } + + // left click to open + openCrate(player, crateLocation, crate); + } + + case RIGHT_CLICK_BLOCK, RIGHT_CLICK_AIR -> { + if (crate.getCrateType() == CrateType.menu) { + preview(player, crate, true); + + return; + } + + final boolean isRightClickToOpen = this.config.getProperty(ConfigKeys.crate_physical_interaction); + + if (isRightClickToOpen) { // right click to open + openCrate(player, crateLocation, crate); + + return; + } + + // right click to preview + preview(player, crate, false); + } + } + } + + private void openCrate(Player player, CrateLocation crateLocation, Crate crate) { + final KeyCheckEvent key = new KeyCheckEvent(player, crateLocation); + player.getServer().getPluginManager().callEvent(key); + + if (key.isCancelled()) return; + + final Location location = crateLocation.getLocation(); + + boolean hasKey = false; + boolean isPhysical = false; + boolean useQuickCrateAgain = false; + + final int requiredKeys = crate.getRequiredKeys(); + + final String fileName = crate.getFileName(); + + final int totalKeys = this.userManager.getTotalKeys(player.getUniqueId(), fileName); + + final String fancyName = crate.getCrateName(); + + if (requiredKeys > 0 && totalKeys < requiredKeys) { + final Map placeholders = new HashMap<>(); + + placeholders.put("{required_amount}", String.valueOf(requiredKeys)); + placeholders.put("{key_amount}", String.valueOf(requiredKeys)); // deprecated, remove in next major version of minecraft. + placeholders.put("{amount}", String.valueOf(totalKeys)); + placeholders.put("{crate}", fancyName); + placeholders.put("{key}", crate.getKeyName()); + + Messages.not_enough_keys.sendMessage(player, placeholders); + + lackingKey(player, crate, location, false); + + key.setCancelled(true); + + return; + } + + final ItemStack itemStack = player.getInventory().getItemInMainHand(); + + if (this.config.getProperty(ConfigKeys.physical_accepts_physical_keys) && crate.getCrateType() != CrateType.crate_on_the_go && ItemUtils.isSimilar(itemStack, crate)) { + hasKey = true; + isPhysical = true; + } else if (this.config.getProperty(ConfigKeys.physical_accepts_virtual_keys) && this.userManager.getVirtualKeys(player.getUniqueId(), fileName) >= 1) { + hasKey = true; + } + + if (hasKey) { + // Checks if the player uses the quick crate again. + if (this.crateManager.isInOpeningList(player) && this.crateManager.getOpeningCrate(player).getCrateType() == CrateType.quick_crate && this.crateManager.isCrateInUse(player) && this.crateManager.getCrateInUseLocation(player).equals(crateLocation.getLocation())) { + useQuickCrateAgain = true; + } + + if (!useQuickCrateAgain) { + if (this.crateManager.isInOpeningList(player)) { + Messages.already_opening_crate.sendMessage(player, "{crate}", fancyName); + + return; + } + + if (this.crateManager.getCratesInUse().containsValue(crateLocation.getLocation())) { + Messages.crate_in_use.sendMessage(player, "{crate}", fancyName); + + return; + } + } + + if (MiscUtils.isInventoryFull(player)) { + Messages.inventory_not_empty.sendMessage(player, "{crate}", fancyName); + + return; + } + + if (useQuickCrateAgain) this.crateManager.endQuickCrate(player, crateLocation.getLocation(), crate, true); + + final KeyType keyType = isPhysical ? KeyType.physical_key : KeyType.virtual_key; + + // Only cosmic crate type uses this method. + if (crate.getCrateType() == CrateType.cosmic) this.crateManager.addPlayerKeyType(player, keyType); + + this.crateManager.addPlayerToOpeningList(player, crate); + + this.crateManager.openCrate(player, crate, keyType, location, false, true, EventType.event_crate_opened); + + return; + } + + lackingKey(player, crate, location, true); + + key.setCancelled(true); + } + + private void lackingKey(final Player player, final Crate crate, final Location location, final boolean sendMessage) { + final String keyName = crate.getKeyName(); + + final Map placeholders = new HashMap<>() {{ + put("{crate}", crate.getCrateName()); + put("{key}", keyName); + }}; + + if (crate.getCrateType() != CrateType.crate_on_the_go) { + if (this.config.getProperty(ConfigKeys.knock_back)) knockback(player, location); + + if (this.config.getProperty(ConfigKeys.need_key_sound_toggle)) { + net.kyori.adventure.sound.Sound sound = net.kyori.adventure.sound.Sound.sound(Key.key(this.config.getProperty(ConfigKeys.need_key_sound)), Sound.Source.PLAYER, 1f, 1f); + + player.playSound(sound); + } + + if (sendMessage) Messages.no_keys.sendMessage(player, placeholders); + } + } + + private void knockback(final Player player, final Location location) { + final Vector vector = player.getLocation().toVector().subtract(location.toVector()).normalize().multiply(1).setY(.1); + + if (player.isInsideVehicle() && player.getVehicle() != null) { + player.getVehicle().setVelocity(vector); + + return; + } + + player.setVelocity(vector); + } + + private void preview(final Player player, final Crate crate, boolean skipTypeCheck) { + if (skipTypeCheck || crate.getCrateType() == CrateType.menu) { + // this is to stop players in QuadCrate to not be able to try and open a crate set to menu. + if (!this.crateManager.isInOpeningList(player) && this.config.getProperty(ConfigKeys.enable_crate_menu)) { + new CrateMainMenu( + player, + this.config.getProperty(ConfigKeys.inventory_name), + this.config.getProperty(ConfigKeys.inventory_rows) + ).open(); + } else { + Messages.feature_disabled.sendMessage(player); + } + } else { + if (crate.isPreviewEnabled()) { + this.inventoryManager.openNewCratePreview(player, crate); + } else { + Messages.preview_disabled.sendMessage(player, "{crate}", crate.getCrateName()); + } + } + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazycrates/listeners/crates/types/MobileCrateListener.java b/paper/src/main/java/com/badbones69/crazycrates/listeners/crates/types/MobileCrateListener.java index 4396532b6..6598148a7 100644 --- a/paper/src/main/java/com/badbones69/crazycrates/listeners/crates/types/MobileCrateListener.java +++ b/paper/src/main/java/com/badbones69/crazycrates/listeners/crates/types/MobileCrateListener.java @@ -7,7 +7,6 @@ import com.badbones69.crazycrates.tasks.crates.CrateManager; import com.badbones69.crazycrates.api.objects.Crate; import com.badbones69.crazycrates.api.objects.Prize; -import com.badbones69.crazycrates.utils.MiscUtils; import io.papermc.paper.persistence.PersistentDataContainerView; import org.bukkit.Material; import org.bukkit.NamespacedKey; @@ -30,10 +29,10 @@ public class MobileCrateListener implements Listener { @EventHandler public void onCrateUse(PlayerInteractEvent event) { - final Player player = event.getPlayer(); - if (event.getHand() == EquipmentSlot.OFF_HAND) return; + final Player player = event.getPlayer(); + if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; final ItemStack item = player.getInventory().getItemInMainHand(); diff --git a/paper/src/main/java/com/badbones69/crazycrates/listeners/crates/types/QuadCrateListener.java b/paper/src/main/java/com/badbones69/crazycrates/listeners/crates/types/QuadCrateListener.java index 4199fddef..7d877491a 100644 --- a/paper/src/main/java/com/badbones69/crazycrates/listeners/crates/types/QuadCrateListener.java +++ b/paper/src/main/java/com/badbones69/crazycrates/listeners/crates/types/QuadCrateListener.java @@ -3,7 +3,6 @@ import com.badbones69.crazycrates.api.PrizeManager; import com.badbones69.crazycrates.utils.ItemUtils; import com.ryderbelserion.vital.paper.util.scheduler.impl.FoliaScheduler; -import com.ryderbelserion.vital.schedulers.enums.SchedulerType; import net.kyori.adventure.sound.Sound; import org.bukkit.Location; import org.bukkit.event.player.PlayerCommandPreprocessEvent; @@ -33,7 +32,6 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.persistence.PersistentDataType; import org.bukkit.util.Vector; - import java.util.HashMap; import java.util.List; import java.util.Map; diff --git a/paper/src/main/java/com/badbones69/crazycrates/listeners/items/ItemsAdderInteractListener.java b/paper/src/main/java/com/badbones69/crazycrates/listeners/items/ItemsAdderInteractListener.java new file mode 100644 index 000000000..e2fd87952 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazycrates/listeners/items/ItemsAdderInteractListener.java @@ -0,0 +1,65 @@ +package com.badbones69.crazycrates.listeners.items; + +import com.badbones69.crazycrates.CrazyCrates; +import com.badbones69.crazycrates.api.events.CrateInteractEvent; +import com.badbones69.crazycrates.tasks.crates.CrateManager; +import dev.lone.itemsadder.api.Events.FurnitureBreakEvent; +import dev.lone.itemsadder.api.Events.FurnitureInteractEvent; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.inventory.EquipmentSlot; + +public class ItemsAdderInteractListener implements Listener { + + private final CrazyCrates plugin = CrazyCrates.getPlugin(); + + private final CrateManager crateManager = this.plugin.getCrateManager(); + + @EventHandler + public void onFurnitureInteractEvent(FurnitureInteractEvent event) { + final Entity entity = event.getBukkitEntity(); + final Location location = entity.getLocation(); + + final Player player = event.getPlayer(); + + final EquipmentSlot slot = player.getActiveItemHand(); + + if (this.crateManager.hasEditorCrate(player) && slot != EquipmentSlot.OFF_HAND) { + this.crateManager.addCrateByLocation(player, location); + + event.setCancelled(true); + + return; + } + + if (this.crateManager.isCrateLocation(location)) { + new CrateInteractEvent(event, Action.RIGHT_CLICK_BLOCK, location).callEvent(); + } + } + + @EventHandler + public void onFurnitureBreakEvent(FurnitureBreakEvent event) { + final Entity entity = event.getBukkitEntity(); + final Location location = entity.getLocation(); + + final Player player = event.getPlayer(); + + final EquipmentSlot slot = player.getActiveItemHand(); + + if (this.crateManager.hasEditorCrate(player) && slot != EquipmentSlot.OFF_HAND) { + this.crateManager.removeCrateByLocation(player, location); + + event.setCancelled(true); + + return; + } + + if (this.crateManager.isCrateLocation(location)) { + new CrateInteractEvent(event, Action.LEFT_CLICK_BLOCK, location).callEvent(); + } + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazycrates/listeners/items/NexoInteractListener.java b/paper/src/main/java/com/badbones69/crazycrates/listeners/items/NexoInteractListener.java new file mode 100644 index 000000000..75c37bce7 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazycrates/listeners/items/NexoInteractListener.java @@ -0,0 +1,61 @@ +package com.badbones69.crazycrates.listeners.items; + +import com.badbones69.crazycrates.CrazyCrates; +import com.badbones69.crazycrates.api.events.CrateInteractEvent; +import com.badbones69.crazycrates.tasks.crates.CrateManager; +import com.nexomc.nexo.api.events.furniture.NexoFurnitureBreakEvent; +import com.nexomc.nexo.api.events.furniture.NexoFurnitureInteractEvent; +import org.bukkit.Location; +import org.bukkit.entity.ItemDisplay; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.inventory.EquipmentSlot; + +public class NexoInteractListener implements Listener { + + private final CrazyCrates plugin = CrazyCrates.getPlugin(); + + private final CrateManager crateManager = this.plugin.getCrateManager(); + + @EventHandler + public void onFurnitureInteractEvent(NexoFurnitureInteractEvent event) { + final ItemDisplay itemDisplay = event.getBaseEntity(); + final Location location = itemDisplay.getLocation(); + + final Player player = event.getPlayer(); + + if (this.crateManager.hasEditorCrate(player) && event.getHand() != EquipmentSlot.OFF_HAND) { + this.crateManager.addCrateByLocation(player, location); + + event.setCancelled(true); + + return; + } + + if (this.crateManager.isCrateLocation(location)) { + new CrateInteractEvent(event, Action.RIGHT_CLICK_BLOCK, location).callEvent(); + } + } + + @EventHandler + public void onFurnitureBreakEvent(NexoFurnitureBreakEvent event) { + final ItemDisplay itemDisplay = event.getBaseEntity(); + final Location location = itemDisplay.getLocation(); + + final Player player = event.getPlayer(); + + if (this.crateManager.hasEditorCrate(player) && player.getActiveItemHand() != EquipmentSlot.OFF_HAND) { + this.crateManager.removeCrateByLocation(player, location); + + event.setCancelled(true); + + return; + } + + if (this.crateManager.isCrateLocation(location)) { + new CrateInteractEvent(event, Action.LEFT_CLICK_BLOCK, location).callEvent(); + } + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazycrates/listeners/items/OraxenInteractListener.java b/paper/src/main/java/com/badbones69/crazycrates/listeners/items/OraxenInteractListener.java new file mode 100644 index 000000000..6cc95692f --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazycrates/listeners/items/OraxenInteractListener.java @@ -0,0 +1,61 @@ +package com.badbones69.crazycrates.listeners.items; + +import com.badbones69.crazycrates.CrazyCrates; +import com.badbones69.crazycrates.api.events.CrateInteractEvent; +import com.badbones69.crazycrates.tasks.crates.CrateManager; +import io.th0rgal.oraxen.api.events.furniture.OraxenFurnitureBreakEvent; +import io.th0rgal.oraxen.api.events.furniture.OraxenFurnitureInteractEvent; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.inventory.EquipmentSlot; + +public class OraxenInteractListener implements Listener { + + private final CrazyCrates plugin = CrazyCrates.getPlugin(); + + private final CrateManager crateManager = this.plugin.getCrateManager(); + + @EventHandler + public void onFurnitureInteractEvent(OraxenFurnitureInteractEvent event) { + final Entity itemDisplay = event.getBaseEntity(); + final Location location = itemDisplay.getLocation(); + + final Player player = event.getPlayer(); + + if (this.crateManager.hasEditorCrate(player) && event.getHand() != EquipmentSlot.OFF_HAND) { + this.crateManager.addCrateByLocation(player, location); + + event.setCancelled(true); + + return; + } + + if (this.crateManager.isCrateLocation(location)) { + new CrateInteractEvent(event, Action.RIGHT_CLICK_BLOCK, location).callEvent(); + } + } + + @EventHandler + public void onFurnitureBreakEvent(OraxenFurnitureBreakEvent event) { + final Entity itemDisplay = event.getBaseEntity(); + final Location location = itemDisplay.getLocation(); + + final Player player = event.getPlayer(); + + if (this.crateManager.hasEditorCrate(player) && player.getActiveItemHand() != EquipmentSlot.OFF_HAND) { + this.crateManager.removeCrateByLocation(player, location); + + event.setCancelled(true); + + return; + } + + if (this.crateManager.isCrateLocation(location)) { + new CrateInteractEvent(event, Action.LEFT_CLICK_BLOCK, location).callEvent(); + } + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazycrates/listeners/items/PaperInteractListener.java b/paper/src/main/java/com/badbones69/crazycrates/listeners/items/PaperInteractListener.java new file mode 100644 index 000000000..41017480f --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazycrates/listeners/items/PaperInteractListener.java @@ -0,0 +1,79 @@ +package com.badbones69.crazycrates.listeners.items; + +import com.badbones69.crazycrates.CrazyCrates; +import com.badbones69.crazycrates.api.events.CrateInteractEvent; +import com.badbones69.crazycrates.tasks.crates.CrateManager; +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; + +public class PaperInteractListener implements Listener { + + private final CrazyCrates plugin = CrazyCrates.getPlugin(); + + private final CrateManager crateManager = this.plugin.getCrateManager(); + + @EventHandler + public void onEditorClick(final PlayerInteractEvent event) { + if (event.getHand() == EquipmentSlot.OFF_HAND) return; + + final Block block = event.getClickedBlock(); + + if (block == null || block.isEmpty()) return; + + final Player player = event.getPlayer(); + + final Action action = event.getAction(); + + if (!this.crateManager.hasEditorCrate(player)) return; + + final Location location = block.getLocation(); + + switch (action) { + case RIGHT_CLICK_BLOCK -> this.crateManager.addCrateByLocation(player, location); + case LEFT_CLICK_BLOCK -> this.crateManager.removeCrateByLocation(player, location); + } + + event.setCancelled(true); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerInteractEvent(PlayerInteractEvent event) { + if (event.getHand() == EquipmentSlot.OFF_HAND) return; + + final Block block = event.getClickedBlock(); + + if (block == null || block.isEmpty()) return; + + if (this.crateManager.hasEditorCrate(event.getPlayer())) { + event.setCancelled(true); + + return; + } + + final Location location = block.getLocation(); + + if (this.crateManager.isCrateLocation(location)) { + new CrateInteractEvent(event, location).callEvent(); + } + } + + @EventHandler + public void onBlockBreak(BlockPlaceEvent event) { + final ItemStack itemStack = event.getItemInHand(); + + if (itemStack.isEmpty()) return; + + if (this.crateManager.isKey(itemStack)) { + event.setBuild(false); + } + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazycrates/tasks/crates/CrateManager.java b/paper/src/main/java/com/badbones69/crazycrates/tasks/crates/CrateManager.java index 2f19cfeb4..af978bccf 100644 --- a/paper/src/main/java/com/badbones69/crazycrates/tasks/crates/CrateManager.java +++ b/paper/src/main/java/com/badbones69/crazycrates/tasks/crates/CrateManager.java @@ -3,6 +3,10 @@ import ch.jalu.configme.SettingsManager; import com.Zrips.CMI.Modules.ModuleHandling.CMIModule; import com.badbones69.crazycrates.api.builders.CrateBuilder; +import com.badbones69.crazycrates.common.config.impl.EditorKeys; +import com.badbones69.crazycrates.listeners.items.ItemsAdderInteractListener; +import com.badbones69.crazycrates.listeners.items.NexoInteractListener; +import com.badbones69.crazycrates.listeners.items.OraxenInteractListener; import com.badbones69.crazycrates.managers.events.enums.EventType; import com.badbones69.crazycrates.tasks.menus.CrateMainMenu; import com.badbones69.crazycrates.api.objects.crates.CrateHologram; @@ -31,11 +35,16 @@ import com.ryderbelserion.vital.paper.api.enums.Support; import com.ryderbelserion.vital.paper.api.files.PaperCustomFile; import com.ryderbelserion.vital.paper.api.files.PaperFileManager; +import com.ryderbelserion.vital.paper.util.scheduler.impl.FoliaScheduler; import com.ryderbelserion.vital.utils.Methods; import io.papermc.paper.persistence.PersistentDataContainerView; import io.papermc.paper.threadedregions.scheduler.ScheduledTask; import net.kyori.adventure.text.logger.slf4j.ComponentLogger; import org.bukkit.NamespacedKey; +import org.bukkit.entity.Display; +import org.bukkit.entity.ItemDisplay; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemType; import org.bukkit.permissions.Permission; import org.bukkit.permissions.PermissionDefault; import org.bukkit.persistence.PersistentDataType; @@ -44,6 +53,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; +import org.joml.Matrix4f; import us.crazycrew.crazycrates.api.enums.types.CrateType; import us.crazycrew.crazycrates.api.enums.types.KeyType; import com.badbones69.crazycrates.api.enums.misc.Keys; @@ -90,6 +100,24 @@ public class CrateManager { private final List brokeCrates = new ArrayList<>(); private final List crates = new ArrayList<>(); + private final Map crateEditors = new HashMap<>(); + + public void addEditorCrate(final Player player, final Crate crate) { + this.crateEditors.put(player.getUniqueId(), crate); + } + + public void removeEditorCrate(final Player player) { + this.crateEditors.remove(player.getUniqueId()); + } + + public boolean hasEditorCrate(final Player player) { + return this.crateEditors.containsKey(player.getUniqueId()); + } + + public @Nullable Crate getEditorCrate(final Player player) { + return this.crateEditors.getOrDefault(player.getUniqueId(), null); + } + private final Map> tiers = new WeakHashMap<>(); public void addTier(final Player player, final int slot, final Tier tier) { @@ -205,6 +233,36 @@ public void reloadCrate(@Nullable final Crate crate) { } } + public void loadCustomItems() { + final PluginManager manager = this.plugin.getServer().getPluginManager(); + + final String pluginName = this.config.getProperty(ConfigKeys.custom_items_plugin).toLowerCase(); + + switch (pluginName) { + case "nexo" -> manager.registerEvents(new NexoInteractListener(), this.plugin); + + case "oraxen" -> manager.registerEvents(new OraxenInteractListener(), this.plugin); + + case "itemsadder" -> manager.registerEvents(new ItemsAdderInteractListener(), this.plugin); + + case "none" -> {} + + default -> { + if (Support.nexo.isEnabled()) { + manager.registerEvents(new NexoInteractListener(), this.plugin); + } + + if (Support.oraxen.isEnabled()) { + manager.registerEvents(new OraxenInteractListener(), this.plugin); + } + + if (Support.items_adder.isEnabled()) { + manager.registerEvents(new ItemsAdderInteractListener(), this.plugin); + } + } + } + } + /** * Load the holograms. */ @@ -234,6 +292,8 @@ public void loadHolograms() { this.holograms = new CMIHologramsSupport(); } + case "None" -> {} + default -> { if (Support.decent_holograms.isEnabled()) { this.holograms = new DecentHologramsSupport(); @@ -1020,13 +1080,123 @@ public boolean hasCrate(@NotNull final Crate crate) { return this.crates.contains(crate); } + private final SettingsManager editor = ConfigManager.getEditor(); + + public void addCrateByLocation(final Player player, final Location location) { + if (!player.hasPermission("crazycrates.editor")) { + removeEditorCrate(player); + + Messages.force_editor_exit.sendMessage(player, "{reason}", "lacking the permission crazycrates.editor"); + + return; + } + + final Crate crate = getEditorCrate(player); + + if (crate == null) { + removeEditorCrate(player); + + Messages.force_editor_exit.sendMessage(player, "{reason}", "Crate does not exist."); + + return; + } + + if (crate.getCrateType() == CrateType.menu && !this.config.getProperty(ConfigKeys.enable_crate_menu)) { + Messages.cannot_set_type.sendMessage(player); + + return; + } + + if (isCrateLocation(location)) { + if (this.editor.getProperty(EditorKeys.overwrite_old_crate_locations)) { + final CrateLocation crateLocation = getCrateLocation(location); + + if (crateLocation == null) return; + + removeLocation(crateLocation); // remove old location + + addCrateLocation(location, crate); // add new location + + Messages.physical_crate_overridden.sendMessage(player, new HashMap<>() {{ + put("{id}", crateLocation.getID()); + put("{crate}", crate.getCrateName()); + }}); + + spawnItem(location, ItemType.EMERALD.createItemStack()); + + return; + } + + Messages.physical_crate_already_exists.sendMessage(player, new HashMap<>() {{ + final CrateLocation crateLocation = getCrateLocation(location); + + put("{id}", crateLocation != null ? crateLocation.getID() : "N/A"); + put("{crate}", crateLocation != null ? crateLocation.getCrate().getCrateName() : "N/A"); + }}); + + spawnItem(location, ItemType.REDSTONE.createItemStack()); + + return; + } + + addCrateLocation(location, crate); + + Messages.created_physical_crate.sendMessage(player, "{crate}", crate.getCrateName()); + + spawnItem(location, ItemType.EMERALD.createItemStack()); + } + + private void spawnItem(final Location location, final ItemStack itemStack) { + final World world = location.getWorld(); + + final ItemDisplay itemDisplay = world.spawn(location.toCenterLocation().add(0.0, 1.0, 0.0), ItemDisplay.class, entity -> entity.setItemStack(itemStack)); + + itemDisplay.setPersistent(false); + itemDisplay.setBillboard(Display.Billboard.CENTER); + itemDisplay.setDisplayHeight(0.5f); + itemDisplay.setDisplayWidth(0.5f); + + final Matrix4f scale = new Matrix4f().scale(0.5f); + + new FoliaScheduler(this.plugin, null, itemDisplay) { + @Override + public void run() { + if (!itemDisplay.isValid()) { // cancel just in case + cancel(); + + return; + } + + itemDisplay.setTransformationMatrix(scale.rotateY(((float) Math.toRadians(180)) + 0.1F)); + itemDisplay.setInterpolationDelay(0); + itemDisplay.setInterpolationDuration(20); + } + }.runAtFixedRate(1, 20); + + // remove item display after 5 seconds. + new FoliaScheduler(this.plugin, location) { + @Override + public void run() { + if (!itemDisplay.isValid()) { // cancel just in case + cancel(); + + return; + } + + itemDisplay.remove(); + } + }.runDelayed(100); + } + /** * Add a new physical crate location. * * @param location the location you wish to add. * @param crate the crate which you would like to set it to. */ - public void addCrateLocation(@NotNull final Location location, @NotNull final Crate crate) { + public void addCrateLocation(@NotNull final Location location, @Nullable final Crate crate) { + if (crate == null) return; + final YamlConfiguration locations = Files.locations.getConfiguration(); String id = "1"; // Location ID @@ -1130,7 +1300,10 @@ public void removeCrateLocation(@NotNull final String id) { */ public final boolean isCrateLocation(@NotNull final Location location) { for (final CrateLocation crateLocation : getCrateLocations()) { - if (crateLocation.getLocation().equals(location)) return true; //todo() make this light weight + final String arg1 = MiscUtils.location(crateLocation.getLocation()); + final String arg2 = MiscUtils.location(location); + + if (arg1.equals(arg2)) return true; } return false; @@ -1460,6 +1633,39 @@ public void endQuickCrate(@NotNull final Player player, @NotNull final Location } } + public void removeCrateByLocation(final Player player, final Location location) { + if (!player.hasPermission("crazycrates.editor")) { + removeEditorCrate(player); + + Messages.force_editor_exit.sendMessage(player, "{reason}", "lacking the permission crazycrates.editor"); + + return; + } + + if (isCrateLocation(location)) { + final CrateLocation crateLocation = getCrateLocation(location); + + if (crateLocation != null) { + final String id = crateLocation.getID(); + + removeCrateLocation(id); + + Messages.removed_physical_crate.sendMessage(player, "{id}", id); + } + } + } + + /** + * Checks if the player's equipment slot item is a key. + * + * @param player the player + * @param equipmentSlot the equipment slot + * @return true or false + */ + public boolean isKey(final Player player, final EquipmentSlot equipmentSlot) { + return isKey(player.getInventory().getItem(equipmentSlot)); + } + /** * Purge all rewards! */ diff --git a/paper/src/main/resources/paper-plugin.yml b/paper/src/main/resources/paper-plugin.yml index 40c6ecfb4..fdd0fc25b 100644 --- a/paper/src/main/resources/paper-plugin.yml +++ b/paper/src/main/resources/paper-plugin.yml @@ -26,6 +26,10 @@ dependencies: load: BEFORE required: false join-classpath: true + ItemsAdder: + load: BEFORE + required: false + join-classpath: true Oraxen: load: BEFORE required: false