├── .gitbook.yaml ├── .github └── workflows │ ├── build.yml │ └── release.yml ├── .gitignore ├── LICENSE.txt ├── README.md ├── docs ├── README.md ├── SUMMARY.md ├── core-features │ ├── commands.md │ ├── configuration.md │ ├── cooldowns.md │ ├── dependency-injection.md │ ├── events.md │ ├── item-builder.md │ ├── menus.md │ ├── schedulers.md │ ├── terminables.md │ ├── text-and-localization.md │ └── utilities.md ├── optional-modules │ ├── games.md │ ├── mongodb.md │ ├── redis.md │ └── sql.md └── overview │ └── getting-started.md ├── jitpack.yml ├── pluginbase-core ├── pom.xml └── src │ └── main │ └── java │ └── dev │ └── demeng │ └── pluginbase │ ├── BaseSettings.java │ ├── Common.java │ ├── DynamicPlaceholders.java │ ├── Events.java │ ├── Locations.java │ ├── Players.java │ ├── Schedulers.java │ ├── ServerProperties.java │ ├── Services.java │ ├── Sounds.java │ ├── Time.java │ ├── TrimmedUuids.java │ ├── UpdateChecker.java │ ├── YamlConfig.java │ ├── bucket │ ├── AbstractBucket.java │ ├── Bucket.java │ ├── BucketPartition.java │ ├── Cycle.java │ ├── CycleImpl.java │ ├── factory │ │ ├── BucketFactory.java │ │ ├── ConcurrentBucket.java │ │ ├── HashSetBucket.java │ │ ├── SetSuppliedBucket.java │ │ └── SynchronizedHashSetBucket.java │ └── partitioning │ │ ├── GenericPartitioningStrategy.java │ │ ├── PartitioningStrategies.java │ │ └── PartitioningStrategy.java │ ├── command │ ├── BaseExceptionHandler.java │ └── BaseFailureHandler.java │ ├── cooldown │ ├── Cooldown.java │ └── CooldownMap.java │ ├── delegate │ ├── Delegate.java │ └── Delegates.java │ ├── di │ ├── DependencyInjection.java │ ├── annotation │ │ └── Component.java │ ├── container │ │ ├── DependencyContainer.java │ │ └── SimpleDependencyContainer.java │ └── exception │ │ ├── DependencyException.java │ │ ├── MissingDependencyException.java │ │ └── TypeMismatchException.java │ ├── event │ ├── MergedSubscription.java │ ├── SingleSubscription.java │ ├── Subscription.java │ ├── filter │ │ ├── EventFilters.java │ │ └── EventHandlers.java │ └── functional │ │ ├── ExpiryTestStage.java │ │ ├── FunctionalHandlerList.java │ │ ├── SubscriptionBuilder.java │ │ ├── merged │ │ ├── BaseMergedEventListener.java │ │ ├── MergedHandlerList.java │ │ ├── MergedHandlerListImpl.java │ │ ├── MergedHandlerMapping.java │ │ ├── MergedSubscriptionBuilder.java │ │ └── MergedSubscriptionBuilderImpl.java │ │ └── single │ │ ├── BaseEventListener.java │ │ ├── SingleHandlerList.java │ │ ├── SingleHandlerListImpl.java │ │ ├── SingleSubscriptionBuilder.java │ │ └── SingleSubscriptionBuilderImpl.java │ ├── exceptions │ ├── BaseException.java │ ├── EventHandlerException.java │ ├── PluginErrorException.java │ ├── PromiseChainException.java │ └── SchedulerTaskException.java │ ├── gson │ ├── GsonProvider.java │ └── JsonBuilder.java │ ├── input │ └── ChatInputRequest.java │ ├── interfaces │ └── TypeAware.java │ ├── item │ └── ItemBuilder.java │ ├── locale │ ├── LocaleReader.java │ ├── Locales.java │ ├── ResourceBundleLocaleReader.java │ ├── SimpleTranslator.java │ ├── Translator.java │ ├── UTF8Control.java │ └── reader │ │ └── ConfigLocaleReader.java │ ├── menu │ ├── IMenu.java │ ├── MenuManager.java │ ├── layout │ │ ├── Menu.java │ │ └── PagedMenu.java │ └── model │ │ └── MenuButton.java │ ├── model │ ├── BlockPosition.java │ ├── Pair.java │ ├── Placeholders.java │ ├── Point.java │ ├── Position.java │ └── Vector3d.java │ ├── plugin │ ├── BaseManager.java │ └── BasePlugin.java │ ├── promise │ ├── BasePromise.java │ ├── Promise.java │ └── ThreadContext.java │ ├── random │ └── RandomString.java │ ├── scheduler │ ├── BaseAsyncExecutor.java │ ├── BaseExecutors.java │ ├── Scheduler.java │ ├── Task.java │ ├── Ticks.java │ ├── builder │ │ ├── ContextualPromiseBuilder.java │ │ ├── ContextualTaskBuilder.java │ │ ├── TaskBuilder.java │ │ └── TaskBuilderImpl.java │ └── threadlock │ │ ├── ServerThreadLock.java │ │ └── ServerThreadLockImpl.java │ ├── serialize │ ├── ItemSerializer.java │ └── YamlSerializable.java │ ├── terminable │ ├── Terminable.java │ ├── TerminableConsumer.java │ ├── composite │ │ ├── AbstractCompositeTerminable.java │ │ ├── AbstractWeakCompositeTerminable.java │ │ ├── CompositeClosingException.java │ │ └── CompositeTerminable.java │ └── module │ │ └── TerminableModule.java │ └── text │ ├── DefaultFontInfo.java │ ├── StringSimilarity.java │ └── Text.java ├── pluginbase-games ├── pom.xml └── src │ └── main │ └── java │ └── dev │ └── demeng │ └── pluginbase │ └── games │ ├── GameState.java │ └── ScheduledStateSeries.java ├── pluginbase-mongo ├── pom.xml └── src │ └── main │ └── java │ └── dev │ └── demeng │ └── pluginbase │ └── mongo │ ├── IMongo.java │ ├── Mongo.java │ └── MongoCredentials.java ├── pluginbase-redis ├── pom.xml └── src │ └── main │ └── java │ └── dev │ └── demeng │ └── pluginbase │ └── redis │ ├── IRedis.java │ ├── MessageTransferObject.java │ ├── Redis.java │ ├── RedisCredentials.java │ └── event │ ├── AsyncRedisMessageReceiveEvent.java │ ├── IRedisMessageReceiveEvent.java │ └── RedisMessageReceiveEvent.java ├── pluginbase-sql ├── pom.xml └── src │ └── main │ └── java │ └── dev │ └── demeng │ └── pluginbase │ └── sql │ ├── BatchBuilder.java │ ├── ISql.java │ ├── Sql.java │ └── SqlCredentials.java ├── pom.xml └── samples ├── pluginbase_en.properties └── pluginbase_en.yml /.gitbook.yaml: -------------------------------------------------------------------------------- 1 | root: ./docs/ 2 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: SonarQube 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | types: [ opened, synchronize, reopened ] 8 | jobs: 9 | build: 10 | name: Build and analyze 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | with: 15 | fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis 16 | - name: Set up JDK 17 17 | uses: actions/setup-java@v4 18 | with: 19 | java-version: 17 20 | distribution: 'zulu' # Alternative distribution options are available. 21 | - name: Cache SonarQube packages 22 | uses: actions/cache@v4 23 | with: 24 | path: ~/.sonar/cache 25 | key: ${{ runner.os }}-sonar 26 | restore-keys: ${{ runner.os }}-sonar 27 | - name: Cache Maven packages 28 | uses: actions/cache@v4 29 | with: 30 | path: ~/.m2 31 | key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} 32 | restore-keys: ${{ runner.os }}-m2 33 | - name: Build and analyze 34 | env: 35 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} 36 | run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=demengc_PluginBase -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | 8 | env: 9 | JAVA_VERSION: 17 10 | 11 | jobs: 12 | release: 13 | name: Build and Publish Artifacts 14 | runs-on: ubuntu-latest 15 | permissions: 16 | contents: write 17 | steps: 18 | - name: Checkout repository 19 | uses: actions/checkout@v4 20 | with: 21 | fetch-depth: 0 22 | 23 | - name: Set up Temurin JDK 24 | uses: actions/setup-java@v4 25 | with: 26 | distribution: temurin 27 | java-version: ${{ env.JAVA_VERSION }} 28 | cache: maven 29 | 30 | - name: Build release artifacts 31 | run: mvn -B -ntp clean package 32 | 33 | - name: Collect jars for release 34 | run: | 35 | mkdir -p release 36 | find . -path "*/target/*.jar" ! -name "original-*.jar" -exec cp {} release/ \; 37 | 38 | - name: Upload build artifacts 39 | uses: actions/upload-artifact@v4 40 | with: 41 | name: release-bundles 42 | path: release 43 | 44 | - name: Publish GitHub release 45 | uses: softprops/action-gh-release@v1 46 | with: 47 | files: release/* 48 | generate_release_notes: true 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # User-specific stuff 2 | .idea/ 3 | 4 | *.iml 5 | *.ipr 6 | *.iws 7 | 8 | # IntelliJ 9 | out/ 10 | 11 | # Compiled class file 12 | *.class 13 | 14 | # Log file 15 | *.log 16 | 17 | # BlueJ files 18 | *.ctxt 19 | 20 | # Package Files # 21 | *.jar 22 | *.war 23 | *.nar 24 | *.ear 25 | *.zip 26 | *.tar.gz 27 | *.rar 28 | 29 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 30 | hs_err_pid* 31 | 32 | *~ 33 | 34 | # temporary files which can be created if a process still has a handle open of a deleted file 35 | .fuse_hidden* 36 | 37 | # KDE directory preferences 38 | .directory 39 | 40 | # Linux trash folder which might appear on any partition or disk 41 | .Trash-* 42 | 43 | # .nfs files are created when an open file is removed but is still being accessed 44 | .nfs* 45 | 46 | # General 47 | .DS_Store 48 | .AppleDouble 49 | .LSOverride 50 | 51 | # Icon must end with two \r 52 | Icon 53 | 54 | # Thumbnails 55 | ._* 56 | 57 | # Files that might appear in the root of a volume 58 | .DocumentRevisions-V100 59 | .fseventsd 60 | .Spotlight-V100 61 | .TemporaryItems 62 | .Trashes 63 | .VolumeIcon.icns 64 | .com.apple.timemachine.donotpresent 65 | 66 | # Directories potentially created on remote AFP share 67 | .AppleDB 68 | .AppleDesktop 69 | Network Trash Folder 70 | Temporary Items 71 | .apdisk 72 | 73 | # Windows thumbnail cache files 74 | Thumbs.db 75 | Thumbs.db:encryptable 76 | ehthumbs.db 77 | ehthumbs_vista.db 78 | 79 | # Dump file 80 | *.stackdump 81 | 82 | # Folder config file 83 | [Dd]esktop.ini 84 | 85 | # Recycle Bin used on file shares 86 | $RECYCLE.BIN/ 87 | 88 | # Windows Installer files 89 | *.cab 90 | *.msi 91 | *.msix 92 | *.msm 93 | *.msp 94 | 95 | # Windows shortcuts 96 | *.lnk 97 | 98 | target/ 99 | 100 | pom.xml.tag 101 | pom.xml.releaseBackup 102 | pom.xml.versionsBackup 103 | pom.xml.next 104 | 105 | release.properties 106 | dependency-reduced-pom.xml 107 | buildNumber.properties 108 | .mvn/timing.properties 109 | .mvn/wrapper/maven-wrapper.jar 110 | .flattened-pom.xml 111 | 112 | # Common working directory 113 | run/ 114 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-2025 Demeng Chen 4 | Copyright (c) contributors 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PluginBase 2 | 3 | PluginBase is an extensive library designed to streamline the creation of Spigot plugins. This 4 | library provides a solid foundation to build upon, making plugin development more efficient and 5 | manageable. 6 | 7 | The majority of my public Spigot 8 | plugins ([CommandButtons](https://github.com/demengc/CommandButtons), [RankGrant+](https://github.com/demengc/RankGrantPlus), [UltraRepair](https://github.com/demengc/UltraRepair), 9 | etc.) and private projects are using PluginBase! 10 | 11 | ## Modules 12 | 13 | ### pluginbase-core 14 | 15 | The main module containing the core functionality of PluginBase. A rough, incomplete overview of the 16 | features is as follows: 17 | 18 | - Schedulers (async/sync runnables, delayed/repeated tasks, etc.) 19 | - Text utilities (i.e. colorizing strings with HEX and Adventure support, centered messages, 20 | components, 21 | etc.) 22 | - Localization/translation system 23 | - Event handling and listener registration 24 | - Serialization from immutable equivalents of Bukkit objects to YAML 25 | - Custom GUIs with deserializable buttons 26 | - Cooldown maps 27 | - Chat input requests 28 | - Item builder 29 | - GSON provider 30 | - Custom YAML configuration files 31 | - SpigotMC resource update checker 32 | - Cross-version compatibility utilities 33 | - Powerful command framework (Lamp) 34 | 35 | ### pluginbase-games 36 | 37 | A framework for creating minigames. Uses a state-based system to allow for efficient handling of 38 | games that are composed of multiple stages (i.e. preparation phase, fighting phase, celebration 39 | phase, etc.). 40 | 41 | ### pluginbase-sql 42 | 43 | A module for handling SQL databases using the connection pooling 44 | library [HikariCP](https://github.com/brettwooldridge/HikariCP). Some features include connection 45 | management, credential deserialization, statement handlers (prepared statements), result set 46 | handlers, and sync/async queries/executions. 47 | 48 | ### pluginbase-mongo 49 | 50 | A simple module that allows for easy connections to MongoDB databases. 51 | 52 | ### pluginbase-redis 53 | 54 | A module that facilitates cross-server communication using Redis publish-subscribe messaging. 55 | Capable 56 | of handling objects. 57 | 58 | ## Documentation 59 | 60 | For installation instructions, feature guides, and examples, visit 61 | the **[PluginBase Documentation](https://demeng.gitbook.io/pluginbase)**. 62 | 63 | ## Contributing 64 | 65 | Contributions are welcome! If you have suggestions for improvements or find bugs, feel free to 66 | create a pull request. 67 | 68 | ## License 69 | 70 | This project is licensed under the MIT License. For more details, refer to the LICENSE.txt file in 71 | the repository. 72 | 73 | ## Special Thanks 74 | 75 | Special thanks to the following for their contribution to this project: 76 | 77 | - [lucko](https://github.com/lucko/helper) for creating helper, a major part of this library 78 | - [CryptoMorin](https://github.com/CryptoMorin/XSeries) for creating XSeries, a library that enables 79 | cross-version compatibility 80 | - [Revxrsal](https://github.com/Revxrsal/Lamp) for creating Lamp, a powerful command framework 81 | 82 | ## Support 83 | 84 | If you need help or have any questions, you can create an issue in this repository or find me on 85 | my [Discord server](https://demeng.dev/discord). While support for PluginBase is limited, I'll do my 86 | best to assist where possible. 87 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: Comprehensive utility library for Spigot plugin development. 3 | --- 4 | 5 | # Introduction 6 | 7 | ## What is PluginBase? 8 | 9 | PluginBase streamlines Spigot plugin development by providing ready-to-use components that eliminate boilerplate code and enforce best practices. 10 | 11 | ## Key Features 12 | 13 | ### Core Features 14 | 15 | * **Dependency Injection** - Simple DI with @Component annotation 16 | * **Events** - Functional event handling 17 | * **Commands** - Powerful annotation-driven commands framework (Lamp) 18 | * **Text & Localization** - HEX colors, MiniMessage, i18n 19 | * **Schedulers** - Sync/async tasks with Promise API 20 | * **Configuration** - YAML config management 21 | * **Terminables** - Automatic resource lifecycle 22 | * **Menus** - Inventory GUIs with buttons 23 | * **ItemBuilder** - Fluent item creation 24 | * **Cooldowns** - Player/action cooldown tracking 25 | * **Utilities** - Common helpers (Players, Locations, Sounds, etc.) 26 | * **Cross-Version Compatibility** - [XSeries](https://github.com/CryptoMorin/XSeries) 27 | * ...and more! This documentation is not comprehensive, and many features are not included here. 28 | 29 | ### Optional Modules 30 | 31 | * **pluginbase-sql** - HikariCP SQL database 32 | * **pluginbase-mongo** - MongoDB integration 33 | * **pluginbase-redis** - Redis pub/sub messaging 34 | * **pluginbase-games** - Minigame state framework 35 | 36 | ## Version Compatibility 37 | 38 | **Supported:** All major versions between Minecraft 1.8.8 - 1.21.10. Java 17+ is required. 39 | 40 | ## Quick Start 41 | 42 | See [Getting Started](overview/getting-started.md) for installation instructions and your first plugin. This documentation focuses on example-driven guides for core features and optional modules. 43 | -------------------------------------------------------------------------------- /docs/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Table of contents 2 | 3 | ## Overview 4 | 5 | * [Introduction](README.md) 6 | * [Getting Started](overview/getting-started.md) 7 | 8 | ## Core Features 9 | 10 | * [Utilities](core-features/utilities.md) 11 | * [Commands](core-features/commands.md) 12 | * [Dependency Injection](core-features/dependency-injection.md) 13 | * [Events](core-features/events.md) 14 | * [Text & Localization](core-features/text-and-localization.md) 15 | * [Schedulers](core-features/schedulers.md) 16 | * [Configuration](core-features/configuration.md) 17 | * [Terminables](core-features/terminables.md) 18 | * [Menus](core-features/menus.md) 19 | * [ItemBuilder](core-features/item-builder.md) 20 | * [Cooldowns](core-features/cooldowns.md) 21 | 22 | ## Optional Modules 23 | 24 | * [SQL](optional-modules/sql.md) 25 | * [MongoDB](optional-modules/mongodb.md) 26 | * [Redis](optional-modules/redis.md) 27 | * [Games](optional-modules/games.md) 28 | -------------------------------------------------------------------------------- /docs/core-features/cooldowns.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: Track cooldowns for players, actions, or any key. 3 | --- 4 | 5 | # Cooldowns 6 | 7 | ## Basic Usage 8 | 9 | ```java 10 | import dev.demeng.pluginbase.cooldown.Cooldown; 11 | import dev.demeng.pluginbase.cooldown.CooldownMap; 12 | import java.util.UUID; 13 | import java.util.concurrent.TimeUnit; 14 | 15 | // Create cooldown map 16 | CooldownMap cooldowns = CooldownMap.create( 17 | Cooldown.of(30, TimeUnit.SECONDS) 18 | ); 19 | 20 | // Test cooldown 21 | UUID playerId = player.getUniqueId(); 22 | if (cooldowns.test(playerId)) { 23 | // Player can perform action 24 | Text.tell(player, "&aAction performed!"); 25 | } else { 26 | // Player is on cooldown 27 | long remaining = cooldowns.remainingTime(playerId, TimeUnit.SECONDS); 28 | Text.tell(player, "&cPlease wait " + remaining + " seconds!"); 29 | } 30 | ``` 31 | 32 | ## Complete Example 33 | 34 | ```java 35 | public class TeleportCommand { 36 | private final CooldownMap cooldowns = CooldownMap.create( 37 | Cooldown.of(5, TimeUnit.MINUTES) 38 | ); 39 | 40 | @Command("home") 41 | public void home(Player sender) { 42 | UUID uuid = sender.getUniqueId(); 43 | 44 | // Check cooldown 45 | if (!cooldowns.test(uuid)) { 46 | long remaining = cooldowns.remainingTime(uuid, TimeUnit.SECONDS); 47 | Text.tell(sender, "&cPlease wait " + remaining + " seconds!"); 48 | return; 49 | } 50 | 51 | // Perform action 52 | Location home = getHome(sender); 53 | sender.teleport(home); 54 | Text.tell(sender, "&aTeleported home!"); 55 | } 56 | } 57 | ``` 58 | 59 | ## Other Key Types 60 | 61 | ```java 62 | // Cooldown by string key 63 | CooldownMap messageCooldowns = CooldownMap.create( 64 | Cooldown.of(1, TimeUnit.MINUTES) 65 | ); 66 | 67 | // Per-message cooldown 68 | String key = player.getName() + ":welcome"; 69 | if (messageCooldowns.test(key)) { 70 | Text.tell(player, "&aWelcome message!"); 71 | } 72 | ``` 73 | 74 | ## Manual Management 75 | 76 | ```java 77 | CooldownMap cooldowns = CooldownMap.create( 78 | Cooldown.of(30, TimeUnit.SECONDS) 79 | ); 80 | 81 | UUID uuid = player.getUniqueId(); 82 | 83 | // Reset cooldown (starts the cooldown timer) 84 | cooldowns.reset(uuid); 85 | 86 | // Get remaining time 87 | long remaining = cooldowns.remainingTime(uuid, TimeUnit.SECONDS); 88 | 89 | // Get elapsed time in milliseconds 90 | long elapsedMillis = cooldowns.elapsed(uuid); 91 | 92 | // Get the cooldown instance for advanced operations 93 | Cooldown cooldown = cooldowns.get(uuid); 94 | 95 | // Put a specific cooldown instance (must have same duration as base) 96 | cooldowns.put(uuid, Cooldown.of(30, TimeUnit.SECONDS)); 97 | ``` 98 | -------------------------------------------------------------------------------- /docs/core-features/dependency-injection.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: Simple DI system for managing class dependencies with constructor injection. 3 | --- 4 | 5 | # Dependency Injection 6 | 7 | ## Basic Usage 8 | 9 | ### Registration 10 | 11 | ```java 12 | @Override 13 | protected DependencyContainer configureDependencies() { 14 | // Create instances 15 | Sql sql = new Sql(null, null, credentials); 16 | DataStorage storage = new MySQLStorage(sql); 17 | 18 | // Register dependencies 19 | return DependencyInjection.builder() 20 | .register(this) // Register plugin instance 21 | .register(Sql.class, sql) 22 | .register(DataStorage.class, storage) 23 | .build(); 24 | } 25 | ``` 26 | 27 | ### Using @Component 28 | 29 | ```java 30 | @Component 31 | public class PlayerManager { 32 | private final DataStorage storage; 33 | 34 | // Constructor injection 35 | public PlayerManager(DataStorage storage) { 36 | this.storage = storage; 37 | } 38 | } 39 | ``` 40 | 41 | Components are automatically created when first requested and reused (singleton). 42 | 43 | ### Getting Dependencies Manually 44 | 45 | ```java 46 | // In BasePlugin 47 | PlayerManager manager = getDependency(PlayerManager.class); 48 | 49 | // Anywhere else (requires access to plugin instance) 50 | PlayerManager manager = plugin.getDependency(PlayerManager.class); 51 | // Or via the container directly 52 | PlayerManager manager = plugin.getDependencyContainer().getInstance(PlayerManager.class); 53 | ``` 54 | 55 | ## Complete Example 56 | 57 | ```java 58 | // Interface 59 | public interface DataStorage { 60 | void save(UUID uuid, PlayerData data); 61 | PlayerData load(UUID uuid); 62 | } 63 | 64 | // Implementation 65 | public class MySQLStorage implements DataStorage { 66 | private final Sql sql; 67 | 68 | public MySQLStorage(Sql sql) { 69 | this.sql = sql; 70 | } 71 | 72 | @Override 73 | public void save(UUID uuid, PlayerData data) { 74 | sql.execute("INSERT INTO players VALUES (?, ?)", stmt -> { 75 | stmt.setString(1, uuid.toString()); 76 | stmt.setString(2, data.serialize()); 77 | }); 78 | } 79 | 80 | @Override 81 | public PlayerData load(UUID uuid) { 82 | return sql.query("SELECT * FROM players WHERE uuid = ?", 83 | stmt -> stmt.setString(1, uuid.toString()), 84 | rs -> rs.next() ? PlayerData.deserialize(rs.getString("data")) : null 85 | ).orElse(null); 86 | } 87 | } 88 | 89 | // Component using the storage 90 | @Component 91 | public class PlayerManager { 92 | private final DataStorage storage; 93 | 94 | public PlayerManager(DataStorage storage) { 95 | this.storage = storage; 96 | } 97 | 98 | public void savePlayer(UUID uuid, PlayerData data) { 99 | storage.save(uuid, data); 100 | } 101 | } 102 | 103 | // Plugin setup 104 | public class MyPlugin extends BasePlugin { 105 | @Override 106 | protected DependencyContainer configureDependencies() { 107 | Sql sql = new Sql(null, null, credentials); 108 | DataStorage storage = new MySQLStorage(sql); 109 | 110 | return DependencyInjection.builder() 111 | .register(this) 112 | .register(Sql.class, sql) 113 | .register(DataStorage.class, storage) // Register by interface 114 | .build(); 115 | } 116 | 117 | @Override 118 | protected void enable() { 119 | PlayerManager manager = getDependency(PlayerManager.class); 120 | // Use manager... 121 | } 122 | } 123 | ``` 124 | -------------------------------------------------------------------------------- /docs/core-features/events.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: Functional event handling with lambda expressions instead of listener classes. 3 | --- 4 | 5 | # Events 6 | 7 | ## Basic Usage 8 | 9 | ```java 10 | Events.subscribe(PlayerJoinEvent.class) 11 | .handler(event -> { 12 | Player player = event.getPlayer(); 13 | Text.tell(player, "&aWelcome!"); 14 | }) 15 | .bindWith(this); // Auto-unregister on disable 16 | ``` 17 | 18 | ## With Filters 19 | 20 | ```java 21 | Events.subscribe(PlayerMoveEvent.class) 22 | .filter(e -> e.getPlayer().hasPermission("special")) 23 | .filter(e -> !e.getFrom().getBlock().equals(e.getTo().getBlock())) 24 | .handler(e -> { 25 | // Only called for players with permission 26 | // And only when moving to different block 27 | }) 28 | .bindWith(this); 29 | ``` 30 | 31 | ## Method References 32 | 33 | ```java 34 | Events.subscribe(PlayerJoinEvent.class) 35 | .handler(this::onPlayerJoin) 36 | .bindWith(this); 37 | 38 | private void onPlayerJoin(PlayerJoinEvent event) { 39 | Text.tell(event.getPlayer(), "&aWelcome!"); 40 | } 41 | ``` 42 | 43 | ## Event Priority 44 | 45 | ```java 46 | Events.subscribe(AsyncPlayerChatEvent.class, EventPriority.HIGHEST) 47 | .handler(e -> { 48 | // Handled at HIGHEST priority 49 | }) 50 | .bindWith(this); 51 | ``` 52 | 53 | ## Expiry 54 | 55 | ```java 56 | // Unregister after 10 calls 57 | Events.subscribe(PlayerInteractEvent.class) 58 | .expireAfter(10) 59 | .handler(e -> {}) 60 | .bindWith(this); 61 | 62 | // Unregister after 30 seconds 63 | Events.subscribe(PlayerMoveEvent.class) 64 | .expireAfter(30, TimeUnit.SECONDS) 65 | .handler(e -> {}) 66 | .bindWith(this); 67 | ``` 68 | 69 | ## Merged Events 70 | 71 | Listen to multiple **related** events: 72 | 73 | ```java 74 | // Both EntityDamageEvent and EntityDeathEvent are related to EntityEvent 75 | Events.merge(EntityEvent.class, EntityDamageEvent.class, EntityDeathEvent.class) 76 | .handler(event -> { 77 | Entity entity = event.getEntity(); 78 | if (entity instanceof Player) { 79 | // Handle either event type 80 | } 81 | }) 82 | .bindWith(this); 83 | ``` 84 | 85 | ## Complete Example 86 | 87 | ```java 88 | public class MyPlugin extends BasePlugin { 89 | 90 | @Override 91 | protected void enable() { 92 | // Welcome VIP players 93 | Events.subscribe(PlayerJoinEvent.class) 94 | .filter(e -> e.getPlayer().hasPermission("vip")) 95 | .handler(e -> Text.tell(e.getPlayer(), "&6Welcome VIP!")) 96 | .bindWith(this); 97 | 98 | // Freeze player for 5 seconds 99 | Events.subscribe(PlayerMoveEvent.class) 100 | .filter(e -> shouldFreeze(e.getPlayer())) 101 | .expireAfter(5, TimeUnit.SECONDS) 102 | .handler(e -> e.setCancelled(true)) 103 | .bindWith(this); 104 | 105 | // Log damage to players 106 | Events.subscribe(EntityDamageEvent.class) 107 | .filter(e -> e.getEntity() instanceof Player) 108 | .handler(e -> { 109 | Player player = (Player) e.getEntity(); 110 | Text.console("&7" + player.getName() + " took " + e.getDamage() + " damage"); 111 | }) 112 | .bindWith(this); 113 | } 114 | } 115 | ``` 116 | -------------------------------------------------------------------------------- /jitpack.yml: -------------------------------------------------------------------------------- 1 | before_install: 2 | - wget https://github.com/sormuras/bach/raw/master/install-jdk.sh 3 | - source ./install-jdk.sh --feature 17 4 | jdk: 5 | - openjdk17 -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/Locations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase; 26 | 27 | import lombok.AccessLevel; 28 | import lombok.NoArgsConstructor; 29 | import org.bukkit.Location; 30 | import org.jetbrains.annotations.NotNull; 31 | 32 | /** Utilities for {@link org.bukkit.Location}. */ 33 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 34 | public final class Locations { 35 | 36 | /** 37 | * Rounds a location to the center of a block. 38 | * 39 | * @param loc The location to center 40 | * @return The centered location 41 | */ 42 | @NotNull 43 | public static Location center(@NotNull final Location loc) { 44 | return new Location( 45 | loc.getWorld(), 46 | loc.getBlockX() + 0.5, 47 | loc.getBlockY(), 48 | loc.getBlockZ() + 0.5, 49 | loc.getYaw(), 50 | loc.getPitch()); 51 | } 52 | 53 | /** 54 | * Converts a location to a block location (world and integer coordinates). 55 | * 56 | * @param loc The location to convert to a block location 57 | * @return The block position 58 | */ 59 | @NotNull 60 | public static Location toBlockLocation(@NotNull final Location loc) { 61 | return new Location(loc.getWorld(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/Players.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * Copyright (c) lucko (Luck) 6 | * Copyright (c) lucko/helper contributors 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | package dev.demeng.pluginbase; 28 | 29 | import java.util.Collection; 30 | import java.util.Objects; 31 | import java.util.function.Consumer; 32 | import java.util.stream.Stream; 33 | import lombok.AccessLevel; 34 | import lombok.NoArgsConstructor; 35 | import org.bukkit.Bukkit; 36 | import org.bukkit.Location; 37 | import org.bukkit.entity.EntityType; 38 | import org.bukkit.entity.Player; 39 | import org.jetbrains.annotations.NotNull; 40 | 41 | /** Utility for operations involving multiple players. */ 42 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 43 | public final class Players { 44 | 45 | /** 46 | * Gets all players on the server. 47 | * 48 | * @return All players on the server 49 | */ 50 | @NotNull 51 | public static Collection all() { 52 | //noinspection unchecked 53 | return (Collection) Bukkit.getOnlinePlayers(); 54 | } 55 | 56 | /** 57 | * Gets a stream of all players on the server. 58 | * 59 | * @return A stream of all players on the server 60 | */ 61 | @NotNull 62 | public static Stream stream() { 63 | return all().stream(); 64 | } 65 | 66 | /** 67 | * Applies a given action to all players on the server. 68 | * 69 | * @param consumer The action to apply 70 | */ 71 | public static void forEach(@NotNull final Consumer consumer) { 72 | all().forEach(consumer); 73 | } 74 | 75 | /** 76 | * Gets a stream of all players within a given radius of a point. 77 | * 78 | * @param center The point 79 | * @param radius The radius 80 | * @return A stream of players 81 | */ 82 | @NotNull 83 | public static Stream streamInRange(@NotNull final Location center, final double radius) { 84 | Objects.requireNonNull(center.getWorld(), "Provided location does not specify world"); 85 | return center.getWorld().getNearbyEntities(center, radius, radius, radius).stream() 86 | .filter(e -> e.getType() == EntityType.PLAYER) 87 | .map(Player.class::cast); 88 | } 89 | 90 | /** 91 | * Applies an action to all players within a given radius of a point. 92 | * 93 | * @param center The point 94 | * @param radius The radius 95 | * @param consumer The action to apply 96 | */ 97 | public static void forEachInRange( 98 | @NotNull final Location center, 99 | final double radius, 100 | @NotNull final Consumer consumer) { 101 | streamInRange(center, radius).forEach(consumer); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/ServerProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase; 26 | 27 | import dev.demeng.pluginbase.exceptions.BaseException; 28 | import java.io.File; 29 | import java.io.FileInputStream; 30 | import java.io.IOException; 31 | import java.util.HashMap; 32 | import java.util.Map; 33 | import java.util.Properties; 34 | import lombok.AccessLevel; 35 | import lombok.NoArgsConstructor; 36 | 37 | /** Utility for getting information from server.properties. */ 38 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 39 | public final class ServerProperties { 40 | 41 | private static final Map cache = new HashMap<>(); 42 | private static File propertiesFile; 43 | 44 | /** 45 | * Gets a property from server.properties. 46 | * 47 | * @param key The property key 48 | * @return The property value, or null if failed to retrieve 49 | */ 50 | public static String getProperty(final String key) { 51 | 52 | if (cache.containsKey(key)) { 53 | return cache.get(key); 54 | } 55 | 56 | final Properties properties = new Properties(); 57 | 58 | try (final FileInputStream in = new FileInputStream(getPropertiesFile())) { 59 | properties.load(in); 60 | 61 | final String value = properties.getProperty(key); 62 | cache.put(key, value); 63 | return value; 64 | 65 | } catch (final IOException ex) { 66 | Common.error(ex, "Failed to get server property: " + key, false); 67 | return null; 68 | } 69 | } 70 | 71 | /** Clears the properties cache. */ 72 | public static void clearCache() { 73 | cache.clear(); 74 | } 75 | 76 | private static File getPropertiesFile() { 77 | 78 | if (propertiesFile != null) { 79 | return propertiesFile; 80 | } 81 | 82 | propertiesFile = new File("server.properties"); 83 | 84 | if (!propertiesFile.exists()) { 85 | throw new BaseException("Could not locate server.properties"); 86 | } 87 | 88 | return propertiesFile; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/TrimmedUuids.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase; 26 | 27 | import java.util.UUID; 28 | import lombok.AccessLevel; 29 | import lombok.NoArgsConstructor; 30 | 31 | /** Utility for converting to and from trimmed UUIDs. */ 32 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 33 | public final class TrimmedUuids { 34 | 35 | /** 36 | * Returns a UUID string without dashes (trimmed). 37 | * 38 | * @param uuid The UUID 39 | * @return The trimmed UUID 40 | */ 41 | public static String toString(final UUID uuid) { 42 | return (digits(uuid.getMostSignificantBits() >> 32, 8) 43 | + digits(uuid.getMostSignificantBits() >> 16, 4) 44 | + digits(uuid.getMostSignificantBits(), 4) 45 | + digits(uuid.getLeastSignificantBits() >> 48, 4) 46 | + digits(uuid.getLeastSignificantBits(), 12)); 47 | } 48 | 49 | /** 50 | * Parses a UUID from a trimmed string. 51 | * 52 | * @param string The trimmed UUID 53 | * @return The UUID 54 | */ 55 | public static UUID fromString(final String string) throws IllegalArgumentException { 56 | 57 | if (string.length() != 32) { 58 | throw new IllegalArgumentException("Invalid length '" + string.length() + "': " + string); 59 | } 60 | 61 | try { 62 | return new UUID( 63 | Long.parseUnsignedLong(string.substring(0, 16), 16), 64 | Long.parseUnsignedLong(string.substring(16), 16)); 65 | } catch (final NumberFormatException ex) { 66 | throw new IllegalArgumentException("Invalid UUID string: " + string, ex); 67 | } 68 | } 69 | 70 | private static String digits(final long val, final int digits) { 71 | final long hi = 1L << (digits * 4); 72 | return Long.toHexString(hi | (val & (hi - 1))).substring(1); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/bucket/Bucket.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.bucket; 27 | 28 | import dev.demeng.pluginbase.bucket.partitioning.PartitioningStrategy; 29 | import java.util.List; 30 | import java.util.Set; 31 | import javax.annotation.Nonnull; 32 | 33 | /** 34 | * A bucket is an extension of {@link Set}, which allows contained elements to be separated into 35 | * parts by a {@link PartitioningStrategy}. 36 | * 37 | *

The performance of {@link Bucket} should be largely similar to the performance of the 38 | * underlying {@link Set}. Elements are stored twice - once in a set containing all elements in the 39 | * bucket, and again in a set representing each partition. 40 | * 41 | * @param the element type 42 | */ 43 | public interface Bucket extends Set { 44 | 45 | /** 46 | * Gets the number of partitions used to form this bucket. 47 | * 48 | * @return the number of partitions in this bucket 49 | */ 50 | int getPartitionCount(); 51 | 52 | /** 53 | * Gets the partition with the given index value 54 | * 55 | * @param i the partition index 56 | * @return the partition 57 | * @throws IndexOutOfBoundsException if the index is out of range (index < 0 || index >= 58 | * getPartitionCount()) 59 | */ 60 | @Nonnull 61 | BucketPartition getPartition(int i); 62 | 63 | /** 64 | * Gets the partitions which form this bucket. 65 | * 66 | * @return the partitions within the bucket 67 | */ 68 | @Nonnull 69 | List> getPartitions(); 70 | 71 | /** 72 | * Returns a cycle instance unique to this bucket. 73 | * 74 | *

This method is provided as a utility for operating deterministically on all elements within 75 | * the bucket over a period of time. 76 | * 77 | *

The same cycle instance is returned for each bucket. 78 | * 79 | * @return a cycle of partitions 80 | */ 81 | @Nonnull 82 | Cycle> asCycle(); 83 | } 84 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/bucket/BucketPartition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.bucket; 27 | 28 | import java.util.Collection; 29 | import java.util.Set; 30 | 31 | /** 32 | * Represents a partition of elements within a {@link Bucket}. 33 | * 34 | * @param the element type 35 | */ 36 | public interface BucketPartition extends Set { 37 | 38 | /** 39 | * Gets the index of this partition within the bucket 40 | * 41 | * @return the index 42 | */ 43 | int getPartitionIndex(); 44 | 45 | /** 46 | * {@inheritDoc} 47 | * 48 | * @deprecated as partitions do not support this method. 49 | */ 50 | @Override 51 | @Deprecated 52 | default boolean add(final E e) { 53 | throw new UnsupportedOperationException(); 54 | } 55 | 56 | /** 57 | * {@inheritDoc} 58 | * 59 | * @deprecated as partitions do not support this method. 60 | */ 61 | @Override 62 | @Deprecated 63 | default boolean addAll(final Collection c) { 64 | throw new UnsupportedOperationException(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/bucket/factory/BucketFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.bucket.factory; 27 | 28 | import dev.demeng.pluginbase.bucket.Bucket; 29 | import dev.demeng.pluginbase.bucket.partitioning.PartitioningStrategy; 30 | import java.util.Set; 31 | import java.util.function.Supplier; 32 | 33 | /** A set of methods for creating {@link Bucket}s. */ 34 | public final class BucketFactory { 35 | 36 | public static Bucket newBucket( 37 | final int size, final PartitioningStrategy strategy, final Supplier> setSupplier) { 38 | return new SetSuppliedBucket<>(size, strategy, setSupplier); 39 | } 40 | 41 | public static Bucket newHashSetBucket( 42 | final int size, final PartitioningStrategy strategy) { 43 | return new HashSetBucket<>(size, strategy); 44 | } 45 | 46 | public static Bucket newSynchronizedHashSetBucket( 47 | final int size, final PartitioningStrategy strategy) { 48 | return new SynchronizedHashSetBucket<>(size, strategy); 49 | } 50 | 51 | public static Bucket newConcurrentBucket( 52 | final int size, final PartitioningStrategy strategy) { 53 | return new ConcurrentBucket<>(size, strategy); 54 | } 55 | 56 | private BucketFactory() { 57 | throw new UnsupportedOperationException("This class cannot be instantiated"); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/bucket/factory/ConcurrentBucket.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.bucket.factory; 27 | 28 | import dev.demeng.pluginbase.bucket.AbstractBucket; 29 | import dev.demeng.pluginbase.bucket.partitioning.PartitioningStrategy; 30 | import java.util.Set; 31 | import java.util.concurrent.ConcurrentHashMap; 32 | 33 | class ConcurrentBucket extends AbstractBucket { 34 | 35 | ConcurrentBucket(final int size, final PartitioningStrategy strategy) { 36 | super(size, strategy); 37 | } 38 | 39 | @Override 40 | protected Set createSet() { 41 | return ConcurrentHashMap.newKeySet(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/bucket/factory/HashSetBucket.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.bucket.factory; 27 | 28 | import dev.demeng.pluginbase.bucket.AbstractBucket; 29 | import dev.demeng.pluginbase.bucket.partitioning.PartitioningStrategy; 30 | import java.util.HashSet; 31 | import java.util.Set; 32 | 33 | class HashSetBucket extends AbstractBucket { 34 | 35 | HashSetBucket(final int size, final PartitioningStrategy partitioningStrategy) { 36 | super(size, partitioningStrategy); 37 | } 38 | 39 | @Override 40 | protected Set createSet() { 41 | return new HashSet<>(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/bucket/factory/SetSuppliedBucket.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.bucket.factory; 27 | 28 | import dev.demeng.pluginbase.bucket.AbstractBucket; 29 | import dev.demeng.pluginbase.bucket.partitioning.PartitioningStrategy; 30 | import java.util.Set; 31 | import java.util.function.Supplier; 32 | 33 | class SetSuppliedBucket extends AbstractBucket { 34 | 35 | private final Supplier> setSupplier; 36 | 37 | SetSuppliedBucket( 38 | final int size, final PartitioningStrategy strategy, final Supplier> setSupplier) { 39 | super(size, strategy); 40 | this.setSupplier = setSupplier; 41 | } 42 | 43 | @Override 44 | protected Set createSet() { 45 | return this.setSupplier.get(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/bucket/factory/SynchronizedHashSetBucket.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.bucket.factory; 27 | 28 | import dev.demeng.pluginbase.bucket.AbstractBucket; 29 | import dev.demeng.pluginbase.bucket.partitioning.PartitioningStrategy; 30 | import java.util.Collections; 31 | import java.util.HashSet; 32 | import java.util.Set; 33 | 34 | class SynchronizedHashSetBucket extends AbstractBucket { 35 | 36 | SynchronizedHashSetBucket(final int size, final PartitioningStrategy partitioningStrategy) { 37 | super(size, partitioningStrategy); 38 | } 39 | 40 | @Override 41 | protected Set createSet() { 42 | return Collections.synchronizedSet(new HashSet<>()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/bucket/partitioning/GenericPartitioningStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.bucket.partitioning; 27 | 28 | import dev.demeng.pluginbase.bucket.Bucket; 29 | 30 | /** 31 | * A {@link PartitioningStrategy} which allocates partitions without reference to the object being 32 | * added. 33 | */ 34 | @FunctionalInterface 35 | public interface GenericPartitioningStrategy extends PartitioningStrategy { 36 | 37 | /** 38 | * Calculates the index of the partition to use for any given object. 39 | * 40 | * @param bucket the bucket 41 | * @return the index 42 | */ 43 | int allocate(Bucket bucket); 44 | 45 | /** 46 | * Casts this {@link GenericPartitioningStrategy} to a {@link PartitioningStrategy} of type T. 47 | * 48 | * @param the type 49 | * @return a casted strategy 50 | */ 51 | default PartitioningStrategy cast() { 52 | //noinspection unchecked 53 | return (PartitioningStrategy) this; 54 | } 55 | 56 | @Override 57 | @Deprecated 58 | default int allocate(final Object object, final Bucket bucket) { 59 | return allocate(bucket); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/bucket/partitioning/PartitioningStrategies.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.bucket.partitioning; 27 | 28 | import dev.demeng.pluginbase.bucket.Bucket; 29 | import dev.demeng.pluginbase.bucket.BucketPartition; 30 | import java.util.concurrent.ThreadLocalRandom; 31 | 32 | /** Some standard partitioning strategies for use in {@link Bucket}s. */ 33 | public final class PartitioningStrategies { 34 | 35 | public static PartitioningStrategy random() { 36 | return Strategies.RANDOM.cast(); 37 | } 38 | 39 | public static PartitioningStrategy lowestSize() { 40 | return Strategies.LOWEST_SIZE.cast(); 41 | } 42 | 43 | public static PartitioningStrategy nextInCycle() { 44 | return Strategies.NEXT_IN_CYCLE.cast(); 45 | } 46 | 47 | public static PartitioningStrategy previousInCycle() { 48 | return Strategies.PREVIOUS_IN_CYCLE.cast(); 49 | } 50 | 51 | private enum Strategies implements GenericPartitioningStrategy { 52 | RANDOM { 53 | @Override 54 | public int allocate(final Bucket bucket) { 55 | return ThreadLocalRandom.current().nextInt(bucket.getPartitionCount()); 56 | } 57 | }, 58 | LOWEST_SIZE { 59 | @Override 60 | public int allocate(final Bucket bucket) { 61 | int index = -1; 62 | int lowestSize = Integer.MAX_VALUE; 63 | 64 | for (final BucketPartition partition : bucket.getPartitions()) { 65 | final int size = partition.size(); 66 | final int i = partition.getPartitionIndex(); 67 | 68 | if (size == 0) { 69 | return i; 70 | } 71 | 72 | if (size < lowestSize) { 73 | lowestSize = size; 74 | index = i; 75 | } 76 | } 77 | 78 | if (index == -1) { 79 | throw new AssertionError(); 80 | } 81 | return index; 82 | } 83 | }, 84 | NEXT_IN_CYCLE { 85 | @Override 86 | public int allocate(final Bucket bucket) { 87 | return bucket.asCycle().next().getPartitionIndex(); 88 | } 89 | }, 90 | PREVIOUS_IN_CYCLE { 91 | @Override 92 | public int allocate(final Bucket bucket) { 93 | return bucket.asCycle().previous().getPartitionIndex(); 94 | } 95 | } 96 | } 97 | 98 | private PartitioningStrategies() { 99 | throw new UnsupportedOperationException("This class cannot be instantiated"); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/bucket/partitioning/PartitioningStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.bucket.partitioning; 27 | 28 | import dev.demeng.pluginbase.bucket.Bucket; 29 | 30 | /** 31 | * A function which determines the position of an object within a {@link Bucket}. 32 | * 33 | *

Functions will not necessarily return consistent results for subsequent calls using the same 34 | * parameters, as their behaviour usually depends heavily on current bucket state. 35 | * 36 | * @param the object type 37 | */ 38 | @FunctionalInterface 39 | public interface PartitioningStrategy { 40 | 41 | /** 42 | * Calculates the index of the partition to use for the object. 43 | * 44 | *

The index must be within range of the buckets size. 45 | * 46 | * @param object the object 47 | * @param bucket the bucket 48 | * @return the index 49 | */ 50 | int allocate(T object, Bucket bucket); 51 | } 52 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/delegate/Delegate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.delegate; 27 | 28 | /** 29 | * Represents a class which delegates calls to a different object. 30 | * 31 | * @param The delegate type 32 | */ 33 | public interface Delegate { 34 | 35 | /** 36 | * Resolves for the provided object. 37 | * 38 | * @param obj The object to resolve 39 | * @return The delegated result 40 | */ 41 | static Object resolve(Object obj) { 42 | while (obj instanceof Delegate) { 43 | final Delegate delegate = (Delegate) obj; 44 | obj = delegate.getDelegate(); 45 | } 46 | 47 | return obj; 48 | } 49 | 50 | /** 51 | * Gets the delegate object. 52 | * 53 | * @return The delegate object 54 | */ 55 | T getDelegate(); 56 | } 57 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/di/annotation/Component.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase.di.annotation; 26 | 27 | import java.lang.annotation.ElementType; 28 | import java.lang.annotation.Retention; 29 | import java.lang.annotation.RetentionPolicy; 30 | import java.lang.annotation.Target; 31 | 32 | /** 33 | * Marks a class as a component that can be auto-created by the dependency injection container. 34 | * 35 | *

Classes marked with this annotation will be automatically instantiated when requested, with 36 | * their dependencies injected from the container. All components are singletons - only one instance 37 | * is created and cached. 38 | * 39 | *

Dependencies are injected via constructor. The container supports Lombok's 40 | * {@code @RequiredArgsConstructor} and {@code @AllArgsConstructor}. 41 | * 42 | *

Example usage: 43 | * 44 | *

{@code
45 |  * @Component
46 |  * public class PlayerDataManager {
47 |  *   private final DatabaseConnection database;
48 |  *   private final CacheService cache;
49 |  *
50 |  *   // Dependencies auto-injected
51 |  *   public PlayerDataManager(DatabaseConnection database, CacheService cache) {
52 |  *     this.database = database;
53 |  *     this.cache = cache;
54 |  *   }
55 |  * }
56 |  *
57 |  * // With Lombok:
58 |  * @Component
59 |  * @RequiredArgsConstructor
60 |  * public class PlayerDataManager {
61 |  *   private final DatabaseConnection database;
62 |  *   private final CacheService cache;
63 |  * }
64 |  * }
65 | */ 66 | @Target(ElementType.TYPE) 67 | @Retention(RetentionPolicy.RUNTIME) 68 | public @interface Component { 69 | 70 | } 71 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/di/exception/DependencyException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase.di.exception; 26 | 27 | import dev.demeng.pluginbase.exceptions.BaseException; 28 | import org.jetbrains.annotations.NotNull; 29 | 30 | /** 31 | * Base exception for all dependency injection related errors. 32 | * 33 | *

This exception is thrown when errors occur during dependency resolution, instance creation, 34 | * or 35 | * container operations. 36 | */ 37 | public class DependencyException extends BaseException { 38 | 39 | public DependencyException(@NotNull final String message) { 40 | super(message); 41 | } 42 | 43 | public DependencyException(@NotNull final Throwable cause) { 44 | super(cause); 45 | } 46 | 47 | public DependencyException(@NotNull final String message, @NotNull final Throwable cause) { 48 | super(message, cause); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/di/exception/MissingDependencyException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase.di.exception; 26 | 27 | import org.jetbrains.annotations.NotNull; 28 | 29 | /** 30 | * Thrown when a required dependency cannot be resolved. 31 | * 32 | *

This typically occurs when: 33 | * 34 | *

    35 | *
  • An interface or abstract class has no registered binding 36 | *
  • A required type has not been registered in the container 37 | *
  • A dependency is missing from the dependency graph 38 | *
39 | */ 40 | public class MissingDependencyException extends DependencyException { 41 | 42 | /** 43 | * Creates a new missing dependency exception. 44 | * 45 | * @param type The type that could not be resolved 46 | */ 47 | public MissingDependencyException(@NotNull final Class type) { 48 | super("No binding found for: " + type.getName()); 49 | } 50 | 51 | /** 52 | * Creates a new missing dependency exception with a custom message. 53 | * 54 | * @param message The error message 55 | */ 56 | public MissingDependencyException(@NotNull final String message) { 57 | super(message); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/di/exception/TypeMismatchException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase.di.exception; 26 | 27 | import org.jetbrains.annotations.NotNull; 28 | 29 | /** 30 | * Exception thrown when attempting to register an instance with a type that is not assignable from 31 | * the instance's actual class. 32 | * 33 | *

This occurs when trying to register an instance with an incompatible explicit type parameter. 34 | */ 35 | public class TypeMismatchException extends DependencyException { 36 | 37 | /** 38 | * Creates a new type mismatch exception with details about the expected and actual types. 39 | * 40 | * @param expected The expected type (what was specified in register) 41 | * @param actual The actual type of the instance 42 | */ 43 | public TypeMismatchException(@NotNull final Class expected, @NotNull final Class actual) { 44 | super( 45 | "Instance type " 46 | + actual.getName() 47 | + " is not assignable to " 48 | + expected.getName() 49 | + ". Ensure the instance implements or extends the specified type."); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/event/MergedSubscription.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.event; 27 | 28 | import java.util.Set; 29 | import org.bukkit.event.Event; 30 | import org.jetbrains.annotations.NotNull; 31 | 32 | /** 33 | * Represents a subscription to a set of events. 34 | * 35 | * @param the handled type 36 | */ 37 | public interface MergedSubscription extends Subscription { 38 | 39 | /** 40 | * Gets the handled class 41 | * 42 | * @return the handled class 43 | */ 44 | @NotNull 45 | Class getHandledClass(); 46 | 47 | /** 48 | * Gets a set of the individual event classes being listened to 49 | * 50 | * @return the individual classes 51 | */ 52 | @NotNull 53 | Set> getEventClasses(); 54 | } 55 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/event/SingleSubscription.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.event; 27 | 28 | import org.bukkit.event.Event; 29 | import org.jetbrains.annotations.NotNull; 30 | 31 | /** 32 | * Represents a subscription to a single given event. 33 | * 34 | * @param the event type 35 | */ 36 | public interface SingleSubscription extends Subscription { 37 | 38 | /** 39 | * Gets the class the handler is handling 40 | * 41 | * @return the class the handler is handling. 42 | */ 43 | @NotNull 44 | Class getEventClass(); 45 | } 46 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/event/Subscription.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.event; 27 | 28 | import dev.demeng.pluginbase.terminable.Terminable; 29 | import java.util.Collection; 30 | 31 | /** Represents a subscription to a given (set of) event(s). */ 32 | public interface Subscription extends Terminable { 33 | 34 | /** 35 | * Gets whether the handler is active 36 | * 37 | * @return if the handler is active 38 | */ 39 | boolean isActive(); 40 | 41 | /** 42 | * Gets the number of times the handler has been called 43 | * 44 | * @return the number of times the handler has been called 45 | */ 46 | long getCallCounter(); 47 | 48 | /** 49 | * Unregisters the handler 50 | * 51 | * @return true if the handler wasn't already unregistered 52 | */ 53 | boolean unregister(); 54 | 55 | @Override 56 | default void close() { 57 | unregister(); 58 | } 59 | 60 | /** 61 | * Gets the functional handlers and filters used by this subscription. 62 | * 63 | * @return the functions used by this subscription. 64 | * @deprecated not API, subject to change or removal 65 | */ 66 | @Deprecated 67 | Collection getFunctions(); 68 | } 69 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/event/filter/EventHandlers.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.event.filter; 27 | 28 | import java.util.function.Consumer; 29 | import lombok.AccessLevel; 30 | import lombok.NoArgsConstructor; 31 | import org.bukkit.event.Cancellable; 32 | import org.jetbrains.annotations.NotNull; 33 | 34 | /** Defines standard event predicates for use in functional event handlers. */ 35 | @SuppressWarnings("unchecked") 36 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 37 | public final class EventHandlers { 38 | 39 | private static final Consumer SET_CANCELLED = e -> e.setCancelled(true); 40 | private static final Consumer UNSET_CANCELLED = e -> e.setCancelled(false); 41 | 42 | /** 43 | * Returns a consumer which cancels the event 44 | * 45 | * @param the event type 46 | * @return a consumer which cancels the event 47 | */ 48 | @NotNull 49 | public static Consumer cancel() { 50 | return (Consumer) SET_CANCELLED; 51 | } 52 | 53 | /** 54 | * Returns a consumer which un-cancels the event 55 | * 56 | * @param the event type 57 | * @return a consumer which un-cancels the event 58 | */ 59 | @NotNull 60 | public static Consumer uncancel() { 61 | return (Consumer) UNSET_CANCELLED; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/event/functional/ExpiryTestStage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.event.functional; 27 | 28 | /** Represents when a expiry predicate should be tested relative to the handling of the event. */ 29 | public enum ExpiryTestStage { 30 | 31 | /** The expiry predicate should be tested before the event is filtered or handled */ 32 | PRE, 33 | 34 | /** The expiry predicate should be tested after the subscriptions filters have been evaluated */ 35 | POST_FILTER, 36 | 37 | /** The expiry predicate should be tested after the event has been handled */ 38 | POST_HANDLE 39 | } 40 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/event/functional/FunctionalHandlerList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.event.functional; 27 | 28 | import java.util.function.BiConsumer; 29 | import java.util.function.Consumer; 30 | import org.jetbrains.annotations.NotNull; 31 | 32 | /** 33 | * A functional builder which accumulates event handlers 34 | * 35 | * @param the handled type 36 | * @param the resultant subscription type 37 | */ 38 | public interface FunctionalHandlerList { 39 | 40 | /** 41 | * Add a {@link Consumer} handler. 42 | * 43 | * @param handler the handler 44 | * @return this handler list 45 | */ 46 | @NotNull 47 | FunctionalHandlerList consumer(@NotNull Consumer handler); 48 | 49 | /** 50 | * Add a {@link BiConsumer} handler. 51 | * 52 | * @param handler the handler 53 | * @return this handler list 54 | */ 55 | @NotNull 56 | FunctionalHandlerList biConsumer(@NotNull BiConsumer handler); 57 | 58 | /** 59 | * Builds and registers the Handler. 60 | * 61 | * @return a registered {@link R} instance. 62 | * @throws IllegalStateException if no handlers have been registered 63 | */ 64 | @NotNull 65 | R register(); 66 | } 67 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/event/functional/SubscriptionBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.event.functional; 27 | 28 | import dev.demeng.pluginbase.Common; 29 | import dev.demeng.pluginbase.event.Subscription; 30 | import dev.demeng.pluginbase.exceptions.EventHandlerException; 31 | import java.util.concurrent.TimeUnit; 32 | import java.util.function.BiConsumer; 33 | import java.util.function.Predicate; 34 | import org.jetbrains.annotations.NotNull; 35 | 36 | /** 37 | * Abstract {@link Subscription} builder. 38 | * 39 | * @param the handled / event type 40 | */ 41 | public interface SubscriptionBuilder { 42 | 43 | BiConsumer DEFAULT_EXCEPTION_CONSUMER = 44 | (object, t) -> 45 | Common.error(new EventHandlerException(t, object), "Error whilst handling event.", false); 46 | 47 | /** 48 | * Add a expiry predicate. 49 | * 50 | * @param predicate the expiry test 51 | * @return ths builder instance 52 | */ 53 | @NotNull 54 | SubscriptionBuilder expireIf(@NotNull Predicate predicate); 55 | 56 | /** 57 | * Sets the expiry time on the handler 58 | * 59 | * @param duration the duration until expiry 60 | * @param unit the unit for the duration 61 | * @return the builder instance 62 | * @throws IllegalArgumentException if duration is not greater than or equal to 1 63 | */ 64 | @NotNull 65 | SubscriptionBuilder expireAfter(long duration, @NotNull TimeUnit unit); 66 | 67 | /** 68 | * Sets the number of calls until the handler will automatically be unregistered 69 | * 70 | *

The call counter is only incremented if the event call passes all filters and if the handler 71 | * completes without throwing an exception. 72 | * 73 | * @param maxCalls the number of times the handler will be called until being unregistered. 74 | * @return the builder instance 75 | * @throws IllegalArgumentException if maxCalls is not greater than or equal to 1 76 | */ 77 | @NotNull 78 | SubscriptionBuilder expireAfter(long maxCalls); 79 | 80 | /** 81 | * Adds a filter to the handler. 82 | * 83 | *

An event will only be handled if it passes all filters. Filters are evaluated in the order 84 | * they are registered. 85 | * 86 | * @param predicate the filter 87 | * @return the builder instance 88 | */ 89 | @NotNull 90 | SubscriptionBuilder filter(@NotNull Predicate predicate); 91 | } 92 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/event/functional/merged/MergedHandlerList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.event.functional.merged; 27 | 28 | import dev.demeng.pluginbase.delegate.Delegates; 29 | import dev.demeng.pluginbase.event.MergedSubscription; 30 | import dev.demeng.pluginbase.event.functional.FunctionalHandlerList; 31 | import java.util.Objects; 32 | import java.util.function.BiConsumer; 33 | import java.util.function.Consumer; 34 | import org.jetbrains.annotations.NotNull; 35 | 36 | public interface MergedHandlerList extends FunctionalHandlerList> { 37 | 38 | @NotNull 39 | @Override 40 | default MergedHandlerList consumer(@NotNull final Consumer handler) { 41 | Objects.requireNonNull(handler, "handler"); 42 | return biConsumer(Delegates.consumerToBiConsumerSecond(handler)); 43 | } 44 | 45 | @NotNull 46 | @Override 47 | MergedHandlerList biConsumer(@NotNull BiConsumer, ? super T> handler); 48 | } 49 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/event/functional/merged/MergedHandlerListImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.event.functional.merged; 27 | 28 | import dev.demeng.pluginbase.event.MergedSubscription; 29 | import dev.demeng.pluginbase.plugin.BaseManager; 30 | import java.util.ArrayList; 31 | import java.util.List; 32 | import java.util.Objects; 33 | import java.util.function.BiConsumer; 34 | import org.jetbrains.annotations.NotNull; 35 | 36 | class MergedHandlerListImpl implements MergedHandlerList { 37 | 38 | private final MergedSubscriptionBuilderImpl builder; 39 | private final List, ? super T>> handlers = new ArrayList<>(1); 40 | 41 | MergedHandlerListImpl(@NotNull final MergedSubscriptionBuilderImpl builder) { 42 | this.builder = builder; 43 | } 44 | 45 | @NotNull 46 | @Override 47 | public MergedHandlerList biConsumer( 48 | @NotNull final BiConsumer, ? super T> handler) { 49 | Objects.requireNonNull(handler, "handler"); 50 | this.handlers.add(handler); 51 | return this; 52 | } 53 | 54 | @NotNull 55 | @Override 56 | public MergedSubscription register() { 57 | if (this.handlers.isEmpty()) { 58 | throw new IllegalStateException("No handlers have been registered"); 59 | } 60 | 61 | final BaseMergedEventListener listener = 62 | new BaseMergedEventListener<>(this.builder, this.handlers); 63 | listener.register(BaseManager.getPlugin()); 64 | return listener; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/event/functional/merged/MergedHandlerMapping.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.event.functional.merged; 27 | 28 | import java.util.function.Function; 29 | import org.bukkit.event.Event; 30 | import org.bukkit.event.EventPriority; 31 | 32 | class MergedHandlerMapping { 33 | 34 | private final EventPriority priority; 35 | private final Function function; 36 | 37 | MergedHandlerMapping(final EventPriority priority, final Function function) { 38 | this.priority = priority; 39 | //noinspection unchecked 40 | this.function = o -> function.apply((E) o); 41 | } 42 | 43 | public Function getFunction() { 44 | return this.function; 45 | } 46 | 47 | public EventPriority getPriority() { 48 | return this.priority; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/event/functional/single/SingleHandlerList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.event.functional.single; 27 | 28 | import dev.demeng.pluginbase.delegate.Delegates; 29 | import dev.demeng.pluginbase.event.SingleSubscription; 30 | import dev.demeng.pluginbase.event.functional.FunctionalHandlerList; 31 | import java.util.Objects; 32 | import java.util.function.BiConsumer; 33 | import java.util.function.Consumer; 34 | import org.bukkit.event.Event; 35 | import org.jetbrains.annotations.NotNull; 36 | 37 | public interface SingleHandlerList 38 | extends FunctionalHandlerList> { 39 | 40 | @NotNull 41 | @Override 42 | default SingleHandlerList consumer(@NotNull final Consumer handler) { 43 | Objects.requireNonNull(handler, "handler"); 44 | return biConsumer(Delegates.consumerToBiConsumerSecond(handler)); 45 | } 46 | 47 | @NotNull 48 | @Override 49 | SingleHandlerList biConsumer(@NotNull BiConsumer, ? super T> handler); 50 | } 51 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/event/functional/single/SingleHandlerListImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.event.functional.single; 27 | 28 | import dev.demeng.pluginbase.event.SingleSubscription; 29 | import dev.demeng.pluginbase.plugin.BaseManager; 30 | import java.util.ArrayList; 31 | import java.util.List; 32 | import java.util.Objects; 33 | import java.util.function.BiConsumer; 34 | import org.bukkit.event.Event; 35 | import org.jetbrains.annotations.NotNull; 36 | 37 | class SingleHandlerListImpl implements SingleHandlerList { 38 | 39 | private final SingleSubscriptionBuilderImpl builder; 40 | private final List, ? super T>> handlers = new ArrayList<>(1); 41 | 42 | SingleHandlerListImpl(@NotNull final SingleSubscriptionBuilderImpl builder) { 43 | this.builder = builder; 44 | } 45 | 46 | @NotNull 47 | @Override 48 | public SingleHandlerList biConsumer( 49 | @NotNull final BiConsumer, ? super T> handler) { 50 | Objects.requireNonNull(handler, "handler"); 51 | this.handlers.add(handler); 52 | return this; 53 | } 54 | 55 | @NotNull 56 | @Override 57 | public SingleSubscription register() { 58 | if (this.handlers.isEmpty()) { 59 | throw new IllegalStateException("No handlers have been registered"); 60 | } 61 | 62 | final BaseEventListener listener = new BaseEventListener<>(this.builder, this.handlers); 63 | listener.register(BaseManager.getPlugin()); 64 | return listener; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/exceptions/BaseException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase.exceptions; 26 | 27 | import org.jetbrains.annotations.NotNull; 28 | 29 | /** A custom runtime exception, used for throwing runtime errors related to improper API usage. */ 30 | public class BaseException extends RuntimeException { 31 | 32 | public BaseException(@NotNull final String message) { 33 | super(message); 34 | } 35 | 36 | public BaseException(@NotNull final Throwable cause) { 37 | super(cause); 38 | } 39 | 40 | public BaseException(@NotNull final String message, @NotNull final Throwable cause) { 41 | super(message, cause); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/exceptions/EventHandlerException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase.exceptions; 26 | 27 | /** A general exception caused by an event handler. */ 28 | public class EventHandlerException extends BaseException { 29 | 30 | public EventHandlerException(final Throwable cause, final Object event) { 31 | super("event handler for " + event.getClass().getName(), cause); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/exceptions/PluginErrorException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase.exceptions; 26 | 27 | import dev.demeng.pluginbase.Common; 28 | import org.bukkit.command.CommandSender; 29 | import org.bukkit.entity.Player; 30 | import org.jetbrains.annotations.NotNull; 31 | import org.jetbrains.annotations.Nullable; 32 | 33 | /** 34 | * An extension of RuntimeException that calls {@link Common#error(Throwable, String, boolean, 35 | * CommandSender...)}. 36 | */ 37 | public class PluginErrorException extends RuntimeException { 38 | 39 | public PluginErrorException( 40 | @NotNull final String description, final boolean disable, final Player... players) { 41 | Common.error(this, description, disable, players); 42 | } 43 | 44 | public PluginErrorException( 45 | @Nullable final Throwable t, 46 | @NotNull final String description, 47 | final boolean disable, 48 | final Player... players) { 49 | Common.error(t, description, disable, players); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/exceptions/PromiseChainException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * Copyright (c) lucko (Luck) 6 | * Copyright (c) lucko/helper contributors 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | package dev.demeng.pluginbase.exceptions; 28 | 29 | import org.jetbrains.annotations.NotNull; 30 | 31 | /** A general exception caused by a {@link dev.demeng.pluginbase.promise.Promise} chain. */ 32 | public class PromiseChainException extends BaseException { 33 | 34 | public PromiseChainException(@NotNull final Throwable cause) { 35 | super("promise chain", cause); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/exceptions/SchedulerTaskException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * Copyright (c) lucko (Luck) 6 | * Copyright (c) lucko/helper contributors 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | package dev.demeng.pluginbase.exceptions; 28 | 29 | import dev.demeng.pluginbase.Common; 30 | import dev.demeng.pluginbase.delegate.Delegate; 31 | import lombok.AccessLevel; 32 | import lombok.Getter; 33 | import lombok.RequiredArgsConstructor; 34 | import org.bukkit.command.CommandSender; 35 | import org.jetbrains.annotations.NotNull; 36 | 37 | /** A general exception caused by a scheduler task. */ 38 | public class SchedulerTaskException extends BaseException { 39 | 40 | public SchedulerTaskException(@NotNull final Throwable cause) { 41 | super("scheduler task", cause); 42 | } 43 | 44 | /** 45 | * Wraps a runnable into a runnable that catches its own exceptions and logs them using {@link 46 | * Common#error(Throwable, String, boolean, CommandSender...)}. 47 | * 48 | * @param runnable The runnable 49 | * @return The wrapped runnable 50 | */ 51 | @NotNull 52 | public static Runnable wrap(@NotNull final Runnable runnable) { 53 | return new SchedulerWrappedRunnable(runnable); 54 | } 55 | 56 | @RequiredArgsConstructor(access = AccessLevel.PRIVATE) 57 | private static final class SchedulerWrappedRunnable implements Runnable, Delegate { 58 | 59 | @Getter @NotNull private final Runnable delegate; 60 | 61 | @Override 62 | public void run() { 63 | try { 64 | this.delegate.run(); 65 | } catch (final Throwable t) { 66 | Common.error( 67 | new SchedulerTaskException(t), "Error whilst executing scheduler task.", false); 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/interfaces/TypeAware.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.interfaces; 27 | 28 | import com.google.common.reflect.TypeToken; 29 | import org.jetbrains.annotations.NotNull; 30 | 31 | /** 32 | * Represents an object that knows its own type parameter. 33 | * 34 | * @param The type 35 | */ 36 | public interface TypeAware { 37 | 38 | @NotNull 39 | TypeToken getType(); 40 | } 41 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/locale/LocaleReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2021 Revxrsal 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package dev.demeng.pluginbase.locale; 25 | 26 | import java.util.Locale; 27 | import java.util.ResourceBundle; 28 | import org.jetbrains.annotations.NotNull; 29 | 30 | /** 31 | * A locale reader is a source in which messages for a specific locale are fetched. This can be a 32 | * file, a resource bundle, or even a remote source. 33 | */ 34 | public interface LocaleReader { 35 | 36 | /** 37 | * Returns whether this reader contains a mapping for the given key. 38 | * 39 | * @param key Key to check for 40 | * @return {@code true} if this reader has a mapping for the key 41 | */ 42 | boolean containsKey(@NotNull final String key); 43 | 44 | /** 45 | * Returns the mapping value for this key. It is recommended that this only return values if 46 | * {@link #containsKey(String)} is true, otherwise throwing an exception to avoid confusion. 47 | * 48 | * @param key Key to fetch for 49 | * @return The string value 50 | */ 51 | String get(@NotNull final String key); 52 | 53 | /** 54 | * Returns the mapping value for this key. It is recommended that this only return values if 55 | * {@link #containsKey(String)} is true, otherwise throwing an exception to avoid confusion. 56 | * 57 | * @param key Key to fetch for 58 | * @return The string array value 59 | */ 60 | String[] getArray(@NotNull final String key); 61 | 62 | /** 63 | * Returns the locale of by this reader 64 | * 65 | * @return The reader's locale 66 | */ 67 | @NotNull 68 | Locale getLocale(); 69 | 70 | /** 71 | * Wraps a {@link ResourceBundle} in a {@link LocaleReader}. 72 | * 73 | * @param bundle Bundle to wrap 74 | * @return The locale reader 75 | */ 76 | static @NotNull LocaleReader wrap(@NotNull final ResourceBundle bundle) { 77 | return new ResourceBundleLocaleReader(bundle); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/locale/ResourceBundleLocaleReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2021 Revxrsal 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package dev.demeng.pluginbase.locale; 25 | 26 | import java.util.Locale; 27 | import java.util.ResourceBundle; 28 | import org.jetbrains.annotations.NotNull; 29 | 30 | /** Represents a {@link LocaleReader} that fetches its values from a {@link ResourceBundle}. */ 31 | final class ResourceBundleLocaleReader implements LocaleReader { 32 | 33 | private final ResourceBundle resourceBundle; 34 | 35 | public ResourceBundleLocaleReader(@NotNull final ResourceBundle resourceBundle) { 36 | this.resourceBundle = resourceBundle; 37 | } 38 | 39 | @Override 40 | public boolean containsKey(final @NotNull String key) { 41 | return resourceBundle.containsKey(key); 42 | } 43 | 44 | @Override 45 | public String get(final @NotNull String key) { 46 | return resourceBundle.getString(key); 47 | } 48 | 49 | @Override 50 | public String[] getArray(final @NotNull String key) { 51 | return resourceBundle.getStringArray(key); 52 | } 53 | 54 | @Override 55 | public @NotNull Locale getLocale() { 56 | return resourceBundle.getLocale(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/locale/UTF8Control.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2021 Revxrsal 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase.locale; 26 | 27 | import java.io.IOException; 28 | import java.io.InputStream; 29 | import java.io.InputStreamReader; 30 | import java.net.URL; 31 | import java.net.URLConnection; 32 | import java.nio.charset.StandardCharsets; 33 | import java.util.Locale; 34 | import java.util.PropertyResourceBundle; 35 | import java.util.ResourceBundle; 36 | 37 | /** 38 | * Parses resource files using UTF-8 character encoding. 39 | * 40 | *

See https://stackoverflow.com/a/4660195. 41 | */ 42 | final class UTF8Control extends ResourceBundle.Control { 43 | 44 | public static final UTF8Control INSTANCE = new UTF8Control(); 45 | 46 | @Override 47 | public ResourceBundle newBundle( 48 | final String baseName, 49 | final Locale locale, 50 | final String format, 51 | final ClassLoader loader, 52 | final boolean reload) 53 | throws IOException { 54 | final String bundleName = toBundleName(baseName, locale); 55 | final String resourceName = toResourceName(bundleName, "properties"); 56 | ResourceBundle bundle = null; 57 | InputStream stream = null; 58 | if (reload) { 59 | final URL url = loader.getResource(resourceName); 60 | if (url != null) { 61 | final URLConnection connection = url.openConnection(); 62 | if (connection != null) { 63 | connection.setUseCaches(false); 64 | stream = connection.getInputStream(); 65 | } 66 | } 67 | } else { 68 | stream = loader.getResourceAsStream(resourceName); 69 | } 70 | if (stream != null) { 71 | try { 72 | bundle = new PropertyResourceBundle(new InputStreamReader(stream, StandardCharsets.UTF_8)); 73 | } finally { 74 | stream.close(); 75 | } 76 | } 77 | return bundle; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/locale/reader/ConfigLocaleReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase.locale.reader; 26 | 27 | import dev.demeng.pluginbase.locale.LocaleReader; 28 | import java.util.Locale; 29 | import lombok.Getter; 30 | import lombok.RequiredArgsConstructor; 31 | import org.bukkit.configuration.file.FileConfiguration; 32 | import org.jetbrains.annotations.NotNull; 33 | 34 | /** 35 | * A locale reader that uses Bukkit config files (such as .yml) instead of standard resource bundles 36 | * (.properties). This should typically only be used if you want to have a singular locale file, 37 | * such as a "messages.yml". 38 | * 39 | * @see dev.demeng.pluginbase.locale.Translator#add(LocaleReader) 40 | */ 41 | @RequiredArgsConstructor 42 | public class ConfigLocaleReader implements LocaleReader { 43 | 44 | @NotNull private final FileConfiguration config; 45 | @Getter @NotNull private final Locale locale; 46 | 47 | @Override 48 | public boolean containsKey(@NotNull final String key) { 49 | return config.contains(key); 50 | } 51 | 52 | @Override 53 | public String get(@NotNull final String key) { 54 | return config.getString(key); 55 | } 56 | 57 | @Override 58 | public String[] getArray(@NotNull final String key) { 59 | return config.getStringList(key).toArray(new String[0]); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/menu/IMenu.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase.menu; 26 | 27 | import org.bukkit.entity.Player; 28 | import org.bukkit.event.inventory.InventoryCloseEvent; 29 | import org.jetbrains.annotations.NotNull; 30 | 31 | /** An interface containing common methods between the different menu layouts. */ 32 | public interface IMenu { 33 | 34 | /** 35 | * Opens the menu for the provided player(s). 36 | * 37 | * @param players The players the menu should be opened to 38 | */ 39 | void open(final Player... players); 40 | 41 | /** 42 | * Called when the menu is closed. Does nothing by default. 43 | * 44 | * @param event The inventory close event 45 | * @return True if menu should be re-opened, false if menu should be closed 46 | */ 47 | default boolean onClose(@NotNull final InventoryCloseEvent event) { 48 | return false; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/model/BlockPosition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase.model; 26 | 27 | import dev.demeng.pluginbase.serialize.YamlSerializable; 28 | import java.util.Objects; 29 | import lombok.Data; 30 | import org.bukkit.Bukkit; 31 | import org.bukkit.Location; 32 | import org.bukkit.block.Block; 33 | import org.bukkit.configuration.ConfigurationSection; 34 | import org.jetbrains.annotations.NotNull; 35 | 36 | /** An immutable and serializable Location object with integer values and no yaw nor pitch. */ 37 | @Data(staticConstructor = "of") 38 | public class BlockPosition implements YamlSerializable { 39 | 40 | @NotNull private final String world; 41 | private final int x; 42 | private final int y; 43 | private final int z; 44 | 45 | @NotNull 46 | public static BlockPosition of(@NotNull final Location loc) { 47 | return of( 48 | Objects.requireNonNull(loc.getWorld()).getName(), 49 | loc.getBlockX(), 50 | loc.getBlockY(), 51 | loc.getBlockZ()); 52 | } 53 | 54 | @Override 55 | public void serialize(@NotNull final ConfigurationSection section) { 56 | section.set("world", world); 57 | section.set("x", x); 58 | section.set("y", y); 59 | section.set("z", z); 60 | } 61 | 62 | @NotNull 63 | public static BlockPosition deserialize(@NotNull final ConfigurationSection section) { 64 | return of( 65 | Objects.requireNonNull(section.getString("world")), 66 | section.getInt("x"), 67 | section.getInt("y"), 68 | section.getInt("z")); 69 | } 70 | 71 | /** 72 | * Converts the block position to a Bukkit {@link Location}. 73 | * 74 | * @return The Bukkit Location 75 | */ 76 | @NotNull 77 | public Location toLocation() { 78 | return new Location(Bukkit.getWorld(world), x, y, z); 79 | } 80 | 81 | /** 82 | * Gets the block at the given location. 83 | * 84 | * @return The block at the location 85 | */ 86 | @NotNull 87 | public Block toBlock() { 88 | return toLocation().getBlock(); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/model/Pair.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase.model; 26 | 27 | import lombok.Data; 28 | 29 | /** 30 | * A simple pair of objects. 31 | * 32 | * @param The type of object A 33 | * @param The type of object B 34 | */ 35 | @Data(staticConstructor = "of") 36 | public class Pair { 37 | 38 | private final A a; 39 | private final B b; 40 | 41 | public static Pair of(final Pair pair) { 42 | return of(pair.getA(), pair.getB()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/model/Placeholders.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase.model; 26 | 27 | import dev.demeng.pluginbase.DynamicPlaceholders; 28 | import java.util.function.UnaryOperator; 29 | import lombok.Data; 30 | import org.jetbrains.annotations.NotNull; 31 | 32 | /** 33 | * A shorthand version of {@link DynamicPlaceholders}, allowing for string placeholders to be easily 34 | * applied on strings, lists, and item stacks. 35 | */ 36 | @Data(staticConstructor = "of") 37 | public class Placeholders implements DynamicPlaceholders { 38 | 39 | private final UnaryOperator placeholderReplacer; 40 | 41 | @Override 42 | public @NotNull String setPlaceholders(@NotNull final String str) { 43 | return placeholderReplacer.apply(str); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/model/Point.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase.model; 26 | 27 | import dev.demeng.pluginbase.serialize.YamlSerializable; 28 | import java.util.Objects; 29 | import lombok.Data; 30 | import org.bukkit.Bukkit; 31 | import org.bukkit.Location; 32 | import org.bukkit.configuration.ConfigurationSection; 33 | import org.jetbrains.annotations.NotNull; 34 | 35 | /** An immutable and serializable Location object, including the yaw and pitch. */ 36 | @Data(staticConstructor = "of") 37 | public class Point implements YamlSerializable { 38 | 39 | @NotNull private final String world; 40 | private final double x; 41 | private final double y; 42 | private final double z; 43 | private final float yaw; 44 | private final float pitch; 45 | 46 | @NotNull 47 | public static Point of(@NotNull final Location loc) { 48 | return of( 49 | Objects.requireNonNull(loc.getWorld()).getName(), 50 | loc.getX(), 51 | loc.getY(), 52 | loc.getZ(), 53 | loc.getYaw(), 54 | loc.getPitch()); 55 | } 56 | 57 | @Override 58 | public void serialize(@NotNull final ConfigurationSection section) { 59 | section.set("world", world); 60 | section.set("x", x); 61 | section.set("y", y); 62 | section.set("z", z); 63 | section.set("yaw", yaw); 64 | section.set("pitch", pitch); 65 | } 66 | 67 | @NotNull 68 | public static Point deserialize(@NotNull final ConfigurationSection section) { 69 | return of( 70 | Objects.requireNonNull(section.getString("world")), 71 | section.getDouble("x"), 72 | section.getDouble("y"), 73 | section.getDouble("z"), 74 | (float) section.getDouble("yaw"), 75 | (float) section.getDouble("pitch")); 76 | } 77 | 78 | /** 79 | * Converts the point to a Bukkit {@link Location}. 80 | * 81 | * @return The Bukkit Location 82 | */ 83 | @NotNull 84 | public Location toLocation() { 85 | return new Location(Bukkit.getWorld(world), x, y, z, yaw, pitch); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/model/Position.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase.model; 26 | 27 | import dev.demeng.pluginbase.serialize.YamlSerializable; 28 | import java.util.Objects; 29 | import lombok.Data; 30 | import org.bukkit.Bukkit; 31 | import org.bukkit.Location; 32 | import org.bukkit.configuration.ConfigurationSection; 33 | import org.jetbrains.annotations.NotNull; 34 | 35 | /** An immutable and serializable Location object without the yaw or pitch. */ 36 | @Data(staticConstructor = "of") 37 | public class Position implements YamlSerializable { 38 | 39 | @NotNull private final String world; 40 | private final double x; 41 | private final double y; 42 | private final double z; 43 | 44 | @NotNull 45 | public static Position of(@NotNull final Location loc) { 46 | return of(Objects.requireNonNull(loc.getWorld()).getName(), loc.getX(), loc.getY(), loc.getZ()); 47 | } 48 | 49 | @Override 50 | public void serialize(@NotNull final ConfigurationSection section) { 51 | section.set("world", world); 52 | section.set("x", x); 53 | section.set("y", y); 54 | section.set("z", z); 55 | } 56 | 57 | @NotNull 58 | public static Position deserialize(@NotNull final ConfigurationSection section) { 59 | return of( 60 | Objects.requireNonNull(section.getString("world")), 61 | section.getDouble("x"), 62 | section.getDouble("y"), 63 | section.getDouble("z")); 64 | } 65 | 66 | /** 67 | * Converts the position to a Bukkit {@link Location}. 68 | * 69 | * @return The Bukkit Location 70 | */ 71 | @NotNull 72 | public Location toLocation() { 73 | return new Location(Bukkit.getWorld(world), x, y, z); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/model/Vector3d.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase.model; 26 | 27 | import dev.demeng.pluginbase.serialize.YamlSerializable; 28 | import lombok.Data; 29 | import org.bukkit.Location; 30 | import org.bukkit.World; 31 | import org.bukkit.configuration.ConfigurationSection; 32 | import org.bukkit.util.Vector; 33 | import org.jetbrains.annotations.NotNull; 34 | import org.jetbrains.annotations.Nullable; 35 | 36 | /** An immutable and serializable 3D vector. */ 37 | @Data(staticConstructor = "of") 38 | public class Vector3d implements YamlSerializable { 39 | 40 | private final double x; 41 | private final double y; 42 | private final double z; 43 | 44 | @NotNull 45 | public static Vector3d of(@NotNull final Location loc) { 46 | return of(loc.getX(), loc.getY(), loc.getZ()); 47 | } 48 | 49 | @NotNull 50 | public static Vector3d of(@NotNull final Vector vector) { 51 | return of(vector.getX(), vector.getY(), vector.getZ()); 52 | } 53 | 54 | @Override 55 | public void serialize(@NotNull final ConfigurationSection section) { 56 | section.set("x", x); 57 | section.set("y", y); 58 | section.set("z", z); 59 | } 60 | 61 | @NotNull 62 | public static Vector3d deserialize(@NotNull final ConfigurationSection section) { 63 | return of(section.getDouble("x"), section.getDouble("y"), section.getDouble("z")); 64 | } 65 | 66 | /** 67 | * Converts the 3D vector to a Bukkit {@link Location}. 68 | * 69 | * @param world The world 70 | * @return The Bukkit Location 71 | */ 72 | @NotNull 73 | public Location toLocation(@Nullable final World world) { 74 | return new Location(world, x, y, z); 75 | } 76 | 77 | /** 78 | * Converts the 3D vector to a Bukkit {@link Vector}. 79 | * 80 | * @return The Bukkit Vector 81 | */ 82 | @NotNull 83 | public Vector toBukkitVector() { 84 | return new Vector(x, y, z); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/plugin/BaseManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase.plugin; 26 | 27 | import dev.demeng.pluginbase.BaseSettings; 28 | import dev.demeng.pluginbase.exceptions.BaseException; 29 | import dev.demeng.pluginbase.locale.Translator; 30 | import lombok.AccessLevel; 31 | import lombok.Getter; 32 | import lombok.NoArgsConstructor; 33 | import lombok.Setter; 34 | import net.kyori.adventure.platform.bukkit.BukkitAudiences; 35 | import org.bukkit.Bukkit; 36 | import org.bukkit.plugin.java.JavaPlugin; 37 | import org.jetbrains.annotations.NotNull; 38 | 39 | /** 40 | * A manager containing all other managers associated with the library, as well as the {@link 41 | * JavaPlugin} the library is working with. 42 | */ 43 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 44 | public final class BaseManager { 45 | 46 | private static JavaPlugin plugin = null; 47 | private static Thread mainThread = null; 48 | 49 | /** The translator used for handling localized messages. */ 50 | @NotNull @Getter @Setter private static Translator translator; 51 | 52 | /** The BukkitAudiences instance to use for Adventure. Should be set when your plugin enables. */ 53 | @Getter @Setter private static BukkitAudiences adventure; 54 | 55 | /** The settings the library should use. */ 56 | @NotNull @Getter @Setter private static BaseSettings baseSettings = new BaseSettings() {}; 57 | 58 | /** 59 | * Gets a never-null instance of the {@link JavaPlugin} the library is currently working with. 60 | * 61 | * @return The {@link JavaPlugin} the library is currently working with 62 | * @throws RuntimeException If the plugin is not set 63 | */ 64 | @NotNull 65 | public static JavaPlugin getPlugin() { 66 | 67 | if (plugin == null) { 68 | throw new BaseException("Main class is not set"); 69 | } 70 | 71 | return plugin; 72 | } 73 | 74 | /** 75 | * Sets the {@link JavaPlugin} that the library is currently working with. 76 | * 77 | * @param newPlugin The new instance of {@link JavaPlugin}. 78 | */ 79 | public static void setPlugin(final JavaPlugin newPlugin) { 80 | plugin = newPlugin; 81 | } 82 | 83 | /** 84 | * Gets the main thread of the server that is using the plugin. 85 | * 86 | * @return The main thread 87 | */ 88 | @NotNull 89 | public static synchronized Thread getMainThread() { 90 | 91 | if (mainThread == null && Bukkit.getServer().isPrimaryThread()) { 92 | mainThread = Thread.currentThread(); 93 | } 94 | 95 | return mainThread; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/promise/ThreadContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.promise; 27 | 28 | import dev.demeng.pluginbase.plugin.BaseManager; 29 | 30 | /** Represents the two main types of {@link Thread} on the server. */ 31 | public enum ThreadContext { 32 | SYNC, 33 | ASYNC; 34 | 35 | /** 36 | * Gets the thread context of the current thread. 37 | * 38 | * @return The threat context of the current thread 39 | */ 40 | public static ThreadContext forCurrentThread() { 41 | return forThread(Thread.currentThread()); 42 | } 43 | 44 | /** 45 | * Gets the thread context of the specified thread. 46 | * 47 | * @param thread The thread to get the context of 48 | * @return The thread context of the specified thread 49 | */ 50 | public static ThreadContext forThread(final Thread thread) { 51 | return thread == BaseManager.getMainThread() ? SYNC : ASYNC; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/random/RandomString.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase.random; 26 | 27 | import java.util.concurrent.ThreadLocalRandom; 28 | import lombok.AccessLevel; 29 | import lombok.NoArgsConstructor; 30 | import org.jetbrains.annotations.NotNull; 31 | 32 | /** 33 | * Utility for generating random strings with customizable length. 34 | * 35 | *

WARNING: IDs generated with this utility are NOT guaranteed to be random, though the 36 | * chance of getting a duplicate ID becomes increasingly unlikely as you increase the length. 37 | */ 38 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 39 | public final class RandomString { 40 | 41 | public static final char[] ALPHABET_UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); 42 | public static final char[] ALPHABET_LOWER = "abcdefghijklmnopqrstuvwxyz".toCharArray(); 43 | public static final char[] NUMBERS = "0123456789".toCharArray(); 44 | public static final char[] ALPHANUMERIC_UPPER = 45 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray(); 46 | public static final char[] ALPHANUMERIC_LOWER = 47 | "abcdefghijklmnopqrstuvwxyz0123456789".toCharArray(); 48 | public static final char[] ALPHANUMERIC_MIXED = 49 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".toCharArray(); 50 | 51 | /** 52 | * Generates a new "unique" string identifier with the specified length. 53 | * 54 | * @param length The length of the ID 55 | * @return The generated ID 56 | */ 57 | @NotNull 58 | public static String generate(final int length, final char[] chars) { 59 | 60 | final StringBuilder sb = new StringBuilder(length); 61 | 62 | for (int n = 0; n < length; n++) { 63 | sb.append(chars[(ThreadLocalRandom.current().nextInt(chars.length))]); 64 | } 65 | 66 | return sb.toString(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/scheduler/BaseExecutors.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of helper, licensed under the MIT License. 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.scheduler; 27 | 28 | import dev.demeng.pluginbase.exceptions.SchedulerTaskException; 29 | import dev.demeng.pluginbase.plugin.BaseManager; 30 | import java.util.concurrent.Executor; 31 | import java.util.concurrent.ScheduledExecutorService; 32 | import lombok.AccessLevel; 33 | import lombok.NoArgsConstructor; 34 | import org.bukkit.Bukkit; 35 | 36 | /** Provides common {@link Executor} instances. */ 37 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 38 | public final class BaseExecutors { 39 | 40 | private static final Executor SYNC_BUKKIT = new BukkitSyncExecutor(); 41 | private static final Executor ASYNC_BUKKIT = new BukkitAsyncExecutor(); 42 | private static final BaseAsyncExecutor ASYNC_BASE = new BaseAsyncExecutor(); 43 | 44 | public static Executor sync() { 45 | return SYNC_BUKKIT; 46 | } 47 | 48 | public static ScheduledExecutorService asyncBase() { 49 | return ASYNC_BASE; 50 | } 51 | 52 | public static Executor asyncBukkit() { 53 | return ASYNC_BUKKIT; 54 | } 55 | 56 | public static void shutdown() { 57 | ASYNC_BASE.cancelRepeatingTasks(); 58 | } 59 | 60 | private static final class BukkitSyncExecutor implements Executor { 61 | 62 | @Override 63 | public void execute(final Runnable runnable) { 64 | Bukkit.getScheduler() 65 | .scheduleSyncDelayedTask(BaseManager.getPlugin(), SchedulerTaskException.wrap(runnable)); 66 | } 67 | } 68 | 69 | private static final class BukkitAsyncExecutor implements Executor { 70 | 71 | @Override 72 | public void execute(final Runnable runnable) { 73 | Bukkit.getScheduler() 74 | .runTaskAsynchronously(BaseManager.getPlugin(), SchedulerTaskException.wrap(runnable)); 75 | } 76 | } 77 | 78 | @Deprecated 79 | public static Runnable wrapRunnable(final Runnable runnable) { 80 | return SchedulerTaskException.wrap(runnable); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/scheduler/Task.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of helper, licensed under the MIT License. 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.scheduler; 27 | 28 | import dev.demeng.pluginbase.terminable.Terminable; 29 | 30 | /** Represents a scheduled repeating task. */ 31 | public interface Task extends Terminable { 32 | 33 | /** 34 | * Gets the number of times this task ran. The counter is only incremented at the end of 35 | * execution. 36 | * 37 | * @return the number of times this task ran 38 | */ 39 | int getTimesRan(); 40 | 41 | /** 42 | * Stops the task. 43 | * 44 | * @return true if the task wasn't already cancelled 45 | */ 46 | boolean stop(); 47 | 48 | /** 49 | * Gets the Bukkit ID for this task. 50 | * 51 | * @return the bukkit id for this task 52 | */ 53 | int getBukkitId(); 54 | 55 | /** {@link #stop() Stops} the task. */ 56 | @Override 57 | default void close() { 58 | stop(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/scheduler/Ticks.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of helper, licensed under the MIT License. 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.scheduler; 27 | 28 | import java.util.concurrent.TimeUnit; 29 | import lombok.AccessLevel; 30 | import lombok.NoArgsConstructor; 31 | import org.jetbrains.annotations.NotNull; 32 | 33 | /** Utility for converting between Minecraft game ticks and standard durations. */ 34 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 35 | public final class Ticks { 36 | 37 | // The number of ticks which occur in a second - this is a server implementation detail 38 | public static final int TICKS_PER_SECOND = 20; 39 | // The number of milliseconds in a second - constant 40 | public static final int MILLISECONDS_PER_SECOND = 1000; 41 | // The number of milliseconds in a tick - assuming the server runs at a perfect tick rate 42 | public static final int MILLISECONDS_PER_TICK = MILLISECONDS_PER_SECOND / TICKS_PER_SECOND; 43 | 44 | /** 45 | * Converts a duration in a certain unit of time to ticks. 46 | * 47 | *

Ticks.from(duration) returns the number of ticks from the given 48 | * duration. 49 | * 50 | * @param duration the duration of time 51 | * @param unit the unit the duration is in 52 | * @return the number of ticks which represent the duration 53 | */ 54 | public static long from(final long duration, @NotNull final TimeUnit unit) { 55 | return unit.toMillis(duration) / MILLISECONDS_PER_TICK; 56 | } 57 | 58 | /** 59 | * Converts ticks to a duration in a certain unit of time. 60 | * 61 | *

Ticks.to(ticks) converts the number of ticks to a duration. 62 | * 63 | * @param ticks the number of ticks 64 | * @param unit the unit to return the duration in 65 | * @return a duration value in the given unit, representing the number of ticks 66 | */ 67 | public static long to(final long ticks, @NotNull final TimeUnit unit) { 68 | return unit.convert(ticks * MILLISECONDS_PER_TICK, TimeUnit.MILLISECONDS); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/scheduler/builder/ContextualPromiseBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of helper, licensed under the MIT License. 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.scheduler.builder; 27 | 28 | import dev.demeng.pluginbase.promise.Promise; 29 | import java.util.concurrent.Callable; 30 | import java.util.function.Supplier; 31 | import org.jetbrains.annotations.NotNull; 32 | 33 | /** 34 | * Builds instances of {@link Promise}, often combining parameters with variables already known by 35 | * this instance. 36 | */ 37 | public interface ContextualPromiseBuilder { 38 | 39 | @NotNull 40 | Promise supply(@NotNull Supplier supplier); 41 | 42 | @NotNull 43 | Promise call(@NotNull Callable callable); 44 | 45 | @NotNull 46 | Promise run(@NotNull Runnable runnable); 47 | } 48 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/scheduler/builder/ContextualTaskBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of helper, licensed under the MIT License. 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.scheduler.builder; 27 | 28 | import dev.demeng.pluginbase.scheduler.Task; 29 | import java.util.function.Consumer; 30 | import org.jetbrains.annotations.NotNull; 31 | 32 | /** 33 | * Queues execution of tasks using {@link dev.demeng.pluginbase.scheduler.Scheduler}, often 34 | * combining parameters with variables already known by this instance. 35 | */ 36 | public interface ContextualTaskBuilder { 37 | 38 | @NotNull 39 | Task consume(@NotNull Consumer consumer); 40 | 41 | @NotNull 42 | Task run(@NotNull Runnable runnable); 43 | } 44 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/scheduler/threadlock/ServerThreadLock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of helper, licensed under the MIT License. 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.scheduler.threadlock; 27 | 28 | import dev.demeng.pluginbase.terminable.Terminable; 29 | 30 | /** 31 | * A tool to synchronize code with the main server thread. 32 | * 33 | *

It is highly recommended to use this interface with try-with-resource blocks. 34 | * 35 | * @see dev.demeng.pluginbase.promise.ThreadContext#SYNC 36 | */ 37 | public interface ServerThreadLock extends Terminable { 38 | 39 | /** 40 | * Blocks the current thread until a {@link ServerThreadLock} can be obtained. 41 | * 42 | *

Will attempt to return immediately if the calling thread is the main thread itself. 43 | * 44 | * @return a lock 45 | */ 46 | static ServerThreadLock obtain() { 47 | return new ServerThreadLockImpl(); 48 | } 49 | 50 | /** Closes the lock, and allows the main thread to continue */ 51 | @Override 52 | void close(); 53 | } 54 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/scheduler/threadlock/ServerThreadLockImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of helper, licensed under the MIT License. 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.scheduler.threadlock; 27 | 28 | import dev.demeng.pluginbase.plugin.BaseManager; 29 | import dev.demeng.pluginbase.promise.ThreadContext; 30 | import java.util.concurrent.CountDownLatch; 31 | import org.bukkit.Bukkit; 32 | 33 | final class ServerThreadLockImpl implements ServerThreadLock { 34 | 35 | // used to mark when the main thread has been obtained and blocked 36 | private final CountDownLatch obtainedSignal = new CountDownLatch(1); 37 | 38 | // used to mark when the lock is closed 39 | private final CountDownLatch doneSignal = new CountDownLatch(1); 40 | 41 | ServerThreadLockImpl() { 42 | // already sync - just countdown on obtained & return 43 | if (ThreadContext.forCurrentThread() == ThreadContext.SYNC) { 44 | this.obtainedSignal.countDown(); 45 | return; 46 | } 47 | 48 | // synchronize with the main thread, then countdown 49 | Bukkit.getScheduler().scheduleSyncDelayedTask(BaseManager.getPlugin(), this::signal); 50 | 51 | // wait for the main thread to become synchronized 52 | await(); 53 | } 54 | 55 | @Override 56 | public void close() { 57 | // mark that the work has been completed, and unblock the main thread 58 | this.doneSignal.countDown(); 59 | } 60 | 61 | private void await() { 62 | // await sync with the server thread 63 | try { 64 | this.obtainedSignal.await(); 65 | } catch (final InterruptedException e) { 66 | Thread.currentThread().interrupt(); 67 | } 68 | } 69 | 70 | private void signal() { 71 | // we're on the main thread now 72 | // firstly, countdown the obtained latched so the blocked code can start to execute 73 | this.obtainedSignal.countDown(); 74 | 75 | // then block the main thread & wait for the executed code to run 76 | try { 77 | this.doneSignal.await(); 78 | } catch (final InterruptedException e) { 79 | e.printStackTrace(); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/terminable/Terminable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.terminable; 27 | 28 | import org.jetbrains.annotations.NotNull; 29 | import org.jetbrains.annotations.Nullable; 30 | 31 | /** An extension of {@link AutoCloseable}. */ 32 | @FunctionalInterface 33 | public interface Terminable extends AutoCloseable { 34 | 35 | Terminable EMPTY = () -> {}; 36 | 37 | /** Closes this resource. */ 38 | @Override 39 | void close() throws Exception; 40 | 41 | /** 42 | * Gets if the object represented by this instance is already permanently closed. 43 | * 44 | * @return true if this terminable is closed permanently 45 | */ 46 | default boolean isClosed() { 47 | return false; 48 | } 49 | 50 | /** 51 | * Silently closes this resource, and returns the exception if one is thrown. 52 | * 53 | * @return the exception is one is thrown 54 | */ 55 | @Nullable 56 | default Exception closeSilently() { 57 | try { 58 | close(); 59 | return null; 60 | } catch (final Exception e) { 61 | return e; 62 | } 63 | } 64 | 65 | /** Closes this resource, and prints the exception if one is thrown. */ 66 | default void closeAndReportException() { 67 | try { 68 | close(); 69 | } catch (final Exception e) { 70 | e.printStackTrace(); 71 | } 72 | } 73 | 74 | /** 75 | * Binds this terminable with a terminable consumer 76 | * 77 | * @param consumer the terminable consumer 78 | */ 79 | default void bindWith(@NotNull final TerminableConsumer consumer) { 80 | consumer.bind(this); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/terminable/TerminableConsumer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.terminable; 27 | 28 | import dev.demeng.pluginbase.terminable.module.TerminableModule; 29 | import org.jetbrains.annotations.NotNull; 30 | 31 | /** 32 | * Accepts {@link AutoCloseable}s (and by inheritance {@link Terminable}s), as well as {@link 33 | * TerminableModule}s. 34 | */ 35 | @FunctionalInterface 36 | public interface TerminableConsumer { 37 | 38 | /** 39 | * Binds with the given terminable. 40 | * 41 | * @param terminable the terminable to bind with 42 | * @param the terminable type 43 | * @return the same terminable 44 | */ 45 | @NotNull 46 | T bind(@NotNull T terminable); 47 | 48 | /** 49 | * Binds with the given terminable module. 50 | * 51 | * @param module the module to bind with 52 | * @param the module type 53 | * @return the same module 54 | */ 55 | @NotNull 56 | default T bindModule(@NotNull final T module) { 57 | module.setup(this); 58 | return module; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/terminable/composite/AbstractCompositeTerminable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of helper, licensed under the MIT License. 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.terminable.composite; 27 | 28 | import dev.demeng.pluginbase.terminable.Terminable; 29 | import java.util.ArrayList; 30 | import java.util.Deque; 31 | import java.util.List; 32 | import java.util.Objects; 33 | import java.util.concurrent.ConcurrentLinkedDeque; 34 | 35 | public class AbstractCompositeTerminable implements CompositeTerminable { 36 | 37 | private final Deque closeables = new ConcurrentLinkedDeque<>(); 38 | private boolean closed = false; 39 | 40 | protected AbstractCompositeTerminable() {} 41 | 42 | @Override 43 | public CompositeTerminable with(final AutoCloseable autoCloseable) { 44 | Objects.requireNonNull(autoCloseable, "autoCloseable"); 45 | this.closeables.push(autoCloseable); 46 | return this; 47 | } 48 | 49 | @Override 50 | public void close() throws CompositeClosingException { 51 | final List caught = new ArrayList<>(); 52 | for (AutoCloseable ac; (ac = this.closeables.poll()) != null; ) { 53 | try { 54 | ac.close(); 55 | } catch (final Exception e) { 56 | caught.add(e); 57 | } 58 | } 59 | this.closed = true; 60 | 61 | if (!caught.isEmpty()) { 62 | throw new CompositeClosingException(caught); 63 | } 64 | } 65 | 66 | @Override 67 | public boolean isClosed() { 68 | return this.closed; 69 | } 70 | 71 | @Override 72 | public void cleanup() { 73 | this.closeables.removeIf( 74 | ac -> { 75 | if (!(ac instanceof Terminable)) { 76 | return false; 77 | } 78 | if (ac instanceof CompositeTerminable) { 79 | ((CompositeTerminable) ac).cleanup(); 80 | } 81 | return ((Terminable) ac).isClosed(); 82 | }); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/terminable/composite/AbstractWeakCompositeTerminable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of helper, licensed under the MIT License. 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.terminable.composite; 27 | 28 | import dev.demeng.pluginbase.terminable.Terminable; 29 | import java.lang.ref.WeakReference; 30 | import java.util.ArrayList; 31 | import java.util.Deque; 32 | import java.util.List; 33 | import java.util.Objects; 34 | import java.util.concurrent.ConcurrentLinkedDeque; 35 | 36 | public class AbstractWeakCompositeTerminable implements CompositeTerminable { 37 | 38 | private final Deque> closeables = new ConcurrentLinkedDeque<>(); 39 | private boolean closed = false; 40 | 41 | protected AbstractWeakCompositeTerminable() {} 42 | 43 | @Override 44 | public CompositeTerminable with(final AutoCloseable autoCloseable) { 45 | Objects.requireNonNull(autoCloseable, "autoCloseable"); 46 | this.closeables.push(new WeakReference<>(autoCloseable)); 47 | return this; 48 | } 49 | 50 | @Override 51 | public void close() throws CompositeClosingException { 52 | final List caught = new ArrayList<>(); 53 | for (WeakReference ref; (ref = this.closeables.poll()) != null; ) { 54 | final AutoCloseable ac = ref.get(); 55 | if (ac == null) { 56 | continue; 57 | } 58 | 59 | try { 60 | ac.close(); 61 | } catch (final Exception e) { 62 | caught.add(e); 63 | } 64 | } 65 | this.closed = true; 66 | 67 | if (!caught.isEmpty()) { 68 | throw new CompositeClosingException(caught); 69 | } 70 | } 71 | 72 | @Override 73 | public boolean isClosed() { 74 | return this.closed; 75 | } 76 | 77 | @Override 78 | public void cleanup() { 79 | this.closeables.removeIf( 80 | ref -> { 81 | final AutoCloseable ac = ref.get(); 82 | return ac == null || (ac instanceof Terminable && ((Terminable) ac).isClosed()); 83 | }); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/terminable/composite/CompositeClosingException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.terminable.composite; 27 | 28 | import java.util.Collections; 29 | import java.util.List; 30 | 31 | /** Exception thrown to propagate exceptions thrown by {@link CompositeTerminable#close()}. */ 32 | public class CompositeClosingException extends Exception { 33 | 34 | private final List causes; 35 | 36 | public CompositeClosingException(final List causes) { 37 | super("Exception(s) occurred whilst closing: " + causes.toString()); 38 | if (causes.isEmpty()) { 39 | throw new IllegalArgumentException("No causes"); 40 | } 41 | this.causes = Collections.unmodifiableList(causes); 42 | } 43 | 44 | public List getCauses() { 45 | return this.causes; 46 | } 47 | 48 | public void printAllStackTraces() { 49 | this.printStackTrace(); 50 | for (final Throwable cause : this.causes) { 51 | cause.printStackTrace(); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /pluginbase-core/src/main/java/dev/demeng/pluginbase/terminable/module/TerminableModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) lucko (Luck) 5 | * Copyright (c) lucko/helper contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.terminable.module; 27 | 28 | import dev.demeng.pluginbase.terminable.Terminable; 29 | import dev.demeng.pluginbase.terminable.TerminableConsumer; 30 | import org.jetbrains.annotations.NotNull; 31 | 32 | /** 33 | * A terminable module is a class which manipulates and constructs a number of {@link Terminable}s. 34 | */ 35 | public interface TerminableModule { 36 | 37 | /** 38 | * Performs the tasks to setup this module 39 | * 40 | * @param consumer the terminable consumer 41 | */ 42 | void setup(@NotNull TerminableConsumer consumer); 43 | 44 | /** 45 | * Registers this terminable with a terminable consumer 46 | * 47 | * @param consumer the terminable consumer 48 | */ 49 | default void bindModuleWith(@NotNull final TerminableConsumer consumer) { 50 | consumer.bindModule(this); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /pluginbase-games/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | pluginbase 9 | dev.demeng 10 | 1.36.0-SNAPSHOT 11 | 12 | 13 | pluginbase-games 14 | 15 | 16 | 17 17 | 17 18 | 19 | 20 | 21 | 22 | 23 | org.apache.maven.plugins 24 | maven-compiler-plugin 25 | 3.14.1 26 | 27 | ${java.version} 28 | ${java.version} 29 | 30 | 31 | 32 | org.apache.maven.plugins 33 | maven-shade-plugin 34 | 3.6.1 35 | 36 | 37 | package 38 | 39 | shade 40 | 41 | 42 | false 43 | false 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | dev.demeng 54 | pluginbase-core 55 | 1.36.0-SNAPSHOT 56 | provided 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /pluginbase-mongo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | pluginbase 9 | dev.demeng 10 | 1.36.0-SNAPSHOT 11 | 12 | 13 | pluginbase-mongo 14 | 15 | 16 | 17 17 | 17 18 | 19 | 20 | 21 | clean package 22 | 23 | 24 | org.apache.maven.plugins 25 | maven-compiler-plugin 26 | 3.14.1 27 | 28 | ${java.version} 29 | ${java.version} 30 | 31 | 32 | 33 | org.apache.maven.plugins 34 | maven-shade-plugin 35 | 3.6.1 36 | 37 | 38 | package 39 | 40 | shade 41 | 42 | 43 | false 44 | false 45 | 46 | 47 | org.mongodb:bson-record-codec 48 | 49 | 50 | 51 | 52 | com.mongodb 53 | dev.demeng.pluginbase.mongo.lib.driver 54 | 55 | 56 | org.bson 57 | dev.demeng.pluginbase.mongo.lib.bson 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | src/main/resources 68 | true 69 | 70 | 71 | 72 | 73 | 74 | 75 | dev.demeng 76 | pluginbase-core 77 | 1.36.0-SNAPSHOT 78 | provided 79 | 80 | 81 | org.mongodb 82 | mongodb-driver-sync 83 | 5.6.1 84 | compile 85 | true 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /pluginbase-mongo/src/main/java/dev/demeng/pluginbase/mongo/IMongo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * Copyright (c) lucko (Luck) 6 | * Copyright (c) lucko/helper contributors 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | package dev.demeng.pluginbase.mongo; 28 | 29 | import com.mongodb.client.MongoClient; 30 | import com.mongodb.client.MongoDatabase; 31 | import dev.demeng.pluginbase.terminable.Terminable; 32 | import org.jetbrains.annotations.NotNull; 33 | 34 | /** Represents an individual Mongo datasource, created by the library. */ 35 | public interface IMongo extends Terminable { 36 | 37 | /** 38 | * Gets the client instance backing the datasource 39 | * 40 | * @return the client instance 41 | */ 42 | @NotNull 43 | MongoClient getClient(); 44 | 45 | /** 46 | * Gets the main database in use by the instance. 47 | * 48 | * @return the main database 49 | */ 50 | @NotNull 51 | MongoDatabase getDatabase(); 52 | 53 | /** 54 | * Gets a specific database instance 55 | * 56 | * @param name the name of the database 57 | * @return the database 58 | */ 59 | MongoDatabase getDatabase(String name); 60 | } 61 | -------------------------------------------------------------------------------- /pluginbase-mongo/src/main/java/dev/demeng/pluginbase/mongo/Mongo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * Copyright (c) lucko (Luck) 6 | * Copyright (c) lucko/helper contributors 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | package dev.demeng.pluginbase.mongo; 28 | 29 | import com.mongodb.client.MongoClient; 30 | import com.mongodb.client.MongoClients; 31 | import com.mongodb.client.MongoDatabase; 32 | import lombok.Getter; 33 | import org.jetbrains.annotations.NotNull; 34 | 35 | /** Represents an individual Mongo datasource, created by the library. */ 36 | public class Mongo implements IMongo { 37 | 38 | @Getter @NotNull private final MongoClient client; 39 | @Getter @NotNull private final MongoDatabase database; 40 | 41 | public Mongo(@NotNull final MongoCredentials credentials) { 42 | this.client = MongoClients.create(credentials.getUri()); 43 | this.database = this.client.getDatabase(credentials.getDatabase()); 44 | } 45 | 46 | @Override 47 | public MongoDatabase getDatabase(final String name) { 48 | return this.client.getDatabase(name); 49 | } 50 | 51 | @Override 52 | public void close() { 53 | if (this.client != null) { 54 | this.client.close(); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /pluginbase-mongo/src/main/java/dev/demeng/pluginbase/mongo/MongoCredentials.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase.mongo; 26 | 27 | import lombok.Data; 28 | import org.bukkit.configuration.ConfigurationSection; 29 | import org.jetbrains.annotations.NotNull; 30 | 31 | /** The POJO containing the credentials to a Mongo database. */ 32 | @Data(staticConstructor = "of") 33 | public final class MongoCredentials { 34 | 35 | /** The connection URI for the database. */ 36 | @NotNull private final String uri; 37 | 38 | /** The name of the database. */ 39 | @NotNull private final String database; 40 | 41 | /** 42 | * Gets database credentials from a configuration section. 43 | * 44 | * @param section The configuration section 45 | * @return The database credentials provided 46 | */ 47 | @NotNull 48 | public static MongoCredentials of(@NotNull final ConfigurationSection section) { 49 | return new MongoCredentials( 50 | section.getString("uri", "mongodb://localhost:27017"), 51 | section.getString("database", "minecraft")); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /pluginbase-redis/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | pluginbase 9 | dev.demeng 10 | 1.36.0-SNAPSHOT 11 | 12 | 13 | pluginbase-redis 14 | 15 | 16 | 17 17 | 17 18 | 19 | 20 | 21 | clean package 22 | 23 | 24 | org.apache.maven.plugins 25 | maven-compiler-plugin 26 | 3.14.1 27 | 28 | ${java.version} 29 | ${java.version} 30 | 31 | 32 | 33 | org.apache.maven.plugins 34 | maven-shade-plugin 35 | 3.6.1 36 | 37 | 38 | package 39 | 40 | shade 41 | 42 | 43 | false 44 | false 45 | 46 | 47 | redis.clients:jedis 48 | org.apache.commons:commons-pool2 49 | 50 | 51 | 52 | 53 | redis.clients.jedis 54 | dev.demeng.pluginbase.redis.lib.jedis 55 | 56 | 57 | org.apache.commons.pool 58 | dev.demeng.pluginbase.redis.lib.commonspool 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | src/main/resources 69 | true 70 | 71 | 72 | 73 | 74 | 75 | 76 | dev.demeng 77 | pluginbase-core 78 | 1.36.0-SNAPSHOT 79 | provided 80 | 81 | 82 | redis.clients 83 | jedis 84 | 7.0.0 85 | compile 86 | true 87 | 88 | 89 | org.apache.commons 90 | commons-pool2 91 | 2.12.1 92 | compile 93 | true 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /pluginbase-redis/src/main/java/dev/demeng/pluginbase/redis/IRedis.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * Copyright (c) lucko (Luck) 6 | * Copyright (c) lucko/helper contributors 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | package dev.demeng.pluginbase.redis; 28 | 29 | import dev.demeng.pluginbase.terminable.Terminable; 30 | import org.jetbrains.annotations.NotNull; 31 | import redis.clients.jedis.JedisPool; 32 | 33 | /** Represents an individual redis instance, created by the library. */ 34 | public interface IRedis extends Terminable { 35 | 36 | /** 37 | * Gets the JedisPool instance backing the Redis instance. 38 | * 39 | * @return The JedisPool instance 40 | */ 41 | @NotNull 42 | JedisPool getJedisPool(); 43 | } 44 | -------------------------------------------------------------------------------- /pluginbase-redis/src/main/java/dev/demeng/pluginbase/redis/RedisCredentials.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * Copyright (c) lucko (Luck) 6 | * Copyright (c) lucko/helper contributors 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | package dev.demeng.pluginbase.redis; 28 | 29 | import lombok.Data; 30 | import org.bukkit.configuration.ConfigurationSection; 31 | import org.jetbrains.annotations.NotNull; 32 | import org.jetbrains.annotations.Nullable; 33 | 34 | /** The POJO containing the credentials to a Redis instance. */ 35 | @Data(staticConstructor = "of") 36 | public final class RedisCredentials { 37 | 38 | /** The host (IP) of the instance. Local host is supported. */ 39 | @NotNull private final String host; 40 | 41 | /** The port to the instance, typically 6379. */ 42 | private final int port; 43 | 44 | /** The username of the instance. Null if empty. */ 45 | @Nullable private final String user; 46 | 47 | /** The password to the instance. Null if empty. */ 48 | @Nullable private final String password; 49 | 50 | /** If SSL should be enabled. */ 51 | private final boolean ssl; 52 | 53 | private RedisCredentials( 54 | @NotNull final String host, 55 | final int port, 56 | @Nullable final String user, 57 | @Nullable final String password, 58 | final boolean ssl) { 59 | this.host = host; 60 | this.port = port; 61 | 62 | if (user != null && user.trim().isEmpty()) { 63 | this.user = null; 64 | } else { 65 | this.user = user; 66 | } 67 | 68 | if (password != null && password.trim().isEmpty()) { 69 | this.password = null; 70 | } else { 71 | this.password = password; 72 | } 73 | 74 | this.ssl = ssl; 75 | } 76 | 77 | /** 78 | * Gets Redis credentials from a configuration section. 79 | * 80 | * @param section The configuration section 81 | * @return The Redis credentials provided 82 | */ 83 | @NotNull 84 | public static RedisCredentials of(@NotNull final ConfigurationSection section) { 85 | return of( 86 | section.getString("host", "localhost"), 87 | section.getInt("port", 6379), 88 | section.getString("user"), 89 | section.getString("password"), 90 | section.getBoolean("ssl", false)); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /pluginbase-redis/src/main/java/dev/demeng/pluginbase/redis/event/AsyncRedisMessageReceiveEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2022 Jiří Apjár 5 | * Copyright (c) 2022 Filip Zeman 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.redis.event; 27 | 28 | import dev.demeng.pluginbase.redis.MessageTransferObject; 29 | import java.util.Optional; 30 | import lombok.Getter; 31 | import org.bukkit.event.Event; 32 | import org.bukkit.event.HandlerList; 33 | import org.jetbrains.annotations.NotNull; 34 | 35 | /** Asynchronous event called when a Redis message is received by the server. */ 36 | public class AsyncRedisMessageReceiveEvent extends Event implements IRedisMessageReceiveEvent { 37 | 38 | @NotNull private static final HandlerList HANDLERS = new HandlerList(); 39 | 40 | /** Name of the channel the message came from. */ 41 | @Getter @NotNull private final String channel; 42 | 43 | /** MessageTransferObject containing message's data. */ 44 | @NotNull private final MessageTransferObject messageTransferObject; 45 | 46 | public AsyncRedisMessageReceiveEvent( 47 | @NotNull final String channel, @NotNull final MessageTransferObject mto) { 48 | super(true); 49 | this.channel = channel; 50 | this.messageTransferObject = mto; 51 | } 52 | 53 | @Override 54 | public @NotNull String getSenderId() { 55 | return this.messageTransferObject.getServerId(); 56 | } 57 | 58 | @Override 59 | public @NotNull String getMessage() { 60 | return this.messageTransferObject.getMessage(); 61 | } 62 | 63 | @Override 64 | public @NotNull Optional getMessageObject(@NotNull final Class objectClass) { 65 | return this.messageTransferObject.parseMessageObject(objectClass); 66 | } 67 | 68 | @Override 69 | public long getTimestamp() { 70 | return this.messageTransferObject.getTimestamp(); 71 | } 72 | 73 | @Override 74 | public @NotNull HandlerList getHandlers() { 75 | return HANDLERS; 76 | } 77 | 78 | public static HandlerList getHandlerList() { 79 | return HANDLERS; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /pluginbase-redis/src/main/java/dev/demeng/pluginbase/redis/event/IRedisMessageReceiveEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2022 Jiří Apjár 5 | * Copyright (c) 2022 Filip Zeman 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.redis.event; 27 | 28 | import java.util.Optional; 29 | import org.jetbrains.annotations.NotNull; 30 | 31 | /** The interface of a Redis message receive event. */ 32 | public interface IRedisMessageReceiveEvent { 33 | 34 | /** 35 | * Gets the ID of the sending server. 36 | * 37 | * @return The ID of the sending server 38 | */ 39 | @NotNull 40 | String getSenderId(); 41 | 42 | /** 43 | * Gets the channel of the message. 44 | * 45 | * @return THe channel name 46 | */ 47 | @NotNull 48 | String getChannel(); 49 | 50 | /** 51 | * Gets the raw string message. 52 | * 53 | * @return The raw string message 54 | */ 55 | @NotNull 56 | String getMessage(); 57 | 58 | /** 59 | * Gets the timestamp of the message 60 | * 61 | * @return The timestamp of the message 62 | */ 63 | long getTimestamp(); 64 | 65 | /** 66 | * Gets the object from the received message 67 | * 68 | * @param objectClass Object class 69 | * @param Object type 70 | * @return Parsed object, or null if it cannot be parsed 71 | */ 72 | @SuppressWarnings("Make sure the recieved message can really be converted to provided type!") 73 | @NotNull 74 | Optional getMessageObject(@NotNull Class objectClass); 75 | } 76 | -------------------------------------------------------------------------------- /pluginbase-redis/src/main/java/dev/demeng/pluginbase/redis/event/RedisMessageReceiveEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2022 Jiří Apjár 5 | * Copyright (c) 2022 Filip Zeman 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | package dev.demeng.pluginbase.redis.event; 27 | 28 | import dev.demeng.pluginbase.redis.MessageTransferObject; 29 | import java.util.Optional; 30 | import lombok.Getter; 31 | import lombok.RequiredArgsConstructor; 32 | import org.bukkit.event.Event; 33 | import org.bukkit.event.HandlerList; 34 | import org.jetbrains.annotations.NotNull; 35 | 36 | /** Synchronous event called when a Redis message is received by the server. */ 37 | @RequiredArgsConstructor 38 | public class RedisMessageReceiveEvent extends Event implements IRedisMessageReceiveEvent { 39 | 40 | @NotNull private static final HandlerList HANDLERS = new HandlerList(); 41 | 42 | /** Name of the channel the message came from. */ 43 | @Getter @NotNull private final String channel; 44 | 45 | /** MessageTransferObject containing message's data. */ 46 | @NotNull private final MessageTransferObject messageTransferObject; 47 | 48 | @Override 49 | public @NotNull String getSenderId() { 50 | return this.messageTransferObject.getServerId(); 51 | } 52 | 53 | @Override 54 | public @NotNull String getMessage() { 55 | return this.messageTransferObject.getMessage(); 56 | } 57 | 58 | @Override 59 | public @NotNull Optional getMessageObject(@NotNull final Class objectClass) { 60 | return this.messageTransferObject.parseMessageObject(objectClass); 61 | } 62 | 63 | @Override 64 | public long getTimestamp() { 65 | return this.messageTransferObject.getTimestamp(); 66 | } 67 | 68 | @Override 69 | public @NotNull HandlerList getHandlers() { 70 | return HANDLERS; 71 | } 72 | 73 | public static HandlerList getHandlerList() { 74 | return HANDLERS; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /pluginbase-sql/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | pluginbase 9 | dev.demeng 10 | 1.36.0-SNAPSHOT 11 | 12 | 13 | pluginbase-sql 14 | 15 | 16 | 17 17 | 17 18 | 19 | 20 | 21 | clean package 22 | 23 | 24 | org.apache.maven.plugins 25 | maven-compiler-plugin 26 | 3.14.1 27 | 28 | ${java.version} 29 | ${java.version} 30 | 31 | 32 | 33 | org.apache.maven.plugins 34 | maven-shade-plugin 35 | 3.6.1 36 | 37 | 38 | package 39 | 40 | shade 41 | 42 | 43 | false 44 | false 45 | 46 | 47 | com.zaxxer.hikari 48 | dev.demeng.pluginbase.sql.lib.hikari 49 | 50 | 51 | be.bendem.sqlstreams 52 | dev.demeng.pluginbase.sql.lib.sqlstreams 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | src/main/resources 63 | true 64 | 65 | 66 | 67 | 68 | 69 | 70 | jitpack.io 71 | https://jitpack.io 72 | 73 | 74 | 75 | 76 | 77 | dev.demeng 78 | pluginbase-core 79 | 1.36.0-SNAPSHOT 80 | provided 81 | 82 | 83 | com.zaxxer 84 | HikariCP 85 | 7.0.2 86 | compile 87 | true 88 | 89 | 90 | org.slf4j 91 | slf4j-api 92 | 93 | 94 | 95 | 96 | me.lucko 97 | sql-streams 98 | 1.0.0 99 | compile 100 | true 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /pluginbase-sql/src/main/java/dev/demeng/pluginbase/sql/BatchBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase.sql; 26 | 27 | import be.bendem.sqlstreams.util.SqlConsumer; 28 | import java.sql.PreparedStatement; 29 | import java.sql.SQLException; 30 | import java.util.LinkedList; 31 | import lombok.Getter; 32 | import org.intellij.lang.annotations.Language; 33 | import org.jetbrains.annotations.NotNull; 34 | 35 | /** 36 | * Represents a statement meant to be executed more than a single time. It will be executed all at 37 | * once, using a single database connection. 38 | */ 39 | public class BatchBuilder { 40 | 41 | /** The {@link Sql} that owns this batch builder. */ 42 | @NotNull private final Sql owner; 43 | 44 | /** The statement to be executed. */ 45 | @NotNull @Getter private final String statement; 46 | 47 | /** A linked list of PreparedStatement handlers. */ 48 | @NotNull @Getter 49 | private final LinkedList> handlers = new LinkedList<>(); 50 | 51 | public BatchBuilder(@NotNull final Sql owner, @NotNull @Language("SQL") final String statement) { 52 | this.owner = owner; 53 | this.statement = statement; 54 | } 55 | 56 | /** 57 | * Adds a handler which will be used on the statement. 58 | * 59 | * @param handler A new statement handler 60 | * @return this 61 | */ 62 | @NotNull 63 | public BatchBuilder batch(@NotNull final SqlConsumer handler) { 64 | handlers.add(handler); 65 | return this; 66 | } 67 | 68 | /** 69 | * Executes the statement for this batch, with the handlers used to prepare it. 70 | * 71 | * @throws SQLException If there is an SQL issue executing the batch 72 | */ 73 | public void execute() throws SQLException { 74 | owner.executeBatch(this); 75 | } 76 | 77 | /** 78 | * Resets this BatchBuilder's handlers, making it possible to be reused. 79 | * 80 | * @return this 81 | */ 82 | @NotNull 83 | public BatchBuilder reset() { 84 | handlers.clear(); 85 | return this; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /pluginbase-sql/src/main/java/dev/demeng/pluginbase/sql/SqlCredentials.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2025 Demeng Chen 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.demeng.pluginbase.sql; 26 | 27 | import lombok.Data; 28 | import org.bukkit.configuration.ConfigurationSection; 29 | import org.jetbrains.annotations.NotNull; 30 | 31 | /** The POJO containing the credentials to an SQL database. */ 32 | @Data(staticConstructor = "of") 33 | public final class SqlCredentials { 34 | 35 | /** The host (IP) of the database. Local host is supported. */ 36 | @NotNull private final String host; 37 | 38 | /** The port to the database, typically 3306. */ 39 | private final int port; 40 | 41 | /** The name of the database. */ 42 | @NotNull private final String database; 43 | 44 | /** The username to the database. */ 45 | @NotNull private final String user; 46 | 47 | /** The password to the database. */ 48 | @NotNull private final String password; 49 | 50 | /** 51 | * Gets database credentials from a configuration section. 52 | * 53 | * @param section The configuration section 54 | * @return The database credentials provided 55 | */ 56 | @NotNull 57 | public static SqlCredentials of(@NotNull final ConfigurationSection section) { 58 | return new SqlCredentials( 59 | section.getString("host", "localhost"), 60 | section.getInt("port", 3306), 61 | section.getString("database", "minecraft"), 62 | section.getString("user", "root"), 63 | section.getString("password", "root")); 64 | } 65 | } 66 | --------------------------------------------------------------------------------