From 172df2dfa37331c5b87acf91a29b669c58d3e75c Mon Sep 17 00:00:00 2001 From: Ryder Belserion Date: Sat, 11 Nov 2023 12:53:47 -0500 Subject: [PATCH] update buildscript --- .gitignore | 26 +- CONTRIBUTING.md | 22 + LICENSE | 2 +- README.md | 121 +++- build.gradle.kts | 29 + buildSrc/build.gradle.kts | 11 + buildSrc/settings.gradle.kts | 14 + .../src/main/kotlin/paper-plugin.gradle.kts | 23 + .../src/main/kotlin/root-plugin.gradle.kts | 46 ++ common/build.gradle.kts | 14 + .../common/CrazyAuctionsPlugin.java | 81 +++ .../common/config/ConfigBuilder.java | 30 + .../common/config/types/Config.java | 43 ++ .../common/config/types/Messages.java | 47 ++ .../common/config/types/PluginConfig.java | 33 + .../crazyauctions/common/data/UserCache.java | 39 + gradle.properties | 15 + gradle/libs.versions.toml | 46 ++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 63721 bytes gradle/wrapper/gradle-wrapper.properties | 7 + gradlew | 249 +++++++ gradlew.bat | 92 +++ paper/build.gradle.kts | 125 ++++ .../com/badbones69/crazyauctions/Main.java | 0 .../com/badbones69/crazyauctions/Methods.java | 0 .../crazyauctions/api/Category.java | 0 .../crazyauctions/api/CrazyAuctions.java | 0 .../crazyauctions/api/FileManager.java | 0 .../crazyauctions/api/Messages.java | 0 .../crazyauctions/api/ShopType.java | 0 .../badbones69/crazyauctions/api/Version.java | 0 .../api/enums/CancelledReason.java | 0 .../api/events/AuctionBuyEvent.java | 0 .../api/events/AuctionCancelledEvent.java | 0 .../api/events/AuctionExpireEvent.java | 0 .../api/events/AuctionListEvent.java | 0 .../api/events/AuctionNewBidEvent.java | 0 .../api/events/AuctionWinBidEvent.java | 0 .../crazyauctions/controllers/DupePatch.java | 0 .../crazyauctions/controllers/GUI.java | 0 .../currency/CurrencyManager.java | 0 .../crazyauctions/currency/Vault.java | 0 .../crazyauctions/v2/CrazyAuctions.java | 55 ++ .../crazyauctions/v2/CrazyStarter.java | 30 + .../crazyauctions/v2/api/CrazyManager.java | 34 + .../v2/api/enums/Permissions.java | 38 + .../v2/api/enums/support/DataSupport.java | 19 + .../v2/api/events/AuctionAddEvent.java | 62 ++ .../v2/api/events/AuctionBidEvent.java | 65 ++ .../v2/api/events/AuctionBuyEvent.java | 65 ++ .../v2/api/events/AuctionCancelEvent.java | 82 +++ .../v2/api/events/AuctionExpireEvent.java | 55 ++ .../v2/api/events/AuctionListEvent.java | 65 ++ .../v2/api/events/AuctionWinEvent.java | 65 ++ .../crazyauctions/v2/api/frame/ItemUtils.java | 27 + .../crazyauctions/v2/api/frame/PaperCore.java | 140 ++++ .../v2/api/frame/PaperUtils.java | 25 + .../frame/adapters/LocationTypeAdapter.java | 52 ++ .../v2/api/frame/command/CommandContext.java | 268 +++++++ .../v2/api/frame/command/CommandEngine.java | 164 +++++ .../v2/api/frame/command/CommandFlow.java | 30 + .../v2/api/frame/command/CommandManager.java | 123 ++++ .../frame/command/builders/CommandActor.java | 48 ++ .../command/builders/CommandDataEntry.java | 14 + .../command/builders/CommandHelpEntry.java | 156 ++++ .../command/builders/annotations/Hidden.java | 7 + .../frame/command/builders/args/Argument.java | 3 + .../command/builders/args/ArgumentType.java | 9 + .../command/builders/args/CommandArgs.java | 22 + .../args/builder/BooleanArgument.java | 12 + .../builders/args/builder/DoubleArgument.java | 34 + .../builders/args/builder/FloatArgument.java | 34 + .../builders/args/builder/IntArgument.java | 28 + .../args/builder/custom/PlayerArgument.java | 15 + .../builders/other/ComponentBuilder.java | 94 +++ .../builders/reqs/CommandRequirements.java | 57 ++ .../reqs/CommandRequirementsBuilder.java | 33 + .../v2/api/frame/items/BaseItemBuilder.java | 673 ++++++++++++++++++ .../v2/api/frame/items/ItemBuilder.java | 23 + .../v2/api/frame/items/ItemNbt.java | 57 ++ .../v2/api/manager/enums/AuctionType.java | 28 + .../api/manager/interfaces/AuctionItem.java | 25 + .../api/manager/objects/AuctionButtons.java | 88 +++ .../api/manager/objects/AuctionCategory.java | 44 ++ .../v2/api/manager/objects/AuctionHouse.java | 91 +++ .../manager/objects/InventorySettings.java | 30 + .../objects/auctiontype/BiddingAuction.java | 74 ++ .../objects/auctiontype/SellingAuction.java | 54 ++ .../v2/commands/AuctionCommand.java | 21 + .../v2/commands/admin/CommandReload.java | 23 + .../inventories/AuctionInventory.java | 23 + .../inventories/AuctionInventoryClick.java | 35 + .../crazyauctions/v2/events/DataListener.java | 27 + .../v2/storage/interfaces/UserManager.java | 28 + .../v2/storage/objects/UserData.java | 24 + .../v2/storage/types/StorageManager.java | 17 + .../types/file/yaml/YamlUserManager.java | 110 +++ .../v2/support/PlaceholderSupport.java | 17 + .../v2/support/economy/Currency.java | 51 ++ .../v2/support/economy/CurrencyAPI.java | 131 ++++ .../support/economy/vault/VaultSupport.java | 26 + .../crazyauctions/v2/utils/ItemUtils.java | 10 + .../v2/utils/misc/ColorUtils.java | 15 + .../src}/main/resources/config1.12.2-Down.yml | 0 .../src}/main/resources/config1.13-Up.yml | 0 {src => paper/src}/main/resources/data.yml | 0 .../src}/main/resources/messages.yml | 0 {src => paper/src}/main/resources/plugin.yml | 0 .../src}/main/resources/test-file.yml | 0 pom.xml | 116 --- settings.gradle.kts | 17 + 111 files changed, 4871 insertions(+), 152 deletions(-) create mode 100644 CONTRIBUTING.md create mode 100644 build.gradle.kts create mode 100644 buildSrc/build.gradle.kts create mode 100644 buildSrc/settings.gradle.kts create mode 100644 buildSrc/src/main/kotlin/paper-plugin.gradle.kts create mode 100644 buildSrc/src/main/kotlin/root-plugin.gradle.kts create mode 100644 common/build.gradle.kts create mode 100644 common/src/main/java/com/badbones69/crazyauctions/common/CrazyAuctionsPlugin.java create mode 100644 common/src/main/java/com/badbones69/crazyauctions/common/config/ConfigBuilder.java create mode 100644 common/src/main/java/com/badbones69/crazyauctions/common/config/types/Config.java create mode 100644 common/src/main/java/com/badbones69/crazyauctions/common/config/types/Messages.java create mode 100644 common/src/main/java/com/badbones69/crazyauctions/common/config/types/PluginConfig.java create mode 100644 common/src/main/java/com/badbones69/crazyauctions/common/data/UserCache.java create mode 100644 gradle.properties create mode 100644 gradle/libs.versions.toml create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 paper/build.gradle.kts rename {src => paper/src}/main/java/com/badbones69/crazyauctions/Main.java (100%) rename {src => paper/src}/main/java/com/badbones69/crazyauctions/Methods.java (100%) rename {src => paper/src}/main/java/com/badbones69/crazyauctions/api/Category.java (100%) rename {src => paper/src}/main/java/com/badbones69/crazyauctions/api/CrazyAuctions.java (100%) rename {src => paper/src}/main/java/com/badbones69/crazyauctions/api/FileManager.java (100%) rename {src => paper/src}/main/java/com/badbones69/crazyauctions/api/Messages.java (100%) rename {src => paper/src}/main/java/com/badbones69/crazyauctions/api/ShopType.java (100%) rename {src => paper/src}/main/java/com/badbones69/crazyauctions/api/Version.java (100%) rename {src => paper/src}/main/java/com/badbones69/crazyauctions/api/enums/CancelledReason.java (100%) rename {src => paper/src}/main/java/com/badbones69/crazyauctions/api/events/AuctionBuyEvent.java (100%) rename {src => paper/src}/main/java/com/badbones69/crazyauctions/api/events/AuctionCancelledEvent.java (100%) rename {src => paper/src}/main/java/com/badbones69/crazyauctions/api/events/AuctionExpireEvent.java (100%) rename {src => paper/src}/main/java/com/badbones69/crazyauctions/api/events/AuctionListEvent.java (100%) rename {src => paper/src}/main/java/com/badbones69/crazyauctions/api/events/AuctionNewBidEvent.java (100%) rename {src => paper/src}/main/java/com/badbones69/crazyauctions/api/events/AuctionWinBidEvent.java (100%) rename {src => paper/src}/main/java/com/badbones69/crazyauctions/controllers/DupePatch.java (100%) rename {src => paper/src}/main/java/com/badbones69/crazyauctions/controllers/GUI.java (100%) rename {src => paper/src}/main/java/com/badbones69/crazyauctions/currency/CurrencyManager.java (100%) rename {src => paper/src}/main/java/com/badbones69/crazyauctions/currency/Vault.java (100%) create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/CrazyAuctions.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/CrazyStarter.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/CrazyManager.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/enums/Permissions.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/enums/support/DataSupport.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionAddEvent.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionBidEvent.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionBuyEvent.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionCancelEvent.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionExpireEvent.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionListEvent.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionWinEvent.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/ItemUtils.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/PaperCore.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/PaperUtils.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/adapters/LocationTypeAdapter.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/CommandContext.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/CommandEngine.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/CommandFlow.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/CommandManager.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/CommandActor.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/CommandDataEntry.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/CommandHelpEntry.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/annotations/Hidden.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/Argument.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/ArgumentType.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/CommandArgs.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/builder/BooleanArgument.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/builder/DoubleArgument.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/builder/FloatArgument.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/builder/IntArgument.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/builder/custom/PlayerArgument.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/other/ComponentBuilder.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/reqs/CommandRequirements.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/reqs/CommandRequirementsBuilder.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/items/BaseItemBuilder.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/items/ItemBuilder.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/items/ItemNbt.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/enums/AuctionType.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/interfaces/AuctionItem.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/AuctionButtons.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/AuctionCategory.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/AuctionHouse.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/InventorySettings.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/auctiontype/BiddingAuction.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/auctiontype/SellingAuction.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/commands/AuctionCommand.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/commands/admin/CommandReload.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/commands/inventories/AuctionInventory.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/commands/inventories/AuctionInventoryClick.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/events/DataListener.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/storage/interfaces/UserManager.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/storage/objects/UserData.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/storage/types/StorageManager.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/storage/types/file/yaml/YamlUserManager.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/support/PlaceholderSupport.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/support/economy/Currency.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/support/economy/CurrencyAPI.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/support/economy/vault/VaultSupport.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/utils/ItemUtils.java create mode 100644 paper/src/main/java/com/badbones69/crazyauctions/v2/utils/misc/ColorUtils.java rename {src => paper/src}/main/resources/config1.12.2-Down.yml (100%) rename {src => paper/src}/main/resources/config1.13-Up.yml (100%) rename {src => paper/src}/main/resources/data.yml (100%) rename {src => paper/src}/main/resources/messages.yml (100%) rename {src => paper/src}/main/resources/plugin.yml (100%) rename {src => paper/src}/main/resources/test-file.yml (100%) delete mode 100644 pom.xml create mode 100644 settings.gradle.kts diff --git a/.gitignore b/.gitignore index 72db3d1..a4bf8ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,22 @@ +build +.gradle +.idea -\.idea/ +buildSrc/.gradle +buildSrc/build -*.iml +common/.gradle +common/build -*.class +jars -target/classes/ +paper/build +paper/.gradle -target/ - -\.DS_Store - -dependency-reduced-pom.xml +run +!paper/run/config +!paper/run/spigot.yml +!paper/run/bukkit.yml +!paper/run/eula.txt +!paper/run/server.properties +!paper/run/plugins \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..7ae017d --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,22 @@ +# Contributing to CrazyCrates +Contributions to the project are always welcome, Pull Requests do have some guidelines before being approved. + +## You should always create the fork as a personal repository not in an organization. +Any pull request made by a fork in an organization prevents modifications. Everyone has their own way of doing things and rather asking you to change that. A personal fork lets us change the things +that we have a tick about. + +If you do not use a personal fork, We have to manually merge your pull request which means it's marked as closed instead of merged. + +## Requirements + * `git` + * Java 17 ( Adoptium is recommended ) + +Pull Requests must be labeled properly according to if it's a bug fix, a new feature or enhancements to the code base. + * `git checkout -b fix/your_fix` + * `git checkout -b feature/your_feature` + * `git checkout -b quality/your_enhancement` + * Commit your changes using `git commit -m 'your commit'` + * Push to your branch using `git push` + * Open a pull request to the `main` branch on our repository to add your change. + +You must explain what your pull request is changing and if needed, Supply a video of your change as Pull Requests are a way to get feedback. \ No newline at end of file diff --git a/LICENSE b/LICENSE index 4383cc3..cae7779 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2016 Crazy Crew +Copyright (c) 2016-2023 CrazyCrew Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 07ed220..8998c42 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,110 @@ -## Crazy Auctions +
-[![Join us on Discord](https://img.shields.io/discord/182615261403283459.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.badbones69.com) +[![crazyauctions](https://raw.githubusercontent.com/RyderBelserion/Assets/main/crazycrew/webp/CrazyAuctionsBanner.webp)](https://modrinth.com/plugin/crazyauctions) -[![CrazyAuctions's Stargazers](https://img.shields.io/github/stars/Crazy-Crew/Crazy-Auctions?label=stars&logo=github)](https://github.com/Crazy-Crew/Crazy-Auctions/stargazers) -[![CrazyAuctions's Forks](https://img.shields.io/github/forks/Crazy-Crew/Crazy-Auctions?label=forks&logo=github)](https://github.com/Crazy-Crew/Crazy-Auctions/network/members) -[![CrazyAuctions's Watchers](https://img.shields.io/github/watchers/Crazy-Crew/Crazy-Auctions?label=watchers&logo=github)](https://github.com/Crazy-Crew/Crazy-Auctions/watchers) +
-CrazyAuctions is a simple auctions plugin where you can sell your items and bid on other items! +[![Contributors][contributors-shield]][contributors-url] +[![Forks][forks-shield]][forks-url] +[![Stargazers][stars-shield]][stars-url] +[![Issues][issues-shield]][issues-url] +[![GPU License][license-shield]][license-url] +[![Contact][discord-shield]][discord-url] +![CodeFactor][codefactor-shield] -## Contact -[![Join us on Discord](https://img.shields.io/discord/182615261403283459.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.badbones69.com) +![Paper](https://cdn.jsdelivr.net/gh/intergrav/devins-badges/assets/compact/supported/paper_vector.svg) +![Purpur](https://cdn.jsdelivr.net/gh/intergrav/devins-badges/assets/compact/supported/purpur_vector.svg) -Join us on [Discord](https://discord.badbones69.com) +

+ Auction off your items in style! +
+ Explore the docs » +
+
+ Report Bug + · + Request Feature + · + Get Support +

+
-## Downloads -[![Build Status](https://jenkins.badbones69.com/view/Stable/job/Crazy-Auctions/badge/icon)](https://jenkins.badbones69.com/view/Stable/job/Crazy-Auctions/) + +
+ Table of Contents +
    +
  1. + Getting Started + +
  2. +
  3. Roadmap
  4. +
  5. Contributing
  6. +
  7. License
  8. +
  9. Contact
  10. +
+
-Downloads can be obtained from the [spigot page](https://www.spigotmc.org/resources/crazy-auctions.25219/) or the [Jenkins](https://jenkins.badbones69.com/view/Stable/job/Crazy-Auctions/). +## Resource Page -## Plugin Data -[![bStats Graph Data](https://bstats.org/signatures/bukkit/CrazyAuctions.svg)](https://bstats.org/plugin/bukkit/CrazyAuctions/4624) +### Beta Builds +All beta builds will be on Modrinth marked as beta.
-## API -In Progress. +![Modrinth](https://raw.githubusercontent.com/intergrav/devins-badges/v3/assets/cozy/available/modrinth_64h.png) -### Dependency Information +## Getting Started -#### Maven -In Progress. +How to get started with contributing / maintaining your own version of CrazyAuctions! -#### Gradle -In Progress. +### Prerequisites -## Working with CrazyAuctions. +A list of things necessary to make sure you can build CrazyAuctions properly. +* Intellij IDEA + * > https://www.jetbrains.com/idea/download/ +* Gradle -#### Contributing -Fork the project & open a pull request. +### Installation -#### Compiling -Clone the project & run the install task. +1. Clone the repo + ```sh + git clone https://github.com/Crazy-Crew/CrazyAuctions.git + ``` +2. Open the repository using Intellij IDEA & wait until it finishes downloading/indexing. +3. Run the assemble task. + ```gradle + ./gradlew assemble + ``` + +## Roadmap + +Check our public [trello board](https://trello.com/b/CcPYmsBt) for our current plans, any bugs and general tracking of the project progress. + +## Contributing + +1. Fork the Project +2. Create your Feature Branch (`git checkout -b feature/yourfeature`) +3. Commit your Changes (`git commit -m 'your amazing feature.'`) +4. Push to the Branch (`git push`) +5. Open a Pull Request to the dev branch to add your feature/fix. + +## License + +Distributed under the MIT License. See [`LICENSE`](/LICENSE) for more information. + +[discord-shield]: https://img.shields.io/discord/182615261403283459.svg?style=flat&logo=appveyor +[discord-url]: https://discord.gg/crazycrew + +[contributors-shield]: https://img.shields.io/github/contributors/Crazy-Crew/CrazyAuctions.svg?style=flat&logo=appveyor +[contributors-url]: https://github.com/Crazy-Crew/CrazyAuctions/graphs/contributors +[forks-shield]: https://img.shields.io/github/forks/Crazy-Crew/CrazyAuctions.svg?style=flat&logo=appveyor +[forks-url]: https://github.com/Crazy-Crew/CrazyAuctions/network/members +[stars-shield]: https://img.shields.io/github/stars/Crazy-Crew/CrazyAuctions.svg?style=flat&logo=appveyor +[stars-url]: https://github.com/Crazy-Crew/CrazyAuctions/stargazers +[issues-shield]: https://img.shields.io/github/issues/Crazy-Crew/CrazyAuctions.svg?style=flat&logo=appveyor +[issues-url]: https://github.com/Crazy-Crew/CrazyAuctions/issues +[license-shield]: https://img.shields.io/github/license/Crazy-Crew/CrazyAuctions.svg?style=flat&logo=appveyor +[license-url]: https://github.com/Crazy-Crew/CrazyAuctions/blob/master/LICENSE + +[codefactor-shield]: https://img.shields.io/codefactor/grade/github/crazy-crew/CrazyAuctions/main?style=flat&logo=appveyor \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..c088781 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,29 @@ +plugins { + id("root-plugin") +} + +defaultTasks("build") + +tasks { + assemble { + val jarsDir = File("$rootDir/jars") + if (jarsDir.exists()) jarsDir.delete() + + subprojects.forEach { project -> + dependsOn(":${project.name}:build") + + doLast { + if (!jarsDir.exists()) jarsDir.mkdirs() + + if (project.name == "core") return@doLast + + val file = file("${project.layout.buildDirectory.get()}/libs/${rootProject.name}-${rootProject.version}.jar") + + copy { + from(file) + into(jarsDir) + } + } + } + } +} \ No newline at end of file diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 0000000..742a7b8 --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,11 @@ +plugins { + `kotlin-dsl` +} + +dependencies { + implementation(libs.paperweight.plugin) + + implementation(libs.jpenilla.plugin) + + implementation(libs.shadow.plugin) +} \ No newline at end of file diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts new file mode 100644 index 0000000..4720f82 --- /dev/null +++ b/buildSrc/settings.gradle.kts @@ -0,0 +1,14 @@ +dependencyResolutionManagement { + repositories { + maven("https://repo.papermc.io/repository/maven-public/") + + gradlePluginPortal() + mavenCentral() + } + + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/paper-plugin.gradle.kts b/buildSrc/src/main/kotlin/paper-plugin.gradle.kts new file mode 100644 index 0000000..24d0097 --- /dev/null +++ b/buildSrc/src/main/kotlin/paper-plugin.gradle.kts @@ -0,0 +1,23 @@ +plugins { + id("io.papermc.paperweight.userdev") + + id("root-plugin") +} + +repositories { + maven("https://repo.papermc.io/repository/maven-public/") +} + +dependencies { + paperweight.paperDevBundle("1.20.2-R0.1-SNAPSHOT") +} + +tasks { + assemble { + dependsOn(reobfJar) + } + + reobfJar { + outputJar.set(file("${project.layout.buildDirectory.get()}/libs/${rootProject.name}-${rootProject.version}.jar")) + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/root-plugin.gradle.kts b/buildSrc/src/main/kotlin/root-plugin.gradle.kts new file mode 100644 index 0000000..57bb9dc --- /dev/null +++ b/buildSrc/src/main/kotlin/root-plugin.gradle.kts @@ -0,0 +1,46 @@ +plugins { + id("com.github.johnrengelman.shadow") + + `maven-publish` + `java-library` +} + +repositories { + maven("https://repo.triumphteam.dev/snapshots/") + + maven("https://repo.crazycrew.us/releases/") + + maven("https://jitpack.io") + + mavenCentral() +} + +java { + toolchain.languageVersion.set(JavaLanguageVersion.of("17")) +} + +tasks { + compileJava { + options.encoding = Charsets.UTF_8.name() + options.release.set(17) + } + + shadowJar { + mergeServiceFiles() + + exclude("META-INF/**") + } +} + +publishing { + repositories { + maven { + credentials { + this.username = System.getenv("gradle_username") + this.password = System.getenv("gradle_password") + } + + url = uri("https://repo.crazycrew.us/releases/") + } + } +} \ No newline at end of file diff --git a/common/build.gradle.kts b/common/build.gradle.kts new file mode 100644 index 0000000..89b9b31 --- /dev/null +++ b/common/build.gradle.kts @@ -0,0 +1,14 @@ +plugins { + id("root-plugin") +} + +project.group = "${rootProject.group}.common" +project.version = "${rootProject.version}" + +dependencies { + api(libs.configme) { + exclude("org.yaml", "snakeyaml") + } + + compileOnly(libs.annotations) +} \ No newline at end of file diff --git a/common/src/main/java/com/badbones69/crazyauctions/common/CrazyAuctionsPlugin.java b/common/src/main/java/com/badbones69/crazyauctions/common/CrazyAuctionsPlugin.java new file mode 100644 index 0000000..019f2ee --- /dev/null +++ b/common/src/main/java/com/badbones69/crazyauctions/common/CrazyAuctionsPlugin.java @@ -0,0 +1,81 @@ +package com.badbones69.crazyauctions.common; + +import ch.jalu.configme.SettingsManager; +import ch.jalu.configme.SettingsManagerBuilder; +import com.badbones69.crazyauctions.common.config.ConfigBuilder; +import com.badbones69.crazyauctions.common.config.types.PluginConfig; +import java.io.File; +import java.nio.file.Path; + +public class CrazyAuctionsPlugin { + + private final Path path; + + public CrazyAuctionsPlugin(Path path) { + this.path = path; + } + + private static SettingsManager locale; + private static SettingsManager config; + private static SettingsManager pluginConfig; + + public void load() { + File pluginConfigFile = new File(this.path.toFile(), "plugin-config.yml"); + + pluginConfig = SettingsManagerBuilder + .withYamlFile(pluginConfigFile) + .useDefaultMigrationService() + .configurationData(ConfigBuilder.buildPluginConfig()) + .create(); + + File localeDir = new File(this.path.toFile(), "locale"); + //FileUtils.extract("/locale/", this.path, false); + + File localeFile = new File(localeDir, pluginConfig.getProperty(PluginConfig.LOCALE_FILE) + ".yml"); + + locale = SettingsManagerBuilder + .withYamlFile(localeFile) + .useDefaultMigrationService() + .configurationData(ConfigBuilder.buildLocale()) + .create(); + + // Create config.yml + File configFile = new File(this.path.toFile(), "config.yml"); + + config = SettingsManagerBuilder + .withYamlFile(configFile) + .useDefaultMigrationService() + .configurationData(ConfigBuilder.buildConfig()) + .create(); + + } + + public void reload() { + // Reload configs. + pluginConfig.reload(); + config.reload(); + + locale.reload(); + + File localeDir = new File(this.path.toFile(), "locale"); + File localeFile = new File(localeDir, pluginConfig.getProperty(PluginConfig.LOCALE_FILE) + ".yml"); + + locale = SettingsManagerBuilder + .withYamlFile(localeFile) + .useDefaultMigrationService() + .configurationData(ConfigBuilder.buildLocale()) + .create(); + } + + public static SettingsManager getPluginConfig() { + return pluginConfig; + } + + public static SettingsManager getLocale() { + return locale; + } + + public static SettingsManager getConfig() { + return config; + } +} \ No newline at end of file diff --git a/common/src/main/java/com/badbones69/crazyauctions/common/config/ConfigBuilder.java b/common/src/main/java/com/badbones69/crazyauctions/common/config/ConfigBuilder.java new file mode 100644 index 0000000..a3eb53b --- /dev/null +++ b/common/src/main/java/com/badbones69/crazyauctions/common/config/ConfigBuilder.java @@ -0,0 +1,30 @@ +package com.badbones69.crazyauctions.common.config; + +import ch.jalu.configme.configurationdata.ConfigurationData; +import ch.jalu.configme.configurationdata.ConfigurationDataBuilder; +import com.badbones69.crazyauctions.common.config.types.Config; +import com.badbones69.crazyauctions.common.config.types.Messages; +import com.badbones69.crazyauctions.common.config.types.PluginConfig; + +public class ConfigBuilder { + + private ConfigBuilder() {} + + public static ConfigurationData buildPluginConfig() { + return ConfigurationDataBuilder.createConfiguration( + PluginConfig.class + ); + } + + public static ConfigurationData buildConfig() { + return ConfigurationDataBuilder.createConfiguration( + Config.class + ); + } + + public static ConfigurationData buildLocale() { + return ConfigurationDataBuilder.createConfiguration( + Messages.class + ); + } +} \ No newline at end of file diff --git a/common/src/main/java/com/badbones69/crazyauctions/common/config/types/Config.java b/common/src/main/java/com/badbones69/crazyauctions/common/config/types/Config.java new file mode 100644 index 0000000..0e66d3d --- /dev/null +++ b/common/src/main/java/com/badbones69/crazyauctions/common/config/types/Config.java @@ -0,0 +1,43 @@ +package com.badbones69.crazyauctions.common.config.types; + +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 Config implements SettingsHolder { + + public Config() {} + + @Override + public void registerComments(CommentsConfiguration conf) { + String[] header = { + "Github: https://github.com/Crazy-Crew", + "", + "Issues: https://github.com/Crazy-Crew/CrazyAuctions/issues", + "Features: https://github.com/Crazy-Crew/CrazyAuctions//discussions/categories/features", + "", + "Legacy color codes such as &7,&c no longer work. You must use MiniMessage", + "https://docs.advntr.dev/minimessage/format.html#color" + }; + + String[] deprecation = { + "", + "Warning: This section is subject to change so it is considered deprecated.", + "This is your warning before the change happens.", + "" + }; + + conf.setComment("misc", header); + } + + @Comment("Allow damage items to be auctioned off.") + public static final Property damaged_items = newProperty("misc.allow-damaged-items", false); + + @Comment("Whether or not to allow `ah sell` or not.") + public static final Property selling_module = newProperty("modules.selling-module", true); + + @Comment("Whether or not to allow `ah buy` or not.") + public static final Property bidding_module = newProperty("modules.bidding-module", true); +} \ No newline at end of file diff --git a/common/src/main/java/com/badbones69/crazyauctions/common/config/types/Messages.java b/common/src/main/java/com/badbones69/crazyauctions/common/config/types/Messages.java new file mode 100644 index 0000000..31670d2 --- /dev/null +++ b/common/src/main/java/com/badbones69/crazyauctions/common/config/types/Messages.java @@ -0,0 +1,47 @@ +package com.badbones69.crazyauctions.common.config.types; + +import ch.jalu.configme.SettingsHolder; +import ch.jalu.configme.configurationdata.CommentsConfiguration; +import ch.jalu.configme.properties.Property; +import ch.jalu.configme.properties.PropertyInitializer; + +public class Messages implements SettingsHolder { + + public Messages() {} + + @Override + public void registerComments(CommentsConfiguration conf) { + String[] header = { + "Submit your translations here: https://github.com/Crazy-Crew/CrazyAuctions/discussions/categories/translations", + "", + "Legacy color codes such as &7,&c no longer work. You must use MiniMessage", + "https://docs.advntr.dev/minimessage/format.html#color" + }; + + String[] deprecation = { + "", + "Warning: This section is subject to change so it is considered deprecated.", + "This is your warning before the change happens.", + "" + }; + + conf.setComment("general", header); + } + + public static final Property unknown_command = PropertyInitializer.newProperty("general.unknown-command", "{prefix}The command {command} is not known."); + + public static final Property INVALID_SYNTAX = PropertyInitializer.newProperty("general.invalid-syntax", "{prefix}{value} is an invalid {action}."); + + public static final Property NO_PERMISSION = PropertyInitializer.newProperty("general.no-permission", "{prefix}You do not have permission to use that command!"); + + public static final Property REQUIRED_ARGUMENT = PropertyInitializer.newProperty("general.checks.required-argument", "{prefix}This argument is not optional"); + + public static final Property OPTIONAL_ARGUMENT = PropertyInitializer.newProperty("general.checks.optional-argument", "{prefix}This argument is optional"); + + public static final Property NOT_ENOUGH_ARGS = PropertyInitializer.newProperty("general.checks.not-enough-args", "{prefix}You did not supply enough arguments."); + + public static final Property TOO_MANY_ARGS = PropertyInitializer.newProperty("general.checks.too-many-args", "{prefix}You put more arguments then I can handle."); + + public static final Property MUST_BE_PLAYER = PropertyInitializer.newProperty("general.player-checks.must-be-player", "{prefix}You must be a player to use this command."); + +} \ No newline at end of file diff --git a/common/src/main/java/com/badbones69/crazyauctions/common/config/types/PluginConfig.java b/common/src/main/java/com/badbones69/crazyauctions/common/config/types/PluginConfig.java new file mode 100644 index 0000000..7bc2f51 --- /dev/null +++ b/common/src/main/java/com/badbones69/crazyauctions/common/config/types/PluginConfig.java @@ -0,0 +1,33 @@ +package com.badbones69.crazyauctions.common.config.types; + +import ch.jalu.configme.Comment; +import ch.jalu.configme.SettingsHolder; +import ch.jalu.configme.properties.Property; +import ch.jalu.configme.properties.PropertyInitializer; +import static ch.jalu.configme.properties.PropertyInitializer.newProperty; + +/** + * Description: The plugin-settings.yml options. + */ +public class PluginConfig implements SettingsHolder { + + // Empty constructor required by SettingsHolder + protected PluginConfig() {} + + @Comment({ + "Choose what language you want the plugin to be in.", + "", + "Available Languages: en-US" + }) + public static final Property LOCALE_FILE = PropertyInitializer.newProperty("language", "en-US"); + + @Comment("Whether you want CrazyAuctions to shut up or not, This option is ignored by errors.") + public static final Property verbose_logging = newProperty("verbose_logging", true); + + @Comment({ + "Sends anonymous statistics about how the plugin is used to bstats.org.", + "bstats is a service for plugin developers to find out how the plugin being used,", + "This information helps us figure out how to better improve the plugin." + }) + public static final Property toggle_metrics = newProperty("toggle_metrics", true); +} \ No newline at end of file diff --git a/common/src/main/java/com/badbones69/crazyauctions/common/data/UserCache.java b/common/src/main/java/com/badbones69/crazyauctions/common/data/UserCache.java new file mode 100644 index 0000000..6fae776 --- /dev/null +++ b/common/src/main/java/com/badbones69/crazyauctions/common/data/UserCache.java @@ -0,0 +1,39 @@ +package com.badbones69.crazyauctions.common.data; + +import java.nio.file.Path; +import java.util.UUID; + +public interface UserCache { + + /** + * Add a player to the hashmap if absent. + * + * @param uuid player uuid + */ + void addPlayer(final UUID uuid); + + /** + * Remove the player from the hashmap. + * + * @param uuid player uuid + */ + void removePlayer(final UUID uuid); + + /** + * Fetch the player if online or offline. + * + * @param uuid player uuid + * @return player object + */ + String getPlayerName(final UUID uuid); + + /** + * Fetch the uuid file of the player. + * + * @param path the path i.e. 'CrazyAuctions/userdata/random-uuid.' + * @param uuid the player uuid + * @return the complete path + */ + Path getFile(final Path path, UUID uuid); + +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..4f7595f --- /dev/null +++ b/gradle.properties @@ -0,0 +1,15 @@ +org.gradle.jvmargs = '-Xmx3G' +org.gradle.parallel = false +org.gradle.warning.mode = all + +authors = ["Ryderbelserion, Badbones69"] +website = https://modrinth.com/plugin/crazycrates +sources = https://github.com/Crazy-Crew/CrazyCrates +issues = https://github.com/Crazy-Crew/CrazyCrates/issues + +group = us.crazycrew.crazycrates +description = Add unlimited crates to your server with 10 different crate types to choose from! +version = 1.18 +apiVersion = 1.20 + +minecraftVersion=1.20.2 \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..f8deb82 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,46 @@ +[versions] +paperweight_version = "1.5.8" +run_paper_version = "2.2.0" +shadow_version = "8.1.1" + +jetbrains_kotlin = "1.9.10" + +cluster_version = "2.4" +kyori_version = "4.14.0" + +[plugins] +hangar = { id = "io.papermc.hangar-publish-plugin", version = "0.1.0" } +modrinth = { id = "com.modrinth.minotaur", version = "2.8.4" } + +[libraries] +cluster_paper = { module = "com.ryderbelserion.cluster:cluster-paper", version.ref = "cluster_version" } +cluster_api = { module = "com.ryderbelserion.cluster:cluster-api", version.ref = "cluster_version" } + +adventure = { module = "net.kyori:adventure-api", version.ref = "kyori_version" } +minimessage = { module = "net.kyori:adventure-text-minimessage", version.ref = "kyori_version" } + +nbtapi = { module = "de.tr7zw:item-nbt-api", version = "2.12.0" } + +annotations = { module = "org.jetbrains:annotations", version = "24.0.1" } +kotlin = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "jetbrains_kotlin" } + +triumphcmds = { module = "dev.triumphteam:triumph-cmd-bukkit", version = "2.0.0-SNAPSHOT" } + +configme = { module = "ch.jalu:configme", version = "1.4.1" } + +metrics = { module = "org.bstats:bstats-bukkit", version = "3.0.2" } + +itemsadder = { module = "com.github.LoneDev6:api-itemsadder", version = "3.6.1" } +oraxen = { module = "com.github.oraxen:oraxen", version = "1.162.0" } + +holographicdisplays = { module = "me.filoghost.holographicdisplays:holographicdisplays-api", version = "3.0.0" } +decentholograms = { module = "com.github.decentsoftware-eu:decentholograms", version = "2.8.4" } + +placeholderapi = { module = "me.clip:placeholderapi", version = "2.11.4" } + +# Plugins +paperweight_plugin = { module = "io.papermc.paperweight:paperweight-userdev", version.ref = "paperweight_version" } +jpenilla_plugin = { module = "xyz.jpenilla:run-task", version.ref = "run_paper_version" } +shadow_plugin = { module = "com.github.johnrengelman:shadow", version.ref = "shadow_version" } + +kotlin_plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "jetbrains_kotlin" } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..7f93135c49b765f8051ef9d0a6055ff8e46073d8 GIT binary patch literal 63721 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鯊%1Et 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⁢ zv5o9#E7!G0XmdzfsS{efPNi`1b44~SZ4Z8fuX!I}#8g+(wxzQwUT#Xb2(tbY1+EUhGKoT@KEU9Ktl>_0 z%bjDJg;#*gtJZv!-Zs`?^}v5eKmnbjqlvnSzE@_SP|LG_PJ6CYU+6zY6>92%E+ z=j@TZf-iW4(%U{lnYxQA;7Q!b;^brF8n0D>)`q5>|WDDXLrqYU_tKN2>=#@~OE7grMnNh?UOz-O~6 z6%rHy{#h9K0AT+lDC7q4{hw^|q6*Ry;;L%Q@)Ga}$60_q%D)rv(CtS$CQbpq9|y1e zRSrN4;$Jyl{m5bZw`$8TGvb}(LpY{-cQ)fcyJv7l3S52TLXVDsphtv&aPuDk1OzCA z4A^QtC(!11`IsNx_HnSy?>EKpHJWT^wmS~hc^p^zIIh@9f6U@I2 zC=Mve{j2^)mS#U$e{@Q?SO6%LDsXz@SY+=cK_QMmXBIU)j!$ajc-zLx3V60EXJ!qC zi<%2x8Q24YN+&8U@CIlN zrZkcT9yh%LrlGS9`G)KdP(@9Eo-AQz@8GEFWcb7U=a0H^ZVbLmz{+&M7W(nXJ4sN8 zJLR7eeK(K8`2-}j(T7JsO`L!+CvbueT%izanm-^A1Dn{`1Nw`9P?cq;7no+XfC`K(GO9?O^5zNIt4M+M8LM0=7Gz8UA@Z0N+lg+cX)NfazRu z5D)~HA^(u%w^cz+@2@_#S|u>GpB+j4KzQ^&Wcl9f z&hG#bCA(Yk0D&t&aJE^xME^&E-&xGHhXn%}psEIj641H+Nl-}boj;)Zt*t(4wZ5DN z@GXF$bL=&pBq-#vkTkh>7hl%K5|3 z{`Vn9b$iR-SoGENp}bn4;fR3>9sA%X2@1L3aE9yTra;Wb#_`xWwLSLdfu+PAu+o3| zGVnpzPr=ch{uuoHjtw7+_!L_2;knQ!DuDl0R`|%jr+}jFzXtrHIKc323?JO{l&;VF z*L1+}JU7%QJOg|5|Tc|D8fN zJORAg=_vsy{ak|o);@)Yh8Lkcg@$FG3k@ep36BRa^>~UmnRPziS>Z=`Jb2x*Q#`%A zU*i3&Vg?TluO@X0O;r2Jl6LKLUOVhSqg1*qOt^|8*c7 zo(298@+r$k_wQNGHv{|$tW(T8L+4_`FQ{kEW5Jgg{yf7ey4ss_(SNKfz(N9lx&a;< je(UuV8hP?p&}TPdm1I$XmG#(RzlD&B2izSj9sl%y5~4qc literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..3fa8f86 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..1aa94a4 --- /dev/null +++ b/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..93e3f59 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/paper/build.gradle.kts b/paper/build.gradle.kts new file mode 100644 index 0000000..be8b59b --- /dev/null +++ b/paper/build.gradle.kts @@ -0,0 +1,125 @@ +import io.papermc.hangarpublishplugin.model.Platforms + +plugins { + alias(libs.plugins.modrinth) + alias(libs.plugins.hangar) + + id("xyz.jpenilla.run-paper") + + id("paper-plugin") +} + +project.group = "${rootProject.group}.paper" + +repositories { + maven("https://repo.extendedclip.com/content/repositories/placeholderapi/") + + maven("https://repo.codemc.org/repository/maven-public/") + + maven("https://repo.crazycrew.us/first-party/") + + maven("https://repo.crazycrew.us/third-party/") + + flatDir { dirs("libs") } +} + +dependencies { + +} + +tasks { + runServer { + jvmArgs("-Dnet.kyori.ansi.colorLevel=truecolor") + + minecraftVersion("1.20.2") + } + + shadowJar { + listOf( + "de.tr7zw.changeme.nbtapi", + "org.bstats", + "ch.jalu" + ).forEach { + relocate(it, "libs.$it") + } + } + + processResources { + val props = mapOf( + "name" to rootProject.name, + "group" to project.group.toString(), + "version" to rootProject.version, + "description" to rootProject.description, + "authors" to rootProject.properties["authors"], + "apiVersion" to "1.20", + "website" to "https://modrinth.com/plugin/${rootProject.name.lowercase()}" + ) + + filesMatching("plugin.yml") { + expand(props) + } + } +} + +val isSnapshot = true +val type = if (isSnapshot) "beta" else "release" +val other = if (isSnapshot) "Beta" else "Release" + +val file = file("${rootProject.rootDir}/jars/${rootProject.name}-${rootProject.version}.jar") + +val description = """ +## Fixes: + * Fix not crates being wrongly labeled as virtual crates if they are quadcrate, quickcrate or ones that need to be in the physical world. + +## Other: + * [Feature Requests](https://github.com/Crazy-Crew/${rootProject.name}/issues) + * [Bug Reports](https://github.com/Crazy-Crew/${rootProject.name}/issues) +""".trimIndent() + +val versions = listOf( + "1.20", + "1.20.1", + "1.20.2" +) + +modrinth { + autoAddDependsOn.set(false) + + token.set(System.getenv("modrinth_token")) + + projectId.set(rootProject.name.lowercase()) + + versionName.set("${rootProject.name} ${rootProject.version}") + versionNumber.set("${rootProject.version}") + + versionType.set(type) + + uploadFile.set(file("${rootProject.rootDir}/jars/${rootProject.name}-${rootProject.version}.jar")) + + gameVersions.addAll(versions) + + changelog.set(description) + + loaders.addAll("paper", "purpur") +} + +hangarPublish { + publications.register("plugin") { + version.set(rootProject.version as String) + + id.set(rootProject.name) + + channel.set(if (isSnapshot) "Beta" else "Release") + + changelog.set(description) + + apiKey.set(System.getenv("hangar_key")) + + platforms { + register(Platforms.PAPER) { + jar.set(file("${rootProject.rootDir}/jars/${rootProject.name}-${rootProject.version}.jar")) + platformVersions.set(versions) + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/badbones69/crazyauctions/Main.java b/paper/src/main/java/com/badbones69/crazyauctions/Main.java similarity index 100% rename from src/main/java/com/badbones69/crazyauctions/Main.java rename to paper/src/main/java/com/badbones69/crazyauctions/Main.java diff --git a/src/main/java/com/badbones69/crazyauctions/Methods.java b/paper/src/main/java/com/badbones69/crazyauctions/Methods.java similarity index 100% rename from src/main/java/com/badbones69/crazyauctions/Methods.java rename to paper/src/main/java/com/badbones69/crazyauctions/Methods.java diff --git a/src/main/java/com/badbones69/crazyauctions/api/Category.java b/paper/src/main/java/com/badbones69/crazyauctions/api/Category.java similarity index 100% rename from src/main/java/com/badbones69/crazyauctions/api/Category.java rename to paper/src/main/java/com/badbones69/crazyauctions/api/Category.java diff --git a/src/main/java/com/badbones69/crazyauctions/api/CrazyAuctions.java b/paper/src/main/java/com/badbones69/crazyauctions/api/CrazyAuctions.java similarity index 100% rename from src/main/java/com/badbones69/crazyauctions/api/CrazyAuctions.java rename to paper/src/main/java/com/badbones69/crazyauctions/api/CrazyAuctions.java diff --git a/src/main/java/com/badbones69/crazyauctions/api/FileManager.java b/paper/src/main/java/com/badbones69/crazyauctions/api/FileManager.java similarity index 100% rename from src/main/java/com/badbones69/crazyauctions/api/FileManager.java rename to paper/src/main/java/com/badbones69/crazyauctions/api/FileManager.java diff --git a/src/main/java/com/badbones69/crazyauctions/api/Messages.java b/paper/src/main/java/com/badbones69/crazyauctions/api/Messages.java similarity index 100% rename from src/main/java/com/badbones69/crazyauctions/api/Messages.java rename to paper/src/main/java/com/badbones69/crazyauctions/api/Messages.java diff --git a/src/main/java/com/badbones69/crazyauctions/api/ShopType.java b/paper/src/main/java/com/badbones69/crazyauctions/api/ShopType.java similarity index 100% rename from src/main/java/com/badbones69/crazyauctions/api/ShopType.java rename to paper/src/main/java/com/badbones69/crazyauctions/api/ShopType.java diff --git a/src/main/java/com/badbones69/crazyauctions/api/Version.java b/paper/src/main/java/com/badbones69/crazyauctions/api/Version.java similarity index 100% rename from src/main/java/com/badbones69/crazyauctions/api/Version.java rename to paper/src/main/java/com/badbones69/crazyauctions/api/Version.java diff --git a/src/main/java/com/badbones69/crazyauctions/api/enums/CancelledReason.java b/paper/src/main/java/com/badbones69/crazyauctions/api/enums/CancelledReason.java similarity index 100% rename from src/main/java/com/badbones69/crazyauctions/api/enums/CancelledReason.java rename to paper/src/main/java/com/badbones69/crazyauctions/api/enums/CancelledReason.java diff --git a/src/main/java/com/badbones69/crazyauctions/api/events/AuctionBuyEvent.java b/paper/src/main/java/com/badbones69/crazyauctions/api/events/AuctionBuyEvent.java similarity index 100% rename from src/main/java/com/badbones69/crazyauctions/api/events/AuctionBuyEvent.java rename to paper/src/main/java/com/badbones69/crazyauctions/api/events/AuctionBuyEvent.java diff --git a/src/main/java/com/badbones69/crazyauctions/api/events/AuctionCancelledEvent.java b/paper/src/main/java/com/badbones69/crazyauctions/api/events/AuctionCancelledEvent.java similarity index 100% rename from src/main/java/com/badbones69/crazyauctions/api/events/AuctionCancelledEvent.java rename to paper/src/main/java/com/badbones69/crazyauctions/api/events/AuctionCancelledEvent.java diff --git a/src/main/java/com/badbones69/crazyauctions/api/events/AuctionExpireEvent.java b/paper/src/main/java/com/badbones69/crazyauctions/api/events/AuctionExpireEvent.java similarity index 100% rename from src/main/java/com/badbones69/crazyauctions/api/events/AuctionExpireEvent.java rename to paper/src/main/java/com/badbones69/crazyauctions/api/events/AuctionExpireEvent.java diff --git a/src/main/java/com/badbones69/crazyauctions/api/events/AuctionListEvent.java b/paper/src/main/java/com/badbones69/crazyauctions/api/events/AuctionListEvent.java similarity index 100% rename from src/main/java/com/badbones69/crazyauctions/api/events/AuctionListEvent.java rename to paper/src/main/java/com/badbones69/crazyauctions/api/events/AuctionListEvent.java diff --git a/src/main/java/com/badbones69/crazyauctions/api/events/AuctionNewBidEvent.java b/paper/src/main/java/com/badbones69/crazyauctions/api/events/AuctionNewBidEvent.java similarity index 100% rename from src/main/java/com/badbones69/crazyauctions/api/events/AuctionNewBidEvent.java rename to paper/src/main/java/com/badbones69/crazyauctions/api/events/AuctionNewBidEvent.java diff --git a/src/main/java/com/badbones69/crazyauctions/api/events/AuctionWinBidEvent.java b/paper/src/main/java/com/badbones69/crazyauctions/api/events/AuctionWinBidEvent.java similarity index 100% rename from src/main/java/com/badbones69/crazyauctions/api/events/AuctionWinBidEvent.java rename to paper/src/main/java/com/badbones69/crazyauctions/api/events/AuctionWinBidEvent.java diff --git a/src/main/java/com/badbones69/crazyauctions/controllers/DupePatch.java b/paper/src/main/java/com/badbones69/crazyauctions/controllers/DupePatch.java similarity index 100% rename from src/main/java/com/badbones69/crazyauctions/controllers/DupePatch.java rename to paper/src/main/java/com/badbones69/crazyauctions/controllers/DupePatch.java diff --git a/src/main/java/com/badbones69/crazyauctions/controllers/GUI.java b/paper/src/main/java/com/badbones69/crazyauctions/controllers/GUI.java similarity index 100% rename from src/main/java/com/badbones69/crazyauctions/controllers/GUI.java rename to paper/src/main/java/com/badbones69/crazyauctions/controllers/GUI.java diff --git a/src/main/java/com/badbones69/crazyauctions/currency/CurrencyManager.java b/paper/src/main/java/com/badbones69/crazyauctions/currency/CurrencyManager.java similarity index 100% rename from src/main/java/com/badbones69/crazyauctions/currency/CurrencyManager.java rename to paper/src/main/java/com/badbones69/crazyauctions/currency/CurrencyManager.java diff --git a/src/main/java/com/badbones69/crazyauctions/currency/Vault.java b/paper/src/main/java/com/badbones69/crazyauctions/currency/Vault.java similarity index 100% rename from src/main/java/com/badbones69/crazyauctions/currency/Vault.java rename to paper/src/main/java/com/badbones69/crazyauctions/currency/Vault.java diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/CrazyAuctions.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/CrazyAuctions.java new file mode 100644 index 0000000..de1e841 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/CrazyAuctions.java @@ -0,0 +1,55 @@ +package com.badbones69.crazyauctions; + +import com.badbones69.crazyauctions.api.CrazyManager; +import com.badbones69.crazyauctions.api.frame.PaperCore; +import com.badbones69.crazyauctions.api.frame.command.CommandManager; +import com.badbones69.crazyauctions.commands.inventories.AuctionInventoryClick; +import com.badbones69.crazyauctions.events.DataListener; +import org.bukkit.plugin.java.JavaPlugin; + +public class CrazyAuctions extends JavaPlugin { + + private final ApiManager apiManager; + private final PaperCore paperCore; + private CommandManager commandManager; + + private CrazyManager crazyManager; + + public CrazyAuctions(ApiManager apiManager, PaperCore paperCore) { + this.apiManager = apiManager; + this.paperCore = paperCore; + } + + @Override + public void onEnable() { + this.commandManager = CommandManager.create(); + + this.crazyManager = new CrazyManager(); + this.crazyManager.load(true); + + getServer().getPluginManager().registerEvents(new DataListener(), this); + getServer().getPluginManager().registerEvents(new AuctionInventoryClick(), this); + + } + + @Override + public void onDisable() { + if (this.crazyManager != null) this.crazyManager.stop(); + } + + public ApiManager getApiManager() { + return this.apiManager; + } + + public PaperCore getPaperCore() { + return this.paperCore; + } + + public CommandManager getCommandManager() { + return this.commandManager; + } + + public CrazyManager getCrazyManager() { + return this.crazyManager; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/CrazyStarter.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/CrazyStarter.java new file mode 100644 index 0000000..700825f --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/CrazyStarter.java @@ -0,0 +1,30 @@ +package com.badbones69.crazyauctions; + +import com.badbones69.crazyauctions.api.frame.PaperCore; +import io.papermc.paper.plugin.bootstrap.BootstrapContext; +import io.papermc.paper.plugin.bootstrap.PluginBootstrap; +import io.papermc.paper.plugin.bootstrap.PluginProviderContext; +import org.bukkit.Bukkit; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; +import com.badbones69.crazyauctions.config.types.PluginConfig; + +@SuppressWarnings("ALL") +public class CrazyStarter implements PluginBootstrap { + + private ApiManager apiManager; + + @Override + public void bootstrap(@NotNull BootstrapContext context) { + this.apiManager = new ApiManager(context.getDataDirectory()); + this.apiManager.load(); + } + + @Override + public @NotNull JavaPlugin createPlugin(@NotNull PluginProviderContext context) { + PaperCore paperCore = new PaperCore(context.getDataDirectory(), Bukkit.getConsoleSender(), ApiManager.getPluginConfig().getProperty(PluginConfig.COMMAND_PREFIX), ApiManager.getPluginConfig().getProperty(PluginConfig.CONSOLE_PREFIX)); + paperCore.enable(); + + return new CrazyAuctions(this.apiManager, paperCore); + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/CrazyManager.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/CrazyManager.java new file mode 100644 index 0000000..884856d --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/CrazyManager.java @@ -0,0 +1,34 @@ +package com.badbones69.crazyauctions.api; + +import com.badbones69.crazyauctions.CrazyAuctions; +import com.badbones69.crazyauctions.storage.types.StorageManager; +import org.bukkit.plugin.java.JavaPlugin; + +public class CrazyManager { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + private StorageManager storageManager; + + public void load(boolean serverStart) { + if (serverStart) { + this.storageManager = new StorageManager(); + + this.storageManager.init(); + } + } + + public void reload() { + if (this.plugin.getApiManager() != null) this.plugin.getApiManager().reload(); + + if (this.storageManager.getUserManager() != null) this.storageManager.getUserManager().save(false); + } + + public void stop() { + + } + + public StorageManager getStorageManager() { + return this.storageManager; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/enums/Permissions.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/enums/Permissions.java new file mode 100644 index 0000000..7f2b613 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/enums/Permissions.java @@ -0,0 +1,38 @@ +package com.badbones69.crazyauctions.api.enums; + +import org.bukkit.permissions.PermissionDefault; + +public enum Permissions { + + PLAYER_HELP("player.help", "Gives access to the help command.", PermissionDefault.TRUE); + + private final String node; + private final String description; + private final PermissionDefault permissionDefault; + + Permissions(String node, String description, PermissionDefault permissionDefault) { + this.node = node; + this.description = description; + this.permissionDefault = permissionDefault; + } + + public String getNode() { + return this.node; + } + + public String getDescription() { + return this.description; + } + + public PermissionDefault getPermissionDefault() { + return this.permissionDefault; + } + + public String getBuiltPermission(String action) { + return "crazyauctions." + action + "." + this.node; + } + + public String getBuiltPermission() { + return "crazyauctions.command." + this.node; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/enums/support/DataSupport.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/enums/support/DataSupport.java new file mode 100644 index 0000000..affcc65 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/enums/support/DataSupport.java @@ -0,0 +1,19 @@ +package com.badbones69.crazyauctions.api.enums.support; + +import com.badbones69.crazyauctions.storage.interfaces.UserManager; +import com.badbones69.crazyauctions.storage.types.file.yaml.YamlUserManager; + +public enum DataSupport { + + yaml(YamlUserManager.class); + + private final Class classObject; + + DataSupport(Class classObject) { + this.classObject = classObject; + } + + public Class getClassObject() { + return this.classObject; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionAddEvent.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionAddEvent.java new file mode 100644 index 0000000..ca70dfc --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionAddEvent.java @@ -0,0 +1,62 @@ +package com.badbones69.crazyauctions.api.events; + +import com.badbones69.crazyauctions.CrazyAuctions; +import com.badbones69.crazyauctions.api.manager.interfaces.AuctionItem; +import com.badbones69.crazyauctions.api.manager.objects.AuctionHouse; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; +import java.util.UUID; + +/** + * Description: This event is fired when an item is added to an auction house. + */ +public class AuctionAddEvent extends Event { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + private static final HandlerList handlerList = new HandlerList(); + + private final UUID uuid; + private final Player player; + private final AuctionItem auctionItem; + private final AuctionHouse auctionHouse; + + /** + * A constructor to include values for a bid event. + * + * @param uuid the uuid of the player who placed the bid. + * @param auctionHouse the auction house the item is being added to. + * @param auctionItem the auction item being added. + */ + public AuctionAddEvent(UUID uuid, AuctionHouse auctionHouse, AuctionItem auctionItem) { + this.uuid = uuid; + this.player = this.plugin.getServer().getPlayer(uuid); + this.auctionHouse = auctionHouse; + this.auctionItem = auctionItem; + } + + public AuctionItem getAuctionItem() { + return auctionItem; + } + + public AuctionHouse getAuctionHouse() { + return auctionHouse; + } + + public Player getPlayer() { + return this.player; + } + + public UUID getUUID() { + return this.uuid; + } + + @Override + public @NotNull HandlerList getHandlers() { + return handlerList; + } + +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionBidEvent.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionBidEvent.java new file mode 100644 index 0000000..c928dbd --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionBidEvent.java @@ -0,0 +1,65 @@ +package com.badbones69.crazyauctions.api.events; + +import com.badbones69.crazyauctions.CrazyAuctions; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; +import java.util.UUID; + +/** + * Description: This event is fired when a player bids on an auction. + */ +public class AuctionBidEvent extends Event { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + private static final HandlerList handlerList = new HandlerList(); + + private final UUID uuid; + private final Player player; + + private final ItemStack item; + + private final long bidPrice; + + /** + * A constructor to include values for a bid event. + * + * @param uuid the uuid of the player who placed the bid. + * @param item the item that was bid on. + * @param bidPrice the amount of money that was bid. + */ + public AuctionBidEvent(UUID uuid, ItemStack item, long bidPrice) { + this.uuid = uuid; + + this.player = this.plugin.getServer().getPlayer(uuid); + + this.item = item; + + this.bidPrice = bidPrice; + } + + public ItemStack getBidItem() { + return this.item; + } + + public long getBidPrice() { + return this.bidPrice; + } + + public Player getPlayer() { + return this.player; + } + + public UUID getUUID() { + return this.uuid; + } + + @Override + public @NotNull HandlerList getHandlers() { + return handlerList; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionBuyEvent.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionBuyEvent.java new file mode 100644 index 0000000..3a37ddb --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionBuyEvent.java @@ -0,0 +1,65 @@ +package com.badbones69.crazyauctions.api.events; + +import com.badbones69.crazyauctions.CrazyAuctions; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; +import java.util.UUID; + +/** + * Description: This event is fired when a player buys an item. + */ +public class AuctionBuyEvent extends Event { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + private static final HandlerList handlerList = new HandlerList(); + + private final UUID uuid; + private final Player player; + + private final ItemStack item; + + private final long price; + + /** + * A constructor to include values for a buy event. + * + * @param uuid the uuid of the player who purchased the item. + * @param item the item that was purchased. + * @param price the amount of money used to buy. + */ + public AuctionBuyEvent(UUID uuid, ItemStack item, long price) { + this.uuid = uuid; + + this.player = this.plugin.getServer().getPlayer(uuid); + + this.item = item; + + this.price = price; + } + + public ItemStack getWinningItem() { + return this.item; + } + + public long getBuyPrice() { + return this.price; + } + + public Player getPlayer() { + return this.player; + } + + public UUID getUUID() { + return this.uuid; + } + + @Override + public @NotNull HandlerList getHandlers() { + return handlerList; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionCancelEvent.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionCancelEvent.java new file mode 100644 index 0000000..8b3e87d --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionCancelEvent.java @@ -0,0 +1,82 @@ +package com.badbones69.crazyauctions.api.events; + +import com.badbones69.crazyauctions.CrazyAuctions; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; +import java.util.UUID; + +/** + * Description: This event is fired when an auction is cancelled. + */ +public class AuctionCancelEvent extends Event { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + private static final HandlerList handlerList = new HandlerList(); + + private final UUID uuid; + private final Player player; + private final OfflinePlayer offlinePlayer; + + private final ItemStack item; + + /** + * A constructor to include values for when an item is cancelled. + * + * @param uuid the uuid of the player whose item cancelled. + */ + public AuctionCancelEvent(UUID uuid, ItemStack item) { + this.uuid = uuid; + + this.player = this.plugin.getServer().getPlayer(uuid); + + this.offlinePlayer = this.plugin.getServer().getOfflinePlayer(uuid); + + this.item = item; + } + + /** + * @return the expired item. + */ + public ItemStack getExpiredItem() { + return this.item; + } + + /** + * Only use this when the player is online. + * + * @return the online player. + */ + public Player getPlayer() { + return this.player; + } + + /** + * Only use this when the player is offline. + * + * @return the offline player. + */ + public OfflinePlayer getOfflinePlayer() { + return this.offlinePlayer; + } + + /** + * @return the player's uuid. + */ + public UUID getUUID() { + return this.uuid; + } + + /** + * @return the handler list. + */ + @Override + public @NotNull HandlerList getHandlers() { + return handlerList; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionExpireEvent.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionExpireEvent.java new file mode 100644 index 0000000..62e1cd2 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionExpireEvent.java @@ -0,0 +1,55 @@ +package com.badbones69.crazyauctions.api.events; + +import com.badbones69.crazyauctions.CrazyAuctions; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; +import java.util.UUID; + +/** + * Description: This event is fired when an auction expires. + */ +public class AuctionExpireEvent extends Event { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + private static final HandlerList handlerList = new HandlerList(); + + private final UUID uuid; + private final Player player; + + private final ItemStack item; + + /** + * A constructor to include values for when an item expired. + * + * @param uuid the uuid of the player whose auction expired. + */ + public AuctionExpireEvent(UUID uuid, ItemStack item) { + this.uuid = uuid; + + this.player = this.plugin.getServer().getPlayer(uuid); + + this.item = item; + } + + public ItemStack getExpiredItem() { + return this.item; + } + + public Player getPlayer() { + return this.player; + } + + public UUID getUUID() { + return this.uuid; + } + + @Override + public @NotNull HandlerList getHandlers() { + return handlerList; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionListEvent.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionListEvent.java new file mode 100644 index 0000000..43a747c --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionListEvent.java @@ -0,0 +1,65 @@ +package com.badbones69.crazyauctions.api.events; + +import com.badbones69.crazyauctions.CrazyAuctions; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; +import java.util.UUID; + +/** + * Description: This event is fired when a player lists an item. + */ +public class AuctionListEvent extends Event { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + private static final HandlerList handlerList = new HandlerList(); + + private final UUID uuid; + private final Player player; + + private final ItemStack item; + + private final long bidPrice; + + /** + * A constructor to include values for a bid event. + * + * @param uuid the uuid of the player who placed the bid. + * @param item the item that was bid on. + * @param bidPrice the amount of money that was bid. + */ + public AuctionListEvent(UUID uuid, ItemStack item, long bidPrice) { + this.uuid = uuid; + + this.player = this.plugin.getServer().getPlayer(uuid); + + this.item = item; + + this.bidPrice = bidPrice; + } + + public ItemStack getBidItem() { + return this.item; + } + + public long getBidPrice() { + return this.bidPrice; + } + + public Player getPlayer() { + return this.player; + } + + public UUID getUUID() { + return this.uuid; + } + + @Override + public @NotNull HandlerList getHandlers() { + return handlerList; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionWinEvent.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionWinEvent.java new file mode 100644 index 0000000..8dd2ba3 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/events/AuctionWinEvent.java @@ -0,0 +1,65 @@ +package com.badbones69.crazyauctions.api.events; + +import com.badbones69.crazyauctions.CrazyAuctions; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; +import java.util.UUID; + +/** + * Description: This event is fired when an auction has a winner. + */ +public class AuctionWinEvent extends Event { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + private static final HandlerList handlerList = new HandlerList(); + + private final UUID uuid; + private final Player player; + + private final ItemStack item; + + private final long price; + + /** + * A constructor to include values for a win event. + * + * @param uuid the uuid of the player who won the bid. + * @param item the item that was won. + * @param price the amount of money that was bid. + */ + public AuctionWinEvent(UUID uuid, ItemStack item, long price) { + this.uuid = uuid; + + this.player = this.plugin.getServer().getPlayer(uuid); + + this.item = item; + + this.price = price; + } + + public ItemStack getWinningItem() { + return this.item; + } + + public long getWinningPrice() { + return this.price; + } + + public Player getPlayer() { + return this.player; + } + + public UUID getUUID() { + return this.uuid; + } + + @Override + public @NotNull HandlerList getHandlers() { + return handlerList; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/ItemUtils.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/ItemUtils.java new file mode 100644 index 0000000..98e128e --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/ItemUtils.java @@ -0,0 +1,27 @@ +package com.badbones69.crazyauctions.api.frame; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +public class ItemUtils { + + private final Material skull = Material.PLAYER_HEAD; + + public ItemStack skull() { + return new ItemStack(skull); + } + + public boolean isPlayerSkull(Material itemStack) { + return itemStack != skull; + } + + private String getVersion() { + String version = Bukkit.getServer().getClass().getPackage().getName(); + return version.substring(version.lastIndexOf('.') + 1); + } + + public Class craftClass(String name) throws ClassNotFoundException { + return Class.forName("org.bukkit.craftbukkit." + getVersion() + "." + name); + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/PaperCore.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/PaperCore.java new file mode 100644 index 0000000..bf43192 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/PaperCore.java @@ -0,0 +1,140 @@ +package com.badbones69.crazyauctions.api.frame; + +import com.badbones69.crazyauctions.ApiManager; +import com.badbones69.crazyauctions.config.types.Locale; +import com.badbones69.crazyauctions.config.types.PluginConfig; +import com.badbones69.crazyauctions.frame.CrazyCore; +import com.badbones69.crazyauctions.frame.storage.FileHandler; +import net.kyori.adventure.audience.Audience; +import java.nio.file.Path; + +public class PaperCore extends CrazyCore { + + private final Path path; + private final Audience audience; + private final FileHandler fileHandler; + private final String prefix; + private final String consolePrefix; + + public PaperCore(Path path, Audience audience, String prefix, String consolePrefix) { + // Create directory. + this.path = path; + this.path.toFile().mkdir(); + + this.audience = audience; + this.prefix = prefix; + this.consolePrefix = consolePrefix; + + this.fileHandler = new FileHandler(); + } + + @Override + public void enable() { + super.enable(); + } + + @Override + public void disable() { + super.disable(); + } + + @Override + public Path getDirectory() { + return this.path; + } + + @Override + public String getPrefix() { + return this.prefix; + } + + @Override + public String getConsolePrefix() { + return this.consolePrefix; + } + + @Override + public FileHandler getFileHandler() { + return this.fileHandler; + } + + @Override + public Audience adventure() { + return this.audience; + } + + @Override + public String commandTooFewArgs() { + return ApiManager.getLocale().getProperty(Locale.NOT_ENOUGH_ARGS); + } + + @Override + public String commandTooManyArgs() { + return ApiManager.getLocale().getProperty(Locale.TOO_MANY_ARGS); + } + + @Override + public String commandOptionalMsg() { + return ApiManager.getLocale().getProperty(Locale.OPTIONAL_ARGUMENT); + } + + @Override + public String commandRequiredMsg() { + return ApiManager.getLocale().getProperty(Locale.REQUIRED_ARGUMENT); + } + + @Override + public String commandRequirementNotPlayer() { + return ApiManager.getLocale().getProperty(Locale.MUST_BE_PLAYER); + } + + @Override + public String commandRequirementNoPermission() { + return ApiManager.getLocale().getProperty(Locale.NO_PERMISSION); + } + + @Override + public String commandHelpHeader() { + return ApiManager.getPluginConfig().getProperty(PluginConfig.HELP_PAGE_HEADER); + } + + @Override + public String commandHelpFooter() { + return ApiManager.getPluginConfig().getProperty(PluginConfig.HELP_PAGE_FOOTER); + } + + @Override + public String commandInvalidPage() { + return ApiManager.getPluginConfig().getProperty(PluginConfig.INVALID_HELP_PAGE); + } + + @Override + public String commandPageFormat() { + return ApiManager.getPluginConfig().getProperty(PluginConfig.HELP_PAGE_FORMAT); + } + + @Override + public String commandHoverFormat() { + return ApiManager.getPluginConfig().getProperty(PluginConfig.HELP_PAGE_HOVER_FORMAT); + } + + @Override + public String commandHoverAction() { + return ApiManager.getPluginConfig().getProperty(PluginConfig.HELP_PAGE_HOVER_ACTION); + } + + @Override + public String commandNavigationText() { + return ApiManager.getPluginConfig().getProperty(PluginConfig.HELP_PAGE_GO_TO_PAGE); + } + + @Override + public String commandNavigationNextButton() { + return ApiManager.getPluginConfig().getProperty(PluginConfig.HELP_PAGE_NEXT); + } + + @Override + public String commandNavigationBackButton() { + return ApiManager.getPluginConfig().getProperty(PluginConfig.HELP_PAGE_BACK); + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/PaperUtils.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/PaperUtils.java new file mode 100644 index 0000000..43e1bf3 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/PaperUtils.java @@ -0,0 +1,25 @@ +package com.badbones69.crazyauctions.api.frame; + +public class PaperUtils { + + private static boolean hasClass(String className) { + try { + Class.forName(className); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } + + public static boolean isSpigot() { + return hasClass("org.spigotmc.SpigotConfig") && !hasClass("io.papermc.paper.configuration.Configuration") || !hasClass("com.destroystokyo.paper.PaperConfig"); + } + + public static boolean isPaper() { + return hasClass("io.papermc.paper.configuration.Configuration") || hasClass("com.destroystokyo.paper.PaperConfig"); + } + + public static boolean isFolia() { + return hasClass("io.papermc.paper.threadedregions.RegionizedServer"); + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/adapters/LocationTypeAdapter.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/adapters/LocationTypeAdapter.java new file mode 100644 index 0000000..da9219f --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/adapters/LocationTypeAdapter.java @@ -0,0 +1,52 @@ +package com.badbones69.crazyauctions.api.frame.adapters; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import org.bukkit.Bukkit; +import org.bukkit.Location; + +import java.io.IOException; + +public class LocationTypeAdapter extends TypeAdapter { + + @Override + public void write(JsonWriter out, Location location) throws IOException { + out.beginObject(); + out.name("world").value(location.getWorld().getName()); + out.name("x").value(location.getX()); + out.name("y").value(location.getY()); + out.name("z").value(location.getZ()); + out.name("yaw").value(location.getYaw()); + out.name("pitch").value(location.getPitch()); + out.endObject(); + } + + @Override + public Location read(JsonReader reader) throws IOException { + reader.beginObject(); + + String worldName = null; + double x = 0, y = 0, z = 0; + float yaw = 0, pitch = 0; + + while (reader.hasNext()) { + String name = reader.nextName(); + + switch (name) { + case "world" -> worldName = reader.nextString(); + case "x" -> x = reader.nextDouble(); + case "y" -> y = reader.nextDouble(); + case "z" -> z = reader.nextDouble(); + case "yaw" -> yaw = (float) reader.nextDouble(); + case "pitch" -> pitch = (float) reader.nextDouble(); + default -> reader.skipValue(); + } + } + + reader.endObject(); + + assert worldName != null; + return new Location(Bukkit.getWorld(worldName), x, y, z, yaw, pitch); + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/CommandContext.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/CommandContext.java new file mode 100644 index 0000000..a5dd49d --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/CommandContext.java @@ -0,0 +1,268 @@ +package com.badbones69.crazyauctions.api.frame.command; + +import com.badbones69.crazyauctions.ApiManager; +import com.badbones69.crazyauctions.api.frame.command.builders.CommandActor; +import com.badbones69.crazyauctions.api.frame.command.builders.args.CommandArgs; +import com.badbones69.crazyauctions.config.types.Locale; +import com.badbones69.crazyauctions.frame.utils.AdventureUtils; +import com.badbones69.crazyauctions.support.PlaceholderSupport; +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.permissions.Permission; +import java.util.Collections; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +public class CommandContext implements CommandActor, CommandArgs { + + private final Audience audience; + private final List args; + private String label; + + private Player player; + + public CommandContext(Audience audience, String label, List args) { + this.audience = audience; + + if (audience instanceof Player) { + this.player = (Player) audience; + } + + this.label = label; + this.args = args; + } + + @Override + public void reply(String message) { + if (message.isBlank() || message.isEmpty()) return; + + Component component = AdventureUtils.parse(message); + + this.audience.sendMessage(component); + } + + @Override + public void reply(boolean hasPrefix, String prefix, String message) { + if (message.isBlank() || message.isEmpty()) return; + + if (hasPrefix) { + Component component = AdventureUtils.parse(prefix).append(AdventureUtils.parse(prefix)); + + this.audience.sendMessage(component); + + return; + } + + Component component = AdventureUtils.parse(message); + + this.audience.sendMessage(component); + } + + @Override + public void reply(boolean hasPrefix, String prefix, Component component) { + if (hasPrefix) { + this.audience.sendMessage(AdventureUtils.parse(prefix).append(component)); + return; + } + + this.audience.sendMessage(component); + } + + @Override + public void reply(Component component) { + this.audience.sendMessage(component); + } + + @Override + public void send(Audience audience, String message) { + if (message.isBlank() || message.isEmpty()) return; + + Component component = AdventureUtils.parse(message); + + audience.sendMessage(component); + } + + @Override + public void send(Audience audience, Component component) { + audience.sendMessage(component); + } + + @Override + public void send(Audience audience, String message, String prefix, boolean hasPrefix) { + if (hasPrefix) { + audience.sendMessage(AdventureUtils.parse(prefix).append(AdventureUtils.parse(message))); + return; + } + + send(audience, message); + } + + @Override + public void send(Audience audience, Component message, String prefix, boolean hasPrefix) { + if (hasPrefix) { + audience.sendMessage(AdventureUtils.parse(prefix).append(message)); + return; + } + + send(audience, message); + } + + @Override + public Audience getSender() { + return this.audience; + } + + @Override + public boolean isPlayer() { + return getPlayer() != null; + } + + @Override + public Player getPlayer() { + return this.player; + } + + @Override + public boolean hasPermission(Permission permission) { + return this.player.hasPermission(permission); + } + + @Override + public boolean hasPermission(String rawPermission) { + return this.player.hasPermission(rawPermission); + } + + @Override + public void setLabel(String label) { + this.label = label; + } + + @Override + public String getLabel() { + return this.label; + } + + public List getArgs() { + return Collections.unmodifiableList(this.args); + } + + @Override + public void removeArgs(int arg) { + this.args.remove(arg); + } + + @Override + public int getArgAsInt(int index, boolean notifySender) { + Integer value = null; + + try { + value = Integer.parseInt(this.args.get(index)); + } catch (NumberFormatException exception) { + if (notifySender) reply(PlaceholderSupport.setPlaceholders(ApiManager.getLocale().getProperty(Locale.INVALID_SYNTAX) + .replaceAll("\\{value}", this.args.get(index)) + .replaceAll("\\{action}", "number"))); + } + + if (value != null) return value; + + return 1; + } + + @Override + public long getArgAsLong(int index, boolean notifySender) { + Long value = null; + + try { + value = Long.parseLong(this.args.get(index)); + } catch (NumberFormatException exception) { + if (notifySender) reply(PlaceholderSupport.setPlaceholders(ApiManager.getLocale().getProperty(Locale.INVALID_SYNTAX) + .replaceAll("\\{value}", this.args.get(index)) + .replaceAll("\\{action}", "number"))); + } + + if (value != null) return value; + + return 1L; + } + + @Override + public double getArgAsDouble(int index, boolean notifySender) { + Double value = null; + + try { + value = Double.parseDouble(this.args.get(index)); + } catch (NumberFormatException exception) { + if (notifySender) reply(PlaceholderSupport.setPlaceholders(ApiManager.getLocale().getProperty(Locale.INVALID_SYNTAX) + .replaceAll("\\{value}", this.args.get(index)) + .replaceAll("\\{action}", "number"))); + } + + if (value != null) return value; + + return 0.1; + } + + @Override + public boolean getArgAsBoolean(int index, boolean notifySender) { + String lowercase = this.args.get(index).toLowerCase(); + + switch (lowercase) { + case "true", "on", "1" -> { + return true; + } + case "false", "off", "0" -> { + return false; + } + default -> { + if (notifySender) reply(PlaceholderSupport.setPlaceholders(ApiManager.getLocale().getProperty(Locale.INVALID_SYNTAX) + .replaceAll("\\{value}", this.args.get(index).toLowerCase()) + .replaceAll("\\{action}", "boolean"))); + + return false; + } + } + } + + @Override + public float getArgAsFloat(int index, boolean notifySender) { + Float value = null; + + try { + value = Float.parseFloat(this.args.get(index)); + } catch (NumberFormatException exception) { + if (notifySender) reply(PlaceholderSupport.setPlaceholders(ApiManager.getLocale().getProperty(Locale.INVALID_SYNTAX) + .replaceAll("\\{value}", this.args.get(index)) + .replaceAll("\\{action}", "number"))); + } + + if (value != null) return value; + + return 1F; + } + + @Override + public Player getArgAsPlayer(int index, boolean notifySender) { + Player player = Bukkit.getServer().getPlayer(this.args.get(index)); + + if (player == null) { + if (notifySender) reply(PlaceholderSupport.setPlaceholders(ApiManager.getLocale().getProperty(Locale.INVALID_SYNTAX) + .replaceAll("\\{value}", this.args.get(index)) + .replaceAll("\\{action}", "player"))); + + return null; + } + + return player; + } + + @Override + public OfflinePlayer getArgAsOfflinePlayer(int index) { + CompletableFuture future = CompletableFuture.supplyAsync(() -> Bukkit.getServer().getOfflinePlayer(this.args.get(index))).thenApply(OfflinePlayer::getUniqueId); + + return Bukkit.getServer().getOfflinePlayer(future.join()); + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/CommandEngine.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/CommandEngine.java new file mode 100644 index 0000000..b5a8fee --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/CommandEngine.java @@ -0,0 +1,164 @@ +package com.badbones69.crazyauctions.api.frame.command; + +import com.badbones69.crazyauctions.CrazyAuctions; +import com.badbones69.crazyauctions.api.frame.command.builders.CommandDataEntry; +import com.badbones69.crazyauctions.api.frame.command.builders.args.Argument; +import com.badbones69.crazyauctions.frame.CrazyCore; +import com.badbones69.crazyauctions.frame.utils.AdventureUtils; +import com.badbones69.crazyauctions.support.PlaceholderSupport; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.event.HoverEvent; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; +import java.util.*; + +public abstract class CommandEngine extends Command { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + private final LinkedList labels = new LinkedList<>(); + public final LinkedList requiredArgs = new LinkedList<>(); + public final LinkedList optionalArgs = new LinkedList<>(); + + private final HashMap commandData = new HashMap<>(); + + protected CommandEngine(@NotNull String name, @NotNull String description, @NotNull String usageMessage, @NotNull List aliases) { + super(name, description, usageMessage, aliases); + } + + public void execute(CommandContext context, String[] args) { + perform(context, args); + } + + public void execute(CommandContext context) { + StringBuilder label = new StringBuilder(context.getLabel()); + + if (!context.getArgs().isEmpty()) { + for (CommandEngine engine : this.plugin.getCommandManager().getClasses()) { + boolean isPresent = context.getArgs().stream().findFirst().isPresent(); + + if (isPresent) { + label.append(" ").append(context.getArgs().get(0)); + + context.removeArgs(0); + context.setLabel(label.toString()); + + engine.execute(context); + return; + } + } + } + + if (!validate(context)) return; + + perform(context, new String[0]); + } + + @Override + public boolean execute(@NotNull CommandSender sender, @NotNull String label, @NotNull String[] args) { + List arguments = Arrays.asList(args); + + CommandContext context = new CommandContext( + sender, + label, + arguments + ); + + if (arguments.isEmpty()) { + execute(context); + return true; + } + + execute(context, args); + + return true; + } + + protected abstract void perform(CommandContext context, String[] args); + + private boolean validate(CommandContext context) { + if (context.getArgs().size() < this.requiredArgs.size()) { + context.reply(CrazyCore.api().commandTooFewArgs()); + sendValidFormat(context); + return false; + } + + if (context.getArgs().size() > this.requiredArgs.size() + this.optionalArgs.size()) { + context.reply(CrazyCore.api().commandTooManyArgs()); + sendValidFormat(context); + return false; + } + + return true; + } + + private void sendValidFormat(CommandContext context) { + ArrayList arguments = new ArrayList<>(); + + arguments.addAll(this.requiredArgs); + arguments.addAll(this.optionalArgs); + + this.requiredArgs.sort(Comparator.comparing(Argument::order)); + + if (context.isPlayer()) { + StringBuilder format = new StringBuilder("/" + "crazycrates:" + getLabel()); + + TextComponent.@NotNull Builder emptyComponent = Component.text(); + + StringBuilder types = new StringBuilder(); + + for (Argument arg : arguments) { + String value = this.optionalArgs.contains(arg) ? " (" + arg.name() + ") " : " <" + arg.name() + ">"; + + String msg = this.optionalArgs.contains(arg) ? CrazyCore.api().commandOptionalMsg() : CrazyCore.api().commandRequiredMsg(); + + Component argComponent = AdventureUtils.parse(value).hoverEvent(HoverEvent.showText(AdventureUtils.parse(PlaceholderSupport.setPlaceholders(msg)))).asComponent(); + + emptyComponent.append(argComponent); + + boolean isPresent = arg.argumentType().getPossibleValues().stream().findFirst().isPresent(); + + if (isPresent) types.append(" ").append(arg.argumentType().getPossibleValues().stream().findFirst().get()); + } + + TextComponent.@NotNull Builder finalComponent = emptyComponent + .hoverEvent(HoverEvent.showText(AdventureUtils.parse("Click me to insert into chat"))) + .clickEvent(ClickEvent.clickEvent(ClickEvent.Action.SUGGEST_COMMAND, format.append(types).toString())) + .append(emptyComponent.build()); + + context.reply(finalComponent.build()); + + return; + } + + StringBuilder format = new StringBuilder("/" + "crazycrates:" + getLabel()); + + for (Argument arg : arguments) { + String value = this.optionalArgs.contains(arg) ? "(" + arg.name() + ") " : "<" + arg.name() + "> "; + + format.append(value); + } + + context.reply(format.toString()); + } + + public List getLabels() { + return Collections.unmodifiableList(this.labels); + } + + public Map getCommandData() { + return Collections.unmodifiableMap(this.commandData); + } + + public List getRequiredArgs() { + return Collections.unmodifiableList(this.requiredArgs); + } + + public List getOptionalArgs() { + return Collections.unmodifiableList(this.optionalArgs); + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/CommandFlow.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/CommandFlow.java new file mode 100644 index 0000000..d8f80cd --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/CommandFlow.java @@ -0,0 +1,30 @@ +package com.badbones69.crazyauctions.api.frame.command; + +import com.badbones69.crazyauctions.api.frame.command.builders.CommandActor; +import com.badbones69.crazyauctions.api.frame.command.builders.CommandDataEntry; +import com.badbones69.crazyauctions.api.frame.command.builders.CommandHelpEntry; +import java.util.List; +import java.util.Map; + +public interface CommandFlow { + + void addCommand(CommandEngine engine); + + boolean hasCommand(String label); + + CommandHelpEntry generateCommandHelp(CommandActor actor); + + int defaultHelpPerPage(); + + void updateHelpPerPage(int newAmount); + + CommandDataEntry getCommand(String label); + + void removeCommand(String label); + + Map getCommands(); + + List getClasses(); + + List handleTabComplete(String[] args, CommandEngine engine); +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/CommandManager.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/CommandManager.java new file mode 100644 index 0000000..1618ac3 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/CommandManager.java @@ -0,0 +1,123 @@ +package com.badbones69.crazyauctions.api.frame.command; + +import com.badbones69.crazyauctions.api.frame.command.builders.CommandActor; +import com.badbones69.crazyauctions.api.frame.command.builders.CommandDataEntry; +import com.badbones69.crazyauctions.api.frame.command.builders.CommandHelpEntry; +import com.badbones69.crazyauctions.api.frame.command.builders.annotations.Hidden; +import com.badbones69.crazyauctions.api.frame.command.builders.args.Argument; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import java.util.*; + +public class CommandManager implements CommandFlow { + + private final HashMap commands = new HashMap<>(); + + private final LinkedList classes = new LinkedList<>(); + + private int defaultHelpPerPage = 10; + + public static CommandManager create() { + return new CommandManager(); + } + + @Override + public void addCommand(CommandEngine engine) { + // If the label already exists. We return! + if (hasCommand(engine.getLabel())) return; + + // Create data entry. + CommandDataEntry entry = new CommandDataEntry(); + + // Set visibility if annotation is present. + entry.setHidden(engine.getClass().isAnnotationPresent(Hidden.class)); + + if (entry.isHidden()) return; + + // Add to the hash-map & linked list! + this.commands.put(engine.getLabel(), entry); + this.classes.add(engine); + + // Add command to the server map! + Bukkit.getServer().getCommandMap().register("crazycrates", engine); + } + + @Override + public boolean hasCommand(String label) { + return this.commands.containsKey(label); + } + + @Override + public CommandHelpEntry generateCommandHelp(CommandActor actor) { + return new CommandHelpEntry(this, actor); + } + + @Override + public int defaultHelpPerPage() { + return this.defaultHelpPerPage; + } + + @Override + public void updateHelpPerPage(int newAmount) { + this.defaultHelpPerPage = newAmount; + } + + @Override + public CommandDataEntry getCommand(String label) { + if (hasCommand(label)) return this.commands.get(label); + + return null; + } + + @Override + public void removeCommand(String label) { + if (!hasCommand(label)) return; + + Command value = Bukkit.getServer().getCommandMap().getCommand(label); + + if (value != null && value.isRegistered()) value.unregister(Bukkit.getServer().getCommandMap()); + + this.commands.remove(label); + } + + @Override + public Map getCommands() { + return Collections.unmodifiableMap(this.commands); + } + + @Override + public List getClasses() { + return Collections.unmodifiableList(this.classes); + } + + @Override + public List handleTabComplete(String[] args, CommandEngine engine) { + List completions = Arrays.asList(args); + + if (completions.size() >= 1) { + int relativeIndex = this.classes.size(); + int argToComplete = completions.size() + 1 - relativeIndex; + if (engine.requiredArgs.size() >= argToComplete) { + ArrayList arguments = new ArrayList<>(); + + arguments.addAll(engine.requiredArgs); + arguments.addAll(engine.optionalArgs); + + ArrayList possibleValues = new ArrayList<>(); + + for (Argument argument : arguments) { + if (argument.order() == argToComplete) { + List possibleValuesArgs = argument.argumentType().getPossibleValues(); + + possibleValues = new ArrayList<>(possibleValuesArgs); + break; + } + } + + return possibleValues; + } + } + + return Collections.emptyList(); + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/CommandActor.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/CommandActor.java new file mode 100644 index 0000000..2b88bab --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/CommandActor.java @@ -0,0 +1,48 @@ +package com.badbones69.crazyauctions.api.frame.command.builders; + +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.text.Component; +import org.bukkit.entity.Player; +import org.bukkit.permissions.Permission; + +import java.util.List; + +public interface CommandActor { + + void reply(String message); + + void reply(boolean hasPrefix, String prefix, String message); + + void reply(boolean hasPrefix, String prefix, Component component); + + void reply(Component component); + + void send(Audience audience, String message); + + void send(Audience audience, Component component); + + void send(Audience audience, String message, String prefix, boolean hasPrefix); + + void send(Audience audience, Component message, String prefix, boolean hasPrefix); + + Audience getSender(); + + boolean isPlayer(); + + Player getPlayer(); + + boolean hasPermission(Permission permission); + + boolean hasPermission(String rawPermission); + + void setLabel(String alias); + + String getLabel(); + + List getArgs(); + + void removeArgs(int arg); + + //CommandHelpEntry getHelpEntry(); + +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/CommandDataEntry.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/CommandDataEntry.java new file mode 100644 index 0000000..1d9d28c --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/CommandDataEntry.java @@ -0,0 +1,14 @@ +package com.badbones69.crazyauctions.api.frame.command.builders; + +public class CommandDataEntry { + + private boolean isHidden = false; + + public void setHidden(boolean value) { + this.isHidden = value; + } + + public boolean isHidden() { + return this.isHidden; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/CommandHelpEntry.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/CommandHelpEntry.java new file mode 100644 index 0000000..8a33077 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/CommandHelpEntry.java @@ -0,0 +1,156 @@ +package com.badbones69.crazyauctions.api.frame.command.builders; + +import com.badbones69.crazyauctions.ApiManager; +import com.badbones69.crazyauctions.api.frame.command.CommandEngine; +import com.badbones69.crazyauctions.api.frame.command.CommandManager; +import com.badbones69.crazyauctions.api.frame.command.builders.args.Argument; +import com.badbones69.crazyauctions.api.frame.command.builders.other.ComponentBuilder; +import com.badbones69.crazyauctions.config.types.PluginConfig; +import com.badbones69.crazyauctions.frame.CrazyCore; +import com.badbones69.crazyauctions.support.PlaceholderSupport; +import net.kyori.adventure.text.event.ClickEvent; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Map; +import static com.badbones69.crazyauctions.frame.utils.AdventureUtils.hover; +import static com.badbones69.crazyauctions.frame.utils.AdventureUtils.send; + +public class CommandHelpEntry { + + private final CommandManager manager; + private final CommandActor actor; + + private int page = 1; + private int perPage; + private int totalPages; + private int totalResults; + private boolean lastPage; + + public CommandHelpEntry(CommandManager manager, CommandActor actor) { + this.manager = manager; + this.actor = actor; + + this.perPage = manager.defaultHelpPerPage(); + } + + public void showHelp() { + this.showHelp(this.actor); + } + + public void showHelp(CommandActor actor) { + int min = this.perPage * (this.page - 1); + int max = min + this.perPage; + + this.totalResults = this.manager.getCommands().size(); + + this.totalPages = this.totalResults / this.perPage; + + if (min >= this.totalResults) { + actor.reply(ApiManager.getPluginConfig().getProperty(PluginConfig.INVALID_HELP_PAGE).replaceAll("\\{page}", String.valueOf(page))); + return; + } + + Map entries = this.manager.getCommands(); + + for (int value = min; value < max; value++) { + if (this.totalResults - 1 < value) continue; + + CommandEngine command = this.manager.getClasses().get(value); + + CommandDataEntry dataEntry = entries.get(command.getLabel()); + + boolean isHidden = dataEntry.isHidden(); + + StringBuilder baseFormat = new StringBuilder("/" + command.getLabel()); + + String format = CrazyCore.api().commandPageFormat() + .replaceAll("\\{command}", baseFormat.toString()) + .replaceAll("\\{description}", command.getDescription()); + + // Only add aliases if the list isn't empty. + if (!command.getAliases().isEmpty()) baseFormat.append(" ").append(command.getLabels().get(0)); + + ArrayList arguments = new ArrayList<>(); + + arguments.addAll(command.getOptionalArgs()); + arguments.addAll(command.getRequiredArgs()); + + arguments.sort(Comparator.comparingInt(Argument::order)); + + if (actor.isPlayer()) { + StringBuilder types = new StringBuilder(); + + ComponentBuilder builder = new ComponentBuilder(); + + for (Argument arg : arguments) { + String argValue = command.optionalArgs.contains(arg) ? " (" + arg.name() + ") " : " <" + arg.name() + ">"; + + types.append(argValue); + } + + builder.setMessage(format.replaceAll("\\{args}", String.valueOf(types))); + + String hoverShit = baseFormat.append(types).toString(); + + String hoverFormat = CrazyCore.api().commandHoverFormat(); + + builder.hover(PlaceholderSupport.setPlaceholders(hoverFormat).replaceAll("\\{commands}", hoverShit)).click(hoverShit, ClickEvent.Action.valueOf(CrazyCore.api().commandHoverAction().toUpperCase())); + + actor.reply(builder.build()); + } + + String footer = CrazyCore.api().commandHelpFooter(); + + if (actor.isPlayer()) { + String text = CrazyCore.api().commandNavigationText(); + + if (page > 1) { + int number = page-1; + + hover(actor.getPlayer(), footer.replaceAll("\\{page}", String.valueOf(page)), text.replaceAll("\\{page}", String.valueOf(number)), CrazyCore.api().commandNavigationBackButton(), "/crazycrates help " + number, ClickEvent.Action.RUN_COMMAND); + } else if (page < this.manager.getClasses().size()) { + int number = page+1; + + hover(actor.getPlayer(), footer.replaceAll("\\{page}", String.valueOf(page)), text.replaceAll("\\{page}", String.valueOf(number)), CrazyCore.api().commandNavigationNextButton(), "/crazycrates help " + number, ClickEvent.Action.RUN_COMMAND); + } + } else { + send(actor.getSender(), footer.replaceAll("\\{page}", String.valueOf(page)), false, ""); + } + } + + this.lastPage = max >= this.totalResults; + } + + public void setPage(int page) { + this.page = page; + } + + public void setPerPage(int perPage) { + this.perPage = perPage; + } + + public void setPage(int page, int perPage) { + this.setPage(page); + this.setPerPage(perPage); + } + + public int getPage() { + return this.page; + } + + public int getPerPage() { + return this.perPage; + } + + public int getTotalResults() { + return this.totalResults; + } + + public int getTotalPages() { + return this.totalPages; + } + + public boolean isLastPage() { + return this.lastPage; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/annotations/Hidden.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/annotations/Hidden.java new file mode 100644 index 0000000..10fe620 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/annotations/Hidden.java @@ -0,0 +1,7 @@ +package com.badbones69.crazyauctions.api.frame.command.builders.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Hidden {} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/Argument.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/Argument.java new file mode 100644 index 0000000..b8e8dd3 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/Argument.java @@ -0,0 +1,3 @@ +package com.badbones69.crazyauctions.api.frame.command.builders.args; + +public record Argument(String name, int order, ArgumentType argumentType) {} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/ArgumentType.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/ArgumentType.java new file mode 100644 index 0000000..3de171b --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/ArgumentType.java @@ -0,0 +1,9 @@ +package com.badbones69.crazyauctions.api.frame.command.builders.args; + +import java.util.List; + +public abstract class ArgumentType { + + public abstract List getPossibleValues(); + +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/CommandArgs.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/CommandArgs.java new file mode 100644 index 0000000..b769c88 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/CommandArgs.java @@ -0,0 +1,22 @@ +package com.badbones69.crazyauctions.api.frame.command.builders.args; + +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +public interface CommandArgs { + + int getArgAsInt(int index, boolean notifySender); + + long getArgAsLong(int index, boolean notifySender); + + double getArgAsDouble(int index, boolean notifySender); + + boolean getArgAsBoolean(int index, boolean notifySender); + + float getArgAsFloat(int index, boolean notifySender); + + Player getArgAsPlayer(int index, boolean notifySender); + + OfflinePlayer getArgAsOfflinePlayer(int index); + +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/builder/BooleanArgument.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/builder/BooleanArgument.java new file mode 100644 index 0000000..7311812 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/builder/BooleanArgument.java @@ -0,0 +1,12 @@ +package com.badbones69.crazyauctions.api.frame.command.builders.args.builder; + +import com.badbones69.crazyauctions.api.frame.command.builders.args.ArgumentType; +import java.util.List; + +public class BooleanArgument extends ArgumentType { + + @Override + public List getPossibleValues() { + return List.of("true", "false"); + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/builder/DoubleArgument.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/builder/DoubleArgument.java new file mode 100644 index 0000000..dbc4007 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/builder/DoubleArgument.java @@ -0,0 +1,34 @@ +package com.badbones69.crazyauctions.api.frame.command.builders.args.builder; + +import com.badbones69.crazyauctions.api.frame.command.builders.args.ArgumentType; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; + +public class DoubleArgument extends ArgumentType { + + private final int numberCap; + + public DoubleArgument(Integer numberCap) { + if (numberCap == null) { + this.numberCap = 100; + return; + } + + this.numberCap = numberCap; + } + + @Override + public List getPossibleValues() { + List numbers = new ArrayList<>(); + + DecimalFormat decimalFormat = new DecimalFormat("0.0"); + + for (double value = 0.1; value <= this.numberCap; value += 0.1) { + String formattedNumber = decimalFormat.format(value); + numbers.add(formattedNumber); + } + + return numbers; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/builder/FloatArgument.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/builder/FloatArgument.java new file mode 100644 index 0000000..751a92e --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/builder/FloatArgument.java @@ -0,0 +1,34 @@ +package com.badbones69.crazyauctions.api.frame.command.builders.args.builder; + +import com.badbones69.crazyauctions.api.frame.command.builders.args.ArgumentType; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; + +public class FloatArgument extends ArgumentType { + + private final int numberCap; + + public FloatArgument(Integer numberCap) { + if (numberCap == null) { + this.numberCap = 100; + return; + } + + this.numberCap = numberCap; + } + + @Override + public List getPossibleValues() { + List numbers = new ArrayList<>(); + + DecimalFormat decimalFormat = new DecimalFormat("0.0f"); + + for (float value = 0.1f; value <= this.numberCap; value += 0.1f) { + String formattedValue = decimalFormat.format(value); + numbers.add(formattedValue); + } + + return numbers; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/builder/IntArgument.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/builder/IntArgument.java new file mode 100644 index 0000000..be72dc9 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/builder/IntArgument.java @@ -0,0 +1,28 @@ +package com.badbones69.crazyauctions.api.frame.command.builders.args.builder; + +import com.badbones69.crazyauctions.api.frame.command.builders.args.ArgumentType; +import java.util.ArrayList; +import java.util.List; + +public class IntArgument extends ArgumentType { + + private final int numberCap; + + public IntArgument(Integer numberCap) { + if (numberCap == null) { + this.numberCap = 100; + return; + } + + this.numberCap = numberCap; + } + + @Override + public List getPossibleValues() { + List numbers = new ArrayList<>(); + + for (int value = 1; value <= this.numberCap; value += 1) numbers.add(String.valueOf(value)); + + return numbers; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/builder/custom/PlayerArgument.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/builder/custom/PlayerArgument.java new file mode 100644 index 0000000..418a102 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/args/builder/custom/PlayerArgument.java @@ -0,0 +1,15 @@ +package com.badbones69.crazyauctions.api.frame.command.builders.args.builder.custom; + +import com.badbones69.crazyauctions.api.frame.command.builders.args.ArgumentType; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import java.util.List; +import java.util.stream.Collectors; + +public class PlayerArgument extends ArgumentType { + + @Override + public List getPossibleValues() { + return Bukkit.getServer().getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/other/ComponentBuilder.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/other/ComponentBuilder.java new file mode 100644 index 0000000..8de7164 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/other/ComponentBuilder.java @@ -0,0 +1,94 @@ +package com.badbones69.crazyauctions.api.frame.command.builders.other; + +import com.badbones69.crazyauctions.frame.utils.AdventureUtils; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.event.HoverEvent; +import org.jetbrains.annotations.NotNull; + +public class ComponentBuilder { + + private String message; + + private final TextComponent.@NotNull Builder builder = Component.text(); + + private final PreciseComponentBuilder preciseBuilder; + + public ComponentBuilder() { + this.preciseBuilder = new PreciseComponentBuilder(); + } + + public void setMessage(String message) { + this.message = message; + } + + public ComponentBuilder append(Component component) { + this.builder.append(component); + + return this; + } + + public Component parse(String value) { + return AdventureUtils.parse(value); + } + + public ComponentBuilder hover(String hoverText) { + this.builder.hoverEvent(HoverEvent.showText(parse(hoverText))); + + return this; + } + + public ComponentBuilder click(String clickText, ClickEvent.Action action) { + this.builder.clickEvent(ClickEvent.clickEvent(action, clickText)); + + return this; + } + + public class PreciseComponentBuilder { + private final TextComponent.@NotNull Builder preciseBuilder = Component.text(); + + public PreciseComponentBuilder text(String text) { + this.preciseBuilder.append(parse(text)); + + return this; + } + + public PreciseComponentBuilder hoverText(String text, String hoverText) { + this.preciseBuilder.append(parse(text)); + this.preciseBuilder.hoverEvent(HoverEvent.showText(parse(hoverText))); + + return this; + } + + public PreciseComponentBuilder hoverText(String hoverText) { + this.preciseBuilder.hoverEvent(HoverEvent.showText(parse(hoverText))); + + return this; + } + + public PreciseComponentBuilder click(String clickText, ClickEvent.Action action) { + this.preciseBuilder.clickEvent(ClickEvent.clickEvent(action, clickText)); + + return this; + } + + public @NotNull TextComponent getPreciseBuilder() { + return this.preciseBuilder.build(); + } + } + + public PreciseComponentBuilder getPreciseComponent() { + return this.preciseBuilder; + } + + public @NotNull TextComponent build() { + Component message = AdventureUtils.parse(this.message); + + if (getPreciseComponent() != null) { + return this.builder.append(message).append(getPreciseComponent().getPreciseBuilder()).build(); + } + + return this.builder.append(message).build(); + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/reqs/CommandRequirements.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/reqs/CommandRequirements.java new file mode 100644 index 0000000..209154c --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/reqs/CommandRequirements.java @@ -0,0 +1,57 @@ +package com.badbones69.crazyauctions.api.frame.command.builders.reqs; + +import com.badbones69.crazyauctions.api.frame.command.CommandContext; +import com.badbones69.crazyauctions.frame.CrazyCore; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.permissions.Permission; + +public class CommandRequirements { + + private final boolean asPlayer; + private Permission permission; + private String rawPermission; + + public CommandRequirements(boolean asPlayer, Permission permission, String rawPermission) { + this.asPlayer = asPlayer; + + if (permission != null) this.permission = permission; + + if (!rawPermission.isEmpty() || !rawPermission.isBlank()) this.rawPermission = rawPermission; + } + + public boolean checkRequirements(boolean notifySender, CommandContext context) { + if (asPlayer && !context.isPlayer()) { + if (notifySender) context.reply(CrazyCore.api().commandRequirementNotPlayer()); + + // The command is not valid. + return false; + } + + // The sender is console sender so automatically valid. + if (context.getSender() instanceof ConsoleCommandSender) return true; + + if (this.permission != null && !context.hasPermission(this.permission) || this.rawPermission != null && !context.hasPermission(this.rawPermission)) { + String value = this.permission != null ? this.permission.getName() : this.rawPermission; + + if (notifySender) context.reply(CrazyCore.api().commandRequirementNoPermission().replaceAll("\\{permission}", value)); + + // The command is not valid. + return false; + } + + // The command is valid. + return true; + } + + public Permission getPermission() { + return this.permission; + } + + public String getRawPermission() { + return this.rawPermission; + } + + public boolean isPlayer() { + return this.asPlayer; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/reqs/CommandRequirementsBuilder.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/reqs/CommandRequirementsBuilder.java new file mode 100644 index 0000000..7e76844 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/command/builders/reqs/CommandRequirementsBuilder.java @@ -0,0 +1,33 @@ +package com.badbones69.crazyauctions.api.frame.command.builders.reqs; + +import org.bukkit.permissions.Permission; + +public class CommandRequirementsBuilder { + + private boolean asPlayer = false; + private Permission permission = null; + private String rawPermission = ""; + + public CommandRequirementsBuilder asPlayer(boolean value) { + this.asPlayer = value; + return this; + } + + public CommandRequirementsBuilder withPermission(Permission permission) { + this.permission = permission; + return this; + } + + public CommandRequirementsBuilder withOutPermission(Permission permission) { + return this; + } + + public CommandRequirementsBuilder withRawPermission(String rawPermission) { + this.rawPermission = rawPermission; + return this; + } + + public CommandRequirements build() { + return new CommandRequirements(asPlayer, permission, rawPermission); + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/items/BaseItemBuilder.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/items/BaseItemBuilder.java new file mode 100644 index 0000000..5b4956c --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/items/BaseItemBuilder.java @@ -0,0 +1,673 @@ +package com.badbones69.crazyauctions.api.frame.items; + +import com.badbones69.crazyauctions.api.frame.ItemUtils; +import com.badbones69.crazyauctions.frame.CrazyLogger; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextDecoration; +import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; +import org.bukkit.Bukkit; +import org.bukkit.Color; +import org.bukkit.DyeColor; +import org.bukkit.FireworkEffect; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.block.Banner; +import org.bukkit.block.banner.Pattern; +import org.bukkit.block.banner.PatternType; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ArmorMeta; +import org.bukkit.inventory.meta.BannerMeta; +import org.bukkit.inventory.meta.BlockStateMeta; +import org.bukkit.inventory.meta.Damageable; +import org.bukkit.inventory.meta.FireworkEffectMeta; +import org.bukkit.inventory.meta.FireworkMeta; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.LeatherArmorMeta; +import org.bukkit.inventory.meta.PotionMeta; +import org.bukkit.inventory.meta.SkullMeta; +import org.bukkit.inventory.meta.trim.ArmorTrim; +import org.bukkit.inventory.meta.trim.TrimMaterial; +import org.bukkit.inventory.meta.trim.TrimPattern; +import org.bukkit.potion.PotionData; +import org.bukkit.potion.PotionType; +import org.bukkit.util.Consumer; +import java.lang.reflect.Field; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; + +public class BaseItemBuilder> { + + private final ItemUtils SKULL_CHECKER = new ItemUtils(); + + private final GsonComponentSerializer gson = GsonComponentSerializer.gson(); + + // Core. + private ItemStack itemStack; + private ItemMeta itemMeta; + + private Material material; + + // Custom Lore. + private Field LORE_FIELD; + + // Custom Model Data. + private boolean isCustomModelData; + + private int customModelData; + + // Custom Heads. + private boolean isHead; + private Field profile; + private String texture; + + // Potions + private boolean isPotion; + private boolean isTippedArrow; + private Color potionColor; + private PotionType potionType; + + // Leather. + private boolean isLeather; + private boolean isArmor; + private TrimMaterial trimMaterial; + private TrimPattern trimPattern; + private Color armorColor; + + // Banners. + private boolean isBanner; + private List patterns; + + // Shields. + private boolean isShield; + + // Firework. + private boolean isFirework; + private boolean isFireworkStar; + + // Enchantments/Flags + private boolean isDurable; + private boolean hideFlags; + private boolean isGlowing; + + protected BaseItemBuilder() { + this.itemStack = null; + this.itemMeta = null; + this.material = Material.AIR; + this.LORE_FIELD = null; + this.isCustomModelData = false; + this.customModelData = 0; + this.isHead = false; + this.profile = null; + this.texture = ""; + this.isPotion = false; + this.isTippedArrow = false; + this.potionColor = Color.WHITE; + this.potionType = PotionType.MUNDANE; + this.isLeather = false; + this.armorColor = Color.WHITE; + this.isBanner = false; + this.patterns = Collections.emptyList(); + this.isShield = false; + this.isFirework = false; + this.isFireworkStar = false; + this.isDurable = false; + this.hideFlags = false; + this.isGlowing = false; + } + + protected BaseItemBuilder(ItemStack itemStack) { + this.itemStack = itemStack; + + try { + Class metaClass = SKULL_CHECKER.craftClass("inventory.CraftMetaItem"); + + LORE_FIELD = metaClass.getDeclaredField("lore"); + LORE_FIELD.setAccessible(true); + } catch (NoSuchFieldException | ClassNotFoundException exception) { + CrazyLogger.warn("Failed to make the lore field accessible as it was not found. Perhaps an invalid item was supplied?"); + } + + this.material = itemStack.getType(); + + switch (this.material) { + case PLAYER_HEAD -> this.isHead = true; + case POTION, SPLASH_POTION -> this.isPotion = true; + case TIPPED_ARROW -> this.isTippedArrow = true; + case LEATHER_HELMET, LEATHER_CHESTPLATE, LEATHER_LEGGINGS, LEATHER_BOOTS, LEATHER_HORSE_ARMOR -> this.isLeather = true; + case SHIELD -> this.isShield = true; + case FIREWORK_ROCKET -> this.isFirework = true; + case FIREWORK_STAR -> this.isFireworkStar = true; + } + + String name = this.material.name(); + + this.isArmor = name.endsWith("_HELMET") || name.endsWith("_CHESTPLATE") || name.endsWith("_LEGGINGS") || name.endsWith("_BOOTS"); + + // Accounts for all banners. + if (this.material.name().contains("BANNER")) this.isBanner = true; + + // if (this.material.name().contains("SPAWN_EGG")) this.isEgg = true; + + this.itemMeta = itemStack.hasItemMeta() ? itemStack.getItemMeta() : Bukkit.getServer().getItemFactory().getItemMeta(material); + } + + public Base setDisplayName(Component displayName) { + this.itemMeta.displayName(displayName.decorationIfAbsent(TextDecoration.ITALIC, TextDecoration.State.FALSE)); + return (Base) this; + } + + public Base setLore(Component ... lore) { + return setLore(Arrays.asList(lore)); + } + + public Base setLore(List lore) { + List jsonLore = lore.stream().filter(Objects::nonNull).map(this.gson::serialize).toList(); + + try { + LORE_FIELD.set(this.itemMeta, jsonLore); + } catch (IllegalAccessException exception) { + exception.printStackTrace(); + } + + return (Base) this; + } + + public Base addLore(Consumer> lore) { + List components; + + try { + List jsonLore = (List) LORE_FIELD.get(this.itemMeta); + + components = (jsonLore == null) ? new ArrayList<>() : jsonLore.stream().map(this.gson::deserialize).collect(Collectors.toList()); + } catch (Exception exception) { + components = new ArrayList<>(); + exception.printStackTrace(); + } + + lore.accept(components); + return (Base) this; + } + + public Base setAmount(int amount) { + this.itemStack.setAmount(amount); + return (Base) this; + } + + public Base addEnchantment(Enchantment enchantment, int level, boolean ignoreLevelRestriction) { + this.itemMeta.addEnchant(enchantment, level, ignoreLevelRestriction); + return (Base) this; + } + + public Base removeEnchantment(Enchantment enchantment) { + this.itemMeta.removeEnchant(enchantment); + return (Base) this; + } + + public Base setEnchantments(HashMap enchantments, boolean ignoreLevelRestriction) { + enchantments.forEach((enchantment, integer) -> this.itemMeta.addEnchant(enchantment, integer, ignoreLevelRestriction)); + return (Base) this; + } + + public Base addPatterns(List patterns) { + patterns.forEach(this::addPatterns); + return (Base) this; + } + + public Base addPattern(Pattern pattern) { + this.patterns.add(pattern); + return (Base) this; + } + + public Base setPattern(List patterns) { + this.patterns = patterns; + return (Base) this; + } + + public Base addItemFlags(List flags) { + flags.forEach(flag -> { + try { + ItemFlag itemFlag = ItemFlag.valueOf(flag.toUpperCase()); + + addItemFlag(itemFlag); + } catch (Exception exception) { + CrazyLogger.warn("Failed to add item flag: " + flag + ". The flag is invalid!"); + } + }); + + return (Base) this; + } + + public Base setTexture(String texture) { + this.texture = texture; + + return (Base) this; + } + + public Base setValue(String material) { + if (material == null || material.isEmpty()) { + CrazyLogger.warn("Material cannot be null or empty, Output: " + material + "."); + CrazyLogger.warn("Please take a screenshot of this before asking for support."); + + return (Base) this; + } + + String metaData; + + if (isPotion || isTippedArrow) { + if (material.contains(";")) { + String[] section = material.split(";"); + + String[] sectionOne = section[0].split(":"); + String[] sectionTwo = section[1].split(":"); + + try { + this.potionType = PotionType.valueOf(sectionOne[1]); + } catch (Exception exception) { + CrazyLogger.warn("Failed to set potion type " + sectionOne[1] + ". The potion type inputted is invalid."); + } + + this.potionColor = getColor(sectionTwo[1]); + } + + return (Base) this; + } + + if (material.contains(":")) { // Sets the durability or another value option. + String[] materialSplit = material.split(":"); + + material = materialSplit[0]; + metaData = materialSplit[1]; + + if (metaData.contains("#")) { // :# + String modelData = metaData.split("#")[1]; + + if (isValidInteger(modelData)) { + this.isCustomModelData = true; + this.customModelData = Integer.parseInt(modelData); + } + } + + metaData = metaData.replace("#" + customModelData, ""); + + if (isValidInteger(metaData)) { // Value is durability. + int damage = Integer.parseInt(metaData); + + if (this.itemMeta instanceof Damageable) ((Damageable) this.itemMeta).setDamage(damage); + } else { // Value is something else. + if (isPotion) { + this.potionType = PotionType.valueOf(metaData); + + if (getColor(metaData) != null) this.potionColor = getColor(metaData); + } + + if (isLeather) this.armorColor = getColor(metaData); + } + } else if (material.contains("#")) { + String[] materialSplit = material.split("#"); + material = materialSplit[0]; + + if (isValidInteger(materialSplit[1])) { // Value is a number. + this.isCustomModelData = true; + this.customModelData = Integer.parseInt(materialSplit[1]); + } + } + + Material matchedMaterial = Material.matchMaterial(material); + + if (matchedMaterial != null) this.material = matchedMaterial; + + if (this.isArmor) ((ArmorMeta) itemMeta).setTrim(new ArmorTrim(this.trimMaterial, this.trimPattern)); + + this.itemStack.setType(this.material); + + setItemMeta(this.itemStack.getItemMeta()); + + return (Base) this; + } + + public Base hideFlags(boolean hideFlags) { + this.hideFlags = hideFlags; + return (Base) this; + } + + public Base setGlow(boolean isGlowing) { + this.isGlowing = isGlowing; + return (Base) this; + } + + public Base setTrim(TrimMaterial trimMaterial, TrimPattern trimPattern) { + this.trimMaterial = trimMaterial; + this.trimPattern = trimPattern; + + return (Base) this; + } + + public Base setDurable(boolean isDurable) { + this.isDurable = isDurable; + return (Base) this; + } + + public Base setEffect(FireworkEffect... effects) { + return setEffect(Arrays.asList(effects)); + } + + public Base setEffect(List effects) { + if (effects.isEmpty()) return (Base) this; + + if (this.isFireworkStar) { + FireworkEffectMeta effectMeta = (FireworkEffectMeta) this.getItemMeta(); + + effectMeta.setEffect(effects.get(0)); + this.setItemMeta(effectMeta); + } + + if (this.isFirework) { + FireworkMeta fireworkMeta = (FireworkMeta) this.getItemMeta(); + + fireworkMeta.addEffects(effects); + this.setItemMeta(fireworkMeta); + } + + return (Base) this; + } + + public Base setPower(int power) { + if (this.isFirework) { + FireworkMeta fireworkMeta = (FireworkMeta) this.getItemMeta(); + + fireworkMeta.setPower(power); + + this.setItemMeta(fireworkMeta); + } + + return (Base) this; + } + + public ItemStack build() { + if (this.material != Material.AIR) { + if (this.isHead) { + // Set the field to accessible. + exposeField(); + + setPlayerTexture(this.texture); + } + + if (this.isPotion || this.isTippedArrow && (this.potionType != null || this.potionColor != null)) { + PotionMeta potionMeta = (PotionMeta) this.itemMeta; + + if (this.potionType != null) potionMeta.setBasePotionData(new PotionData(this.potionType)); + + if (this.potionColor != null) potionMeta.setColor(this.potionColor); + + this.setItemMeta(potionMeta); + } + + if (this.isLeather && this.armorColor != null) { + LeatherArmorMeta leatherArmorMeta = (LeatherArmorMeta) this.itemMeta; + leatherArmorMeta.setColor(this.armorColor); + } + + if (this.isBanner && !this.patterns.isEmpty()) { + BannerMeta bannerMeta = (BannerMeta) this.itemMeta; + bannerMeta.setPatterns(this.patterns); + } + + if (this.isShield && !this.patterns.isEmpty()) { + BlockStateMeta shieldMeta = (BlockStateMeta) this.itemMeta; + Banner banner = (Banner) shieldMeta.getBlockState(); + + banner.setPatterns(this.patterns); + banner.update(); + + shieldMeta.setBlockState(banner); + } + + if (this.isCustomModelData) this.itemMeta.setCustomModelData(this.customModelData); + + if (this.hideFlags) this.itemMeta.addItemFlags(ItemFlag.values()); + + this.itemMeta.setUnbreakable(this.isDurable); + + this.addGlow(); + } else { + CrazyLogger.warn("Material cannot be AIR."); + } + + this.itemStack.setItemMeta(this.itemMeta); + + return this.itemStack; + } + + private void addItemFlag(ItemFlag itemFlag) { + this.itemMeta.addItemFlags(itemFlag); + } + + private void setPlayerTexture(String texture) { + this.texture = texture; + + Player player = Bukkit.getServer().getPlayer(this.texture); + + if (player != null) { + setOwner(player); + return; + } + + if (this.texture.startsWith("http")) { + setTexture(convert(this.texture), UUID.randomUUID()); + return; + } + + setTexture(this.texture, UUID.randomUUID()); + } + + private void setOwner(OfflinePlayer player) { + if (this.SKULL_CHECKER.isPlayerSkull(this.material)) return; + + SkullMeta skullMeta = (SkullMeta) this.getItemMeta(); + + skullMeta.setOwningPlayer(player); + + this.setItemMeta(skullMeta); + } + + private void addGlow() { + if (this.isGlowing) { + if (this.itemMeta.hasEnchants()) return; + + this.itemMeta.addEnchant(Enchantment.LUCK, 1, false); + + this.setItemMeta(this.itemMeta); + } + } + + private void exposeField() { + if (this.SKULL_CHECKER.isPlayerSkull(this.material)) return; + + Field field; + + try { + SkullMeta skullMeta = (SkullMeta) this.SKULL_CHECKER.skull().getItemMeta(); + field = skullMeta.getClass().getDeclaredField("profile"); + + field.setAccessible(true); + } catch (NoSuchFieldException exception) { + CrazyLogger.warn("Failed to make the meta field for profile accessible as it was not found. Perhaps an invalid item meta or field supplied?"); + + field = null; + } + + this.profile = field; + } + + private boolean isValidInteger(String value) { + try { + Integer.parseInt(value); + } catch (NumberFormatException exception) { + return false; + } + + return true; + } + + private Color getColor(String color) { + if (color != null) { + switch (color.toUpperCase()) { + case "AQUA" -> { + return Color.AQUA; + } + case "BLACK" -> { + return Color.BLACK; + } + case "BLUE" -> { + return Color.BLUE; + } + case "FUCHSIA" -> { + return Color.FUCHSIA; + } + case "GRAY" -> { + return Color.GRAY; + } + case "GREEN" -> { + return Color.GREEN; + } + case "LIME" -> { + return Color.LIME; + } + case "MAROON" -> { + return Color.MAROON; + } + case "NAVY" -> { + return Color.NAVY; + } + case "OLIVE" -> { + return Color.OLIVE; + } + case "ORANGE" -> { + return Color.ORANGE; + } + case "PURPLE" -> { + return Color.PURPLE; + } + case "RED" -> { + return Color.RED; + } + case "SILVER" -> { + return Color.SILVER; + } + case "TEAL" -> { + return Color.TEAL; + } + case "WHITE" -> { + return Color.WHITE; + } + case "YELLOW" -> { + return Color.YELLOW; + } + } + + try { + String[] rgb = color.split(","); + return Color.fromRGB(Integer.parseInt(rgb[0]), Integer.parseInt(rgb[1]), Integer.parseInt(rgb[2])); + } catch (Exception ignore) {} + } + + return null; + } + + private void addPatterns(String stringPattern) { + try { + String[] split = stringPattern.split(":"); + + for (PatternType pattern : PatternType.values()) { + + if (split[0].equalsIgnoreCase(pattern.name()) || split[0].equalsIgnoreCase(pattern.getIdentifier())) { + DyeColor color = getDyeColor(split[1]); + + if (color != null) this.addPattern(new Pattern(color, pattern)); + + break; + } + } + } catch (Exception ignored) {} + } + + public DyeColor getDyeColor(String color) { + if (color != null) { + try { + return DyeColor.valueOf(color.toUpperCase()); + } catch (Exception exception) { + try { + String[] rgb = color.split(","); + return DyeColor.getByColor(Color.fromRGB(Integer.parseInt(rgb[0]), Integer.parseInt(rgb[1]), Integer.parseInt(rgb[2]))); + } catch (Exception ignore) {} + } + } + + return null; + } + + private void setTexture(String texture, UUID uuid) { + if (this.SKULL_CHECKER.isPlayerSkull(this.material)) return; + + if (this.profile == null) return; + + SkullMeta skullMeta = (SkullMeta) this.itemMeta; + GameProfile gameProfile = new GameProfile(uuid, null); + + gameProfile.getProperties().put("textures", new Property("textures", texture)); + + try { + this.profile.set(skullMeta, gameProfile); + } catch (Exception exception) { + CrazyLogger.warn("Failed to set the meta & game profile. Perhaps an invalid texture?"); + CrazyLogger.warn("Your Input: " + texture + "."); + } + + setItemMeta(skullMeta); + } + + private String convert(String url) { + URL actualLink; + + try { + actualLink = new URL(url); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + + String encode = "{\"textures\":{\"SKIN\":{\"url\":\"" + actualLink + "\"}}}"; + + return Base64.getEncoder().encodeToString(encode.getBytes()); + } + + // Protected getters for extended builders. + protected ItemStack getItemStack() { + return this.itemStack; + } + + protected void setItemStack(ItemStack itemStack) { + this.itemStack = itemStack; + } + + protected ItemMeta getItemMeta() { + return this.itemMeta; + } + + protected void setItemMeta(ItemMeta itemMeta) { + this.itemMeta = itemMeta; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/items/ItemBuilder.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/items/ItemBuilder.java new file mode 100644 index 0000000..4c6d422 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/items/ItemBuilder.java @@ -0,0 +1,23 @@ +package com.badbones69.crazyauctions.api.frame.items; + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +public class ItemBuilder extends BaseItemBuilder { + + public ItemBuilder() { + super(); + } + + public ItemBuilder(ItemStack itemStack) { + super(itemStack); + } + + public static ItemBuilder setStack(ItemStack itemStack) { + return new ItemBuilder(itemStack); + } + + public static ItemBuilder setMaterial(Material material) { + return new ItemBuilder(new ItemStack(material)); + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/items/ItemNbt.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/items/ItemNbt.java new file mode 100644 index 0000000..f4ce10f --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/frame/items/ItemNbt.java @@ -0,0 +1,57 @@ +package com.badbones69.crazyauctions.api.frame.items; + +import org.bukkit.NamespacedKey; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; +import org.bukkit.plugin.java.JavaPlugin; + +public class ItemNbt { + + private final JavaPlugin plugin; + + public ItemNbt(JavaPlugin plugin) { + this.plugin = plugin; + } + + public ItemStack setString(ItemStack itemStack, String key, String value) { + ItemMeta meta = itemStack.getItemMeta(); + + if (meta == null) return null; + + meta.getPersistentDataContainer().set(new NamespacedKey(this.plugin, key), PersistentDataType.STRING, value); + itemStack.setItemMeta(meta); + + return itemStack; + } + + public String getString(ItemStack itemStack, String key) { + ItemMeta meta = itemStack.getItemMeta(); + + if (meta == null) return null; + + return meta.getPersistentDataContainer().get(new NamespacedKey(this.plugin, key), PersistentDataType.STRING); + } + + public ItemStack setBoolean(ItemStack itemStack, String key, boolean value) { + ItemMeta meta = itemStack.getItemMeta(); + + if (meta == null) return null; + + meta.getPersistentDataContainer().set(new NamespacedKey(this.plugin, key), PersistentDataType.BOOLEAN, value); + itemStack.setItemMeta(meta); + + return itemStack; + } + + public ItemStack removeTag(ItemStack itemStack, String key) { + ItemMeta meta = itemStack.getItemMeta(); + + if (meta == null) return null; + + meta.getPersistentDataContainer().remove(new NamespacedKey(this.plugin, key)); + itemStack.setItemMeta(meta); + + return itemStack; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/enums/AuctionType.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/enums/AuctionType.java new file mode 100644 index 0000000..ada77c8 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/enums/AuctionType.java @@ -0,0 +1,28 @@ +package com.badbones69.crazyauctions.api.manager.enums; + +/** + * Description: Defines the auction type to use + */ +public enum AuctionType { + + BID("Bid"), + SELL("Sell"); + + private final String name; + + AuctionType(String name) { + this.name = name; + } + + public static AuctionType getTypeFromName(String name) { + for (AuctionType type : AuctionType.values()) { + if (type.getName().equalsIgnoreCase(name)) return type; + } + + return null; + } + + public String getName() { + return this.name; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/interfaces/AuctionItem.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/interfaces/AuctionItem.java new file mode 100644 index 0000000..d365f3f --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/interfaces/AuctionItem.java @@ -0,0 +1,25 @@ +package com.badbones69.crazyauctions.api.manager.interfaces; + +import com.badbones69.crazyauctions.api.manager.enums.AuctionType; +import org.bukkit.inventory.ItemStack; +import java.util.UUID; + +public interface AuctionItem { + + UUID auctionID = UUID.randomUUID(); + + default UUID getAuctionID() { + return auctionID; + } + + AuctionType getAuctionType(); + + UUID getSeller(); + + long getPrice(); + + long getExpireTime(); + + ItemStack getSellingItem(); + +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/AuctionButtons.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/AuctionButtons.java new file mode 100644 index 0000000..761622f --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/AuctionButtons.java @@ -0,0 +1,88 @@ +package com.badbones69.crazyauctions.api.manager.objects; + +import com.badbones69.crazyauctions.CrazyAuctions; +import org.bukkit.plugin.java.JavaPlugin; + +public class AuctionButtons { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + /* + private final ItemBuilder sellingItemsButton; + private final ItemBuilder sellingInfoButton; + private final ItemBuilder biddingInfoButton; + private final ItemBuilder currentListingsInfoButton; + private final ItemBuilder expiredItemsButton; + private final ItemBuilder expiredInfoButton; + private final ItemBuilder categoriesButton; + private final ItemBuilder categoriesInfoButton; + private final ItemBuilder nextPageButton; + private final ItemBuilder refreshPageButton; + private final ItemBuilder backPageButton; + private final ItemBuilder switchModeButton; + + public AuctionButtons(FileConfiguration file) { + String path = "auction-house.settings.buttons."; + sellingItemsButton = ItemUtils.convertString(file.getString(path + "selling-items")); + sellingInfoButton = ItemUtils.convertString(file.getString(path + "info.selling-items")); + biddingInfoButton = ItemUtils.convertString(file.getString(path + "info.bidding")); + currentListingsInfoButton = ItemUtils.convertString(file.getString(path + "info.current-listings")); + expiredItemsButton = ItemUtils.convertString(file.getString(path + "expired-items")); + expiredInfoButton = ItemUtils.convertString(file.getString(path + "info.expired-items")); + categoriesButton = ItemUtils.convertString(file.getString(path + "categories")); + categoriesInfoButton = ItemUtils.convertString(file.getString(path + "info.categories")); + nextPageButton = ItemUtils.convertString(file.getString(path + "next-page")); + refreshPageButton = ItemUtils.convertString(file.getString(path + "refresh-page")); + backPageButton = ItemUtils.convertString(file.getString(path + "back-page")); + switchModeButton = ItemUtils.convertString(file.getString(path + "switch-mode")); + } + + + public ItemBuilder getSellingItemsButton() { + return sellingItemsButton; + } + + public ItemBuilder getSellingInfoButton() { + return sellingInfoButton; + } + + public ItemBuilder getBiddingInfoButton() { + return biddingInfoButton; + } + + public ItemBuilder getCurrentListingsInfoButton() { + return currentListingsInfoButton; + } + + public ItemBuilder getExpiredItemsButton() { + return expiredItemsButton; + } + + public ItemBuilder getExpiredInfoButton() { + return expiredInfoButton; + } + + public ItemBuilder getCategoriesButton() { + return categoriesButton; + } + + public ItemBuilder getCategoriesInfoButton() { + return categoriesInfoButton; + } + + public ItemBuilder getNextPageButton() { + return nextPageButton; + } + + public ItemBuilder getRefreshPageButton() { + return refreshPageButton; + } + + public ItemBuilder getBackPageButton() { + return backPageButton; + } + + public ItemBuilder getSwitchModeButton() { + return switchModeButton; + }*/ +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/AuctionCategory.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/AuctionCategory.java new file mode 100644 index 0000000..5b63411 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/AuctionCategory.java @@ -0,0 +1,44 @@ +package com.badbones69.crazyauctions.api.manager.objects; + +import com.badbones69.crazyauctions.CrazyAuctions; +import com.badbones69.crazyauctions.api.frame.items.ItemBuilder; +import org.bukkit.Material; +import org.bukkit.plugin.java.JavaPlugin; +import java.util.List; + +/** + * Description: Creates the auction categories + */ +public class AuctionCategory { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + private String name; + private int slot; + //private ItemBuilder displayItem; + private List categoryItemList; + + //TODO make it so each AH can have their own categories and the default ones should be able to be disabled. + public AuctionCategory(String name, int slot, ItemBuilder displayItem, List categoryItemList) { + this.name = name; + this.slot = slot; + //this.displayItem = displayItem; + this.categoryItemList = categoryItemList; + } + + public String getName() { + return name; + } + + public int getSlot() { + return slot; + } + + //public ItemBuilder getDisplayItem() { + // return displayItem; + //} + + public List getCategoryItemList() { + return categoryItemList; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/AuctionHouse.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/AuctionHouse.java new file mode 100644 index 0000000..e0b3727 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/AuctionHouse.java @@ -0,0 +1,91 @@ +package com.badbones69.crazyauctions.api.manager.objects; + +import com.badbones69.crazyauctions.CrazyAuctions; +import com.badbones69.crazyauctions.api.manager.enums.AuctionType; +import com.badbones69.crazyauctions.api.manager.interfaces.AuctionItem; +import com.badbones69.crazyauctions.api.manager.objects.auctiontype.BiddingAuction; +import com.badbones69.crazyauctions.api.manager.objects.auctiontype.SellingAuction; +import com.badbones69.crazyauctions.api.events.AuctionAddEvent; +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.plugin.java.JavaPlugin; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * Description: Creates the main auction house menu + */ +public class AuctionHouse { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + private String name; + private FileConfiguration auctionFile; + private InventorySettings inventorySettings; + private List auctionItems = new ArrayList<>(); + private List auctionCategories = new ArrayList<>(); + + public AuctionHouse(FileConfiguration file) { + this.name = file.getString("auction-house.settings.name"); + this.auctionFile = file; + this.inventorySettings = new InventorySettings(file); + //Loads the auction house listings into the auction house. + //TODO this needs to be moved to a seperated data file that doesnt hold all the auction house settings. + for (String auctionID : file.getConfigurationSection("auction-house.item-on-auction").getKeys(false)) { + String path = "auction-house.item-on-auction" + auctionID + "."; + AuctionType auctionType = AuctionType.getTypeFromName(file.getString(path + "auction-type")); + if (auctionType == AuctionType.SELL) { + auctionItems.add(new SellingAuction( + UUID.fromString(file.getString(path + "seller-uuid")), + file.getLong(path + "price"), + file.getLong(path + "expire-time"), + file.getItemStack(path + "selling-item"))); + } else { + auctionItems.add(new BiddingAuction( + UUID.fromString(file.getString(path + "seller-uuid")), + UUID.fromString(file.getString(path + "highest-bidder-uuid")), + file.getLong(path + "price"), + file.getLong(path + "current-bid"), + file.getLong(path + "expire-time"), + file.getItemStack(path + "selling-item"))); + } + } + //Loads the category items into the auction house. + //TODO Need to add the default categories like isPotion, isArmor, isFood, Ect... + //for (String category : file.getConfigurationSection("auction-house.categories").getKeys(false)) { + // String path = "auction-house.categories." + category + "."; + // auctionCategories.add(new AuctionCategory( + // category, + // file.getInt(path + "slot"), + //ItemUtils.convertString(file.getString(path + "item")), + //file.getStringList(path + "items").stream().map(Material :: matchMaterial).collect(Collectors.toList()))); + //} + } + + public String getName() { + return name; + } + + public FileConfiguration getAuctionFile() { + return auctionFile; + } + + public InventorySettings getInventorySettings() { + return inventorySettings; + } + + public List getAuctionItems() { + return auctionItems; + } + + public long getAuctionCount(AuctionType auctionType) { + return auctionItems.stream().filter(auctionItem -> auctionType == auctionItem.getAuctionType()).count(); + } + + public void addAuctionItem(AuctionItem auctionItem) { + auctionItems.add(auctionItem); + AuctionAddEvent event = new AuctionAddEvent(auctionItem.getSeller(), this, auctionItem); + Bukkit.getServer().getPluginManager().callEvent(event); + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/InventorySettings.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/InventorySettings.java new file mode 100644 index 0000000..3170b66 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/InventorySettings.java @@ -0,0 +1,30 @@ +package com.badbones69.crazyauctions.api.manager.objects; + +import com.badbones69.crazyauctions.CrazyAuctions; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.plugin.java.JavaPlugin; + +/** + * Description: Creates the auction house inventory settings + */ +public class InventorySettings { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + private final String title; + private final AuctionButtons auctionButtons = null; + + public InventorySettings(FileConfiguration file) { + String path = "auction-house.settings."; + this.title = file.getString(path + "inventory-title"); + //this.auctionButtons = new AuctionButtons(file); + } + + public String getTitle() { + return title; + } + + public AuctionButtons getAuctionButtons() { + return auctionButtons; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/auctiontype/BiddingAuction.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/auctiontype/BiddingAuction.java new file mode 100644 index 0000000..14ede86 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/auctiontype/BiddingAuction.java @@ -0,0 +1,74 @@ +package com.badbones69.crazyauctions.api.manager.objects.auctiontype; + +import com.badbones69.crazyauctions.CrazyAuctions; +import com.badbones69.crazyauctions.api.manager.enums.AuctionType; +import com.badbones69.crazyauctions.api.manager.interfaces.AuctionItem; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; +import java.util.UUID; + +/** + * Description: Creates the bidding auction type + */ +public class BiddingAuction implements AuctionItem { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + AuctionType auctionType = AuctionType.BID; + UUID seller; + UUID highestBidder; + long price; + long currentBid; + long expireTime; + ItemStack sellingItem; + + public BiddingAuction(UUID seller, UUID highestBidder, long price, long currentBid, long expireTime, ItemStack sellingItem) { + this.seller = seller; + this.highestBidder = highestBidder; + this.price = price; + this.currentBid = 0; + this.expireTime = expireTime; + this.sellingItem = sellingItem; + } + + @Override + public AuctionType getAuctionType() { + return auctionType; + } + + @Override + public UUID getSeller() { + return seller; + } + + public UUID getHighestBidder() { + return highestBidder; + } + + public void setHighestBidder(UUID highestBidder) { + this.highestBidder = highestBidder; + } + + @Override + public long getPrice() { + return price; + } + + public long getCurrentBid() { + return currentBid; + } + + public void setCurrentBid(long currentBid) { + this.currentBid = currentBid; + } + + @Override + public long getExpireTime() { + return expireTime; + } + + @Override + public ItemStack getSellingItem() { + return sellingItem; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/auctiontype/SellingAuction.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/auctiontype/SellingAuction.java new file mode 100644 index 0000000..12a2578 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/api/manager/objects/auctiontype/SellingAuction.java @@ -0,0 +1,54 @@ +package com.badbones69.crazyauctions.api.manager.objects.auctiontype; + +import com.badbones69.crazyauctions.CrazyAuctions; +import com.badbones69.crazyauctions.api.manager.enums.AuctionType; +import com.badbones69.crazyauctions.api.manager.interfaces.AuctionItem; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; +import java.util.UUID; + +/** + * Description: Creates the selling auction type + */ +public class SellingAuction implements AuctionItem { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + AuctionType auctionType = AuctionType.SELL; + UUID seller; + long price; + long expireTime; + ItemStack sellingItem; + + public SellingAuction(UUID seller, long price, long expireTime, ItemStack sellingItem) { + this.seller = seller; + this.price = price; + this.expireTime = expireTime; + this.sellingItem = sellingItem; + } + + @Override + public AuctionType getAuctionType() { + return auctionType; + } + + @Override + public UUID getSeller() { + return seller; + } + + @Override + public long getPrice() { + return price; + } + + @Override + public long getExpireTime() { + return expireTime; + } + + @Override + public ItemStack getSellingItem() { + return sellingItem; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/commands/AuctionCommand.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/commands/AuctionCommand.java new file mode 100644 index 0000000..68135c4 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/commands/AuctionCommand.java @@ -0,0 +1,21 @@ +package com.badbones69.crazyauctions.commands; + +import com.badbones69.crazyauctions.CrazyAuctions; +import com.badbones69.crazyauctions.api.frame.command.CommandContext; +import com.badbones69.crazyauctions.api.frame.command.CommandEngine; +import org.bukkit.plugin.java.JavaPlugin; +import java.util.Collections; + +public class AuctionCommand extends CommandEngine { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + protected AuctionCommand() { + super("auctions", "Opens the auction house", "/crazyauctions:auctions", Collections.emptyList()); + } + + @Override + protected void perform(CommandContext context, String[] args) { + + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/commands/admin/CommandReload.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/commands/admin/CommandReload.java new file mode 100644 index 0000000..bd2479d --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/commands/admin/CommandReload.java @@ -0,0 +1,23 @@ +package com.badbones69.crazyauctions.commands.admin; + +import com.badbones69.crazyauctions.CrazyAuctions; +import com.badbones69.crazyauctions.api.CrazyManager; +import com.badbones69.crazyauctions.api.frame.command.CommandContext; +import com.badbones69.crazyauctions.api.frame.command.CommandEngine; +import org.bukkit.plugin.java.JavaPlugin; +import java.util.Collections; + +public class CommandReload extends CommandEngine { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + private final CrazyManager crazyManager = this.plugin.getCrazyManager(); + + public CommandReload() { + super("reload", "Reloads the plugin.", "/crazyauctions:reload", Collections.emptyList()); + } + + @Override + protected void perform(CommandContext context, String[] args) { + this.crazyManager.reload(); + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/commands/inventories/AuctionInventory.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/commands/inventories/AuctionInventory.java new file mode 100644 index 0000000..a96c988 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/commands/inventories/AuctionInventory.java @@ -0,0 +1,23 @@ +package com.badbones69.crazyauctions.commands.inventories; + +import com.badbones69.crazyauctions.CrazyAuctions; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; + +public class AuctionInventory implements InventoryHolder { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + private final Inventory inventory; + + public AuctionInventory() { + this.inventory = plugin.getServer().createInventory(this, 9); + } + + @Override + public @NotNull Inventory getInventory() { + return this.inventory; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/commands/inventories/AuctionInventoryClick.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/commands/inventories/AuctionInventoryClick.java new file mode 100644 index 0000000..fb49a6c --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/commands/inventories/AuctionInventoryClick.java @@ -0,0 +1,35 @@ +package com.badbones69.crazyauctions.commands.inventories; + +import com.badbones69.crazyauctions.api.frame.items.ItemBuilder; +import com.badbones69.crazyauctions.frame.utils.AdventureUtils; +import org.bukkit.Material; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +public class AuctionInventoryClick implements Listener { + + @EventHandler + public void onAuctionClick(InventoryClickEvent event) { + Inventory inventory = event.getClickedInventory(); + + if (inventory == null || (!(inventory.getHolder() instanceof AuctionInventory auctionInventory))) return; + + event.setCancelled(true); + + ItemStack clicked = event.getCurrentItem(); + + if (clicked != null) { + event.getWhoClicked().sendMessage("Beep Boo Boo Beep!"); + + ItemBuilder builder = ItemBuilder.setStack(new ItemStack(Material.DIAMOND_SWORD)); + + builder.setAmount(3); + builder.setDisplayName(AdventureUtils.parse("This is a test")); + + auctionInventory.getInventory().addItem(builder.build()); + } + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/events/DataListener.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/events/DataListener.java new file mode 100644 index 0000000..5d230ae --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/events/DataListener.java @@ -0,0 +1,27 @@ +package com.badbones69.crazyauctions.events; + +import com.badbones69.crazyauctions.CrazyAuctions; +import com.badbones69.crazyauctions.storage.interfaces.UserManager; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.plugin.java.JavaPlugin; + +public class DataListener implements Listener { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + private final UserManager userManager = this.plugin.getCrazyManager().getStorageManager().getUserManager(); + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onPlayerJoin(PlayerJoinEvent event) { + this.userManager.load(event.getPlayer().getUniqueId()); + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onPlayerQuit(PlayerQuitEvent event) { + this.userManager.saveSingular(event.getPlayer().getUniqueId(), true); + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/storage/interfaces/UserManager.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/storage/interfaces/UserManager.java new file mode 100644 index 0000000..fd76a9a --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/storage/interfaces/UserManager.java @@ -0,0 +1,28 @@ +package com.badbones69.crazyauctions.storage.interfaces; + +import com.badbones69.crazyauctions.frame.storage.enums.StorageType; +import com.badbones69.crazyauctions.storage.objects.UserData; +import java.io.File; +import java.nio.file.Path; +import java.util.Map; +import java.util.UUID; + +public interface UserManager { + + void load(UUID uuid); + + void saveSingular(UUID uuid, boolean serverExit); + + void save(boolean serverExit); + + void convert(File file, UUID uuid, StorageType storageType); + + void addAuction(UUID uuid); + + File getFile(Path path, UUID uuid); + + UserData getUser(UUID uuid); + + Map getUsers(); + +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/storage/objects/UserData.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/storage/objects/UserData.java new file mode 100644 index 0000000..e39dc32 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/storage/objects/UserData.java @@ -0,0 +1,24 @@ +package com.badbones69.crazyauctions.storage.objects; + +import com.badbones69.crazyauctions.CrazyAuctions; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class UserData { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + private final UUID uuid; + + private ConcurrentHashMap auctionData = new ConcurrentHashMap<>(); + + public UserData(UUID uuid) { + this.uuid = uuid; + } + + public Player getPlayer() { + return this.plugin.getServer().getPlayer(this.uuid); + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/storage/types/StorageManager.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/storage/types/StorageManager.java new file mode 100644 index 0000000..c978530 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/storage/types/StorageManager.java @@ -0,0 +1,17 @@ +package com.badbones69.crazyauctions.storage.types; + +import com.badbones69.crazyauctions.storage.interfaces.UserManager; +import com.badbones69.crazyauctions.storage.types.file.yaml.YamlUserManager; + +public class StorageManager { + + private UserManager userManager; + + public void init() { + this.userManager = new YamlUserManager(); + } + + public UserManager getUserManager() { + return this.userManager; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/storage/types/file/yaml/YamlUserManager.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/storage/types/file/yaml/YamlUserManager.java new file mode 100644 index 0000000..5fc8f73 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/storage/types/file/yaml/YamlUserManager.java @@ -0,0 +1,110 @@ +package com.badbones69.crazyauctions.storage.types.file.yaml; + +import com.badbones69.crazyauctions.CrazyAuctions; +import com.badbones69.crazyauctions.frame.storage.enums.StorageType; +import com.badbones69.crazyauctions.storage.interfaces.UserManager; +import com.badbones69.crazyauctions.storage.objects.UserData; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Collections; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class YamlUserManager extends YamlConfiguration implements UserManager { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + private final ConcurrentHashMap userData = new ConcurrentHashMap<>(); + + public YamlUserManager() { + + } + + @Override + public void load(UUID uuid) { + try { + File file = new File(this.plugin.getDataFolder() + "/users/" + uuid + ".yml"); + + if (!file.exists()) file.createNewFile(); + + load(file); + } catch (IOException | InvalidConfigurationException e) { + e.printStackTrace(); + } + } + + @Override + public void saveSingular(UUID uuid, boolean serverExit) { + // If user data empty return. + if (this.userData.isEmpty()) return; + + // Check if user data contains keys. + if (this.userData.containsKey(uuid)) { + // Remove user when done. + this.userData.remove(uuid); + + // Save the file then load the changes back in. + reload(uuid, serverExit); + } + } + + private void reload(UUID uuid, boolean serverExit) { + try { + File file = new File(this.plugin.getDataFolder() + "/users/" + uuid + ".yml"); + + save(file); + + if (!serverExit) load(uuid); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void save(boolean serverExit) { + // If user data empty return. + if (this.userData.isEmpty()) return; + + // If the player is not leaving, continue here as we are stopping the server or doing periodic save. + this.userData.forEach((id, user) -> { + //user.getKeys().forEach((crateMap, keys) -> set("users." + id + "." + crateMap, keys)); + + // Save the file then load the changes back in. + reload(id, serverExit); + }); + } + + @Override + public void convert(File file, UUID uuid, StorageType storageType) { + + } + + @Override + public void addAuction(UUID uuid) { + Player player = this.plugin.getServer().getPlayer(uuid); + } + + @Override + public File getFile(Path path, UUID uuid) { + return new File(this.plugin.getDataFolder() + "/users/" + uuid + ".yml"); + } + + @Override + public UserData getUser(UUID uuid) { + Player player = this.plugin.getServer().getPlayer(uuid); + + // Return with their user data. + return this.userData.get(uuid); + } + + @Override + public Map getUsers() { + return Collections.unmodifiableMap(this.userData); + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/support/PlaceholderSupport.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/support/PlaceholderSupport.java new file mode 100644 index 0000000..3aef78e --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/support/PlaceholderSupport.java @@ -0,0 +1,17 @@ +package com.badbones69.crazyauctions.support; + +import com.badbones69.crazyauctions.ApiManager; +import com.badbones69.crazyauctions.CrazyAuctions; +import com.badbones69.crazyauctions.config.types.PluginConfig; +import org.bukkit.plugin.java.JavaPlugin; + +public class PlaceholderSupport { + + private static final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + public static String setPlaceholders(String placeholder) { + placeholder = placeholder.replaceAll("\\{prefix}", ApiManager.getPluginConfig().getProperty(PluginConfig.COMMAND_PREFIX)); + + return placeholder; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/support/economy/Currency.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/support/economy/Currency.java new file mode 100644 index 0000000..046c464 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/support/economy/Currency.java @@ -0,0 +1,51 @@ +package com.badbones69.crazyauctions.support.economy; + +/** + * Description: This event is fired when an item is added to an auction house. + */ +public enum Currency { + + VAULT("Vault"), + XP_LEVEL("XP_Level"), + XP_TOTAL("XP_Total"); + + private final String name; + + Currency(String name) { + this.name = name; + } + + /** + * Checks if it is a compatible currency. + * @param currency The currency name you are checking. + * @return True if it is supported and false if not. + */ + public static boolean isCurrency(String currency) { + for (Currency value : Currency.values()) { + if (currency.equalsIgnoreCase(value.getName())) return true; + } + + return false; + } + + /** + * Get a currency enum. + * @param currency The currency you want. + * @return The currency enum. + */ + public static Currency getCurrency(String currency) { + for (Currency value : Currency.values()) { + if (currency.equalsIgnoreCase(value.getName())) return value; + } + + return null; + } + + /** + * Get the name of the currency. + * @return The name of the currency. + */ + public String getName() { + return name; + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/support/economy/CurrencyAPI.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/support/economy/CurrencyAPI.java new file mode 100644 index 0000000..ab92b20 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/support/economy/CurrencyAPI.java @@ -0,0 +1,131 @@ +package com.badbones69.crazyauctions.support.economy; + +import com.badbones69.crazyauctions.CrazyAuctions; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; +import java.util.UUID; + +/** + * Description: Defines what currency to use. + */ +public class CurrencyAPI { + + // TODO() Add item support as a currency. + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + /** + * Get the amount that a player has from a specific currency. + * + * @param uuid - The uuid of the player. + * @param currency - The currency you wish to get from. + * @return amount that the player has of that currency. + */ + public int getCurrency(UUID uuid, Currency currency) { + try { + OfflinePlayer offlinePlayer = plugin.getServer().getOfflinePlayer(uuid); + Player player = plugin.getServer().getPlayer(uuid); + + switch (currency) { + case VAULT: //if (player != null) return (int) plugin.getVaultSupport().getVault().getBalance(player); + + case XP_LEVEL: if (player != null) return player.getLevel(); + + case XP_TOTAL: if (player != null) return getTotalExperience(player); + } + } catch (Exception | NoClassDefFoundError ignored) {} + return 0; + } + + /** + * Take an amount from a player's currency. + * + * @param uuid - The uuid of the player. + * @param currency - The currency you wish to use. + * @param amount - The amount you want to take. + */ + public void takeCurrency(UUID uuid, Currency currency, int amount) { + try { + Player player = plugin.getServer().getPlayer(uuid); + + switch (currency) { + //case VAULT: if (player != null) plugin.getVaultSupport().getVault().withdrawPlayer(player, amount); + case XP_LEVEL: if (player != null) player.setLevel(player.getLevel() - amount); + case XP_TOTAL: if (player != null) takeTotalExperience(player, amount); + } + } catch (Exception | NoClassDefFoundError ignored) {} + } + + /** + * Give an amount to a player's currency. + * + * @param uuid - The uuid of the player. + * @param currency - The currency you want to use. + * @param amount - The amount you are giving to the player. + */ + public void giveCurrency(UUID uuid, Currency currency, int amount) { + try { + Player player = plugin.getServer().getPlayer(uuid); + + switch (currency) { + //case VAULT: if (player != null) plugin.getVaultSupport().getVault().depositPlayer(player, amount); + case XP_LEVEL: if (player != null) player.setLevel(player.getLevel() + amount); + case XP_TOTAL: if (player != null) takeTotalExperience(player, -amount); + } + } catch (Exception | NoClassDefFoundError ignored) {} + } + + /** + * Checks if the player has enough of a currency. + * + * @param uuid - The uuid of the player. + * @param currency The currency you wish to check. + * @param cost The cost of the item you are checking. + * @return true if they have enough to buy it or false if they don't. + */ + public boolean canBuy(UUID uuid, Currency currency, int cost) { + return getCurrency(uuid, currency) >= cost; + } + + private void takeTotalExperience(Player player, int amount) { + int total = getTotalExperience(player) - amount; + player.setTotalExperience(0); + player.setTotalExperience(total); + player.setLevel(0); + player.setExp(0); + + while (total > player.getExpToLevel()) { + total -= player.getExpToLevel(); + player.setLevel(player.getLevel() + 1); + } + + float xp = (float) total / (float) player.getExpToLevel(); + player.setExp(xp); + } + + private int getTotalExperience(Player player) { // https://www.spigotmc.org/threads/72804 + int experience; + int level = player.getLevel(); + + if (level >= 0 && level <= 15) { + experience = (int) Math.ceil(Math.pow(level, 2) + (6 * level)); + int requiredExperience = 2 * level + 7; + double currentExp = Double.parseDouble(Float.toString(player.getExp())); + experience += Math.ceil(currentExp * requiredExperience); + return experience; + } else if (level > 15 && level <= 30) { + experience = (int) Math.ceil((2.5 * Math.pow(level, 2) - (40.5 * level) + 360)); + int requiredExperience = 5 * level - 38; + double currentExp = Double.parseDouble(Float.toString(player.getExp())); + experience += Math.ceil(currentExp * requiredExperience); + return experience; + } else { + experience = (int) Math.ceil((4.5 * Math.pow(level, 2) - (162.5 * level) + 2220)); + int requiredExperience = 9 * level - 158; + double currentExp = Double.parseDouble(Float.toString(player.getExp())); + experience += Math.ceil(currentExp * requiredExperience); + return experience; + } + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/support/economy/vault/VaultSupport.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/support/economy/vault/VaultSupport.java new file mode 100644 index 0000000..3051a51 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/support/economy/vault/VaultSupport.java @@ -0,0 +1,26 @@ +package com.badbones69.crazyauctions.support.economy.vault; + +import com.badbones69.crazyauctions.CrazyAuctions; +import net.milkbowl.vault.economy.Economy; +import org.bukkit.plugin.RegisteredServiceProvider; +import org.bukkit.plugin.java.JavaPlugin; + +/** + * Description: Vault support related code. + */ +public class VaultSupport { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + private Economy vault = null; + + public Economy getVault() { + return vault; + } + + public void loadVault() { + RegisteredServiceProvider serviceProvider = plugin.getServer().getServicesManager().getRegistration(Economy.class); + + if (serviceProvider != null) vault = serviceProvider.getProvider(); + } +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/utils/ItemUtils.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/utils/ItemUtils.java new file mode 100644 index 0000000..70219f4 --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/utils/ItemUtils.java @@ -0,0 +1,10 @@ +package com.badbones69.crazyauctions.utils; + +import com.badbones69.crazyauctions.CrazyAuctions; +import org.bukkit.plugin.java.JavaPlugin; + +public class ItemUtils { + + private final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + +} \ No newline at end of file diff --git a/paper/src/main/java/com/badbones69/crazyauctions/v2/utils/misc/ColorUtils.java b/paper/src/main/java/com/badbones69/crazyauctions/v2/utils/misc/ColorUtils.java new file mode 100644 index 0000000..cd7a27f --- /dev/null +++ b/paper/src/main/java/com/badbones69/crazyauctions/v2/utils/misc/ColorUtils.java @@ -0,0 +1,15 @@ +package com.badbones69.crazyauctions.utils.misc; + +import com.badbones69.crazyauctions.ApiManager; +import com.badbones69.crazyauctions.CrazyAuctions; +import com.badbones69.crazyauctions.config.types.PluginConfig; +import org.bukkit.plugin.java.JavaPlugin; + +public class ColorUtils { + + private static final CrazyAuctions plugin = JavaPlugin.getPlugin(CrazyAuctions.class); + + public static String getPrefix() { + return ApiManager.getPluginConfig().getProperty(PluginConfig.COMMAND_PREFIX); + } +} \ No newline at end of file diff --git a/src/main/resources/config1.12.2-Down.yml b/paper/src/main/resources/config1.12.2-Down.yml similarity index 100% rename from src/main/resources/config1.12.2-Down.yml rename to paper/src/main/resources/config1.12.2-Down.yml diff --git a/src/main/resources/config1.13-Up.yml b/paper/src/main/resources/config1.13-Up.yml similarity index 100% rename from src/main/resources/config1.13-Up.yml rename to paper/src/main/resources/config1.13-Up.yml diff --git a/src/main/resources/data.yml b/paper/src/main/resources/data.yml similarity index 100% rename from src/main/resources/data.yml rename to paper/src/main/resources/data.yml diff --git a/src/main/resources/messages.yml b/paper/src/main/resources/messages.yml similarity index 100% rename from src/main/resources/messages.yml rename to paper/src/main/resources/messages.yml diff --git a/src/main/resources/plugin.yml b/paper/src/main/resources/plugin.yml similarity index 100% rename from src/main/resources/plugin.yml rename to paper/src/main/resources/plugin.yml diff --git a/src/main/resources/test-file.yml b/paper/src/main/resources/test-file.yml similarity index 100% rename from src/main/resources/test-file.yml rename to paper/src/main/resources/test-file.yml diff --git a/pom.xml b/pom.xml deleted file mode 100644 index d3a603e..0000000 --- a/pom.xml +++ /dev/null @@ -1,116 +0,0 @@ - - - 4.0.0 - - com.badbones69 - crazyauctions - 1.2.19 - Crazy-Auctions - - - UTF-8 - - - - - - - crazycrew-repo-releases - CrazyCrew Team - https://repo.badbones69.com/releases - - - - - - spigot-repo - https://hub.spigotmc.org/nexus/content/repositories/snapshots/ - - - vault-repo - http://nexus.hc.to/content/repositories/pub_releases - - - codemc-repo - https://repo.codemc.io/repository/maven-public/ - - - - - - org.spigotmc - spigot-api - 1.19.3-R0.1-SNAPSHOT - provided - - - net.milkbowl.vault - VaultAPI - 1.7 - provided - - - bukkit - org.bukkit - - - - - net.tnemc - Reserve - 0.1.5.0 - provided - - - org.bstats - bstats-bukkit - 3.0.0 - provided - - - - - ${project.name}-[v${project.version}] - - - src/main/resources - true - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 1.8 - 1.8 - - - - org.apache.maven.plugins - maven-shade-plugin - 3.1.0 - - - - org.bstats - - com.badbones69.crazyauctions.libraries - - - - - - package - - shade - - - - - - - \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..2a6847f --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,17 @@ +pluginManagement { + repositories { + maven("https://repo.papermc.io/repository/maven-public/") + + gradlePluginPortal() + mavenCentral() + } +} + +rootProject.name = "CrazyAuctions" + +listOf( + "paper", + "common" +).forEach { + include(it) +} \ No newline at end of file