├── docs ├── troubleshooting │ ├── index.txt │ └── reporting-pack-errors.md ├── developers │ ├── index.txt │ ├── api-usage.md │ └── api-introduction.md ├── external │ ├── index.txt │ ├── model-engine.md │ ├── oraxen.md │ └── itemsadder.md ├── index.txt ├── configuration │ ├── index.txt │ ├── custom-resources.md │ ├── actions.md │ ├── resource-pack-prompt.md │ └── resource-pack-exporting.md ├── creative-central.md └── commands.md ├── .idea ├── .name ├── codeStyles │ ├── codeStyleConfig.xml │ └── Project.xml ├── vcs.xml ├── kotlinc.xml ├── copyright │ ├── profiles_settings.xml │ └── creative_mit_license.xml ├── inspectionProfiles │ └── Project_Default.xml ├── misc.xml └── checkstyle-idea.xml ├── .github ├── game-output-example.png ├── resource-pack-prompt.png ├── example-error-in-game-output.png ├── pack-in-resource-pack-selection.png ├── open-output-log-when-game-starts-setting.png ├── settings-button-in-the-minecraft-launcher.png └── workflows │ └── build.yml ├── gradle ├── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties └── libs.versions.toml ├── common ├── src │ ├── main │ │ ├── resources │ │ │ └── resources │ │ │ │ ├── pack.png │ │ │ │ └── pack.mcmeta │ │ └── java │ │ │ └── team │ │ │ └── unnamed │ │ │ └── creative │ │ │ └── central │ │ │ └── common │ │ │ ├── action │ │ │ ├── Action.java │ │ │ ├── ActionExecutor.java │ │ │ ├── KickAction.java │ │ │ ├── MessageAction.java │ │ │ ├── AudienceActionExecutor.java │ │ │ ├── TitleAction.java │ │ │ └── ActionParser.java │ │ │ ├── util │ │ │ ├── Components.java │ │ │ ├── Permissions.java │ │ │ ├── HttpUtil.java │ │ │ ├── Monitor.java │ │ │ ├── LocalAddressProvider.java │ │ │ └── Streams.java │ │ │ ├── event │ │ │ ├── RegisteredEventListener.java │ │ │ ├── EventExceptionHandler.java │ │ │ └── EventBusImpl.java │ │ │ ├── export │ │ │ ├── FolderExporter.java │ │ │ ├── FileExporter.java │ │ │ ├── LocalHostExporter.java │ │ │ └── ResourcePackExporterFactory.java │ │ │ ├── config │ │ │ ├── SendConfiguration.java │ │ │ ├── ExportConfiguration.java │ │ │ └── Configuration.java │ │ │ └── server │ │ │ └── CommonResourcePackServer.java │ └── test │ │ └── java │ │ └── team │ │ └── unnamed │ │ └── creative │ │ └── central │ │ └── common │ │ ├── event │ │ ├── TestEvent.java │ │ └── EventBusTest.java │ │ └── export │ │ ├── PolymathExporterTest.java │ │ └── MCPacksExporterTest.java └── build.gradle.kts ├── renovate.json ├── api ├── build.gradle.kts └── src │ └── main │ └── java │ └── team │ └── unnamed │ └── creative │ └── central │ ├── event │ ├── Event.java │ ├── EventListener.java │ ├── pack │ │ ├── ResourcePackStatusEvent.java │ │ └── ResourcePackGenerateEvent.java │ └── EventBus.java │ ├── request │ └── ResourcePackRequestSender.java │ ├── server │ ├── CentralResourcePackServer.java │ └── ServeOptions.java │ ├── export │ ├── ResourcePackExporter.java │ └── ResourcePackLocation.java │ ├── CreativeCentral.java │ └── CreativeCentralProvider.java ├── gradle.properties ├── .editorconfig ├── minestom ├── src │ └── main │ │ ├── resources │ │ └── extension.json │ │ └── java │ │ └── team │ │ └── unnamed │ │ └── creative │ │ └── central │ │ └── minestom │ │ ├── action │ │ └── MinestomActionExecutor.java │ │ ├── listener │ │ ├── ResourcePackStatusListener.java │ │ ├── CreativeResourcePackStatusListener.java │ │ └── ResourcePackSendListener.java │ │ └── request │ │ └── MinestomResourcePackRequestSender.java └── build.gradle.kts ├── settings.gradle.kts ├── readme.md ├── license.txt ├── header.txt ├── bukkit ├── src │ └── main │ │ ├── resources │ │ └── plugin.yml │ │ └── java │ │ └── team │ │ └── unnamed │ │ └── creative │ │ └── central │ │ └── bukkit │ │ ├── external │ │ ├── ExternalResourcePackProviders.java │ │ ├── OraxenResourcePackProvider.java │ │ ├── ItemsAdderResourcePackProvider.java │ │ ├── ExternalResourcePackProvider.java │ │ └── ModelEngineResourcePackProvider.java │ │ ├── util │ │ ├── Messages.java │ │ └── PluginResources.java │ │ ├── action │ │ ├── PaperActionExecutor.java │ │ └── BukkitActionExecutor.java │ │ ├── listener │ │ ├── ResourcePackStatusListener.java │ │ ├── ResourcePackSendListener.java │ │ └── CreativeResourcePackStatusListener.java │ │ └── request │ │ └── BukkitResourcePackRequestSender.java └── build.gradle.kts ├── .gitignore └── gradlew.bat /docs/troubleshooting/index.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | creative-central-parent -------------------------------------------------------------------------------- /docs/developers/index.txt: -------------------------------------------------------------------------------- 1 | api-introduction.md 2 | api-usage.md -------------------------------------------------------------------------------- /docs/external/index.txt: -------------------------------------------------------------------------------- 1 | model-engine.md 2 | oraxen.md 3 | itemsadder.md -------------------------------------------------------------------------------- /docs/index.txt: -------------------------------------------------------------------------------- 1 | creative-central.md 2 | commands.md 3 | configuration 4 | external 5 | developers 6 | troubleshooting -------------------------------------------------------------------------------- /.github/game-output-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unnamed/creative-central/HEAD/.github/game-output-example.png -------------------------------------------------------------------------------- /docs/configuration/index.txt: -------------------------------------------------------------------------------- 1 | custom-resources.md 2 | resource-pack-prompt.md 3 | actions.md 4 | resource-pack-exporting.md -------------------------------------------------------------------------------- /.github/resource-pack-prompt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unnamed/creative-central/HEAD/.github/resource-pack-prompt.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unnamed/creative-central/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /.github/example-error-in-game-output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unnamed/creative-central/HEAD/.github/example-error-in-game-output.png -------------------------------------------------------------------------------- /.github/pack-in-resource-pack-selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unnamed/creative-central/HEAD/.github/pack-in-resource-pack-selection.png -------------------------------------------------------------------------------- /common/src/main/resources/resources/pack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unnamed/creative-central/HEAD/common/src/main/resources/resources/pack.png -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:recommended" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.github/open-output-log-when-game-starts-setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unnamed/creative-central/HEAD/.github/open-output-log-when-game-starts-setting.png -------------------------------------------------------------------------------- /.github/settings-button-in-the-minecraft-launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unnamed/creative-central/HEAD/.github/settings-button-in-the-minecraft-launcher.png -------------------------------------------------------------------------------- /api/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("creative.publishing-conventions") 3 | } 4 | 5 | dependencies { 6 | api(libs.creative.api) 7 | api(libs.adventure.api) 8 | } -------------------------------------------------------------------------------- /common/src/main/resources/resources/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "description": "A creative resource pack", 4 | "pack_format": 9 5 | } 6 | } -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | group=team.unnamed 2 | version=1.5.0 3 | description=The resource-pack unifier for Minecraft: Java Edition servers. 4 | 5 | repositoryName=ossrh 6 | snapshotRepository=https\://s01.oss.sonatype.org/content/repositories/snapshots/ 7 | releaseRepository=https\://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = false 7 | indent_size = 4 8 | indent_style = space 9 | 10 | # intellij idea 11 | ij_continuation_indent_size = 8 12 | ij_java_do_not_wrap_after_single_annotation = true 13 | ij_java_class_count_to_use_import_on_demand = 10 -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | -------------------------------------------------------------------------------- /common/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("creative.java-conventions") 3 | } 4 | 5 | dependencies { 6 | implementation(project(":creative-central-api")) 7 | implementation(libs.creative.serializer.minecraft) 8 | implementation(libs.creative.server) 9 | 10 | // -- provided by server or plugin implementations -- 11 | compileOnly(libs.adventure.text.minimessage) 12 | compileOnly("org.yaml:snakeyaml:2.2") 13 | } -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | -------------------------------------------------------------------------------- /minestom/src/main/resources/extension.json: -------------------------------------------------------------------------------- 1 | { 2 | "entrypoint": "team.unnamed.creative.central.minestom.CreativeCentralExtension", 3 | "name": "creative-central", 4 | "version": "${project.version}", 5 | "externalDependencies": { 6 | "repositories": [ 7 | { "name": "Central", "url": "https://repo1.maven.org/maven2/" } 8 | ], 9 | "artifacts": [ 10 | "org.yaml:snakeyaml:2.0" 11 | ] 12 | } 13 | } -------------------------------------------------------------------------------- /docs/external/model-engine.md: -------------------------------------------------------------------------------- 1 | ## ModelEngine 4 2 | 3 | `creative-central` supports ModelEngine 4 by default, it can take the resource-pack 4 | that ModelEngine generates and merge it with the resource-pack that `creative-central` 5 | generates, this way you can use ModelEngine and any plugin that uses `creative-central` 6 | at the same time. 7 | 8 | ### No extra configuration needed! 9 | 10 | You don't need to do anything to make `creative-central` work with ModelEngine 4, 11 | just have both plugins installed and they will work! -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0" 3 | } 4 | 5 | rootProject.name = "creative-central-parent" 6 | 7 | includePrefixed("api") 8 | includePrefixed("common") 9 | includePrefixed("bukkit") 10 | //includePrefixed("minestom") 11 | 12 | fun includePrefixed(name: String) { 13 | val kebabName = name.replace(':', '-') 14 | val path = name.replace(':', '/') 15 | 16 | include("creative-central-$kebabName") 17 | project(":creative-central-$kebabName").projectDir = file(path) 18 | } -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: 'build' 2 | 3 | on: [ 'push', 'pull_request' ] 4 | 5 | jobs: 6 | build: 7 | if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }} 8 | runs-on: 'ubuntu-latest' 9 | steps: 10 | - name: 'checkout repo' 11 | uses: 'actions/checkout@v4' 12 | - name: 'setup JDK 1.8' 13 | uses: 'actions/setup-java@v1' 14 | with: 15 | java-version: 1.8 16 | - name: 'build' 17 | run: './gradlew build' -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | creative = "1.8.0-SNAPSHOT" 3 | adventure = "4.14.0" 4 | 5 | [libraries] 6 | creative-api = { group = "team.unnamed", name = "creative-api", version.ref = "creative" } 7 | creative-serializer-minecraft = { group = "team.unnamed", name = "creative-serializer-minecraft", version.ref = "creative" } 8 | creative-server = { group = "team.unnamed", name = "creative-server", version.ref = "creative" } 9 | adventure-api = { group = "net.kyori", name = "adventure-api", version.ref = "adventure" } 10 | adventure-text-minimessage = { group = "net.kyori", name = "adventure-text-minimessage", version.ref = "adventure" } -------------------------------------------------------------------------------- /.idea/checkstyle-idea.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # creative-central 2 | [![Build Status](https://img.shields.io/github/actions/workflow/status/unnamed/creative-central/build.yml?branch=main)](https://github.com/unnamed/creative-central/actions/workflows/build.yml) 3 | [![MIT License](https://img.shields.io/badge/license-MIT-blue)](license.txt) 4 | [![Discord](https://img.shields.io/discord/683899335405994062)](https://discord.gg/xbba2fy) 5 | 6 | A Minecraft plugin that unifies the server's resource-pack, allowing other plugins 7 | to programmatically add resources to the server's resource-pack. 8 | 9 | `creative-central` allows server administrators to use multiple plugins that 10 | use resource-packs without conflicts. `creative-central` currently supports 11 | Paper and Minestom *(Network support with Velocity soon)* 12 | 13 | Check the [documentation](https://unnamed.team/docs/creative-central/) for installation 14 | and usage information for this project -------------------------------------------------------------------------------- /minestom/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("creative.dist-conventions") 3 | } 4 | 5 | repositories { 6 | maven("https://jitpack.io") // for minestom 7 | } 8 | 9 | dependencies { 10 | implementation(libs.creative.serializer.minecraft) 11 | implementation(project(":creative-central-api")) 12 | implementation(project(":creative-central-common")) 13 | compileOnly("com.github.Minestom:Minestom:2cdb3911b0") 14 | } 15 | 16 | java { 17 | toolchain { 18 | languageVersion.set(JavaLanguageVersion.of(17)) 19 | } 20 | } 21 | 22 | tasks { 23 | shadowJar { 24 | dependencies { 25 | // all these dependencies are provided by the server 26 | exclude(dependency("com.google.code.gson:gson")) 27 | exclude(dependency("net.kyori:adventure-api")) 28 | exclude(dependency("net.kyori:adventure-key")) 29 | exclude(dependency("net.kyori:examination-api")) 30 | exclude(dependency("net.kyori:examination-string")) 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-2023 Unnamed Team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /header.txt: -------------------------------------------------------------------------------- 1 | This file is part of creative-central, licensed under the MIT license 2 | 3 | Copyright (c) 2021-2023 Unnamed Team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /bukkit/src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | main: team.unnamed.creative.central.bukkit.CreativeCentralPlugin 2 | name: creative-central 3 | version: ${project.version} 4 | api-version: 1.13 5 | description: Creative central, the resource-pack unifier 6 | author: Unnamed Team 7 | website: https://unnamed.team/docs/creative/central/creative-central 8 | libraries: 9 | - net.kyori:adventure-api:4.14.0 10 | - net.kyori:adventure-text-minimessage:4.14.0 11 | - net.kyori:adventure-text-serializer-legacy:4.14.0 12 | commands: 13 | central: 14 | description: The central main command, used to manage the plugin 15 | usage: / [help|reload|apply] 16 | permissions: 17 | creative-central.command.help: 18 | description: Permission to use the help command 19 | default: true 20 | creative-central.command.reload: 21 | description: Permission to reload the plugin 22 | default: op 23 | creative-central.command.apply: 24 | description: Permission to apply the resource-pack to yourself 25 | default: true 26 | creative-central.command.apply.others: 27 | description: Permission to apply the resource-pack to others 28 | default: op -------------------------------------------------------------------------------- /docs/creative-central.md: -------------------------------------------------------------------------------- 1 | ## Creative Central 2 | 3 | Welcome to the `creative-central` documentation, creative-central is a plugin 4 | that unifies the server's resource-pack, allowing other plugins to 5 | programmatically add resources to the server's resource-pack 6 | 7 | `creative-central` allows administrators to use multiple plugins that 8 | use resource-packs without generating conflicts 9 | 10 | ### I don't understand yet... 11 | 12 | Do you know [Vault](https://github.com/MilkBowl/Vault)? Vault provides an API to 13 | unify the server's permissions, chat and economy, imagine a plugin that could do 14 | this, but for resource-packs, that's `creative-central`! 15 | 16 | 17 | ### Features 18 | - Add resources from your manually created resource-pack 19 | - Automatically generate the server's resource-pack 20 | - Automatically upload the resource-pack to a server or host it locally 21 | - Automatically send the resource-pack to everyone 22 | - Plug & play! 23 | - Say goodbye to bloated resource-packs! With `creative-central`, you can even have an empty resource-pack! 24 | - **..and all the benefits from [creative](https://unnamed.team/docs/creative)** 25 | - - Validate and compress your resource-pack 26 | - - `adventure` support! -------------------------------------------------------------------------------- /docs/commands.md: -------------------------------------------------------------------------------- 1 | ## Commands 2 | 3 | `creative-central` only has the necessary commands to administrate server's resource-pack 4 | and to apply it to players. The commands are: 5 | 6 | 7 | 8 | ### Command `/central help` 9 | **Permission:** `creative-central.command.help` *(Default for everyone)* 10 | 11 | Or just `/central`, sends a list of all commands to the player. Similar 12 | to this page. 13 | 14 | 15 | ### Command `/central reload` 16 | **Permission:** `creative-central.command.reload` *(Default for operators)* 17 | 18 | **Reloads** the plugin's configuration, **regenerates** and **exports** the server 19 | resource-pack, and **sends** it to all players connected to the server. 20 | 21 | 22 | ### Command `/central apply [target]` 23 | 24 | **Permissions:** 25 | - `creative-central.command.apply` *(Default for everyone, but won't let them apply the resource-pack for others)* 26 | - `creative-central.command.apply.others` *(Default for operators)* 27 | 28 | **Applies** the server resource-pack to the given player *(Specified in the [target] 29 | argument)* or to the player who executed the command if no target is specified. 30 | 31 | As the `[target]` argument, you can use a player's name or `@a` to apply the resource-pack 32 | to all players connected to the server. 33 | -------------------------------------------------------------------------------- /docs/developers/api-usage.md: -------------------------------------------------------------------------------- 1 | ## API Usage 2 | 3 | Now that we have a `CreativeCentral` instance, we can use it to subscribe to 4 | events, fire the resource-pack generate event, etc. 5 | 6 | ### Adding resources to the server resource-pack 7 | You can add your own resources to the server resource-pack by subscribing 8 | to the `ResourcePackGenerateEvent`, which is called when the server is 9 | loading or when the `/central reload` command is executed. 10 | 11 | ```java 12 | CreativeCentral central = ...; 13 | 14 | central.eventBus().listen(plugin, ResourcePackGenerateEvent.class, event -> { 15 | ResourcePack resourcePack = event.resourcePack(); 16 | 17 | // now we do the most important part, adding our own resources to 18 | // the resource-pack, imagine that we want to add a texture, we 19 | // would do the following: 20 | 21 | // here we create the texture for the minecraft note block 22 | Texture texture = Texture.builder() 23 | .key(Key.key("minecraft:block/note_block.png")) 24 | .data(Writable.file(new File("path/to/texture.png")) 25 | .build(); 26 | 27 | // here we register the texture 28 | resourcePack.texture(texture); 29 | }); 30 | ``` 31 | 32 | For more information, check the [creative API](../getting-started.md) -------------------------------------------------------------------------------- /.idea/copyright/creative_mit_license.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/action/Action.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.action; 25 | 26 | public interface Action { 27 | } 28 | -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/action/ActionExecutor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.action; 25 | 26 | public interface ActionExecutor { 27 | 28 | void execute(Action action, T target); 29 | 30 | } -------------------------------------------------------------------------------- /api/src/main/java/team/unnamed/creative/central/event/Event.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.event; 25 | 26 | /** 27 | * Marker interface for events in the creative-central 28 | * API 29 | * 30 | * @since 1.0.0 31 | */ 32 | public interface Event { 33 | } 34 | -------------------------------------------------------------------------------- /api/src/main/java/team/unnamed/creative/central/request/ResourcePackRequestSender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.request; 25 | 26 | public interface ResourcePackRequestSender { 27 | 28 | void send(Object player, ResourcePackRequest request); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /docs/configuration/custom-resources.md: -------------------------------------------------------------------------------- 1 | ## Custom Resources 2 | `creative-central` lets you add your own resources to the resource-pack, those 3 | resources will be automatically merged with the resources that plugins add. 4 | 5 | The resources that you add will be called the **base resource-pack**, since it is 6 | loaded first, and then plugin resources are added and merged. *(Note that merging 7 | is done by the plugins, not by creative-central)* 8 | 9 | ### Where is the base resource-pack? 10 | The base resource-pack "lives" in `/plugins/creative-central/resources/`. By default, 11 | you will find two files: `pack.mcmeta` and `pack.png` 12 | 13 | ### How should I modify it? 14 | The only necessary file is `pack.mcmeta`, here are some tips: 15 | - You **MUST** keep the `pack_format` version in sync with your server's version, you 16 | can find a table [here](https://minecraft.fandom.com/wiki/Pack_format#Resource_Pack) 17 | - You **CAN** update the `description` to whatever you want, it is shown in the 18 | resource-pack selection list 19 | ```json 20 | { 21 | "pack": { 22 | "description": "A creative description", 23 | "pack_format": 9 24 | } 25 | } 26 | ``` 27 | *creative-central also works as a pre-processor, so you can use MiniMessage there, 28 | soon we will support non-strict JSON syntax (supporting comments)* 29 | 30 | There is also the `pack.png` file, it is optional and you can replace it by your own 31 | resource-pack icon, the recommended size is 64x64px. 32 | 33 | ![Pack in Resource Pack Selection Screen](../../.github/pack-in-resource-pack-selection.png) -------------------------------------------------------------------------------- /docs/external/oraxen.md: -------------------------------------------------------------------------------- 1 | ## Oraxen 2 | 3 | `creative-central` supports Oraxen by default, it can take the resource-pack 4 | that Oraxen generates and merge it with the resource-pack that `creative-central` 5 | generates, this way you can use Oraxen and any plugin that uses `creative-central` 6 | at the same time. 7 | 8 | ### Configuration 9 | 10 | You need to make some changes to Oraxen's configuration in order to make it work 11 | with `creative-central`. 12 | 13 | #### 1. Disable upload 14 | 15 | First of all, disable Oraxen resource-pack upload in `settings.yml`: 16 | 17 | ```yaml 18 | Pack: 19 | ... 20 | upload: 21 | enabled: false # <- Set to false here 22 | type: ... 23 | ... 24 | ``` 25 | 26 | 27 | creative-central can upload resource-packs too, so this shouldn't be a problem. 28 | If you are using Polymath hosting, you can also configure `creative-central` to 29 | upload the resource-pack to that Polymath server. 30 | 31 | 32 | ```yaml 33 | # (creative-central's config.yml) 34 | export: 35 | # e.g. 'polymath atlas.oraxen.com atlas' 36 | type: 'polymath ' 37 | ``` 38 | 39 | 40 | #### 2. Disable receive 41 | 42 | Then, you need to set `Pack.receive.enabled` to `false`. `creative-central` can also 43 | manage actions on resource-pack feedback, so this shouldn't be a problem either. 44 | 45 | ```yaml 46 | Pack: 47 | ... 48 | receive: 49 | enabled: false # <- Set to false here 50 | ... 51 | ``` 52 | 53 | And that's it, you can now use Oraxen and creative-central at the same time! -------------------------------------------------------------------------------- /docs/configuration/actions.md: -------------------------------------------------------------------------------- 1 | ## Actions / Feedback 2 | The `creative-central` also has an actions/feedback system, that is, execute 3 | certain actions when the player accepts, successfully downloads, rejects or 4 | fails to download the server's resource-pack. 5 | 6 | The actions can be: send a message to the player, send a title to the player, 7 | kick the player. 8 | 9 | ### Configuring 10 | 11 | Open `config.yml` and go to the `feedback` section, you will find something 12 | like this: 13 | ```yaml 14 | feedback: 15 | accepted: ... 16 | success: ... 17 | declined: ... 18 | failed: ... 19 | ``` 20 | 21 | Those subsections have a list of actions to execute when the player: 22 | - `accepted`: accepted the resource-pack 23 | - `success`: finished downloading the resource-pack 24 | - `declined`: declined the resource-pack 25 | - `failed`: failed to download the resource-pack 26 | 27 | The supported actions are: 28 | - `message`: Just sends a chat message to the player 29 | - `title`: Sends a title to the player, has `title`, `subtitle`, 30 | `fade-in`, `stay` and `fade-out` options 31 | - `kick`: Just kicks the player with the given message, which can be multi-line 32 | 33 | Examples: 34 | ```yaml 35 | feedback: 36 | accepted: 37 | - message: 'You just accepted the resource-pack!' 38 | - message: 'Yay!' 39 | success: 40 | - title: 41 | title: 'You just downloaded the resource-pack!' 42 | subtitle: 'Yay!' 43 | fade-in: 20 44 | stay: 20 45 | fade-out: 20 46 | - message: 'You are so cool!' 47 | - message: 'Yay!' 48 | declined: 49 | - kick: 'Please accept!' 50 | failed: 51 | - kick: 'You failed to download the resource-pack :(' 52 | ``` -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/util/Components.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.util; 25 | 26 | import net.kyori.adventure.text.Component; 27 | import net.kyori.adventure.text.minimessage.MiniMessage; 28 | 29 | public final class Components { 30 | 31 | private Components() { 32 | } 33 | 34 | public static Component deserialize(String src) { 35 | return MiniMessage.miniMessage().deserialize(src); 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /bukkit/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("creative.dist-conventions") 3 | id("xyz.jpenilla.run-paper") version "2.3.0" 4 | } 5 | 6 | repositories { 7 | maven("https://repo.papermc.io/repository/maven-public/") 8 | maven("https://mvn.lumine.io/repository/maven-public/") // Model Engine 9 | maven("https://jitpack.io/") // ItemsAdder 10 | maven("https://repo.oraxen.com/releases") // oraxen 11 | } 12 | 13 | dependencies { 14 | implementation(libs.creative.serializer.minecraft) 15 | implementation(project(":creative-central-api")) 16 | implementation(project(":creative-central-common")) 17 | compileOnly("io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT") 18 | 19 | compileOnly("com.ticxo.modelengine:ModelEngine:R4.0.3") // Model Engine 20 | compileOnly("com.github.LoneDev6:API-ItemsAdder:3.6.1") // ItemsAdder 21 | compileOnly("io.th0rgal:oraxen:1.178.0") // oraxen 22 | 23 | implementation("org.bstats:bstats-bukkit:3.0.2") // bstats 24 | } 25 | 26 | java { 27 | toolchain { 28 | languageVersion.set(JavaLanguageVersion.of(21)) 29 | } 30 | } 31 | 32 | tasks { 33 | compileJava { 34 | options.release = 17 35 | } 36 | runServer { 37 | minecraftVersion("1.20.6") 38 | } 39 | shadowJar { 40 | dependencies { 41 | // all these dependencies are provided by the server 42 | exclude(dependency("com.google.code.gson:gson")) 43 | exclude(dependency("net.kyori:adventure-api")) 44 | exclude(dependency("net.kyori:adventure-key")) 45 | exclude(dependency("net.kyori:examination-api")) 46 | exclude(dependency("net.kyori:examination-string")) 47 | 48 | // relocate bstats 49 | relocate("org.bstats", "team.unnamed.creative.central.bukkit.lib.bstats") 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/util/Permissions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.util; 25 | 26 | public final class Permissions { 27 | 28 | public static final String HELP_COMMAND = "creative-central.command.help"; 29 | public static final String RELOAD_COMMAND = "creative-central.command.reload"; 30 | public static final String APPLY_COMMAND = "creative-central.command.apply"; 31 | public static final String APPLY_OTHERS_COMMAND = "creative-central.command.apply.others"; 32 | 33 | private Permissions() { 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /bukkit/src/main/java/team/unnamed/creative/central/bukkit/external/ExternalResourcePackProviders.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.bukkit.external; 25 | 26 | import org.jetbrains.annotations.NotNull; 27 | 28 | public final class ExternalResourcePackProviders { 29 | private ExternalResourcePackProviders() { 30 | } 31 | 32 | public static @NotNull ExternalResourcePackProvider @NotNull [] get() { 33 | return new ExternalResourcePackProvider[] { 34 | new ItemsAdderResourcePackProvider(), 35 | new ModelEngineResourcePackProvider(), 36 | new OraxenResourcePackProvider() 37 | }; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /docs/configuration/resource-pack-prompt.md: -------------------------------------------------------------------------------- 1 | ## Resource Pack Prompt 2 | `creative-central` lets you configure **everything**. In this page we are explaining 3 | how to configure the resource-pack prompt. All the settings for the resource-pack 4 | prompt can be found in the `config.yml` file. 5 | 6 | This is what the configuration section for it looks like: 7 | 8 | ```yaml 9 | send: 10 | request: 11 | required: true 12 | prompt: '<#ff8df8>Creative Central | Please accept the server resource pack to enjoy the full server experience' 13 | delay: 0 14 | ``` 15 | 16 | ### `required` 17 | The `required` setting tells the Minecraft client whether it is necessary or not to 18 | use the resource-pack to play in your server. *Note that setting this to true 19 | will not necessarily kick the player from the server if they don't download the 20 | resource-pack, to do that, you will have to configure the actions.* 21 | 22 | ### `prompt` 23 | The resource-pack prompt message, shown in the prompt screen. Supports MiniMessage 24 | format and newlines with `\n`, or using YAML's `|-` 25 | ```yaml 26 | send: 27 | request: 28 | required: true 29 | prompt: |- 30 | Welcome! 31 | Please accept the resource-pack! 32 | delay: 0 33 | ``` 34 | 35 | ### `delay` 36 | The resource-pack prompt delay, in seconds, determines how much time to wait before 37 | sending the resource pack to the player. Set to zero or less to send immediately. 38 | 39 | ### And that's it! 40 | Now when you join your server, you should see a screen like this: 41 | 42 | ![Resource Pack Prompt Screen](../../.github/resource-pack-prompt.png) 43 | 44 | And please note that, the Minecraft client will remember the player's choice, so 45 | the screen will appear only once. If you want to be asked again, do the following: 46 | - Go back to the Server List screen 47 | - Select your server and click 'Edit' 48 | - Click the `Server Resource Packs` button until it says 'Server Resource Packs: Prompt' -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/action/KickAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.action; 25 | 26 | import net.kyori.adventure.text.Component; 27 | import team.unnamed.creative.central.common.util.Components; 28 | 29 | public class KickAction implements Action { 30 | 31 | public static final String IDENTIFIER = "kick"; 32 | 33 | private final Component reason; 34 | 35 | public KickAction(Component reason) { 36 | this.reason = reason; 37 | } 38 | 39 | public Component reason() { 40 | return reason; 41 | } 42 | 43 | public static Action deserialize(Object src) { 44 | return new KickAction(Components.deserialize(src.toString())); 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /docs/troubleshooting/reporting-pack-errors.md: -------------------------------------------------------------------------------- 1 | ## Reporting Pack Errors 2 | 3 | When you join a server that needs a resource-pack, the server asks your client *(your 4 | Minecraft game)* to download it. However, there might errors while downloading a 5 | resource-pack. 6 | 7 | In this quick troubleshooting guide, we will check what the error was, so that we can 8 | easily report it to the server administrators *(or to the plugin developers)*. 9 | 10 | ### Step 1: Open output log 11 | Close the game, re-open the launcher and enable the **"Open output log when Minecraft: 12 | Java Edition starts" setting**. We do this to see the game logs, all the errors should 13 | be visible there. 14 | 15 | If you use a launcher other than vanilla launcher, you will have to find a similar setting 16 | and enable it. 17 | 18 | - Go to the launcher **Settings** *(Should be in the bottom-left corner)* 19 | ![Settings](../../.github/settings-button-in-the-minecraft-launcher.png) 20 | - **Check** the **"Open output log when Minecraft: Java Edition starts" setting** 21 | ![Open output log setting](../../.github/open-output-log-when-game-starts-setting.png) 22 | - **Start** the game. When the game starts, there should be another window open, 23 | and should look like this: 24 | ![Game Output Example](../../.github/game-output-example.png) 25 | 26 | ### Step 2: Join the server 27 | 28 | Now all you have to do is to try joining the server you are having trouble with, 29 | and check the game output window after you get kicked from the server. 30 | 31 | There should be some error *(in red text)*, similar to this *example error*: 32 | 33 | ![Error Example](../../.github/example-error-in-game-output.png) 34 | 35 | Don't worry if you don't understand the error, you just have to send it to the 36 | server administrators *(or to the plugin developers)* and they will help you! 37 | 38 | ### Why do I need to do this? 39 | 40 | Sadly, the vanilla Minecraft client doesn't tell the server **why** the resource 41 | packs fail to load, it just tells the server that it **just failed**. -------------------------------------------------------------------------------- /api/src/main/java/team/unnamed/creative/central/server/CentralResourcePackServer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.server; 25 | 26 | import org.jetbrains.annotations.Nullable; 27 | import team.unnamed.creative.BuiltResourcePack; 28 | 29 | import java.io.Closeable; 30 | import java.io.IOException; 31 | 32 | public interface CentralResourcePackServer extends Closeable { 33 | 34 | @Nullable BuiltResourcePack resourcePack(); 35 | 36 | void resourcePack(@Nullable BuiltResourcePack resourcePack); 37 | 38 | boolean isOpen(); 39 | 40 | void open(String address, String publicAddress, int port) throws IOException; 41 | 42 | String publicAddress(); 43 | 44 | @Nullable String address(); 45 | 46 | int port(); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/action/MessageAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.action; 25 | 26 | import net.kyori.adventure.text.Component; 27 | import team.unnamed.creative.central.common.util.Components; 28 | 29 | public class MessageAction implements Action { 30 | 31 | public static final String IDENTIFIER = "message"; 32 | 33 | private final Component message; 34 | 35 | public MessageAction(Component message) { 36 | this.message = message; 37 | } 38 | 39 | public Component message() { 40 | return message; 41 | } 42 | 43 | public static Action deserialize(Object src) { 44 | return new MessageAction(Components.deserialize(src.toString())); 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /common/src/test/java/team/unnamed/creative/central/common/event/TestEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.event; 25 | 26 | import org.junit.jupiter.api.Assertions; 27 | import team.unnamed.creative.central.event.Event; 28 | 29 | public final class TestEvent implements Event { 30 | 31 | private int counter = 0; 32 | 33 | public int counter() { 34 | return counter; 35 | } 36 | 37 | public void counter(int counter) { 38 | this.counter = counter; 39 | } 40 | 41 | public int increment() { 42 | return ++counter; 43 | } 44 | 45 | public void assertAndIncrement(int expected) { 46 | Assertions.assertEquals(expected, counter, "Counter is not equal to expected value"); 47 | ++counter; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/action/AudienceActionExecutor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.action; 25 | 26 | import net.kyori.adventure.audience.Audience; 27 | 28 | public abstract class AudienceActionExecutor implements ActionExecutor { 29 | 30 | @Override 31 | public final void execute(Action action, T target) { 32 | if (action instanceof MessageAction) { 33 | target.sendMessage(((MessageAction) action).message()); 34 | } else if (action instanceof TitleAction) { 35 | target.showTitle(((TitleAction) action).title()); 36 | } else { 37 | executeAction(action, target); 38 | } 39 | } 40 | 41 | protected abstract void executeAction(Action action, T target); 42 | 43 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Gradle files 2 | .gradle 3 | 4 | # Output files 5 | /build/ 6 | /*/build/ 7 | 8 | # Editors files 9 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 10 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 11 | 12 | # User-specific stuff 13 | .idea/**/workspace.xml 14 | .idea/**/tasks.xml 15 | .idea/**/usage.statistics.xml 16 | .idea/**/dictionaries 17 | .idea/**/shelf 18 | .idea/**/copilot/chatSessions/ 19 | 20 | # AWS User-specific 21 | .idea/**/aws.xml 22 | 23 | # Generated files 24 | .idea/**/contentModel.xml 25 | 26 | # Sensitive or high-churn files 27 | .idea/**/dataSources/ 28 | .idea/**/dataSources.ids 29 | .idea/**/dataSources.local.xml 30 | .idea/**/sqlDataSources.xml 31 | .idea/**/dynamic.xml 32 | .idea/**/uiDesigner.xml 33 | .idea/**/dbnavigator.xml 34 | 35 | # Gradle 36 | .idea/**/gradle.xml 37 | .idea/**/libraries 38 | 39 | # Gradle and Maven with auto-import 40 | # When using Gradle or Maven with auto-import, you should exclude module files, 41 | # since they will be recreated, and may cause churn. Uncomment if using 42 | # auto-import. 43 | .idea/artifacts 44 | .idea/compiler.xml 45 | .idea/jarRepositories.xml 46 | .idea/modules.xml 47 | .idea/*.iml 48 | .idea/modules 49 | *.iml 50 | *.ipr 51 | 52 | # CMake 53 | cmake-build-*/ 54 | 55 | # Mongo Explorer plugin 56 | .idea/**/mongoSettings.xml 57 | 58 | # File-based project format 59 | *.iws 60 | 61 | # IntelliJ 62 | out/ 63 | 64 | # mpeltonen/sbt-idea plugin 65 | .idea_modules/ 66 | 67 | # JIRA plugin 68 | atlassian-ide-plugin.xml 69 | 70 | # Cursive Clojure plugin 71 | .idea/replstate.xml 72 | 73 | # SonarLint plugin 74 | .idea/sonarlint/ 75 | 76 | # Discord plugin 77 | .idea/discord.xml 78 | 79 | # Crashlytics plugin (for Android Studio and IntelliJ) 80 | com_crashlytics_export_strings.xml 81 | crashlytics.properties 82 | crashlytics-build.properties 83 | fabric.properties 84 | 85 | # Editor-based Rest Client 86 | .idea/httpRequests 87 | 88 | # Android studio 3.1+ serialized cache file 89 | .idea/caches/build_file_checksums.ser 90 | 91 | # run-task 92 | /bukkit/run/ -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/event/RegisteredEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.event; 25 | 26 | import org.jetbrains.annotations.Nullable; 27 | import team.unnamed.creative.central.event.Event; 28 | import team.unnamed.creative.central.event.EventListener; 29 | 30 | public class RegisteredEventListener { 31 | 32 | private final @Nullable Object plugin; 33 | private final EventListener listener; 34 | 35 | public RegisteredEventListener(@Nullable Object plugin, EventListener listener) { 36 | this.plugin = plugin; 37 | this.listener = listener; 38 | } 39 | 40 | public @Nullable Object plugin() { 41 | return plugin; 42 | } 43 | 44 | public EventListener listener() { 45 | return listener; 46 | } 47 | 48 | 49 | } 50 | -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/util/HttpUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.util; 25 | 26 | import org.jetbrains.annotations.NotNull; 27 | 28 | import java.net.MalformedURLException; 29 | import java.net.URL; 30 | 31 | public final class HttpUtil { 32 | public static final String LINE_FEED = "\r\n"; 33 | 34 | private HttpUtil() { 35 | throw new UnsupportedOperationException("This class cannot be instantiated"); 36 | } 37 | 38 | public static @NotNull String generateBoundary() { 39 | return "----------------UnnamedBoundary" + Long.toHexString(System.nanoTime()); 40 | } 41 | 42 | public static @NotNull URL url(final @NotNull String url) { 43 | try { 44 | return new URL(url); 45 | } catch (final MalformedURLException e) { 46 | throw new IllegalArgumentException("Invalid URL: " + url, e); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /docs/external/itemsadder.md: -------------------------------------------------------------------------------- 1 | ## ItemsAdder 2 | 3 | `creative-central` supports ItemsAdder by default, it can take the resource-pack 4 | that ItemsAdder generates and merge it with the resource-pack that `creative-central` 5 | generates, this way you can use ItemsAdder and any plugin that uses `creative-central` 6 | at the same time. 7 | 8 | ### Configuration 9 | 10 | You need to make some changes to ItemsAdder's configuration in order to make it work 11 | with `creative-central`. 12 | 13 | #### 1. Disable hosting 14 | 15 | First of all, disable ItemsAdder resource-pack hosting in `config.yml`. By default, 16 | it shouldn't be enabled, but if you have it enabled, you need to disable it: 17 | 18 | ```yaml 19 | resource-pack: 20 | hosting: 21 | no-host: 22 | enabled: true # <-- Set this to true 23 | self-host: 24 | enabled: false # <-- Set this to false 25 | server-ip: ... 26 | pack-port: ... 27 | external-host: 28 | enabled: false # <-- Set this to false 29 | url: ... 30 | skip-url-file-type-check___DONT_ASK_HELP_IF_SET_TRUE: false 31 | ... 32 | ``` 33 | 34 | 35 | creative-central can upload/host resource-packs too, so this shouldn't be a problem. 36 | 37 | #### 2. Disable apply-on-join 38 | 39 | Then, you need to set `resource-pack.apply-on-join` to `false`. `creative-central` can also 40 | send the resource-pack to players when they join, so this shouldn't be a problem either. 41 | 42 | ```yaml 43 | resource-pack: 44 | ... 45 | apply-on-join: false 46 | ... 47 | ``` 48 | 49 | #### 3. Disable merging other resource-packs 50 | 51 | Finally, you need to prevent ItemsAdder from merging other plugins' resource-pack 52 | with its own resource-pack. This prevents a resource-pack from being merged twice. 53 | 54 | ```yaml 55 | resource-pack: 56 | ... 57 | zip: 58 | ... 59 | merge_other_plugins_resourcepacks_folders: [] # <-- Set this to an empty list 60 | # or just remove known plugins 61 | # like ModelEngine from the list 62 | ``` 63 | 64 | And that's it, you can now use ItemsAdder and creative-central at the same time! -------------------------------------------------------------------------------- /minestom/src/main/java/team/unnamed/creative/central/minestom/action/MinestomActionExecutor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.minestom.action; 25 | 26 | import net.minestom.server.entity.Player; 27 | import team.unnamed.creative.central.common.action.*; 28 | 29 | public final class MinestomActionExecutor extends AudienceActionExecutor { 30 | 31 | private static final ActionExecutor INSTANCE = new MinestomActionExecutor(); 32 | 33 | private MinestomActionExecutor() { 34 | } 35 | 36 | @Override 37 | public void executeAction(Action action, Player player) { 38 | if (action instanceof KickAction kickAction) { 39 | player.kick(kickAction.reason()); 40 | } else { 41 | throw new IllegalArgumentException("Unknown action type: '" + action + "'"); 42 | } 43 | } 44 | 45 | public static ActionExecutor minestom() { 46 | return INSTANCE; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /api/src/main/java/team/unnamed/creative/central/server/ServeOptions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.server; 25 | 26 | import org.jetbrains.annotations.Nullable; 27 | import team.unnamed.creative.central.request.ResourcePackRequest; 28 | 29 | public final class ServeOptions { 30 | 31 | private @Nullable ResourcePackRequest request = null; 32 | private int delay = 0; 33 | private boolean serve = true; 34 | 35 | public @Nullable ResourcePackRequest request() { 36 | return request; 37 | } 38 | 39 | public void request(@Nullable ResourcePackRequest request) { 40 | this.request = request; 41 | } 42 | 43 | public int delay() { 44 | return delay; 45 | } 46 | 47 | public void delay(int delay) { 48 | this.delay = delay; 49 | } 50 | 51 | public boolean serve() { 52 | return serve; 53 | } 54 | 55 | public void serve(boolean serve) { 56 | this.serve = serve; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /bukkit/src/main/java/team/unnamed/creative/central/bukkit/util/Messages.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.bukkit.util; 25 | 26 | import net.kyori.adventure.text.Component; 27 | import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; 28 | import org.bukkit.command.CommandSender; 29 | import org.jetbrains.annotations.NotNull; 30 | 31 | public final class Messages { 32 | private static final boolean PAPER_AVAILABLE; 33 | 34 | static { 35 | boolean paperAvailable = false; 36 | try { 37 | CommandSender.class.getMethod("sendMessage", Component.class); 38 | paperAvailable = true; 39 | } catch (final NoSuchMethodException ignored) { 40 | } 41 | PAPER_AVAILABLE = paperAvailable; 42 | } 43 | 44 | private Messages() { 45 | } 46 | 47 | public static void send(final @NotNull CommandSender sender, final @NotNull Component message) { 48 | if (PAPER_AVAILABLE) { 49 | sender.sendMessage(message); 50 | } else { 51 | sender.sendMessage(LegacyComponentSerializer.legacySection().serialize(message)); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /api/src/main/java/team/unnamed/creative/central/export/ResourcePackExporter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.export; 25 | 26 | import org.jetbrains.annotations.Nullable; 27 | import team.unnamed.creative.ResourcePack; 28 | 29 | import java.io.IOException; 30 | 31 | /** 32 | * Interface for exporting resource packs to different 33 | * targets like files, external servers (like MCPacks, 34 | * Polymath, Dropbox, etc.) or a local server 35 | * 36 | * @since 1.0.0 37 | */ 38 | public interface ResourcePackExporter { 39 | 40 | /** 41 | * Exports the given {@code resourcePack} to the 42 | * target of this exporter, returning the location 43 | * of the exported resource pack, or {@code null} 44 | * if the exporting method is not hosted 45 | * 46 | * @param resourcePack The resource pack to export 47 | * @return The location of the exported resource pack, 48 | * null if the exporting method is not hosted 49 | * @throws IOException If the exporting process fails 50 | * @since 1.0.0 51 | */ 52 | @Nullable ResourcePackLocation export(ResourcePack resourcePack) throws IOException; 53 | 54 | } 55 | -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/export/FolderExporter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.export; 25 | 26 | import org.jetbrains.annotations.Contract; 27 | import org.jetbrains.annotations.Nullable; 28 | import team.unnamed.creative.ResourcePack; 29 | import team.unnamed.creative.central.export.ResourcePackExporter; 30 | import team.unnamed.creative.central.export.ResourcePackLocation; 31 | import team.unnamed.creative.serialize.minecraft.MinecraftResourcePackWriter; 32 | 33 | import java.io.File; 34 | import java.util.logging.Logger; 35 | 36 | public class FolderExporter implements ResourcePackExporter { 37 | 38 | private final File target; 39 | private final Logger logger; 40 | 41 | public FolderExporter(File target, Logger logger) { 42 | this.target = target; 43 | this.logger = logger; 44 | } 45 | 46 | @Override 47 | @Contract("_ -> null") 48 | public @Nullable ResourcePackLocation export(ResourcePack resourcePack) { 49 | MinecraftResourcePackWriter.minecraft().writeToDirectory(target, resourcePack); 50 | logger.info("Exported resource pack to folder: " + target); 51 | return null; 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/config/SendConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.config; 25 | 26 | import org.jetbrains.annotations.Nullable; 27 | 28 | public class SendConfiguration { 29 | 30 | private final RequestConfiguration request = new RequestConfiguration(); 31 | private int delay = 0; 32 | 33 | public RequestConfiguration request() { 34 | return request; 35 | } 36 | 37 | public void delay(int delay) { 38 | this.delay = delay; 39 | } 40 | 41 | public int delay() { 42 | return delay; 43 | } 44 | 45 | public static class RequestConfiguration { 46 | 47 | private boolean required = true; 48 | private @Nullable String prompt = ""; 49 | 50 | public void required(boolean required) { 51 | this.required = required; 52 | } 53 | 54 | public boolean required() { 55 | return required; 56 | } 57 | 58 | public void prompt(@Nullable String prompt) { 59 | this.prompt = prompt; 60 | } 61 | 62 | public @Nullable String prompt() { 63 | return prompt; 64 | } 65 | 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/util/Monitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.util; 25 | 26 | import java.util.Collections; 27 | import java.util.HashSet; 28 | import java.util.Set; 29 | import java.util.function.BiConsumer; 30 | 31 | import static java.util.Objects.requireNonNull; 32 | 33 | public final class Monitor { 34 | 35 | private T value; 36 | private final Set> listeners = Collections.synchronizedSet(new HashSet<>()); 37 | 38 | private Monitor(T initialValue) { 39 | this.value = requireNonNull(initialValue, "initialValue"); 40 | } 41 | 42 | public synchronized T get() { 43 | return value; 44 | } 45 | 46 | public synchronized void set(T value) { 47 | T oldValue = this.value; 48 | this.value = value; 49 | listeners.forEach(listener -> listener.accept(oldValue, value)); 50 | } 51 | 52 | public synchronized void onChange(BiConsumer listener) { 53 | requireNonNull(listener, "listener"); 54 | listeners.add(listener); 55 | } 56 | 57 | public static Monitor monitor(T initialValue) { 58 | return new Monitor<>(initialValue); 59 | } 60 | 61 | } -------------------------------------------------------------------------------- /api/src/main/java/team/unnamed/creative/central/export/ResourcePackLocation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.export; 25 | 26 | import org.jetbrains.annotations.ApiStatus; 27 | import org.jetbrains.annotations.NotNull; 28 | 29 | import java.net.URI; 30 | 31 | import static java.util.Objects.requireNonNull; 32 | 33 | public final class ResourcePackLocation { 34 | 35 | private final URI uri; 36 | private final String hash; 37 | 38 | private ResourcePackLocation(URI uri, String hash) { 39 | this.uri = requireNonNull(uri, "url"); 40 | this.hash = requireNonNull(hash, "hash"); 41 | } 42 | 43 | @Deprecated 44 | @ApiStatus.ScheduledForRemoval(inVersion = "2.0.0") 45 | public String url() { 46 | return uri.toString(); 47 | } 48 | 49 | public @NotNull URI uri() { 50 | return uri; 51 | } 52 | 53 | public String hash() { 54 | return hash; 55 | } 56 | 57 | public static @NotNull ResourcePackLocation of(final @NotNull URI uri, final @NotNull String hash) { 58 | return new ResourcePackLocation(uri, hash); 59 | } 60 | 61 | @Deprecated 62 | @ApiStatus.ScheduledForRemoval(inVersion = "2.0.0") 63 | public static @NotNull ResourcePackLocation of(String url, String hash) { 64 | return new ResourcePackLocation(URI.create(url), hash); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /minestom/src/main/java/team/unnamed/creative/central/minestom/listener/ResourcePackStatusListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.minestom.listener; 25 | 26 | import net.minestom.server.entity.Player; 27 | import net.minestom.server.event.player.PlayerResourcePackStatusEvent; 28 | import team.unnamed.creative.central.CreativeCentral; 29 | import team.unnamed.creative.central.event.pack.ResourcePackStatusEvent; 30 | import team.unnamed.creative.central.pack.ResourcePackStatus; 31 | 32 | public class ResourcePackStatusListener { 33 | 34 | private final CreativeCentral central; 35 | 36 | public ResourcePackStatusListener(CreativeCentral central) { 37 | this.central = central; 38 | } 39 | 40 | public void onResourcePackStatus(PlayerResourcePackStatusEvent minestomEvent) { 41 | Player player = minestomEvent.getPlayer(); 42 | 43 | // convert bukkit status to creative status 44 | ResourcePackStatus status = switch (minestomEvent.getStatus()) { 45 | case ACCEPTED -> ResourcePackStatus.ACCEPTED; 46 | case DECLINED -> ResourcePackStatus.DECLINED; 47 | case FAILED_DOWNLOAD -> ResourcePackStatus.FAILED; 48 | case SUCCESS -> ResourcePackStatus.LOADED; 49 | }; 50 | 51 | central.eventBus().call(ResourcePackStatusEvent.class, new ResourcePackStatusEvent(player, status)); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/util/LocalAddressProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.util; 25 | 26 | import org.jetbrains.annotations.Nullable; 27 | 28 | import java.io.ByteArrayOutputStream; 29 | import java.io.IOException; 30 | import java.io.InputStream; 31 | import java.net.HttpURLConnection; 32 | import java.net.URL; 33 | import java.util.List; 34 | 35 | public final class LocalAddressProvider { 36 | 37 | private LocalAddressProvider() { 38 | } 39 | 40 | public static @Nullable String getLocalAddress(List whatIsMyIpServicesAddresses) throws IOException { 41 | for (String serviceAddress : whatIsMyIpServicesAddresses) { 42 | URL url = new URL(serviceAddress); 43 | HttpURLConnection httpUrlConnection = (HttpURLConnection) url.openConnection(); 44 | 45 | try (InputStream input = httpUrlConnection.getInputStream()) { 46 | ByteArrayOutputStream output = new ByteArrayOutputStream(); 47 | byte[] buf = new byte[32]; 48 | int read; 49 | while ((read = input.read(buf)) != -1) { 50 | output.write(buf, 0, read); 51 | } 52 | 53 | return output.toString(); 54 | } catch (IOException ignored) { 55 | } 56 | } 57 | return null; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/action/TitleAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.action; 25 | 26 | import net.kyori.adventure.title.Title; 27 | import net.kyori.adventure.util.Ticks; 28 | import team.unnamed.creative.central.common.util.Components; 29 | 30 | import java.util.Map; 31 | 32 | public class TitleAction implements Action { 33 | 34 | public static final String IDENTIFIER = "title"; 35 | 36 | private final Title title; 37 | 38 | public TitleAction(Title title) { 39 | this.title = title; 40 | } 41 | 42 | public Title title() { 43 | return title; 44 | } 45 | 46 | public static Action deserialize(Object src) { 47 | @SuppressWarnings("unchecked") 48 | Map data = (Map) src; 49 | 50 | return new TitleAction(Title.title( 51 | Components.deserialize(data.getOrDefault("title", "").toString()), 52 | Components.deserialize(data.getOrDefault("subtitle", "").toString()), 53 | Title.Times.times( 54 | Ticks.duration(Integer.parseInt(data.getOrDefault("fade-in", 10).toString())), 55 | Ticks.duration(Integer.parseInt(data.getOrDefault("stay", 70).toString())), 56 | Ticks.duration(Integer.parseInt(data.getOrDefault("fade-out", 20).toString())) 57 | ) 58 | )); 59 | } 60 | 61 | } -------------------------------------------------------------------------------- /bukkit/src/main/java/team/unnamed/creative/central/bukkit/action/PaperActionExecutor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.bukkit.action; 25 | 26 | import net.kyori.adventure.text.Component; 27 | import org.bukkit.entity.Player; 28 | import team.unnamed.creative.central.common.action.Action; 29 | import team.unnamed.creative.central.common.action.ActionExecutor; 30 | import team.unnamed.creative.central.common.action.AudienceActionExecutor; 31 | import team.unnamed.creative.central.common.action.KickAction; 32 | 33 | public final class PaperActionExecutor extends AudienceActionExecutor { 34 | private static final ActionExecutor INSTANCE = new PaperActionExecutor(); 35 | 36 | private PaperActionExecutor() { 37 | } 38 | 39 | @Override 40 | protected void executeAction(Action action, Player player) { 41 | if (action instanceof KickAction kickAction) { 42 | player.kick(kickAction.reason()); 43 | } else { 44 | throw new IllegalArgumentException("Unknown action type: '" + action + "'"); 45 | } 46 | } 47 | 48 | public static ActionExecutor paper() { 49 | return INSTANCE; 50 | } 51 | 52 | public static boolean isAvailable() { 53 | try { 54 | Player.class.getMethod("sendMessage", Component.class); 55 | return true; 56 | } catch (final NoSuchMethodException e) { 57 | return false; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /bukkit/src/main/java/team/unnamed/creative/central/bukkit/util/PluginResources.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.bukkit.util; 25 | 26 | import org.bukkit.plugin.Plugin; 27 | import org.jetbrains.annotations.Nullable; 28 | 29 | import java.io.File; 30 | import java.io.FileInputStream; 31 | import java.io.FileNotFoundException; 32 | import java.io.InputStream; 33 | 34 | public final class PluginResources { 35 | 36 | private PluginResources() { 37 | } 38 | 39 | public static @Nullable InputStream get(Plugin plugin, String path) { 40 | File file = new File(plugin.getDataFolder(), path); 41 | if (!file.exists()) { 42 | // file doesn't exist in the plugin's data folder, 43 | // try to get it from the jar and copy it to the 44 | // data folder 45 | InputStream stream = plugin.getResource(path); 46 | if (stream == null) { 47 | // file doesn't exist in the jar either 48 | return null; 49 | } 50 | plugin.saveResource(path, false); 51 | return stream; 52 | } 53 | 54 | // file exists in the plugin's data folder, 55 | // read the resource from there 56 | try { 57 | return new FileInputStream(file); 58 | } catch (FileNotFoundException e) { 59 | // should never happen 60 | throw new IllegalStateException("File doesn't exist", e); 61 | } 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /minestom/src/main/java/team/unnamed/creative/central/minestom/listener/CreativeResourcePackStatusListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.minestom.listener; 25 | 26 | import net.minestom.server.entity.Player; 27 | import team.unnamed.creative.central.common.action.Action; 28 | import team.unnamed.creative.central.common.config.Configuration; 29 | import team.unnamed.creative.central.common.util.Monitor; 30 | import team.unnamed.creative.central.event.EventListener; 31 | import team.unnamed.creative.central.event.pack.ResourcePackStatusEvent; 32 | import team.unnamed.creative.central.minestom.action.MinestomActionExecutor; 33 | import team.unnamed.creative.central.pack.ResourcePackStatus; 34 | 35 | import java.util.Collections; 36 | import java.util.List; 37 | 38 | public class CreativeResourcePackStatusListener implements EventListener { 39 | 40 | private final Monitor config; 41 | 42 | public CreativeResourcePackStatusListener(Monitor config) { 43 | this.config = config; 44 | } 45 | 46 | @Override 47 | public void on(ResourcePackStatusEvent event) { 48 | ResourcePackStatus status = event.status(); 49 | Player player = (Player) event.player(); 50 | 51 | List actions = config.get().feedback().getOrDefault(status, Collections.emptyList()); 52 | for (Action action : actions) { 53 | MinestomActionExecutor.minestom().execute(action, player); 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/export/FileExporter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.export; 25 | 26 | import org.jetbrains.annotations.Contract; 27 | import org.jetbrains.annotations.Nullable; 28 | import team.unnamed.creative.ResourcePack; 29 | import team.unnamed.creative.central.export.ResourcePackExporter; 30 | import team.unnamed.creative.central.export.ResourcePackLocation; 31 | import team.unnamed.creative.serialize.minecraft.MinecraftResourcePackWriter; 32 | 33 | import java.io.File; 34 | import java.io.IOException; 35 | import java.util.logging.Logger; 36 | 37 | /** 38 | * Fluent-style class for exporting resource 39 | * packs to {@link File}s 40 | */ 41 | public class FileExporter implements ResourcePackExporter { 42 | 43 | private final File target; 44 | private final Logger logger; 45 | 46 | public FileExporter(File target, Logger logger) { 47 | this.target = target; 48 | this.logger = logger; 49 | } 50 | 51 | @Override 52 | @Contract("_ -> null") 53 | public @Nullable ResourcePackLocation export(ResourcePack resourcePack) throws IOException { 54 | if (!target.exists() && !target.createNewFile()) { 55 | throw new IOException("Failed to create target resource pack file"); 56 | } 57 | 58 | MinecraftResourcePackWriter.minecraft().writeToZipFile(target, resourcePack); 59 | logger.info("Exported resource-pack to file: " + target); 60 | return null; 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /minestom/src/main/java/team/unnamed/creative/central/minestom/request/MinestomResourcePackRequestSender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.minestom.request; 25 | 26 | import net.kyori.adventure.text.Component; 27 | import net.minestom.server.entity.Player; 28 | import net.minestom.server.resourcepack.ResourcePack; 29 | import team.unnamed.creative.central.request.ResourcePackRequest; 30 | import team.unnamed.creative.central.request.ResourcePackRequestSender; 31 | 32 | public final class MinestomResourcePackRequestSender implements ResourcePackRequestSender { 33 | 34 | private static final ResourcePackRequestSender INSTANCE = new MinestomResourcePackRequestSender(); 35 | 36 | private MinestomResourcePackRequestSender() { 37 | } 38 | 39 | @Override 40 | public void send(Object playerObject, ResourcePackRequest request) { 41 | if (!(playerObject instanceof Player player)) { 42 | throw new IllegalArgumentException("Provided 'player' is not an actual Minestom Player: " + playerObject); 43 | } 44 | 45 | String url = request.uri().toString(); 46 | String hash = request.hash(); 47 | Component prompt = request.prompt(); 48 | 49 | player.setResourcePack( 50 | request.required() 51 | ? ResourcePack.forced(url, hash, prompt) 52 | : ResourcePack.optional(url, hash, prompt) 53 | ); 54 | } 55 | 56 | public static ResourcePackRequestSender minestom() { 57 | return INSTANCE; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /api/src/main/java/team/unnamed/creative/central/event/EventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.event; 25 | 26 | /** 27 | * Functional interface, called when the given {@code E} 28 | * event is called/fired. All the event listeners must 29 | * be registered in a {@link EventBus} in order to be 30 | * executed. 31 | * 32 | * @param The subscribed event type 33 | * @see EventBus#call(Class, Event) 34 | * @since 1.0.0 35 | */ 36 | @FunctionalInterface 37 | public interface EventListener { 38 | 39 | /** 40 | * The functional method, executed when the provided 41 | * {@code event} is called 42 | * 43 | * @param event The fired event 44 | * @see EventBus#call(Class, Event) 45 | * @since 1.0.0 46 | */ 47 | void on(E event); 48 | 49 | /** 50 | * Returns this event listener's priority. 51 | * 52 | *

Lowest priority = first, highest priority 53 | * = last

54 | * 55 | * @return This listener's priority 56 | * @since 1.0.0 57 | */ 58 | default Priority priority() { 59 | return Priority.NORMAL; 60 | } 61 | 62 | /** 63 | * The priority of an {@link EventListener}. 64 | * 65 | *

Listeners with lowest priority are executed 66 | * as first, listeners with highest priority are 67 | * executed last.

68 | * 69 | * @since 1.0.0 70 | */ 71 | enum Priority { 72 | LOWEST, 73 | LOW, 74 | NORMAL, 75 | HIGH, 76 | HIGHEST 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /docs/developers/api-introduction.md: -------------------------------------------------------------------------------- 1 | ## API Introduction 2 | 3 | ### Adding central to your project 4 | The first step to using `creative-central` is to add it to your project, you can do 5 | this using Gradle *(recommended)* or Maven 6 | 7 | #### Gradle 8 | If you are using Gradle, you have to add our repository and the central dependency 9 | to your build script *(`build.gradle(.kts)`)* 10 | 11 | ##### Kotlin DSL: 12 | ```kotlin 13 | repositories { 14 | maven("https://repo.unnamed.team/repository/unnamed-public/") 15 | } 16 | 17 | dependencies { 18 | compileOnly("team.unnamed:creative-central-api:%%REPLACE_latestReleaseOrSnapshot{team.unnamed:creative-central-api}%%") 19 | } 20 | ``` 21 | 22 | ##### Groovy DSL: 23 | ```groovy 24 | repositories { 25 | maven { 26 | url "https://repo.unnamed.team/repository/unnamed-public/" 27 | } 28 | } 29 | 30 | dependencies { 31 | compileOnly "team.unnamed:creative-central-api:%%REPLACE_latestReleaseOrSnapshot{team.unnamed:creative-central-api}%%" 32 | } 33 | ``` 34 | 35 | #### Maven 36 | If you are using Maven, you have to add our repository and the central dependency 37 | to your `pom.xml` 38 | ```xml 39 | 40 | 41 | unnamed-public 42 | https://repo.unnamed.team/repository/unnamed-public/ 43 | 44 | 45 | 46 | 47 | 48 | team.unnamed 49 | creative-central-api 50 | %%REPLACE_latestReleaseOrSnapshot{team.unnamed:creative-central-api}%% 51 | provided 52 | 53 | 54 | ``` 55 | 56 | ### Declaring a dependency on central 57 | 58 | If you are developing a plugin that uses `creative-central`, you should declare a dependency 59 | on it in your plugin's `plugin.yml`, this will make sure that your plugin will not be loaded 60 | if `creative-central` is not present 61 | 62 | **plugin.yml in Bukkit plugins** 63 | ```yaml 64 | name: ... 65 | main: ... 66 | version: ... 67 | ... 68 | depend: [creative-central] 69 | ``` 70 | 71 | ### Getting an instance of the API 72 | 73 | First of all, you need to obtain an instance of `CreativeCentral`, you can do this by using 74 | your platform's service provider *(preferred)* or using `CreativeCentralProvider#get()`, the 75 | static service provider 76 | 77 | **Using Bukkit's service provider** 78 | ```java 79 | RegisteredServiceProvider provider = Bukkit.getServicesManager().getRegistration(CreativeCentral.class); 80 | if (provider != null) { 81 | CreativeCentral central = provider.getProvider(); 82 | // ... 83 | } 84 | ``` 85 | 86 | **Using the static service provider** 87 | ```java 88 | CreativeCentral central = CreativeCentralProvider.get(); 89 | ``` 90 | 91 | Now that we have a `CreativeCentral` instance, we can get to the next step -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/config/ExportConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.config; 25 | 26 | public class ExportConfiguration { 27 | 28 | private String type = "mcpacks"; 29 | private LocalHostExportConfiguration localHost = new LocalHostExportConfiguration(); 30 | 31 | public String type() { 32 | return type; 33 | } 34 | 35 | public void type(String type) { 36 | this.type = type; 37 | } 38 | 39 | public LocalHostExportConfiguration localHost() { 40 | return localHost; 41 | } 42 | 43 | public static class LocalHostExportConfiguration { 44 | 45 | private boolean enabled = false; 46 | private String publicAddress = ""; 47 | private String address = ""; 48 | private int port = 7270; 49 | 50 | public boolean enabled() { 51 | return enabled; 52 | } 53 | 54 | public void enabled(boolean enabled) { 55 | this.enabled = enabled; 56 | } 57 | 58 | public String publicAddress() { 59 | return publicAddress; 60 | } 61 | 62 | public void publicAddress(String publicAddress) { 63 | this.publicAddress = publicAddress; 64 | } 65 | 66 | public String address() { 67 | return address; 68 | } 69 | 70 | public void address(String address) { 71 | this.address = address; 72 | } 73 | 74 | public int port() { 75 | return port; 76 | } 77 | 78 | public void port(int port) { 79 | this.port = port; 80 | } 81 | 82 | } 83 | 84 | } -------------------------------------------------------------------------------- /bukkit/src/main/java/team/unnamed/creative/central/bukkit/listener/ResourcePackStatusListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.bukkit.listener; 25 | 26 | import org.bukkit.entity.Player; 27 | import org.bukkit.event.EventHandler; 28 | import org.bukkit.event.Listener; 29 | import org.bukkit.event.player.PlayerResourcePackStatusEvent; 30 | import team.unnamed.creative.central.CreativeCentral; 31 | import team.unnamed.creative.central.event.pack.ResourcePackStatusEvent; 32 | import team.unnamed.creative.central.pack.ResourcePackStatus; 33 | 34 | public class ResourcePackStatusListener implements Listener { 35 | 36 | private final CreativeCentral central; 37 | 38 | public ResourcePackStatusListener(CreativeCentral central) { 39 | this.central = central; 40 | } 41 | 42 | @EventHandler 43 | public void onResourcePackStatus(PlayerResourcePackStatusEvent bukkitEvent) { 44 | Player player = bukkitEvent.getPlayer(); 45 | 46 | // convert bukkit status to creative status 47 | ResourcePackStatus status = switch (bukkitEvent.getStatus()) { 48 | case ACCEPTED -> ResourcePackStatus.ACCEPTED; 49 | case DECLINED -> ResourcePackStatus.DECLINED; 50 | case FAILED_DOWNLOAD -> ResourcePackStatus.FAILED; 51 | case SUCCESSFULLY_LOADED -> ResourcePackStatus.LOADED; 52 | case DOWNLOADED -> ResourcePackStatus.DOWNLOADED; 53 | case INVALID_URL -> ResourcePackStatus.INVALID_URL; 54 | case FAILED_RELOAD -> ResourcePackStatus.FAILED_RELOAD; 55 | case DISCARDED -> ResourcePackStatus.DISCARDED; 56 | }; 57 | 58 | central.eventBus().call(ResourcePackStatusEvent.class, new ResourcePackStatusEvent(player, status)); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /minestom/src/main/java/team/unnamed/creative/central/minestom/listener/ResourcePackSendListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.minestom.listener; 25 | 26 | import net.minestom.server.entity.Player; 27 | import net.minestom.server.event.player.PlayerSpawnEvent; 28 | import net.minestom.server.utils.time.TimeUnit; 29 | import team.unnamed.creative.central.CreativeCentral; 30 | import team.unnamed.creative.central.request.ResourcePackRequest; 31 | import team.unnamed.creative.central.server.ServeOptions; 32 | 33 | public class ResourcePackSendListener { 34 | 35 | private final CreativeCentral central; 36 | 37 | public ResourcePackSendListener(CreativeCentral central) { 38 | this.central = central; 39 | } 40 | 41 | public void onJoin(PlayerSpawnEvent event) { 42 | 43 | if (!event.isFirstSpawn()) { 44 | return; 45 | } 46 | 47 | ServeOptions options = central.serveOptions(); 48 | if (!options.serve()) { 49 | // we don't send the resource pack on join 50 | return; 51 | } 52 | 53 | Player player = event.getPlayer(); 54 | ResourcePackRequest request = options.request(); 55 | if (request == null) { 56 | // todo: should we kick the player? 57 | return; 58 | } 59 | 60 | int delay = options.delay(); 61 | if (delay <= 0) { 62 | // send the resource pack request immediately 63 | central.requestSender().send(player, request); 64 | } else { 65 | // delay the resource pack request 66 | player.scheduler().buildTask(() -> central.requestSender().send(player, request)) 67 | .delay(delay, TimeUnit.SECOND) 68 | .schedule(); 69 | } 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /bukkit/src/main/java/team/unnamed/creative/central/bukkit/listener/ResourcePackSendListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.bukkit.listener; 25 | 26 | import org.bukkit.Bukkit; 27 | import org.bukkit.entity.Player; 28 | import org.bukkit.event.EventHandler; 29 | import org.bukkit.event.Listener; 30 | import org.bukkit.event.player.PlayerJoinEvent; 31 | import team.unnamed.creative.central.bukkit.CreativeCentralPlugin; 32 | import team.unnamed.creative.central.request.ResourcePackRequest; 33 | import team.unnamed.creative.central.server.ServeOptions; 34 | 35 | public class ResourcePackSendListener implements Listener { 36 | 37 | private final CreativeCentralPlugin plugin; 38 | 39 | public ResourcePackSendListener(CreativeCentralPlugin plugin) { 40 | this.plugin = plugin; 41 | } 42 | 43 | @EventHandler 44 | public void onJoin(PlayerJoinEvent event) { 45 | ServeOptions options = plugin.serveOptions(); 46 | if (!options.serve()) { 47 | // we don't send the resource pack on join 48 | return; 49 | } 50 | 51 | Player player = event.getPlayer(); 52 | ResourcePackRequest request = options.request(); 53 | if (request == null) { 54 | // todo: should we kick the player? 55 | return; 56 | } 57 | 58 | int delay = options.delay(); 59 | if (delay <= 0) { 60 | // send the resource pack request immediately 61 | plugin.requestSender().send(player, request); 62 | } else { 63 | // delay the resource pack request 64 | Bukkit.getScheduler().runTaskLater( 65 | plugin, 66 | () -> plugin.requestSender().send(player, request), 67 | delay * 20L 68 | ); 69 | } 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /bukkit/src/main/java/team/unnamed/creative/central/bukkit/listener/CreativeResourcePackStatusListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.bukkit.listener; 25 | 26 | import org.bukkit.entity.Player; 27 | import team.unnamed.creative.central.bukkit.action.BukkitActionExecutor; 28 | import team.unnamed.creative.central.bukkit.action.PaperActionExecutor; 29 | import team.unnamed.creative.central.common.action.Action; 30 | import team.unnamed.creative.central.common.action.ActionExecutor; 31 | import team.unnamed.creative.central.common.config.Configuration; 32 | import team.unnamed.creative.central.common.util.Monitor; 33 | import team.unnamed.creative.central.event.EventListener; 34 | import team.unnamed.creative.central.event.pack.ResourcePackStatusEvent; 35 | import team.unnamed.creative.central.pack.ResourcePackStatus; 36 | 37 | import java.util.Collections; 38 | import java.util.List; 39 | 40 | public class CreativeResourcePackStatusListener implements EventListener { 41 | 42 | private final Monitor config; 43 | private final ActionExecutor actionExecutor; 44 | 45 | public CreativeResourcePackStatusListener(Monitor config) { 46 | this.config = config; 47 | this.actionExecutor = PaperActionExecutor.isAvailable() 48 | ? PaperActionExecutor.paper() 49 | : BukkitActionExecutor.bukkit(); 50 | } 51 | 52 | @Override 53 | public void on(ResourcePackStatusEvent event) { 54 | ResourcePackStatus status = event.status(); 55 | Player player = (Player) event.player(); 56 | 57 | List actions = config.get().feedback().getOrDefault(status, Collections.emptyList()); 58 | for (Action action : actions) { 59 | actionExecutor.execute(action, player); 60 | } 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/export/LocalHostExporter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.export; 25 | 26 | import org.jetbrains.annotations.Nullable; 27 | import team.unnamed.creative.BuiltResourcePack; 28 | import team.unnamed.creative.ResourcePack; 29 | import team.unnamed.creative.central.export.ResourcePackExporter; 30 | import team.unnamed.creative.central.export.ResourcePackLocation; 31 | import team.unnamed.creative.central.server.CentralResourcePackServer; 32 | import team.unnamed.creative.serialize.minecraft.MinecraftResourcePackWriter; 33 | 34 | import java.net.URI; 35 | import java.util.logging.Logger; 36 | 37 | public class LocalHostExporter implements ResourcePackExporter { 38 | 39 | private final CentralResourcePackServer server; 40 | private final Logger logger; 41 | 42 | public LocalHostExporter(CentralResourcePackServer server, Logger logger) { 43 | this.server = server; 44 | this.logger = logger; 45 | } 46 | 47 | @Override 48 | public @Nullable ResourcePackLocation export(ResourcePack resourcePack) { 49 | 50 | if (!server.isOpen()) { 51 | logger.severe( 52 | "The resource-pack server is closed, can't host resource-pack there," 53 | + " you must enable it in the configuration (export.localhost.enabled)" 54 | ); 55 | return null; 56 | } 57 | 58 | // build resource pack in memory 59 | BuiltResourcePack pack = MinecraftResourcePackWriter.minecraft().build(resourcePack); 60 | 61 | server.resourcePack(pack); 62 | 63 | URI uri = URI.create(String.format( 64 | "http://%s:%s/%s.zip", 65 | server.publicAddress(), 66 | server.port(), 67 | pack.hash() 68 | )); 69 | 70 | return ResourcePackLocation.of(uri, pack.hash()); 71 | } 72 | 73 | } -------------------------------------------------------------------------------- /bukkit/src/main/java/team/unnamed/creative/central/bukkit/external/OraxenResourcePackProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.bukkit.external; 25 | 26 | import io.th0rgal.oraxen.api.OraxenPack; 27 | import io.th0rgal.oraxen.api.events.OraxenPackGeneratedEvent; 28 | import io.th0rgal.oraxen.api.events.OraxenPackPreUploadEvent; 29 | import org.bukkit.event.EventHandler; 30 | import org.bukkit.event.Listener; 31 | import org.bukkit.plugin.Plugin; 32 | import org.jetbrains.annotations.NotNull; 33 | import org.jetbrains.annotations.Nullable; 34 | import team.unnamed.creative.ResourcePack; 35 | import team.unnamed.creative.serialize.minecraft.MinecraftResourcePackReader; 36 | 37 | import static java.util.Objects.requireNonNull; 38 | 39 | public final class OraxenResourcePackProvider implements ExternalResourcePackProvider { 40 | @Override 41 | public @NotNull String pluginName() { 42 | return "Oraxen"; 43 | } 44 | 45 | @Override 46 | public boolean awaitOnStart() { 47 | // Oraxen generates its resource-pack on startup 48 | return true; 49 | } 50 | 51 | @Override 52 | public void listenForChanges(final @NotNull Plugin plugin, final @NotNull Runnable changeListener) { 53 | requireNonNull(plugin, "plugin"); 54 | requireNonNull(changeListener, "changeListener"); 55 | plugin.getServer().getPluginManager().registerEvents(new Listener() { 56 | @EventHandler 57 | public void onGenerated(final @NotNull OraxenPackPreUploadEvent event) { 58 | changeListener.run(); 59 | } 60 | }, plugin); 61 | } 62 | 63 | @Override 64 | public @Nullable ResourcePack load() { 65 | final var oraxenPack = OraxenPack.getPack(); 66 | if (!oraxenPack.exists()) { 67 | return null; 68 | } 69 | return MinecraftResourcePackReader.minecraft().readFromZipFile(oraxenPack); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /api/src/main/java/team/unnamed/creative/central/CreativeCentral.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central; 25 | 26 | import team.unnamed.creative.BuiltResourcePack; 27 | import team.unnamed.creative.ResourcePack; 28 | import team.unnamed.creative.central.event.EventBus; 29 | import team.unnamed.creative.central.event.pack.ResourcePackGenerateEvent; 30 | import team.unnamed.creative.central.request.ResourcePackRequestSender; 31 | import team.unnamed.creative.central.server.CentralResourcePackServer; 32 | import team.unnamed.creative.central.server.ServeOptions; 33 | 34 | import java.util.concurrent.CompletableFuture; 35 | 36 | /** 37 | * Main interface for the creative-central system 38 | * 39 | * @since 1.0.0 40 | */ 41 | public interface CreativeCentral { 42 | 43 | /** 44 | * Generates or re-generates the server's resource-pack. 45 | * 46 | *

This will fire the {@link ResourcePackGenerateEvent} 47 | * event, making all the registered plugins add their 48 | * resources into the resource-pack

49 | * 50 | *

After the resource-pack is completed, it is built 51 | * to a {@link BuiltResourcePack} and exported.

52 | * 53 | *

If it was exported to somewhere we know the location 54 | * (URL and Hash), the resource-pack is applied to all the 55 | * online players

56 | * 57 | * @return A completable future of the generated resource-pack 58 | * @since 1.0.0 59 | */ 60 | CompletableFuture generate(); 61 | 62 | /** 63 | * Gets the {@link EventBus} instance used for everything 64 | * within the creative-central system 65 | * 66 | * @return The held event bus instance 67 | * @since 1.0.0 68 | */ 69 | EventBus eventBus(); 70 | 71 | CentralResourcePackServer server(); 72 | 73 | ServeOptions serveOptions(); 74 | 75 | ResourcePackRequestSender requestSender(); 76 | 77 | } 78 | -------------------------------------------------------------------------------- /bukkit/src/main/java/team/unnamed/creative/central/bukkit/external/ItemsAdderResourcePackProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.bukkit.external; 25 | 26 | import dev.lone.itemsadder.api.Events.ItemsAdderPackCompressedEvent; 27 | import org.bukkit.Bukkit; 28 | import org.bukkit.event.EventHandler; 29 | import org.bukkit.event.Listener; 30 | import org.bukkit.plugin.Plugin; 31 | import org.jetbrains.annotations.NotNull; 32 | import org.jetbrains.annotations.Nullable; 33 | import team.unnamed.creative.ResourcePack; 34 | import team.unnamed.creative.serialize.minecraft.MinecraftResourcePackReader; 35 | 36 | import java.io.File; 37 | 38 | import static java.util.Objects.requireNonNull; 39 | 40 | public final class ItemsAdderResourcePackProvider implements ExternalResourcePackProvider { 41 | @Override 42 | public @NotNull String pluginName() { 43 | return "ItemsAdder"; 44 | } 45 | 46 | @Override 47 | public void listenForChanges(final @NotNull Plugin plugin, final @NotNull Runnable changeListener) { 48 | requireNonNull(plugin, "plugin"); 49 | requireNonNull(changeListener, "changeListener"); 50 | Bukkit.getPluginManager().registerEvents(new Listener() { 51 | @EventHandler 52 | public void onPackCompressed(final ItemsAdderPackCompressedEvent event) { 53 | changeListener.run(); 54 | } 55 | }, plugin); 56 | } 57 | 58 | @Override 59 | public @Nullable ResourcePack load() { 60 | final var itemsAdderPlugin = Bukkit.getPluginManager().getPlugin(pluginName()); 61 | if (itemsAdderPlugin == null) { 62 | return null; 63 | } 64 | final var resourcePackZipFile = new File(itemsAdderPlugin.getDataFolder(), "output/generated.zip"); 65 | if (!resourcePackZipFile.exists()) { 66 | return null; 67 | } 68 | return MinecraftResourcePackReader.minecraft().readFromZipFile(resourcePackZipFile); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/config/Configuration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.config; 25 | 26 | import team.unnamed.creative.central.common.action.Action; 27 | import team.unnamed.creative.central.pack.ResourcePackStatus; 28 | 29 | import java.util.ArrayList; 30 | import java.util.HashMap; 31 | import java.util.List; 32 | import java.util.Map; 33 | 34 | public class Configuration { 35 | 36 | // Settings for the resource pack sending. In this section, we specify 37 | // some options for the resource pack request and some extra options on 38 | // how and when to send the resource pack to the player 39 | private final SendConfiguration send = new SendConfiguration(); 40 | 41 | // specifies the actions to perform when the player 42 | // accepts, declines, loads or fails to download the resource pack 43 | private final Map> feedback = new HashMap<>(); 44 | 45 | // settings for Resource Pack exporting, in this section we specify 46 | // how to export the generated resource pack 47 | private final ExportConfiguration export = new ExportConfiguration(); 48 | 49 | private final Map messages = new HashMap<>(); 50 | 51 | // specifies what "What is my ip" services we can use in order to obtain 52 | // the server's IP address (which is sent to the client to download the 53 | // resource pack) 54 | private final List whatIsMyIpServices = new ArrayList<>(); 55 | 56 | public SendConfiguration send() { 57 | return send; 58 | } 59 | 60 | public Map> feedback() { 61 | return feedback; 62 | } 63 | 64 | public ExportConfiguration export() { 65 | return export; 66 | } 67 | 68 | public Map messages() { 69 | return messages; 70 | } 71 | 72 | public List whatIsMyIpServices() { 73 | return whatIsMyIpServices; 74 | } 75 | 76 | } -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 1>&2 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 48 | echo. 1>&2 49 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 50 | echo location of your Java installation. 1>&2 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 1>&2 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 62 | echo. 1>&2 63 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 64 | echo location of your Java installation. 1>&2 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /api/src/main/java/team/unnamed/creative/central/event/pack/ResourcePackStatusEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.event.pack; 25 | 26 | import org.jetbrains.annotations.NotNull; 27 | import team.unnamed.creative.central.event.Event; 28 | import team.unnamed.creative.central.pack.ResourcePackStatus; 29 | 30 | import static java.util.Objects.requireNonNull; 31 | 32 | /** 33 | * An event called when a resource-pack status is received from 34 | * a player. This is normally after the player fails, succeeds 35 | * or rejects the resource-pack when they are asked to download it. 36 | * 37 | * @since 1.0.0 38 | */ 39 | public final class ResourcePackStatusEvent implements Event { 40 | private final Object player; 41 | private final ResourcePackStatus status; 42 | 43 | /** 44 | * Instantiate a new {@link ResourcePackStatusEvent} 45 | * 46 | * @param player The player 47 | * @param status The resource-pack status 48 | * @since 1.0.0 49 | */ 50 | public ResourcePackStatusEvent(final @NotNull Object player, final @NotNull ResourcePackStatus status) { 51 | this.player = requireNonNull(player, "player"); 52 | this.status = requireNonNull(status, "status"); 53 | } 54 | 55 | /** 56 | * Returns the player who send the status. 57 | * The type depends on the server platform. 58 | * 59 | * @return The player object. 60 | * @since 1.0.0 61 | */ 62 | public @NotNull Object player() { 63 | return player; 64 | } 65 | 66 | /** 67 | * Returns the received resource-pack status, 68 | * 69 | * @return The resource-pack status 70 | * @since 1.0.0 71 | * @see ResourcePackStatus 72 | */ 73 | public @NotNull ResourcePackStatus status() { 74 | return status; 75 | } 76 | 77 | @Override 78 | public String toString() { 79 | return "ResourcePackStatusEvent{" + 80 | "player=" + player + 81 | ", status=" + status + 82 | '}'; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/event/EventExceptionHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.event; 25 | 26 | import team.unnamed.creative.central.event.Event; 27 | 28 | import java.util.function.BiConsumer; 29 | import java.util.logging.Level; 30 | import java.util.logging.Logger; 31 | 32 | public interface EventExceptionHandler { 33 | 34 | void handleException(Class eventType, E event, RegisteredEventListener listener, Exception exception); 35 | 36 | static EventExceptionHandler empty() { 37 | return new EventExceptionHandler() { 38 | @Override 39 | public void handleException( 40 | Class eventType, 41 | E event, 42 | RegisteredEventListener listener, 43 | Exception exception 44 | ) { 45 | // no-op 46 | } 47 | }; 48 | } 49 | 50 | static EventExceptionHandler logging(Logger logger) { 51 | return logging((header, exception) -> logger.log(Level.WARNING, header, exception)); 52 | } 53 | 54 | static EventExceptionHandler logging(BiConsumer logger) { 55 | return new EventExceptionHandler() { 56 | @Override 57 | public void handleException( 58 | Class eventType, 59 | E event, 60 | RegisteredEventListener listener, 61 | Exception exception 62 | ) { 63 | Object plugin = listener.plugin(); 64 | logger.accept( 65 | "Unhandled exception caught when calling event\n" 66 | + " Event: " + eventType.getName() + "\n" 67 | + " For listener: " + listener.listener() + "\n" 68 | + " Of plugin: " + (plugin != null ? plugin.toString() : "(No plugin specified)"), 69 | exception 70 | ); 71 | } 72 | }; 73 | } 74 | 75 | } -------------------------------------------------------------------------------- /api/src/main/java/team/unnamed/creative/central/CreativeCentralProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central; 25 | 26 | import org.jetbrains.annotations.ApiStatus; 27 | import org.jetbrains.annotations.Nullable; 28 | 29 | import static java.util.Objects.requireNonNull; 30 | 31 | /** 32 | * Static provider for the {@link CreativeCentral} instance 33 | * 34 | * @since 1.0.0 35 | */ 36 | public final class CreativeCentralProvider { 37 | 38 | // Very based on: 39 | // https://github.com/LuckPerms/LuckPerms/blob/master/api/src/main/java/net/luckperms/api/LuckPermsProvider.java 40 | 41 | private static @Nullable CreativeCentral instance; 42 | 43 | private CreativeCentralProvider() { 44 | } 45 | 46 | public static CreativeCentral get() { 47 | CreativeCentral instance = CreativeCentralProvider.instance; 48 | if (instance == null) { 49 | throw new NotLoadedException(); 50 | } 51 | return instance; 52 | } 53 | 54 | @ApiStatus.Internal 55 | public static void set(CreativeCentral instance) { 56 | requireNonNull(instance, "instance"); 57 | if (CreativeCentralProvider.instance != null) { 58 | throw new IllegalStateException("Service was already set, you cannot set it twice!"); 59 | } 60 | CreativeCentralProvider.instance = instance; 61 | } 62 | 63 | @ApiStatus.Internal 64 | public static void unset() { 65 | CreativeCentralProvider.instance = null; 66 | } 67 | 68 | private static final class NotLoadedException extends IllegalStateException { 69 | 70 | private static final String MESSAGE = "Creative Central isn't loaded yet!\n" + 71 | "This could be because:\n" + 72 | " a) The Creative Central plugin is not installed or it failed to enable\n" + 73 | " b) The plugin in the stacktrace does not declare a dependency on Creative Central\n" + 74 | " c) The plugin in the stacktrace is retrieving the API before the plugin 'enable' phase\n" + 75 | " (call the #get method in onEnable, not the constructor!)\n"; 76 | 77 | NotLoadedException() { 78 | super(MESSAGE); 79 | } 80 | 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/util/Streams.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.util; 25 | 26 | import java.io.BufferedOutputStream; 27 | import java.io.File; 28 | import java.io.IOException; 29 | import java.io.InputStream; 30 | import java.io.OutputStream; 31 | import java.nio.file.Files; 32 | 33 | /** 34 | * Utility class for working with 35 | * {@link InputStream}s and {@link OutputStream}s 36 | * @author yusshu (Andre Roldan) 37 | */ 38 | public final class Streams { 39 | 40 | /** 41 | * Determines the length of the buffer 42 | * used in the {@link Streams#pipe} 43 | * operation 44 | */ 45 | private static final int BUFFER_LENGTH = 1024; 46 | 47 | private Streams() { 48 | throw new UnsupportedOperationException("This class cannot be instantiated"); 49 | } 50 | 51 | /** 52 | * Reads and writes the data from the 53 | * given {@code input} to the given {@code output} 54 | * by using a fixed-size byte buffer 55 | * (fastest way) 56 | * 57 | *

Note that this method doesn't close 58 | * the inputs or outputs

59 | * 60 | * @throws IOException If an error occurs while 61 | * reading or writing the data 62 | */ 63 | public static void pipe( 64 | InputStream input, 65 | OutputStream output 66 | ) throws IOException { 67 | byte[] buffer = new byte[BUFFER_LENGTH]; 68 | int length; 69 | while ((length = input.read(buffer)) != -1) { 70 | output.write(buffer, 0, length); 71 | } 72 | } 73 | 74 | /** 75 | * Reads and writes the data from the 76 | * given {@code input} to the given {@code outputFile} 77 | * 78 | *

Note that this method doesn't close 79 | * the given input stream

80 | * 81 | * @throws IOException If an error occurs while 82 | * reading or writing the data 83 | */ 84 | public static void pipeToFile( 85 | InputStream input, 86 | File outputFile 87 | ) throws IOException { 88 | try (OutputStream output = new BufferedOutputStream(Files.newOutputStream(outputFile.toPath()))) { 89 | pipe(input, output); 90 | } 91 | } 92 | 93 | } -------------------------------------------------------------------------------- /bukkit/src/main/java/team/unnamed/creative/central/bukkit/external/ExternalResourcePackProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.bukkit.external; 25 | 26 | import org.bukkit.plugin.Plugin; 27 | import org.jetbrains.annotations.NotNull; 28 | import org.jetbrains.annotations.Nullable; 29 | import team.unnamed.creative.ResourcePack; 30 | 31 | /** 32 | * Interface representing an external (like from another plugin) 33 | * resource pack provider. 34 | */ 35 | public interface ExternalResourcePackProvider { 36 | /** 37 | * Returns the name of the plugin that provides the resource pack. 38 | * 39 | * @return The name of the plugin that provides the resource pack. 40 | */ 41 | @NotNull String pluginName(); 42 | 43 | /** 44 | * Should we wait for the providers to make an initial resource-pack 45 | * zip/export/build before incorporating them to our own resource-pack? 46 | * 47 | *

When it's set to true, the first resource-pack generation will 48 | * wait until the resource-pack is created for this plugin.

49 | * 50 | *

When it's set to false, the first resource-pack generation will 51 | * not wait, but will only check if it can load the current resource-pack

52 | * 53 | * @return Whether we should wait for the providers to make an initial 54 | * resource-pack zip/export/build before incorporating them to our own 55 | * resource-pack. 56 | */ 57 | default boolean awaitOnStart() { 58 | return false; 59 | } 60 | 61 | /** 62 | * Listens for changes/rebuilds in the resource pack provided 63 | * by this plugin. 64 | * 65 | *

It MUST be ensured that, when executing the given {@code changeListener}, 66 | * the changes will be applied and calls to {@link #load()} from {@code changeListener} 67 | * MUST return the updated resource-pack.

68 | * 69 | * @param plugin The plugin that will be used to register the listener. 70 | * @param changeListener The listener that will be called when the 71 | * resource pack changes. 72 | */ 73 | default void listenForChanges(final @NotNull Plugin plugin, final @NotNull Runnable changeListener) { 74 | } 75 | 76 | /** 77 | * Loads the resource-pack. Null if not found. 78 | * 79 | * @return The resource-pack. Null if not found. 80 | */ 81 | @Nullable ResourcePack load(); 82 | } 83 | -------------------------------------------------------------------------------- /common/src/test/java/team/unnamed/creative/central/common/export/PolymathExporterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.export; 25 | 26 | import org.junit.jupiter.api.Test; 27 | import team.unnamed.creative.ResourcePack; 28 | import team.unnamed.creative.central.common.util.Streams; 29 | import team.unnamed.creative.central.export.ResourcePackLocation; 30 | 31 | import java.io.ByteArrayOutputStream; 32 | import java.io.InputStream; 33 | import java.net.URI; 34 | import java.security.DigestOutputStream; 35 | import java.security.MessageDigest; 36 | 37 | import static org.junit.jupiter.api.Assertions.assertEquals; 38 | import static org.junit.jupiter.api.Assertions.assertNotNull; 39 | 40 | class PolymathExporterTest { 41 | // @Test // manually activate it 42 | void test() throws Exception { 43 | final ResourcePack resourcePack = ResourcePack.resourcePack(); 44 | resourcePack.packMeta(8, "Test resource-pack!"); 45 | 46 | // upload the resource-pack to MCPacks 47 | ResourcePackLocation location = new PolymathExporter("atlas.oraxen.com", "oraxen") 48 | .export(resourcePack); 49 | 50 | assertNotNull(location, "Location should not be null"); 51 | assertEquals("7c708abe63955fefc2ff1fca614688874b9bd3f0", location.hash()); 52 | 53 | // download the resource-pack from MCPacks 54 | URI uri = location.uri(); 55 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 56 | MessageDigest digest = MessageDigest.getInstance("SHA-1"); 57 | DigestOutputStream digestOutputStream = new DigestOutputStream(bos, digest); 58 | try (InputStream input = uri.toURL().openStream()) { 59 | Streams.pipe(input, digestOutputStream); 60 | } 61 | // byte[] bytes = bos.toByteArray(); 62 | byte[] hash = digest.digest(); 63 | int len = hash.length; 64 | StringBuilder hashBuilder = new StringBuilder(len * 2); 65 | for (byte b : hash) { 66 | int part1 = (b >> 4) & 0xF; 67 | int part2 = b & 0xF; 68 | hashBuilder 69 | .append(Character.forDigit(part1, 16)) 70 | .append(Character.forDigit(part2, 16)); 71 | } 72 | String hashString = hashBuilder.toString(); 73 | 74 | // check 75 | assertEquals("7c708abe63955fefc2ff1fca614688874b9bd3f0", hashString, "Downloaded hash should be the same as uploaded hash! "); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/export/ResourcePackExporterFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.export; 25 | 26 | import team.unnamed.creative.central.export.ResourcePackExporter; 27 | import team.unnamed.creative.central.server.CentralResourcePackServer; 28 | 29 | import java.io.File; 30 | import java.util.Locale; 31 | import java.util.logging.Logger; 32 | 33 | public final class ResourcePackExporterFactory { 34 | 35 | private ResourcePackExporterFactory() { 36 | } 37 | 38 | public static ResourcePackExporter create( 39 | String key, 40 | File root, 41 | CentralResourcePackServer server, 42 | Logger logger 43 | ) { 44 | key = key.toLowerCase(Locale.ROOT).trim(); 45 | 46 | if (key.startsWith("polymath ")) { 47 | final String[] args = key.substring("polymath ".length()).split(" ", 2); 48 | if (args.length != 2) { 49 | throw new IllegalArgumentException("Invalid polymath arguments provided: '" + key 50 | + "'. Correct format: 'polymath '"); 51 | } 52 | return new PolymathExporter(args[0], args[1]); 53 | } 54 | 55 | switch (key) { 56 | case "mcpacks": 57 | case "mc-packs": 58 | return new MCPacksHttpExporter(); 59 | case "localhost": 60 | return new LocalHostExporter(server, logger); 61 | case "file": 62 | return new FileExporter(new File(root, "output.zip"), logger); 63 | case "folder": 64 | return new FolderExporter(new File(root, "output"), logger); 65 | default: 66 | throw new IllegalArgumentException( 67 | "Unknown exporter method: '" + key + "'. Possible values:\n" 68 | + " - 'mcpacks': (hosted) Exports the resource-pack to MCPacks\n" 69 | + " - 'localhost': (hosted) Exports the resource-pack to a local server\n" 70 | + " - 'polymath ': (hosted) Exports the reosurce-pack to a Polymath server\n" 71 | + " - 'file': (non-hosted) Exports the resource-pack to a file\n" 72 | + " - 'folder': (non-hosted) Exports the resource-pack to a folder\n" 73 | ); 74 | } 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /api/src/main/java/team/unnamed/creative/central/event/EventBus.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.event; 25 | 26 | import java.util.function.Consumer; 27 | 28 | /** 29 | * An event bus. Main interface for an event/listener 30 | * or pub/sub local system. 31 | * 32 | * @since 1.0.0 33 | */ 34 | public interface EventBus { 35 | 36 | /** 37 | * Registers a new {@link EventListener} for the given 38 | * {@code eventType}, from the given {@code plugin} 39 | * 40 | * @param plugin The registerer plugin 41 | * @param eventType The subscribed event type 42 | * @param listener The actual event listener 43 | * @param The event type 44 | * @since 1.0.0 45 | */ 46 | void listen(Object plugin, Class eventType, EventListener listener); 47 | 48 | /** 49 | * Registers a new {@link EventListener} using the given 50 | * {@code listener} and {@code priority}, from the given 51 | * {@code plugin} and for the given event type 52 | * 53 | * @param plugin The registerer plugin 54 | * @param eventType The subscribed event type 55 | * @param priority The event listener priority 56 | * @param listener The actual event listener 57 | * @param The event type 58 | * @since 1.0.0 59 | */ 60 | default void listen(Object plugin, Class eventType, EventListener.Priority priority, Consumer listener) { 61 | listen(plugin, eventType, new EventListener() { 62 | 63 | @Override 64 | public void on(E event) { 65 | listener.accept(event); 66 | } 67 | 68 | @Override 69 | public Priority priority() { 70 | return priority; 71 | } 72 | 73 | @Override 74 | public String toString() { 75 | return "EventListener<" + eventType + "> { " + 76 | "priority = '" + priority + "', " + 77 | "listener = '" + listener + "' " + 78 | "}"; 79 | } 80 | 81 | }); 82 | } 83 | 84 | /** 85 | * Calls the given {@code event}. This will execute 86 | * all the listener subscribed to the provided event 87 | * type. 88 | * 89 | * @param eventType The event type 90 | * @param event The event data 91 | * @param The event type 92 | * @since 1.0.0 93 | */ 94 | void call(Class eventType, E event); 95 | 96 | } 97 | -------------------------------------------------------------------------------- /common/src/test/java/team/unnamed/creative/central/common/export/MCPacksExporterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.export; 25 | 26 | import org.junit.jupiter.api.Test; 27 | import team.unnamed.creative.ResourcePack; 28 | import team.unnamed.creative.central.common.util.Streams; 29 | import team.unnamed.creative.central.export.ResourcePackLocation; 30 | 31 | import java.io.ByteArrayOutputStream; 32 | import java.io.InputStream; 33 | import java.net.URI; 34 | import java.security.DigestOutputStream; 35 | import java.security.MessageDigest; 36 | import java.util.logging.Logger; 37 | 38 | import static org.junit.jupiter.api.Assertions.assertEquals; 39 | import static org.junit.jupiter.api.Assertions.assertNotNull; 40 | 41 | class MCPacksExporterTest { 42 | 43 | // @Test // manually activate it 44 | void test() throws Exception { 45 | ResourcePack resourcePack = ResourcePack.create(); 46 | resourcePack.packMeta(8, "Test resource-pack!"); 47 | 48 | // upload the resource-pack to MCPacks 49 | ResourcePackLocation location = new MCPacksHttpExporter() 50 | .export(resourcePack); 51 | 52 | assertNotNull(location, "Location should not be null"); 53 | assertEquals("https://download.mc-packs.net/pack/7c708abe63955fefc2ff1fca614688874b9bd3f0.zip", location.uri().toString()); 54 | assertEquals("7c708abe63955fefc2ff1fca614688874b9bd3f0", location.hash()); 55 | 56 | // download the resource-pack from MCPacks 57 | URI uri = location.uri(); 58 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 59 | MessageDigest digest = MessageDigest.getInstance("SHA-1"); 60 | DigestOutputStream digestOutputStream = new DigestOutputStream(bos, digest); 61 | try (InputStream input = uri.toURL().openStream()) { 62 | Streams.pipe(input, digestOutputStream); 63 | } 64 | // byte[] bytes = bos.toByteArray(); 65 | byte[] hash = digest.digest(); 66 | int len = hash.length; 67 | StringBuilder hashBuilder = new StringBuilder(len * 2); 68 | for (byte b : hash) { 69 | int part1 = (b >> 4) & 0xF; 70 | int part2 = b & 0xF; 71 | hashBuilder 72 | .append(Character.forDigit(part1, 16)) 73 | .append(Character.forDigit(part2, 16)); 74 | } 75 | String hashString = hashBuilder.toString(); 76 | 77 | // check 78 | assertEquals("7c708abe63955fefc2ff1fca614688874b9bd3f0", hashString, "Downloaded hash should be the same as uploaded hash! "); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /docs/configuration/resource-pack-exporting.md: -------------------------------------------------------------------------------- 1 | ## Pack Exporting/Hosting 2 | 3 | `creative-central` relies on collecting the required assets *(textures, assets, 4 | fonts, etc.)* on the server start-up, **compile** the resource-pack and then **export** 5 | it. 6 | 7 | In this section we will explore the **export** stage, `creative-central` supports 8 | the following methods of exporting: 9 | - **MCPacks** (External hosting) **(Default export method)** 10 | - **Localhost** (Self hosting) 11 | - **File** (Not hosted) 12 | - **Folder** (Not hosted) 13 | 14 | ### MCPacks 15 | *(Default export method)* `creative-central` can automatically upload the generated 16 | resource-pack to [MCPacks](https://mc-packs.net/), a public & free resource-pack host. 17 | *(Please note that we are not part of MCPacks development team)*. 18 | 19 | To make `creative-central` do this, open `config.yml` and set `export.type` 20 | to `mcpacks`, like this: 21 | 22 | ```yaml 23 | export: 24 | type: 'mcpacks' 25 | ``` 26 | 27 | Please consider [donating to MCPacks](https://mc-packs.net/) if you use their 28 | free hosting service! 29 | 30 | ### Polymath 31 | `creative-central` can automatically upload the generated resource-pack to a Polymath 32 | server, the Oraxen's resource-pack hosting server. 33 | 34 | To make `creative-central` do this, open `config.yml` and set `export.type` to 35 | `polymath `, replacing *\* by the desired Polymath server's 36 | URL and *\* by the Polymath server's secret. 37 | 38 | Example: 39 | ```yaml 40 | export: 41 | type: 'polymath https://mypolymathserver.com/ oraxen' 42 | ``` 43 | 44 | ### Localhost (Self hosting) 45 | We can set up a resource-pack server, on your server! 46 | 47 | *Note that this export method requires you to have access to one additional port. If 48 | your hosting service doesn't provide you additional ports, consider using another 49 | export method.* 50 | 51 | To start using self-hosting, open `config.yml` and set the following options: 52 | ```yaml 53 | export: 54 | type: 'localhost' 55 | localhost: 56 | # Enables the local resource-pack server, this is required even if you 57 | # have already set 'type' to 'localhost' 58 | enabled: true 59 | # Your server's address 60 | address: '' 61 | # The port to use 62 | port: 7270 63 | # The public address 64 | public-address: '' 65 | ``` 66 | 67 | The settings you may want to modify now are: 68 | - `address`: The address that the resource-pack server will use. If you leave it 69 | empty, the plugin will automatically detect your server's public IP address, however, 70 | if you want to skip the detection, you can manually set it too. *Note: If you use 71 | NAT (Network Address Translation), set this to `0.0.0.0` and pay extra attention to 72 | the `public-address` setting explanation* 73 | - `port`: The port that the resource-pack server will use. **It can't be the same as 74 | your Minecraft server's port!** 75 | - `public-address`: The public address, sent to players to ask them to download the 76 | server's resource pack. *If you use NAT, you will have to set your public's address 77 | or domain* 78 | 79 | ### File 80 | Export the resource-pack to a ZIP file! However, this export type is **not hosted**, 81 | so players will not be automatically asked to download the resource-pack. 82 | 83 | To make `creative-central` export the resource-pack as a ZIP file, open `config.yml` 84 | and set: 85 | ```yaml 86 | export: 87 | type: 'file' 88 | ``` 89 | And that's it! The resource-pack will be created at `/plugins/creative-central/output.zip` 90 | 91 | ### Folder 92 | `creative-central` can also export the resource-pack to a folder! This is pretty 93 | similar to the `file` export method, and is also **not hosted**, so players will 94 | not be automatically asked to download the resource-pack. 95 | 96 | To make `creative-central` export the resource-pack as a folder, open `config.yml` 97 | and set: 98 | ```yaml 99 | export: 100 | type: 'folder' 101 | ``` 102 | 103 | And that's it too! The resource-pack will be created at `/plugins/creative-central/output/` -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/event/EventBusImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.event; 25 | 26 | import org.jetbrains.annotations.Nullable; 27 | import team.unnamed.creative.central.event.Event; 28 | import team.unnamed.creative.central.event.EventListener; 29 | import team.unnamed.creative.central.event.EventBus; 30 | 31 | import java.util.Collection; 32 | import java.util.Comparator; 33 | import java.util.HashMap; 34 | import java.util.Map; 35 | import java.util.TreeSet; 36 | 37 | import static java.util.Objects.requireNonNull; 38 | 39 | public final class EventBusImpl implements EventBus { 40 | 41 | private static final Comparator> LISTENER_COMPARATOR = Comparator 42 | .>comparingInt(listener -> listener.listener().priority().ordinal()) 43 | .thenComparingInt(System::identityHashCode); 44 | 45 | private final Map, Collection>> listenersByEventType = new HashMap<>(); 46 | private final Class pluginClass; 47 | private final EventExceptionHandler exceptionHandler; 48 | 49 | public EventBusImpl(Class pluginClass, EventExceptionHandler exceptionHandler) { 50 | requireNonNull(pluginClass, "pluginClass"); 51 | requireNonNull(exceptionHandler, "exceptionHandler"); 52 | this.pluginClass = pluginClass; 53 | this.exceptionHandler = exceptionHandler; 54 | } 55 | 56 | @Override 57 | public void listen(@Nullable Object plugin, Class eventType, EventListener listener) { 58 | requireNonNull(eventType, "eventType"); 59 | requireNonNull(listener, "listener"); 60 | 61 | if (plugin != null && !pluginClass.isInstance(plugin)) { 62 | throw new IllegalArgumentException("Plugin is not an instance of " + pluginClass.getName()); 63 | } 64 | 65 | RegisteredEventListener registration = new RegisteredEventListener<>(plugin, listener); 66 | 67 | @SuppressWarnings({"unchecked", "rawtypes"}) 68 | Collection> listeners = (Collection) listenersByEventType 69 | .computeIfAbsent(eventType, k -> new TreeSet<>(LISTENER_COMPARATOR)); 70 | listeners.add(registration); 71 | } 72 | 73 | @Override 74 | public void call(Class eventType, E event) { 75 | @SuppressWarnings({"unchecked", "rawtypes"}) 76 | Collection> listeners = (Collection) listenersByEventType.get(eventType); 77 | if (listeners == null) { 78 | return; 79 | } 80 | 81 | for (RegisteredEventListener listener : listeners) { 82 | try { 83 | listener.listener().on(event); 84 | } catch (Exception e) { 85 | exceptionHandler.handleException(eventType, event, listener, e); 86 | } 87 | } 88 | } 89 | 90 | } -------------------------------------------------------------------------------- /bukkit/src/main/java/team/unnamed/creative/central/bukkit/action/BukkitActionExecutor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.bukkit.action; 25 | 26 | import net.kyori.adventure.text.Component; 27 | import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; 28 | import net.kyori.adventure.title.Title; 29 | import org.bukkit.entity.Player; 30 | import org.jetbrains.annotations.NotNull; 31 | import team.unnamed.creative.central.common.action.Action; 32 | import team.unnamed.creative.central.common.action.ActionExecutor; 33 | import team.unnamed.creative.central.common.action.KickAction; 34 | import team.unnamed.creative.central.common.action.MessageAction; 35 | import team.unnamed.creative.central.common.action.TitleAction; 36 | 37 | public final class BukkitActionExecutor implements ActionExecutor { 38 | private static final ActionExecutor INSTANCE = new BukkitActionExecutor(); 39 | 40 | private static final boolean ARE_TITLE_TIMES_AVAILABLE; 41 | 42 | static { 43 | boolean areTitleTimesAvailable = false; 44 | try { 45 | Player.class.getMethod("sendTitle", String.class, String.class, int.class, int.class, int.class); 46 | areTitleTimesAvailable = true; 47 | } catch (final NoSuchMethodException ignored) { 48 | } 49 | ARE_TITLE_TIMES_AVAILABLE = areTitleTimesAvailable; 50 | } 51 | 52 | private BukkitActionExecutor() { 53 | } 54 | 55 | @Override 56 | @SuppressWarnings({"deprecation", "UsagesOfObsoleteApi"}) // Spigot! 57 | public void execute(Action action, Player player) { 58 | if (action instanceof MessageAction) { 59 | player.sendMessage(toLegacy(((MessageAction) action).message())); 60 | } else if (action instanceof TitleAction) { 61 | final Title title = ((TitleAction) action).title(); 62 | final Title.Times times = title.times(); 63 | if (times == null || !ARE_TITLE_TIMES_AVAILABLE) { 64 | player.sendTitle( 65 | toLegacy(title.title()), 66 | toLegacy(title.subtitle()) 67 | ); 68 | } else { 69 | player.sendTitle( 70 | toLegacy(title.title()), 71 | toLegacy(title.subtitle()), 72 | (int) times.fadeIn().getSeconds() * 20, 73 | (int) times.stay().getSeconds() * 20, 74 | (int) times.fadeOut().getSeconds() * 20 75 | ); 76 | } 77 | } else if (action instanceof KickAction kickAction) { 78 | player.kickPlayer(toLegacy(kickAction.reason())); 79 | } else { 80 | throw new IllegalArgumentException("Unknown action type: '" + action + "'"); 81 | } 82 | } 83 | 84 | private static @NotNull String toLegacy(final @NotNull Component component) { 85 | return LegacyComponentSerializer.legacySection().serialize(component); 86 | } 87 | 88 | public static ActionExecutor bukkit() { 89 | return INSTANCE; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /common/src/test/java/team/unnamed/creative/central/common/event/EventBusTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.event; 25 | 26 | import org.junit.jupiter.api.Assertions; 27 | import org.junit.jupiter.api.Test; 28 | import team.unnamed.creative.central.event.EventBus; 29 | import team.unnamed.creative.central.event.EventListener; 30 | 31 | import java.util.concurrent.atomic.AtomicBoolean; 32 | 33 | public class EventBusTest { 34 | 35 | @Test 36 | public void test_listener_is_called() { 37 | EventBus eventBus = new EventBusImpl<>(Object.class, EventExceptionHandler.empty()); 38 | Object plugin1 = new Object(); 39 | 40 | AtomicBoolean wasCalled = new AtomicBoolean(false); 41 | eventBus.listen(plugin1, TestEvent.class, event -> wasCalled.set(true)); 42 | 43 | eventBus.call(TestEvent.class, new TestEvent()); 44 | Assertions.assertTrue(wasCalled.get(), "Event was not called!"); 45 | } 46 | 47 | @Test 48 | public void test_listeners_are_called_in_order() { 49 | EventBus eventBus = new EventBusImpl<>(Object.class, EventExceptionHandler.empty()); 50 | Object plugin1 = new Object(); 51 | 52 | eventBus.listen(plugin1, TestEvent.class, EventListener.Priority.LOWEST, event -> event.assertAndIncrement(0)); 53 | eventBus.listen(plugin1, TestEvent.class, EventListener.Priority.HIGH, event -> event.assertAndIncrement(3)); 54 | eventBus.listen(plugin1, TestEvent.class, EventListener.Priority.LOW, event -> event.assertAndIncrement(1)); 55 | eventBus.listen(plugin1, TestEvent.class, EventListener.Priority.NORMAL, event -> event.assertAndIncrement(2)); 56 | eventBus.listen(plugin1, TestEvent.class, EventListener.Priority.HIGHEST, event -> event.assertAndIncrement(4)); 57 | 58 | TestEvent event = new TestEvent(); 59 | eventBus.call(TestEvent.class, event); 60 | Assertions.assertEquals(5, event.counter(), "Counter should be equal to five after the event is called"); 61 | } 62 | 63 | @Test 64 | public void test_an_exception_doesnt_stop_others() { 65 | EventBus eventBus = new EventBusImpl<>(Object.class, EventExceptionHandler.empty()); 66 | Object plugin1 = new Object(); 67 | 68 | // this listener will not fail 69 | eventBus.listen(plugin1, TestEvent.class, EventListener.Priority.LOWEST, event -> event.assertAndIncrement(0)); 70 | 71 | // this listener will fail 72 | eventBus.listen(plugin1, TestEvent.class, EventListener.Priority.NORMAL, event -> { 73 | Assertions.assertEquals(1, event.counter(), "Counter should be 1!"); 74 | throw new IllegalStateException("Test exception (ignore if this appears in the console)"); 75 | }); 76 | 77 | // this listener will not fail and should be called 78 | eventBus.listen(plugin1, TestEvent.class, EventListener.Priority.HIGH, event -> event.assertAndIncrement(1)); 79 | 80 | TestEvent event = new TestEvent(); 81 | eventBus.call(TestEvent.class, event); 82 | Assertions.assertEquals(2, event.counter(), "Counter should be equal to two after the event is called"); 83 | } 84 | 85 | } -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/action/ActionParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.action; 25 | 26 | import java.util.ArrayList; 27 | import java.util.Collections; 28 | import java.util.List; 29 | import java.util.Locale; 30 | import java.util.Map; 31 | 32 | public class ActionParser { 33 | 34 | public static List parse(Object object) { 35 | List rawActions = (List) object; 36 | if (rawActions == null) { 37 | // no actions with this key 38 | return Collections.emptyList(); 39 | } 40 | List actions = new ArrayList<>(rawActions.size()); 41 | for (Object rawAction : rawActions) { 42 | String actionId; 43 | Object actionData; 44 | 45 | if (rawAction instanceof Map) { 46 | @SuppressWarnings("unchecked") 47 | Map map = (Map) rawAction; 48 | if (map.size() != 1) { 49 | throw new IllegalArgumentException( 50 | "Found an invalid action, invalid format.\n" 51 | + " The format MUST be:\n" 52 | + " declined:\n" 53 | + " - kick: 'Kicked!'\n" 54 | + " - message: 'Kicking...'\n" 55 | + " ^^^^^^^^^^^^^^^^\n" 56 | + " It seems like you forgot the '-' before the action name\n" 57 | + " Check the plugin configuration!\n" 58 | ); 59 | } 60 | 61 | actionId = map.keySet().iterator().next(); 62 | actionData = map.get(actionId); 63 | } else { 64 | throw new IllegalArgumentException( 65 | "Found an invalid action, invalid format.\n" 66 | + " The format MUST be:\n" 67 | + " declined:\n" 68 | + " - kick: 'Message'\n" 69 | + " ^^^^^^^^^^^^^^^^^^\n" 70 | +" It seems like you forgot the action identifier (e.g. 'kick:')\n" 71 | +" Check the plugin configuration!\n" 72 | ); 73 | } 74 | 75 | Action action; 76 | switch (actionId.toLowerCase(Locale.ROOT)) { 77 | case KickAction.IDENTIFIER: { 78 | action = KickAction.deserialize(actionData); 79 | break; 80 | } 81 | case MessageAction.IDENTIFIER: { 82 | action = MessageAction.deserialize(actionData); 83 | break; 84 | } 85 | case TitleAction.IDENTIFIER: { 86 | action = TitleAction.deserialize(actionData); 87 | break; 88 | } 89 | default: 90 | throw new IllegalArgumentException("Unknown action identifier: " + actionId); 91 | } 92 | actions.add(action); 93 | } 94 | return actions; 95 | } 96 | 97 | } -------------------------------------------------------------------------------- /api/src/main/java/team/unnamed/creative/central/event/pack/ResourcePackGenerateEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.event.pack; 25 | 26 | import org.jetbrains.annotations.NotNull; 27 | import team.unnamed.creative.ResourcePack; 28 | import team.unnamed.creative.central.event.Event; 29 | 30 | import static java.util.Objects.requireNonNull; 31 | 32 | /** 33 | * An event called when we want plugins/extensions to register 34 | * their own resources in our unified resource pack (for the 35 | * entire server) 36 | * 37 | * @since 1.0.0 38 | */ 39 | public final class ResourcePackGenerateEvent implements Event { 40 | private static final int ANY_FORMAT = -1; 41 | 42 | private final ResourcePack resourcePack; 43 | private final int format; 44 | 45 | /** 46 | * Instantiate a new {@link ResourcePackGenerateEvent}. 47 | * 48 | * @param format The expected format that the resource pack 49 | * should be generated in, or {@code -1} 50 | * if any format is accepted 51 | * @param resourcePack The resource-pack being generated 52 | * @since 1.0.0 53 | */ 54 | public ResourcePackGenerateEvent(final int format, final @NotNull ResourcePack resourcePack) { 55 | this.format = format; 56 | this.resourcePack = requireNonNull(resourcePack, "resourcePack"); 57 | } 58 | 59 | /** 60 | * Instantiate a new {@link ResourcePackGenerateEvent}. 61 | * 62 | * @param resourcePack The resource-pack being generated 63 | * @since 1.0.0 64 | */ 65 | public ResourcePackGenerateEvent(final @NotNull ResourcePack resourcePack) { 66 | this(ANY_FORMAT, resourcePack); 67 | } 68 | 69 | /** 70 | * Returns the mutable resource pack instance 71 | * being generated and that can be edited when 72 | * listening to this event 73 | * 74 | * @return The resource pack 75 | * @since 1.0.0 76 | */ 77 | public @NotNull ResourcePack resourcePack() { 78 | return resourcePack; 79 | } 80 | 81 | /** 82 | * Returns the expected format that the resource pack 83 | * should be generated in, or {@link #ANY_FORMAT} if 84 | * any format is accepted (or format has not been 85 | * specified) 86 | * 87 | * @return The expected format 88 | * @since 1.0.0 89 | */ 90 | public int format() { 91 | return format; 92 | } 93 | 94 | /** 95 | * Returns whether the resource pack should be 96 | * generated in any format. 97 | * 98 | * @return Whether the resource pack should be 99 | * generated in any format 100 | * @since 1.0.0 101 | */ 102 | public boolean isAnyFormat() { 103 | return format == ANY_FORMAT; 104 | } 105 | 106 | /** 107 | * Returns whether the resource pack should be 108 | * generated in the specified format. 109 | * 110 | * @param format The format to check 111 | * @return Whether the resource pack should be 112 | * generated in the specified format 113 | */ 114 | public boolean isFormat(final int format) { 115 | return this.format == format || isAnyFormat(); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /bukkit/src/main/java/team/unnamed/creative/central/bukkit/external/ModelEngineResourcePackProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.bukkit.external; 25 | 26 | import com.ticxo.modelengine.api.events.ModelRegistrationEvent; 27 | import org.bukkit.Bukkit; 28 | import org.bukkit.event.EventHandler; 29 | import org.bukkit.event.Listener; 30 | import org.bukkit.plugin.Plugin; 31 | import org.jetbrains.annotations.NotNull; 32 | import org.jetbrains.annotations.Nullable; 33 | import team.unnamed.creative.ResourcePack; 34 | import team.unnamed.creative.serialize.minecraft.MinecraftResourcePackReader; 35 | 36 | import java.io.File; 37 | import java.lang.reflect.Method; 38 | 39 | import static java.util.Objects.requireNonNull; 40 | 41 | public final class ModelEngineResourcePackProvider implements ExternalResourcePackProvider { 42 | @Override 43 | public @NotNull String pluginName() { 44 | return "ModelEngine"; 45 | } 46 | 47 | @Override 48 | public boolean awaitOnStart() { 49 | // ModelEngine generates its resource-pack on startup 50 | return true; 51 | } 52 | 53 | @Override 54 | public void listenForChanges(final @NotNull Plugin plugin, final @NotNull Runnable changeListener) { 55 | requireNonNull(plugin, "plugin"); 56 | requireNonNull(changeListener, "changeListener"); 57 | 58 | // We do this to support both ModelEngine3 and ModelEngine4 :( 59 | final Method getPhaseMethod; 60 | try { 61 | getPhaseMethod = ModelRegistrationEvent.class.getDeclaredMethod("getPhase"); 62 | getPhaseMethod.setAccessible(true); 63 | } catch (final ReflectiveOperationException e) { 64 | throw new RuntimeException("Failed to get ModelRegistrationEvent#getPhase method", e); 65 | } 66 | 67 | plugin.getServer().getPluginManager().registerEvents(new Listener() { 68 | @EventHandler 69 | public void onModelRegistration(final @NotNull ModelRegistrationEvent event) { 70 | final Enum phase; 71 | try { 72 | phase = (Enum) getPhaseMethod.invoke(event); 73 | } catch (final ReflectiveOperationException e) { 74 | throw new IllegalStateException("Failed to get phase from ModelRegistrationEvent", e); 75 | } 76 | 77 | final var phaseName = phase.name(); 78 | 79 | // It's FINISHED for ME4, and FINAL for ME3 80 | if (phaseName.equals("FINISHED") || phaseName.equals("FINAL")) { 81 | changeListener.run(); 82 | } 83 | } 84 | }, plugin); 85 | } 86 | 87 | @Override 88 | public @Nullable ResourcePack load() { 89 | final var modelEngine = Bukkit.getPluginManager().getPlugin(pluginName()); 90 | if (modelEngine == null) { 91 | // Should never happen 92 | return null; 93 | } 94 | 95 | final var resourcePackZipFile = new File(modelEngine.getDataFolder(), "resource pack.zip"); 96 | if (!resourcePackZipFile.exists()) { 97 | return null; 98 | } 99 | return MinecraftResourcePackReader.minecraft().readFromZipFile(resourcePackZipFile); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /common/src/main/java/team/unnamed/creative/central/common/server/CommonResourcePackServer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.common.server; 25 | 26 | import com.sun.net.httpserver.HttpExchange; 27 | import org.jetbrains.annotations.NotNull; 28 | import org.jetbrains.annotations.Nullable; 29 | import team.unnamed.creative.BuiltResourcePack; 30 | import team.unnamed.creative.central.server.CentralResourcePackServer; 31 | import team.unnamed.creative.server.ResourcePackServer; 32 | import team.unnamed.creative.server.handler.ResourcePackRequestHandler; 33 | import team.unnamed.creative.server.request.ResourcePackDownloadRequest; 34 | 35 | import java.io.IOException; 36 | import java.nio.charset.StandardCharsets; 37 | 38 | public final class CommonResourcePackServer implements CentralResourcePackServer, ResourcePackRequestHandler { 39 | 40 | private @Nullable ResourcePackServer server; 41 | private @Nullable String address; 42 | private @Nullable String publicAddress; 43 | private int port = -1; 44 | private @Nullable BuiltResourcePack resourcePack; 45 | private boolean open; 46 | 47 | @Override 48 | public @Nullable BuiltResourcePack resourcePack() { 49 | return resourcePack; 50 | } 51 | 52 | @Override 53 | public void resourcePack(@Nullable BuiltResourcePack resourcePack) { 54 | this.resourcePack = resourcePack; 55 | } 56 | 57 | @Override 58 | public boolean isOpen() { 59 | return open; 60 | } 61 | 62 | @Override 63 | public void open(String address, String publicAddress, int port) throws IOException { 64 | if (open) { 65 | throw new IllegalStateException("The resource pack server is already open!"); 66 | } 67 | 68 | this.address = address; 69 | this.publicAddress = publicAddress; 70 | this.port = port; 71 | this.open = true; 72 | 73 | server = ResourcePackServer.server() 74 | .address(address, port) 75 | .handler(this) 76 | .build(); 77 | server.start(); 78 | } 79 | 80 | @Override 81 | public @Nullable String address() { 82 | return address; 83 | } 84 | 85 | @Override 86 | public int port() { 87 | return port; 88 | } 89 | 90 | @Override 91 | public @Nullable String publicAddress() { 92 | return publicAddress; 93 | } 94 | 95 | @Override 96 | public void onRequest(final @Nullable ResourcePackDownloadRequest request, final @NotNull HttpExchange exchange) throws IOException { 97 | if (resourcePack == null) { 98 | byte[] response = "The resource-pack is not loaded yet, please wait...".getBytes(StandardCharsets.UTF_8); 99 | exchange.getResponseHeaders().set("Content-Type", "text/plain"); 100 | exchange.sendResponseHeaders(400, response.length); 101 | exchange.getResponseBody().write(response); 102 | return; 103 | } 104 | 105 | final byte[] data = resourcePack.data().toByteArray(); 106 | exchange.getResponseHeaders().set("Content-Type", "application/zip"); 107 | exchange.sendResponseHeaders(200, data.length); 108 | exchange.getResponseBody().write(data); 109 | } 110 | 111 | @Override 112 | public void close() { 113 | if (!open) return; 114 | if (server != null) { 115 | server.stop(0); 116 | } 117 | address = null; 118 | port = -1; 119 | open = false; 120 | server = null; 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /bukkit/src/main/java/team/unnamed/creative/central/bukkit/request/BukkitResourcePackRequestSender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of creative-central, licensed under the MIT license 3 | * 4 | * Copyright (c) 2021-2023 Unnamed Team 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 team.unnamed.creative.central.bukkit.request; 25 | 26 | import net.kyori.adventure.text.Component; 27 | import org.bukkit.entity.Player; 28 | import team.unnamed.creative.central.request.ResourcePackRequest; 29 | import team.unnamed.creative.central.request.ResourcePackRequestSender; 30 | 31 | import java.util.function.BiConsumer; 32 | 33 | public final class BukkitResourcePackRequestSender implements ResourcePackRequestSender { 34 | 35 | private final BiConsumer delegate; 36 | 37 | private BukkitResourcePackRequestSender(BiConsumer delegate) { 38 | this.delegate = delegate; 39 | } 40 | 41 | @Override 42 | public void send(Object playerObject, ResourcePackRequest request) { 43 | if (!(playerObject instanceof Player)) { 44 | throw new IllegalArgumentException("Provided 'player' is not an actual Bukkit Player: " + playerObject); 45 | } 46 | 47 | delegate.accept((Player) playerObject, request); 48 | } 49 | 50 | @SuppressWarnings("deprecation") 51 | public static ResourcePackRequestSender bukkit() { 52 | 53 | if (isSetResourcePackOverrideAvailable(String.class, String.class, boolean.class, Component.class)) { 54 | // Method that accepts: URL, Hash, Required and Prompt options, 55 | // available since Paper 1.17 (We are currently on 1.20) 56 | return new BukkitResourcePackRequestSender((player, request) -> player.setResourcePack( 57 | request.uri().toString(), 58 | request.hash(), 59 | request.required(), 60 | request.prompt() 61 | )); 62 | } 63 | 64 | if (isSetResourcePackOverrideAvailable(String.class, String.class)) { 65 | // Method that accepts URL and Hash options 66 | // available since Paper 1.12 and probably before too 67 | return new BukkitResourcePackRequestSender((player, request) -> player.setResourcePack( 68 | request.uri().toString(), 69 | request.hash() 70 | )); 71 | } 72 | 73 | if (isSetResourcePackOverrideAvailable(String.class, byte[].class)) { 74 | // Stupid method that accepts URL and Hash options, 75 | // but only accepts hash in a byte array. It's stupid 76 | // because it will internally convert the byte array to 77 | // a string again, to send it using the resource pack 78 | // packet 79 | return new BukkitResourcePackRequestSender((player, request) -> { 80 | // convert to hash byte aray 81 | String hs = request.hash(); 82 | int len = hs.length(); 83 | byte[] hash = new byte[len / 2]; 84 | for (int i = 0; i < len; i += 2) { 85 | hash[i / 2] = (byte) ((Character.digit(hs.charAt(i), 16) << 4) 86 | + Character.digit(hs.charAt(i + 1), 16)); 87 | } 88 | 89 | // now call the stupid method 90 | player.setResourcePack(request.uri().toString(), hash); 91 | }); 92 | } 93 | 94 | if (isSetResourcePackOverrideAvailable(String.class)) { 95 | // Method that accepts URL option only 96 | // This is ancient! Available in Spigot 1.8.8 97 | return new BukkitResourcePackRequestSender((player, request) -> player.setResourcePack( 98 | request.uri().toString() 99 | )); 100 | } 101 | 102 | throw new IllegalStateException("No supported setResourcePack method found on Player!"); 103 | } 104 | 105 | private static boolean isSetResourcePackOverrideAvailable(Class... argumentTypes) { 106 | try { 107 | Player.class.getDeclaredMethod("setResourcePack", argumentTypes); 108 | return true; 109 | } catch (NoSuchMethodException e) { 110 | return false; 111 | } 112 | } 113 | 114 | } 115 | --------------------------------------------------------------------------------