├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── ci.yml │ └── release.yml ├── .gitignore ├── .idea ├── .gitignore ├── encodings.xml ├── git_toolbox_blame.xml ├── icon.svg ├── inspectionProfiles │ └── Project_Default.xml ├── misc.xml ├── swagger-settings.xml ├── uiDesigner.xml └── vcs.xml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── checks.xml ├── dependency-reduced-pom.xml ├── docker └── test.config.yml ├── pom.xml ├── src ├── main │ ├── java │ │ └── com │ │ │ └── shweit │ │ │ └── serverapi │ │ │ ├── MinecraftServerAPI.java │ │ │ ├── WebServer.java │ │ │ ├── commands │ │ │ ├── CommandManager.java │ │ │ ├── RegisterCommands.java │ │ │ ├── SubCommand.java │ │ │ ├── version │ │ │ │ └── VersionCommand.java │ │ │ └── webHook │ │ │ │ ├── DisableWebHookCommand.java │ │ │ │ ├── EnableWebHookCommand.java │ │ │ │ ├── ListWebHook.java │ │ │ │ └── SendWebHookCommand.java │ │ │ ├── endpoints │ │ │ ├── RegisterEndpoints.java │ │ │ └── v1 │ │ │ │ ├── BackupAPI.java │ │ │ │ ├── MaintenanceAPI.java │ │ │ │ ├── PlayerAPI.java │ │ │ │ ├── PluginAPI.java │ │ │ │ ├── ServerAPI.java │ │ │ │ ├── WhitelistAPI.java │ │ │ │ └── WorldAPI.java │ │ │ ├── handlers │ │ │ ├── CommandOutputCapture.java │ │ │ └── LogHandler.java │ │ │ ├── listeners │ │ │ ├── ChatListener.java │ │ │ └── PlayerLoginListener.java │ │ │ ├── utils │ │ │ ├── Helper.java │ │ │ ├── Logger.java │ │ │ └── RouteDefinition.java │ │ │ └── webhooks │ │ │ ├── RegisterWebHooks.java │ │ │ ├── WebHook.java │ │ │ ├── WebHookEnum.java │ │ │ ├── block │ │ │ ├── BlockBreak.java │ │ │ ├── BlockBurn.java │ │ │ ├── BlockPlace.java │ │ │ ├── BlockRedstone.java │ │ │ ├── NotePlay.java │ │ │ └── SignChange.java │ │ │ ├── enchantment │ │ │ └── EnchantItem.java │ │ │ ├── entity │ │ │ ├── CreatureSpawn.java │ │ │ ├── CreeperPower.java │ │ │ ├── EntityDeath.java │ │ │ ├── EntityExplode.java │ │ │ ├── EntityShootBow.java │ │ │ ├── EntityTame.java │ │ │ ├── ExplosionPrime.java │ │ │ └── PlayerDeath.java │ │ │ ├── inventory │ │ │ ├── Brew.java │ │ │ ├── CraftItem.java │ │ │ ├── FurnaceBurn.java │ │ │ └── FurnaceSmelt.java │ │ │ ├── player │ │ │ ├── PlayerChat.java │ │ │ ├── PlayerCommand.java │ │ │ ├── PlayerGamemodeChange.java │ │ │ ├── PlayerItemBreak.java │ │ │ ├── PlayerKick.java │ │ │ ├── PlayerLogin.java │ │ │ ├── PlayerQuit.java │ │ │ └── PlayerRespawn.java │ │ │ ├── server │ │ │ ├── PluginDisable.java │ │ │ ├── PluginEnable.java │ │ │ ├── ServerStart.java │ │ │ └── ServerStop.java │ │ │ ├── weather │ │ │ ├── LightningStrike.java │ │ │ ├── ThunderChange.java │ │ │ └── WeatherChange.java │ │ │ └── world │ │ │ ├── WorldLoad.java │ │ │ ├── WorldSave.java │ │ │ └── WorldUnload.java │ └── resources │ │ ├── META-INF │ │ └── maven │ │ │ └── archetype.xml │ │ ├── api.yaml │ │ ├── archetype-resources │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ └── java │ │ │ │ └── App.java │ │ │ └── test │ │ │ └── java │ │ │ └── AppTest.java │ │ ├── config.yml │ │ ├── plugin.yml │ │ └── swagger │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── index.css │ │ ├── index.html │ │ ├── oauth2-redirect.html │ │ ├── swagger-initializer.js │ │ ├── swagger-ui-bundle.js │ │ ├── swagger-ui-bundle.js.map │ │ ├── swagger-ui-es-bundle-core.js │ │ ├── swagger-ui-es-bundle-core.js.map │ │ ├── swagger-ui-es-bundle.js │ │ ├── swagger-ui-es-bundle.js.map │ │ ├── swagger-ui-standalone-preset.js │ │ ├── swagger-ui-standalone-preset.js.map │ │ ├── swagger-ui.css │ │ ├── swagger-ui.css.map │ │ ├── swagger-ui.js │ │ └── swagger-ui.js.map └── test │ ├── java │ ├── ApiTestHelper.java │ ├── PlayerAPITest.java │ ├── ServerAPITest.java │ ├── SharedDockerComposeContainer.java │ └── WhitelistAPITest.java │ └── resources │ ├── config.yml │ ├── docker-compose.yml │ ├── logback.xml │ └── server-data │ ├── config.yml │ ├── plugins │ ├── Citizens-2.0.35-b3535.jar │ └── Maintenance-4.2.1.jar │ ├── server.properties │ └── whitelist.json └── webhooks.md /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: Shweit 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: shweit 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: shweit 14 | custom: https://www.paypal.com/donate/?hosted_button_id=TBG3UZALFT2T6 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG]" 5 | labels: Bug 6 | assignees: Shweit 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Minecraft Version:** [e.g. 1.21.1] 24 | 25 | **Additional context** 26 | Add any other context about the problem here. 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[Feature Request]" 5 | labels: Feature Request 6 | assignees: Shweit 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Java CI 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | integration-tests: 9 | name: Plugin Integration Tests 10 | runs-on: ubuntu-latest 11 | strategy: 12 | fail-fast: false 13 | matrix: 14 | minecraft-version: ['1.21', '1.21.1', '1.21.3', '1.21.4'] 15 | 16 | services: 17 | minecraft: 18 | image: itzg/minecraft-server:latest 19 | ports: 20 | - 25565:25565 21 | - 7000:7000 22 | env: 23 | EULA: "TRUE" 24 | VERSION: "${{ matrix.minecraft-version }}" 25 | TYPE: "PAPER" 26 | ENABLE_RCON: "true" 27 | RCON_PASSWORD: "testing" 28 | RCON_PORT: 25575 29 | options: >- 30 | --health-cmd "mc-health" 31 | --health-interval 10s 32 | --health-timeout 5s 33 | --health-retries 5 34 | 35 | steps: 36 | - name: Checkout code 37 | uses: actions/checkout@v3 38 | 39 | - name: Set up JDK 21 40 | uses: actions/setup-java@v3 41 | with: 42 | distribution: 'temurin' 43 | java-version: '21' 44 | 45 | - name: Build plugin 46 | run: mvn clean package -DskipTests 47 | 48 | - name: Wait for Minecraft server to start 49 | run: | 50 | echo "Waiting for Minecraft server to be ready..." 51 | timeout 300 bash -c 'until docker exec $(docker ps -q --filter ancestor=itzg/minecraft-server:latest) mc-health; do sleep 5; done' 52 | echo "Minecraft server is ready!" 53 | 54 | - name: Copy plugin to server 55 | run: | 56 | CONTAINER_ID=$(docker ps -q --filter ancestor=itzg/minecraft-server:latest) 57 | docker cp target/MinecraftServerAPI-*.jar $CONTAINER_ID:/data/plugins/ 58 | docker exec $CONTAINER_ID mkdir -p /data/plugins/MinecraftServerAPI 59 | docker cp docker/test.config.yml $CONTAINER_ID:/data/plugins/MinecraftServerAPI/config.yml 60 | 61 | - name: Reload server and verify plugin 62 | run: | 63 | CONTAINER_ID=$(docker ps -q --filter ancestor=itzg/minecraft-server:latest) 64 | docker exec $CONTAINER_ID rcon-cli reload confirm 65 | sleep 30 66 | # Check if plugin is loaded by looking for its name in the plugins list 67 | PLUGIN_CHECK=$(docker exec $CONTAINER_ID rcon-cli plugins | grep -i MinecraftServerAPI || echo "Plugin not found") 68 | if [[ "$PLUGIN_CHECK" == *"Plugin not found"* ]]; then 69 | echo "Plugin failed to load properly" 70 | docker exec $CONTAINER_ID cat /data/logs/latest.log 71 | exit 1 72 | else 73 | echo "Plugin loaded successfully: $PLUGIN_CHECK" 74 | fi 75 | 76 | - name: Test API endpoint 77 | run: | 78 | # Test that the API is responding 79 | curl -f -H "Authorization: TestKey" http://localhost:7000/v1/ping || (echo "API endpoint not responding" && exit 1) 80 | echo "API endpoint is working!" 81 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release to CurseForge and Modrinth 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | jobs: 8 | build-and-release: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout code 12 | uses: actions/checkout@v3 13 | 14 | - name: Set up JDK 17 15 | uses: actions/setup-java@v3 16 | with: 17 | distribution: 'temurin' 18 | java-version: '17' 19 | cache: 'maven' 20 | 21 | - name: Build with Maven 22 | run: mvn clean package -DskipTests 23 | 24 | - name: Get artifact info 25 | id: artifact 26 | run: | 27 | echo "jar_path=$(find target/ -name 'MinecraftServerAPI-*.jar' | head -n 1)" >> $GITHUB_OUTPUT 28 | echo "version=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT 29 | 30 | - name: Upload to Modrinth & Curseforge 31 | uses: Kir-Antipov/mc-publish@v3.3 32 | with: 33 | modrinth-id: H4i6sdRk 34 | modrinth-token: ${{ secrets.MODRINTH_TOKEN }} 35 | 36 | curseforge-id: 1101540 37 | curseforge-token: ${{ secrets.CURSEFORGE_TOKEN }} 38 | 39 | files: ${{ steps.artifact.outputs.jar_path }} 40 | 41 | name: MinecraftServerAPI ${{ github.ref_name }} 42 | version: msa-${{ steps.artifact.outputs.version }} 43 | version-type: release 44 | game-versions: | 45 | >=1.21 46 | loaders: | 47 | paper 48 | spigot 49 | bukkit 50 | changelog: | 51 | See [GitHub Release](${{ github.event.release.html_url }}) for changelog. 52 | 53 | - name: Upload to release 54 | uses: softprops/action-gh-release@v1 55 | with: 56 | files: target/MinecraftServerAPI-*.jar 57 | env: 58 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | !**/src/main/**/target/ 4 | !**/src/test/**/target/ 5 | 6 | ### IntelliJ IDEA ### 7 | .idea/modules.xml 8 | .idea/jarRepositories.xml 9 | .idea/compiler.xml 10 | .idea/libraries/ 11 | *.iws 12 | *.iml 13 | *.ipr 14 | 15 | ### Eclipse ### 16 | .apt_generated 17 | .classpath 18 | .factorypath 19 | .project 20 | .settings 21 | .springBeans 22 | .sts4-cache 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | build/ 31 | !**/src/main/**/build/ 32 | !**/src/test/**/build/ 33 | 34 | ### VS Code ### 35 | .vscode/ 36 | 37 | ### Mac OS ### 38 | .DS_Store 39 | 40 | ### Minecraft Test Server ### 41 | /src/test/resources/minecraft-test-server/* -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/git_toolbox_blame.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/swagger-settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/uiDesigner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | dennisvandenbrock54@gmail.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | > You can add yourself to the contributors in `src/main/resources/plugin.yml` when you make your first contribution. 3 | 4 | If you contribute to this project, you agree to abide by the [code of conduct](CODE_OF_CONDUCT.md). Please read the guidelines below before contributing. 5 | ## Best Practice 6 | 1. **Fork the Repository:** Fork the repository to your GitHub account. 7 | 2. **Create a New Branch:** Create a new branch for your feature or bug fix. 8 | ```bash 9 | git checkout -b feature/my-feature 10 | ``` 11 | 3. **Write Clean Code:** Ensure your code follows the project's coding standards and conventions. 12 | 4. **Write Tests:** Write tests for your code. We use JUnit for unit testing, and the plugin can be tested against a real Minecraft server. 13 | 5. **Commit Changes:** Commit your changes and write meaningful commit messages. 14 | ```bash 15 | git commit -m "Add feature: My new feature" 16 | ``` 17 | 6. **Push Changes:** Push your changes to your forked repository. 18 | ```bash 19 | git push origin feature/my-feature 20 | ``` 21 | 7. **Create a Pull Request:** Create a pull request from your branch to the main repository. Describe the changes you have made and why they are beneficial. 22 | 23 | ## Best Practices 24 | - **Code Style:** Follow the project's code style and conventions. 25 | - **Testing:** Write tests for your code to ensure it works as expected. 26 | - **Documentation:** Document your code and any changes you make. 27 | 28 | ## License 29 | This project is licensed under the MIT License - see the [LICENSE](https://opensource.org/license/mit) file for details. 30 | 31 | ## Contact 32 | If you have any questions or suggestions, feel free to contact me at [dennisvandenbrock54@gmail.com](mailto:dennisvandenbrock54@gmail.com) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MinecraftServerAPI 2 | 3 | 4 | ## Overview 5 | **MinecraftServerAPI** is a powerful and flexible plugin for Minecraft servers, providing RESTful APIs to interact with the server programmatically. This project allows server administrators to automate tasks, gather information, manage the server more efficiently, and even trigger WebHooks for various server events. 6 | 7 | You can find a public list of all available Endpoints [here](https://msa.shweit.com/). 8 | 9 | ## Prerequisites 10 | - **Java:** JDK 20 or higher is required to build and run the project. 11 | - **Maven:** Make sure Maven is installed on your system. 12 | You can download it [here](https://maven.apache.org/download.cgi). 13 | - **Minecraft Server:** Make sure you have a Paper or Spigot Minecraft server running on your machine. 14 | - **Docker:** The Test Environment is set up using Docker. 15 | Make sure you have Docker installed on your system. 16 | You can download it [here](https://www.docker.com/products/docker-desktop). 17 | 18 | ## Installation 19 | ### Cloning the Repository 20 | 1. Clone the repository to your local machine. 21 | ```shell 22 | git clone git@github.com:Shweit/MinecraftServerAPI.git 23 | cd MinecraftServerAPI 24 | ``` 25 | ### Building the Project 26 | 2. Build the project using Maven. 27 | ```shell 28 | mvn clean install 29 | ``` 30 | ### Setting up the Minecraft Server 31 | 3. Copy the generated JAR file to the `plugins` directory of your Minecraft server. 32 | ```shell 33 | cp target/MinecraftServerAPI-*.jar /path/to/your/minecraft/server/plugins 34 | ``` 35 | 4. Start or restart your Minecraft server. 36 | ```shell 37 | java -Xmx1024M -Xms1024M -jar paper-instance.jar nogui 38 | ``` 39 | 5. Once the server is running, the plugin will be loaded automatically. You can verify it by running: 40 | ```shell 41 | /plugins 42 | ``` 43 | ### Accessing the API 44 | 6. The API is accessible at `http://localhost:7000/`. You can test it by sending a GET request to the following endpoint: `GET http://localhost:7000/api/v1/ping`. 45 | 46 | ## API Usage 47 | ### Example API Requests 48 | - **Get all Players:** 49 | ```bash 50 | curl -X 'GET' \ 51 | 'http://localhost:7000/v1/players' \ 52 | -H 'accept: application/json' \ 53 | -H 'Authorization: ' 54 | ``` 55 | 56 | ## WebHook Usage 57 | ### Configuring WebHooks 58 | MinecraftServerAPI supports WebHooks, allowing you to trigger HTTP requests to specified URLs when certain events occur on your server (e.g., server start, server stop, plugin enable/disable). 59 | 60 | ### Setting up WebHooks 61 | 1. **Define WebHooks URLs:** In your `config.yml` located in the `plugins/MinecraftServerAPI`, specify the URLs you want to trigger for different events. 62 | 2. **Enable/Disable WebHooks:** You can enable or disable WebHooks for specific events by setting the `enabled` flag to `true` or `false` in the `config.yml` file. Or you can enable/disable the WebHooks with the following commands: 63 | - **Enable a WebHook:** 64 | ``` 65 | /webhook enable 66 | ``` 67 | - **Disable a WebHook:** 68 | ``` 69 | /webhook disable 70 | ``` 71 | - **List all WebHooks:** 72 | ``` 73 | /webhook list 74 | ``` 75 | 76 | ### Sending a custom WebHook 77 | MinecraftServerAPI allows you to send custom WebHook events to the URLs specified in your config.yml file. This feature enables you to trigger specific WebHook notifications manually. 78 | 79 | To send a custom WebHook event, use the following command in-game or via the server console: 80 | ``` 81 | /webhook send 82 | ``` 83 | 84 | ### More Information 85 | For a detailed list of all available WebHooks and their default settings, please refer to the [WebHooks Documentation](webhooks.md). 86 | 87 | ## Configuration 88 | The plugin is configured via a `config.yml` file in the `plugins/MinecraftServerAPI directory. Here, you can set the authentication key and other settings. 89 | 90 | ## Contributing 91 | Contributions are welcome! Please read the [contributing guidelines](CONTRIBUTING.md) to get started. 92 | -------------------------------------------------------------------------------- /checks.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 33 | 34 | 35 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 175 | 176 | 177 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /dependency-reduced-pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | org.example 5 | MinecraftServerAPI 6 | Archetype - MinecraftServerAPI 7 | 1.0 8 | http://maven.apache.org 9 | 10 | 11 | 12 | maven-compiler-plugin 13 | 3.8.1 14 | 15 | 1.8 16 | 1.8 17 | 18 | 19 | 20 | maven-shade-plugin 21 | 3.2.4 22 | 23 | 24 | package 25 | 26 | shade 27 | 28 | 29 | 30 | 31 | org.spigotmc:spigot-api 32 | 33 | 34 | 35 | 36 | *:* 37 | 38 | META-INF/*.SF 39 | META-INF/*.DSA 40 | META-INF/*.RSA 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | spigot-repo 53 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/ 54 | 55 | 56 | 57 | 58 | org.spigotmc 59 | spigot-api 60 | 1.21-R0.1-SNAPSHOT 61 | provided 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /docker/test.config.yml: -------------------------------------------------------------------------------- 1 | # This is the configuration file for the MinecraftServerAPI-Plugin. 2 | 3 | # The port the API should listen on. 4 | port: 7000 5 | 6 | # Enable swagger documentation for the API endpoints 7 | swagger: true 8 | 9 | # If you want to enable Authentication, set this to true. 10 | # It is not recommended to disable this. If you do, everyone can access the API. 11 | authentication: 12 | enabled: true 13 | key: "TestKey" 14 | 15 | # If you want to enable the debug mode, set this to true. 16 | # This will print more information to the console. 17 | debug: false 18 | 19 | # Here you can turn on/off the different Webhooks. 20 | # If you want to disable a Webhook, set it to false. 21 | webhooks: 22 | 23 | # You can set a list of URLs which should be called when the Webhook is triggered. 24 | # You can set multiple URLs here. 25 | urls: 26 | - "https://example.com/webhook1" 27 | - "https://example.com/webhook2" 28 | 29 | # Here is a list of all available Webhooks. 30 | # You can enable or disable them here. 31 | # Or via the command /webhooks 32 | server_start: true 33 | server_stop: true 34 | plugin_disable: true 35 | plugin_enable: true 36 | block_break: false # This is disabled by default, because it can spam your Webhook-URLs. 37 | block_place: false # This is disabled by default, because it can spam your Webhook-URLs. 38 | block_burn: false # This is disabled by default, because it can spam your Webhook-URLs. 39 | block_redstone: false # This is disabled by default, because it can spam your Webhook-URLs. 40 | note_play: true 41 | sign_change: true 42 | enchant_item: true 43 | creeper_power: true 44 | creature_spawn: false # This is disabled by default, because it can spam your Webhook-URLs. 45 | entity_death: false # This is disabled by default, because it can spam your Webhook-URLs. 46 | entity_explode: true 47 | entity_shoot_bow: true 48 | entity_tame: true 49 | explosion_prime: true 50 | player_death: true 51 | brew: true 52 | craft_item: false # This is disabled by default, because it can spam your Webhook-URLs. 53 | furnace_burn: true # This is disabled by default, because it can spam your Webhook-URLs. 54 | furnace_smelt: true # This is disabled by default, because it can spam your Webhook-URLs. 55 | player_chat: false # This is disabled by default, because it delays the delivery of the message to the server. 56 | player_login: true 57 | player_command: false # This is disabled by default, because it delays the delivery of the command to the server. 58 | player_gamemode_change: true 59 | player_item_break: true 60 | player_join: true 61 | player_kick: true 62 | player_quit: true 63 | player_respawn: true 64 | lightning_strike: true 65 | weather_change: true 66 | thunder_change: true 67 | world_load: true 68 | world_save: true 69 | world_unload: true 70 | 71 | # Here you can list an extra set of Files or Directories which should be saved by the Backup-System. 72 | # Following directories and files are already saved by default: ["world", "world_nether", "world_the_end", "plugins", "config", "server.properties", "banned-ips.json", "banned-players.json", "ops.json", "whitelist.json"] 73 | # e.g.: ["plugins/MyPlugin/config.yml", "plugins/MyPlugin/data/"] 74 | backup_files: [] -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | org.example 5 | MinecraftServerAPI 6 | 1.21.x 7 | MinecraftServerAPI 8 | 9 | 10 | 17 11 | 17 12 | 17 13 | UTF-8 14 | 15 | 16 | 17 | 18 | spigot-repo 19 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/ 20 | 21 | 22 | 23 | 24 | 25 | commons-io 26 | commons-io 27 | 2.11.0 28 | 29 | 30 | org.spigotmc 31 | spigot-api 32 | 1.21-R0.1-SNAPSHOT 33 | provided 34 | 35 | 36 | org.nanohttpd 37 | nanohttpd 38 | 2.3.1 39 | 40 | 41 | io.swagger.core.v3 42 | swagger-annotations 43 | 2.2.12 44 | 45 | 46 | io.swagger.core.v3 47 | swagger-core 48 | 2.2.12 49 | 50 | 51 | io.swagger.core.v3 52 | swagger-jaxrs2 53 | 2.2.12 54 | 55 | 56 | io.swagger.core.v3 57 | swagger-integration 58 | 2.2.12 59 | 60 | 61 | eu.kennytv.maintenance 62 | maintenance-api 63 | 4.2.1 64 | 65 | 66 | org.json 67 | json 68 | 20231013 69 | 70 | 71 | org.junit.jupiter 72 | junit-jupiter-api 73 | 5.7.0 74 | test 75 | 76 | 77 | org.junit.jupiter 78 | junit-jupiter-engine 79 | 5.7.0 80 | test 81 | 82 | 83 | org.testcontainers 84 | testcontainers 85 | 1.20.0 86 | test 87 | 88 | 89 | org.testcontainers 90 | junit-jupiter 91 | 1.17.6 92 | test 93 | 94 | 95 | ch.qos.logback 96 | logback-classic 97 | 1.5.6 98 | runtime 99 | 100 | 101 | org.slf4j 102 | slf4j-api 103 | 2.0.16 104 | 105 | 106 | 107 | 108 | 109 | 110 | org.apache.maven.plugins 111 | maven-compiler-plugin 112 | 3.11.0 113 | 114 | ${maven.compiler.source} 115 | ${maven.compiler.target} 116 | 117 | 118 | 119 | org.apache.maven.plugins 120 | maven-shade-plugin 121 | 3.5.0 122 | 123 | false 124 | 125 | 126 | 127 | package 128 | 129 | shade 130 | 131 | 132 | 133 | 134 | 135 | org.apache.maven.plugins 136 | maven-checkstyle-plugin 137 | 3.4.0 138 | 139 | checks.xml 140 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/MinecraftServerAPI.java: -------------------------------------------------------------------------------- 1 | /** 2 | * MinecraftServerAPI.java 3 | *

4 | * This class is the main class of the plugin. 5 | * It is responsible for starting and stopping the web server. 6 | * It also creates the configuration file if it does not exist. 7 | *

8 | */ 9 | 10 | package com.shweit.serverapi; 11 | 12 | import com.shweit.serverapi.commands.RegisterCommands; 13 | import com.shweit.serverapi.endpoints.RegisterEndpoints; 14 | import com.shweit.serverapi.utils.Logger; 15 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 16 | import com.shweit.serverapi.webhooks.server.ServerStop; 17 | import fi.iki.elonen.NanoHTTPD; 18 | import org.bukkit.Bukkit; 19 | import org.bukkit.configuration.file.FileConfiguration; 20 | import org.bukkit.plugin.java.JavaPlugin; 21 | 22 | import com.shweit.serverapi.listeners.PlayerLoginListener; 23 | 24 | import java.io.File; 25 | 26 | public class MinecraftServerAPI extends JavaPlugin { 27 | 28 | private static final int DEFAULT_PORT = 7000; 29 | private WebServer server; 30 | public static FileConfiguration config; 31 | public static String pluginName = "MinecraftServerAPI"; 32 | private static MinecraftServerAPI instance; 33 | 34 | private static boolean blockNewConnections = false; 35 | private static String blockNewConnectionsMessage; 36 | 37 | public static boolean isPluginInstalled(final String string) { 38 | return Bukkit.getPluginManager().isPluginEnabled(string); 39 | } 40 | 41 | @Override 42 | public final void onEnable() { 43 | registerEvents(); 44 | createConfig(); 45 | 46 | config = getConfig(); 47 | instance = this; 48 | 49 | boolean authEnabled = getConfig().getBoolean("authentication.enabled", true); 50 | String authKey = getConfig().getString("authentication.key", "CHANGE_ME"); 51 | 52 | if (!authEnabled) { 53 | Logger.warning("Authentication is disabled. This is not recommended."); 54 | } else if ("CHANGE_ME".equals(authKey)) { 55 | Logger.error("Please change the authKey in the config.yml file."); 56 | getServer().getPluginManager().disablePlugin(this); 57 | return; 58 | } 59 | 60 | int port = getConfig().getInt("port", DEFAULT_PORT); 61 | server = new WebServer(port, authEnabled, authKey); 62 | 63 | new RegisterEndpoints(server).registerEndpoints(); 64 | 65 | new RegisterWebHooks().registerWebHooks(); 66 | 67 | new RegisterCommands(this).register(); 68 | 69 | try { 70 | server.start(NanoHTTPD.SOCKET_READ_TIMEOUT, false); 71 | Logger.info("Web server started on port " + port); 72 | } catch (Exception e) { 73 | Logger.error("Failed to start web server: " + e.getMessage()); 74 | getServer().getPluginManager().disablePlugin(this); 75 | } 76 | } 77 | 78 | @Override 79 | public final void onDisable() { 80 | new ServerStop().register(); 81 | 82 | if (server != null) { 83 | server.stop(); 84 | Logger.info("Web server stopped."); 85 | } 86 | } 87 | 88 | private void createConfig() { 89 | File configFile = new File(getDataFolder(), "config.yml"); 90 | if (!configFile.exists()) { 91 | saveResource("config.yml", false); 92 | } 93 | } 94 | 95 | public static MinecraftServerAPI getInstance() { 96 | return instance; 97 | } 98 | 99 | private void registerEvents() { 100 | getServer().getPluginManager().registerEvents(new PlayerLoginListener(), this); 101 | } 102 | 103 | public static void setBlockNewConnections(final boolean block, final String message) { 104 | blockNewConnections = block; 105 | if (block) { 106 | blockNewConnectionsMessage = message; 107 | } 108 | } 109 | 110 | public static boolean isBlockNewConnections() { 111 | return blockNewConnections; 112 | } 113 | 114 | public static String getBlockNewConnectionsMessage() { 115 | return blockNewConnectionsMessage; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/WebServer.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi; 2 | 3 | import com.shweit.serverapi.utils.Logger; 4 | import com.shweit.serverapi.utils.RouteDefinition; 5 | import fi.iki.elonen.NanoHTTPD; 6 | 7 | import java.io.InputStream; 8 | import java.util.ArrayList; 9 | import java.util.HashMap; 10 | import java.util.List; 11 | import java.util.Map; 12 | import java.util.function.Function; 13 | 14 | public final class WebServer extends NanoHTTPD { 15 | private final boolean isAuthenticated; 16 | private final String authKey; 17 | private final List routes = new ArrayList<>(); 18 | 19 | public WebServer(final int port, final boolean authenticationEnabled, final String authenticationKey) { 20 | super(port); 21 | this.isAuthenticated = authenticationEnabled; 22 | this.authKey = authenticationKey; 23 | } 24 | 25 | @Override 26 | public Response serve(final IHTTPSession session) { 27 | String uri = session.getUri(); 28 | NanoHTTPD.Method method = session.getMethod(); 29 | Map params = new HashMap<>(); 30 | boolean swaggerDocumentation = MinecraftServerAPI.config.getBoolean("swagger", true); 31 | 32 | Logger.debug("Received request for: " + uri + " with method: " + method); 33 | 34 | // Handle Swagger documentation and static files 35 | Response swaggerResponse = handleSwaggerDocumentation(uri, session, swaggerDocumentation); 36 | if (swaggerResponse != null) { 37 | return swaggerResponse; 38 | } 39 | 40 | // Handle authentication 41 | if (isAuthenticated && !isAllowedPath(uri, swaggerDocumentation)) { 42 | Response authResponse = handleAuthentication(session, uri); 43 | if (authResponse != null) { 44 | return authResponse; 45 | } 46 | } 47 | 48 | // Extract query parameters 49 | extractQueryParams(session, params); 50 | 51 | // Match routes and return appropriate response 52 | return handleRouteMatching(uri, method, params); 53 | } 54 | 55 | // Method to handle Swagger documentation and static files 56 | private Response handleSwaggerDocumentation(final String uri, final IHTTPSession session, final boolean swaggerDocumentation) { 57 | String finalUri = uri; 58 | if (swaggerDocumentation) { 59 | if ("/api-docs".equalsIgnoreCase(finalUri)) { 60 | InputStream apiSpecStream = getClass().getResourceAsStream("/api.yaml"); 61 | if (apiSpecStream != null) { 62 | return newChunkedResponse(Response.Status.OK, "application/yaml", apiSpecStream); 63 | } else { 64 | return newFixedLengthResponse(Response.Status.NOT_FOUND, MIME_PLAINTEXT, "API documentation not found"); 65 | } 66 | } 67 | 68 | if (finalUri.equalsIgnoreCase("/") || finalUri.startsWith("/swagger")) { 69 | if ("/".equals(finalUri)) { 70 | finalUri = "/index.html"; // Redirect to the main Swagger UI page 71 | } 72 | InputStream resourceStream = getClass().getResourceAsStream("/swagger" + finalUri); 73 | if (resourceStream != null) { 74 | String mimeType = determineMimeType(finalUri); 75 | return newChunkedResponse(Response.Status.OK, mimeType, resourceStream); 76 | } else { 77 | Logger.debug("Resource not found: " + finalUri); 78 | return newFixedLengthResponse(Response.Status.NOT_FOUND, "text/plain", "Route not Found"); 79 | } 80 | } 81 | } 82 | return null; 83 | } 84 | 85 | // Method to handle authentication 86 | private Response handleAuthentication(final IHTTPSession session, final String uri) { 87 | String authHeader = session.getHeaders().get("authorization"); 88 | if (authHeader == null || !authHeader.equals(authKey)) { 89 | Logger.debug("Unauthorized request for: " + uri); 90 | return newFixedLengthResponse(Response.Status.UNAUTHORIZED, MIME_PLAINTEXT, "Unauthorized"); 91 | } 92 | return null; 93 | } 94 | 95 | // Method to check if a path is allowed without authentication 96 | private boolean isAllowedPath(final String uri, final boolean swaggerDocumentation) { 97 | List allowedPaths = swaggerDocumentation ? List.of( 98 | "/", "/swagger-ui-bundle.js", "/swagger-ui.css", "/api-docs", "/index.css", 99 | "/searchPlugin.js", "/swagger-ui-standalone-preset.js", "/swagger-initializer.js", 100 | "/favicon-32x32.png", "/swagger-ui.css.map", "/favicon-16x16.png" 101 | ) : List.of(); 102 | 103 | return allowedPaths.stream().anyMatch(path -> uri.equals(path) || uri.startsWith("/swagger")); 104 | } 105 | 106 | // Method to extract query parameters 107 | private void extractQueryParams(final IHTTPSession session, final Map params) { 108 | if (session.getQueryParameterString() != null) { 109 | session.getParameters().forEach((key, value) -> params.put(key, value.get(0))); 110 | } 111 | } 112 | 113 | // Method to handle route matching 114 | private Response handleRouteMatching(final String uri, final NanoHTTPD.Method method, final Map params) { 115 | for (RouteDefinition route : routes) { 116 | if (route.matches(uri, method, params)) { 117 | return route.getHandler().apply(params); 118 | } 119 | } 120 | Logger.debug("No route found for: " + uri + " with method: " + method); 121 | return newFixedLengthResponse(Response.Status.NOT_FOUND, MIME_PLAINTEXT, "Not Found"); 122 | } 123 | 124 | 125 | // Method to determine MIME type 126 | private String determineMimeType(final String uri) { 127 | if (uri.endsWith(".html")) return "text/html"; 128 | if (uri.endsWith(".css")) return "text/css"; 129 | if (uri.endsWith(".js")) return "application/javascript"; 130 | if (uri.endsWith(".yaml")) return "application/yaml"; 131 | return "text/plain"; 132 | } 133 | 134 | public void addRoute(final NanoHTTPD.Method method, final String routePattern, final Function, Response> handler) { 135 | routes.add(new RouteDefinition(method, routePattern, handler)); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/commands/CommandManager.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.commands; 2 | 3 | import org.bukkit.command.Command; 4 | import org.bukkit.command.CommandSender; 5 | import org.bukkit.command.TabExecutor; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | public final class CommandManager implements TabExecutor { 11 | 12 | private final ArrayList subcommands = new ArrayList<>(); 13 | 14 | public CommandManager(final List subCommandList) { 15 | this.subcommands.addAll(subCommandList); 16 | } 17 | 18 | public ArrayList getSubCommands() { 19 | return subcommands; 20 | } 21 | 22 | @Override 23 | public boolean onCommand(final CommandSender commandSender, final Command command, final String label, final String[] args) { 24 | if (args.length > 0) { 25 | for (int i = 0; i < getSubCommands().size(); i++) { 26 | if (args[0].equalsIgnoreCase(getSubCommands().get(i).getName())) { 27 | getSubCommands().get(i).perform(commandSender, command, label, args); 28 | } 29 | } 30 | 31 | } 32 | 33 | return true; 34 | } 35 | 36 | @Override 37 | public List onTabComplete(final CommandSender sender, final Command command, final String alias, final String[] args) { 38 | if (args.length == 1) { 39 | List subcommandsList = new ArrayList<>(); 40 | for (SubCommand subCommand : getSubCommands()) { 41 | subcommandsList.add(subCommand.getName()); 42 | } 43 | return subcommandsList; 44 | } else if (args.length > 1) { 45 | for (SubCommand subCommand : getSubCommands()) { 46 | if (args[0].equalsIgnoreCase(subCommand.getName())) { 47 | return subCommand.getSubcommandArguments(sender, command, alias, args); 48 | } 49 | } 50 | } 51 | 52 | return null; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/commands/RegisterCommands.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.commands; 2 | 3 | import com.shweit.serverapi.commands.version.VersionCommand; 4 | import com.shweit.serverapi.commands.webHook.DisableWebHookCommand; 5 | import com.shweit.serverapi.commands.webHook.EnableWebHookCommand; 6 | import com.shweit.serverapi.commands.webHook.SendWebHookCommand; 7 | import com.shweit.serverapi.commands.webHook.ListWebHook; 8 | import org.bukkit.plugin.java.JavaPlugin; 9 | 10 | import java.util.List; 11 | 12 | public final class RegisterCommands { 13 | private JavaPlugin plugin; 14 | 15 | public RegisterCommands(final JavaPlugin javaPlugin) { 16 | this.plugin = javaPlugin; 17 | } 18 | 19 | public void register() { 20 | List webHookSubCommands = List.of( 21 | new ListWebHook(), 22 | new EnableWebHookCommand(), 23 | new DisableWebHookCommand(), 24 | new SendWebHookCommand() 25 | ); 26 | CommandManager webhookCommandManager = new CommandManager(webHookSubCommands); 27 | plugin.getCommand("webhooks").setExecutor(webhookCommandManager); 28 | 29 | 30 | List mcapiSubCommands = List.of( 31 | new VersionCommand() 32 | ); 33 | CommandManager versionCommandManager = new CommandManager(mcapiSubCommands); 34 | plugin.getCommand("mcapi").setExecutor(versionCommandManager); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/commands/SubCommand.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.commands; 2 | 3 | import org.bukkit.command.Command; 4 | import org.bukkit.command.CommandSender; 5 | 6 | import java.util.List; 7 | 8 | public abstract class SubCommand { 9 | 10 | public abstract String getName(); 11 | 12 | public abstract String getDescription(); 13 | 14 | public abstract String getSyntax(); 15 | 16 | public abstract void perform(CommandSender commandSender, Command command, String label, String[] args); 17 | 18 | public abstract List getSubcommandArguments(CommandSender commandSender, Command command, String label, String[] args); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/commands/version/VersionCommand.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.commands.version; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.commands.SubCommand; 5 | import org.bukkit.ChatColor; 6 | import org.bukkit.command.Command; 7 | import org.bukkit.command.CommandSender; 8 | 9 | import java.util.List; 10 | 11 | public final class VersionCommand extends SubCommand { 12 | @Override 13 | public String getName() { 14 | return "version"; 15 | } 16 | 17 | @Override 18 | public String getDescription() { 19 | return "Shows the current version of the plugin."; 20 | } 21 | 22 | @Override 23 | public String getSyntax() { 24 | return "/mcapi version"; 25 | } 26 | 27 | @Override 28 | public void perform(final CommandSender commandSender, final Command command, final String label, final String[] args) { 29 | commandSender.sendMessage(ChatColor.GREEN + "MinecraftServerAPI version: " + ChatColor.GOLD + MinecraftServerAPI.getInstance().getDescription().getVersion()); 30 | } 31 | 32 | @Override 33 | public List getSubcommandArguments(final CommandSender commandSender, final Command command, final String label, final String[] args) { 34 | return List.of(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/commands/webHook/DisableWebHookCommand.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.commands.webHook; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.commands.SubCommand; 5 | import com.shweit.serverapi.webhooks.WebHookEnum; 6 | import org.bukkit.ChatColor; 7 | import org.bukkit.command.Command; 8 | import org.bukkit.command.CommandSender; 9 | 10 | import java.util.List; 11 | 12 | public final class DisableWebHookCommand extends SubCommand { 13 | @Override 14 | public String getName() { 15 | return "disable"; 16 | } 17 | 18 | @Override 19 | public String getDescription() { 20 | return "Disable a specific webhook."; 21 | } 22 | 23 | @Override 24 | public String getSyntax() { 25 | return "/webhooks disable "; 26 | } 27 | 28 | @Override 29 | public void perform(final CommandSender commandSender, final Command command, final String label, final String[] args) { 30 | // Check the length of the arguments 31 | if (args.length != 2) { 32 | commandSender.sendMessage(ChatColor.RED + "Usage: /webhooks disable "); 33 | return; 34 | } 35 | 36 | // Check if the webhook exists 37 | String webhookName = args[1]; 38 | if (!WebHookEnum.isValid(webhookName)) { 39 | commandSender.sendMessage(ChatColor.RED + "Unknown webhook."); 40 | commandSender.sendMessage(ChatColor.RED + "Available webhooks: " + ChatColor.GREEN + WebHookEnum.getValidHooks()); 41 | return; 42 | } 43 | 44 | // Enable the webhook 45 | MinecraftServerAPI.getInstance().getConfig().set("webhooks." + webhookName, false); 46 | MinecraftServerAPI.getInstance().saveConfig(); 47 | commandSender.sendMessage(ChatColor.GREEN + "Webhook " + webhookName + " disabled."); 48 | } 49 | 50 | @Override 51 | public List getSubcommandArguments(final CommandSender commandSender, final Command command, final String label, final String[] args) { 52 | if (args.length == 2) { 53 | return WebHookEnum.getValidHookList(); 54 | } 55 | 56 | return null; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/commands/webHook/EnableWebHookCommand.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.commands.webHook; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.commands.SubCommand; 5 | import com.shweit.serverapi.webhooks.WebHookEnum; 6 | import org.bukkit.ChatColor; 7 | import org.bukkit.command.Command; 8 | import org.bukkit.command.CommandSender; 9 | 10 | import java.util.List; 11 | 12 | public final class EnableWebHookCommand extends SubCommand { 13 | @Override 14 | public String getName() { 15 | return "enable"; 16 | } 17 | 18 | @Override 19 | public String getDescription() { 20 | return "Enable a specific webhook."; 21 | } 22 | 23 | @Override 24 | public String getSyntax() { 25 | return "/webhooks enable "; 26 | } 27 | 28 | @Override 29 | public void perform(final CommandSender commandSender, final Command command, final String label, final String[] args) { 30 | // Check the length of the arguments 31 | if (args.length != 2) { 32 | commandSender.sendMessage(ChatColor.RED + "Usage: /webhooks enable "); 33 | return; 34 | } 35 | 36 | // Check if the webhook exists 37 | String webhookName = args[1]; 38 | if (!WebHookEnum.isValid(webhookName)) { 39 | commandSender.sendMessage(ChatColor.RED + "Unknown webhook."); 40 | commandSender.sendMessage(ChatColor.RED + "Available webhooks: " + ChatColor.GREEN + WebHookEnum.getValidHooks()); 41 | return; 42 | } 43 | 44 | // Enable the webhook 45 | MinecraftServerAPI.getInstance().getConfig().set("webhooks." + webhookName, true); 46 | MinecraftServerAPI.getInstance().saveConfig(); 47 | commandSender.sendMessage(ChatColor.GREEN + "Webhook " + webhookName + " enabled."); 48 | } 49 | 50 | @Override 51 | public List getSubcommandArguments(final CommandSender commandSender, final Command command, final String label, final String[] args) { 52 | if (args.length == 2) { 53 | return WebHookEnum.getValidHookList(); 54 | } 55 | 56 | return null; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/commands/webHook/ListWebHook.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.commands.webHook; 2 | 3 | import com.shweit.serverapi.commands.SubCommand; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHookEnum; 6 | import org.bukkit.ChatColor; 7 | import org.bukkit.command.Command; 8 | import org.bukkit.command.CommandSender; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | public final class ListWebHook extends SubCommand { 14 | private static final int ENTRIES_PER_PAGE = 7; 15 | 16 | @Override 17 | public String getName() { 18 | return "list"; 19 | } 20 | 21 | @Override 22 | public String getDescription() { 23 | return "List all webhooks."; 24 | } 25 | 26 | @Override 27 | public String getSyntax() { 28 | return "/webhooks list "; 29 | } 30 | 31 | @Override 32 | public void perform(final CommandSender commandSender, final Command command, final String label, final String[] args) { 33 | int page = 1; 34 | 35 | if (args.length == 2) { 36 | try { 37 | page = Integer.parseInt(args[1]); 38 | } catch (NumberFormatException e) { 39 | commandSender.sendMessage(ChatColor.RED + "Invalid page number!"); 40 | return; 41 | } 42 | } 43 | 44 | int totalPages = (int) Math.ceil((double) WebHookEnum.values().length / ENTRIES_PER_PAGE); 45 | 46 | if (page > totalPages || page <= 0) { 47 | commandSender.sendMessage(ChatColor.RED + "Invalid page number! Please enter a number between 1 and " + totalPages); 48 | return; 49 | } 50 | 51 | commandSender.sendMessage( 52 | ChatColor.GRAY + "----------------[" 53 | + ChatColor.LIGHT_PURPLE + " WebHooks - Page " + page + "/" + totalPages + ChatColor.GRAY 54 | + " ]----------------" 55 | ); 56 | commandSender.sendMessage(""); 57 | commandSender.sendMessage(ChatColor.WHITE + "Registered WebHooks (" + WebHookEnum.values().length + "):"); 58 | commandSender.sendMessage(""); 59 | commandSender.sendMessage(ChatColor.GOLD + "Available WebHooks:"); 60 | 61 | int startIndex = (page - 1) * ENTRIES_PER_PAGE; 62 | int endIndex = Math.min(startIndex + ENTRIES_PER_PAGE, WebHookEnum.values().length); 63 | 64 | for (int i = startIndex; i < endIndex; i++) { 65 | WebHookEnum webhook = WebHookEnum.values()[i]; 66 | ChatColor color = RegisterWebHooks.doActivateWebhook(webhook.label) ? ChatColor.GREEN : ChatColor.RED; 67 | commandSender.sendMessage(ChatColor.GRAY + "- " + color + webhook.label + ChatColor.GRAY + ": " + ChatColor.WHITE + webhook.getDescription()); 68 | } 69 | 70 | commandSender.sendMessage(""); 71 | commandSender.sendMessage( 72 | ChatColor.GRAY + "--------------------[" 73 | + ChatColor.LIGHT_PURPLE + " Page " + page + " of " + totalPages + ChatColor.GRAY 74 | + " ]--------------------" 75 | ); 76 | } 77 | 78 | @Override 79 | public List getSubcommandArguments(final CommandSender commandSender, final Command command, final String label, final String[] args) { 80 | // Calculate the number of pages 81 | int totalPages = (int) Math.ceil((double) WebHookEnum.values().length / ENTRIES_PER_PAGE); 82 | 83 | // Create a list of page numbers 84 | List pageNumbers = new ArrayList<>(); 85 | for (int i = 1; i <= totalPages; i++) { 86 | pageNumbers.add(String.valueOf(i)); 87 | } 88 | 89 | return pageNumbers; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/commands/webHook/SendWebHookCommand.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.commands.webHook; 2 | 3 | import com.shweit.serverapi.commands.SubCommand; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import org.bukkit.ChatColor; 6 | import org.bukkit.command.Command; 7 | import org.bukkit.command.CommandSender; 8 | import org.json.JSONObject; 9 | 10 | import java.util.List; 11 | 12 | public final class SendWebHookCommand extends SubCommand { 13 | @Override 14 | public String getName() { 15 | return "send"; 16 | } 17 | 18 | @Override 19 | public String getDescription() { 20 | return "Send a webhook with a specific event."; 21 | } 22 | 23 | @Override 24 | public String getSyntax() { 25 | return "/webhooks send "; 26 | } 27 | 28 | @Override 29 | public void perform(final CommandSender commandSender, final Command command, final String label, final String[] args) { 30 | if (args.length != 2) { 31 | commandSender.sendMessage(ChatColor.RED + "Usage: /webhooks send "); 32 | return; 33 | } 34 | 35 | String event = args[1]; 36 | JSONObject json = new JSONObject(); 37 | json.put("event", event); 38 | 39 | // Send the webhook 40 | RegisterWebHooks.sendToAllUrls(json); 41 | 42 | commandSender.sendMessage(ChatColor.GREEN + "Webhook " + event + " sent."); 43 | } 44 | 45 | @Override 46 | public List getSubcommandArguments(final CommandSender commandSender, final Command command, final String label, final String[] args) { 47 | return List.of(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/endpoints/v1/MaintenanceAPI.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.endpoints.v1; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.utils.Helper; 5 | import eu.kennytv.maintenance.api.Maintenance; 6 | import eu.kennytv.maintenance.api.MaintenanceProvider; 7 | import fi.iki.elonen.NanoHTTPD; 8 | import org.bukkit.Bukkit; 9 | import org.json.JSONObject; 10 | 11 | import java.util.Map; 12 | import java.util.UUID; 13 | 14 | public final class MaintenanceAPI { 15 | public final Maintenance maintenancePlugin = MaintenanceProvider.get(); 16 | 17 | public NanoHTTPD.Response getMaintenanceStatus(final Map ignoredParams) { 18 | if (maintenancePlugin.isMaintenance()) { 19 | JSONObject response = new JSONObject(); 20 | response.put("status", "enabled"); 21 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", response.toString()); 22 | } else { 23 | JSONObject response = new JSONObject(); 24 | response.put("status", "disabled"); 25 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", response.toString()); 26 | } 27 | } 28 | 29 | public NanoHTTPD.Response enableMaintenance(final Map params) { 30 | try { 31 | JSONObject response = new JSONObject(); 32 | if (params.get("startTimer") != null) { 33 | Bukkit.getScheduler().runTask(MinecraftServerAPI.getInstance(), () -> { 34 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "maintenance starttimer " + params.get("startTimer")); 35 | }); 36 | 37 | response.put("startTimer", params.get("startTimer")); 38 | } else { 39 | Bukkit.getScheduler().runTask(MinecraftServerAPI.getInstance(), () -> { 40 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "maintenance on"); 41 | }); 42 | } 43 | 44 | if (params.get("endTimer") != null) { 45 | Bukkit.getScheduler().runTask(MinecraftServerAPI.getInstance(), () -> { 46 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "maintenance endtimer " + params.get("endTimer")); 47 | }); 48 | 49 | response.put("endTimer", params.get("endTimer")); 50 | } 51 | 52 | response.put("status", "enabled"); 53 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", response.toString()); 54 | } catch (Exception e) { 55 | JSONObject response = new JSONObject(); 56 | response.put("error", "Failed to enable maintenance mode"); 57 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.INTERNAL_ERROR, "application/json", response.toString()); 58 | } 59 | } 60 | 61 | public NanoHTTPD.Response disableMaintenance(final Map ignoredParams) { 62 | try { 63 | JSONObject response = new JSONObject(); 64 | Bukkit.getScheduler().runTask(MinecraftServerAPI.getInstance(), () -> { 65 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "maintenance off"); 66 | }); 67 | 68 | response.put("status", "disabled"); 69 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", response.toString()); 70 | } catch (Exception e) { 71 | JSONObject response = new JSONObject(); 72 | response.put("error", "Failed to disable maintenance mode"); 73 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.INTERNAL_ERROR, "application/json", response.toString()); 74 | } 75 | } 76 | 77 | public NanoHTTPD.Response getMaintenanceWhitelist(final Map ignoredParams) { 78 | JSONObject response = new JSONObject(); 79 | 80 | for (Map.Entry entry : maintenancePlugin.getSettings().getWhitelistedPlayers().entrySet()) { 81 | response.put(entry.getKey().toString(), entry.getValue()); 82 | } 83 | 84 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", response.toString()); 85 | } 86 | 87 | public NanoHTTPD.Response addPlayerToMaintenanceWhitelist(final Map params) { 88 | try { 89 | if (!params.containsKey("name")) { 90 | JSONObject response = new JSONObject(); 91 | response.put("error", "Missing player name"); 92 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.BAD_REQUEST, "application/json", response.toString()); 93 | } 94 | 95 | String playerName = params.get("name"); 96 | UUID playerUUID = Helper.usernameToUUID(playerName); 97 | 98 | boolean added = maintenancePlugin.getSettings().addWhitelistedPlayer(playerUUID, playerName); 99 | 100 | if (!added) { 101 | JSONObject response = new JSONObject(); 102 | response.put("error", "The player already is in the maintenance whitelist"); 103 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.CONFLICT, "application/json", response.toString()); 104 | } 105 | 106 | JSONObject response = new JSONObject(); 107 | response.put("uuid", playerUUID.toString()); 108 | response.put("name", playerName); 109 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", response.toString()); 110 | } catch (Exception e) { 111 | JSONObject response = new JSONObject(); 112 | response.put("error", "Failed to add the player to the maintenance whitelist"); 113 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.INTERNAL_ERROR, "application/json", response.toString()); 114 | } 115 | } 116 | 117 | public NanoHTTPD.Response removePlayerFromMaintenanceWhitelist(final Map params) { 118 | try { 119 | if (!params.containsKey("name")) { 120 | JSONObject response = new JSONObject(); 121 | response.put("error", "Missing player name"); 122 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.BAD_REQUEST, "application/json", response.toString()); 123 | } 124 | 125 | String playerName = params.get("name"); 126 | UUID playerUUID = Helper.usernameToUUID(playerName); 127 | 128 | if (!maintenancePlugin.getSettings().isWhitelisted(playerUUID)) { 129 | JSONObject response = new JSONObject(); 130 | response.put("error", "The player is not in the maintenance whitelist"); 131 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.CONFLICT, "application/json", response.toString()); 132 | } 133 | 134 | maintenancePlugin.getSettings().removeWhitelistedPlayer(playerUUID); 135 | 136 | JSONObject response = new JSONObject(); 137 | response.put("uuid", playerUUID.toString()); 138 | response.put("name", playerName); 139 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", response.toString()); 140 | } catch (Exception e) { 141 | JSONObject response = new JSONObject(); 142 | response.put("error", "Failed to remove the player from the maintenance whitelist"); 143 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.INTERNAL_ERROR, "application/json", response.toString()); 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/endpoints/v1/WhitelistAPI.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.endpoints.v1; 2 | 3 | 4 | import com.shweit.serverapi.MinecraftServerAPI; 5 | import com.shweit.serverapi.utils.Helper; 6 | import com.shweit.serverapi.utils.Logger; 7 | import fi.iki.elonen.NanoHTTPD; 8 | import org.bukkit.Bukkit; 9 | import org.bukkit.OfflinePlayer; 10 | import org.json.JSONObject; 11 | 12 | import java.util.Map; 13 | import java.util.Objects; 14 | import java.util.Set; 15 | import java.util.UUID; 16 | 17 | public final class WhitelistAPI { 18 | public NanoHTTPD.Response getWhitelist(final Map ignoredParams) { 19 | if (!Bukkit.hasWhitelist()) { 20 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.BAD_REQUEST, "application/json", "{}"); 21 | } 22 | 23 | Set whitelist = Bukkit.getWhitelistedPlayers(); 24 | 25 | JSONObject whitelistJson = new JSONObject(); 26 | for (OfflinePlayer player : whitelist) { 27 | whitelistJson.put(player.getUniqueId().toString(), player.getName()); 28 | } 29 | 30 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", whitelistJson.toString()); 31 | } 32 | 33 | public NanoHTTPD.Response postWhitelist(final Map params) { 34 | String playerName = params.get("username"); 35 | if (playerName == null) { 36 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.BAD_REQUEST, "application/json", "{error: 'username parameter is required'}"); 37 | } 38 | 39 | UUID uuid = Helper.usernameToUUID(playerName); 40 | if (uuid == null) { 41 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.NOT_FOUND, "application/json", "{}"); 42 | } 43 | 44 | OfflinePlayer player = Bukkit.getOfflinePlayer(uuid); 45 | if (player.isWhitelisted()) { 46 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", "{}"); 47 | } 48 | 49 | Bukkit.getScheduler().runTask(MinecraftServerAPI.getInstance(), () -> player.setWhitelisted(true)); 50 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", "{}"); 51 | } 52 | 53 | public NanoHTTPD.Response deleteWhitelist(final Map params) { 54 | String playerName = params.get("username"); 55 | if (playerName == null) { 56 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.BAD_REQUEST, "application/json", "{error: 'username parameter is required'}"); 57 | } 58 | 59 | UUID uuid = Helper.usernameToUUID(playerName); 60 | if (uuid == null) { 61 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.NOT_FOUND, "application/json", "{}"); 62 | } 63 | 64 | OfflinePlayer player = Bukkit.getOfflinePlayer(uuid); 65 | if (!player.isWhitelisted()) { 66 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", "{}"); 67 | } 68 | 69 | Bukkit.getScheduler().runTask(MinecraftServerAPI.getInstance(), () -> player.setWhitelisted(false)); 70 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", "{}"); 71 | } 72 | 73 | public NanoHTTPD.Response activateWhitelist(final Map params) { 74 | Bukkit.getScheduler().runTask(MinecraftServerAPI.getInstance(), () -> Bukkit.setWhitelist(true)); 75 | 76 | if (Objects.equals(params.get("kickPlayers"), "true")) { 77 | Logger.debug("Kicking all players not on the whitelist"); 78 | // Kick all players not on the whitelist 79 | Bukkit.getOnlinePlayers().stream() 80 | .filter(player -> !player.isWhitelisted()) 81 | .forEach(player -> player.kickPlayer("Whitelist activated. As you are not on the whitelist, you have been kicked.")); 82 | } 83 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", "{}"); 84 | } 85 | 86 | public NanoHTTPD.Response deactivateWhitelist(final Map ignoredParams) { 87 | Bukkit.getScheduler().runTask(MinecraftServerAPI.getInstance(), () -> Bukkit.setWhitelist(false)); 88 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", "{}"); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/handlers/CommandOutputCapture.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.handlers; 2 | 3 | import org.bukkit.Bukkit; 4 | import org.bukkit.Server; 5 | import org.bukkit.command.CommandSender; 6 | import org.bukkit.command.ConsoleCommandSender; 7 | import org.bukkit.conversations.Conversation; 8 | import org.bukkit.conversations.ConversationAbandonedEvent; 9 | import org.bukkit.permissions.Permission; 10 | import org.bukkit.permissions.PermissionAttachment; 11 | import org.bukkit.permissions.PermissionAttachmentInfo; 12 | import org.bukkit.plugin.Plugin; 13 | 14 | import java.text.SimpleDateFormat; 15 | import java.util.ArrayList; 16 | import java.util.Date; 17 | import java.util.HashMap; 18 | import java.util.List; 19 | import java.util.Set; 20 | import java.util.UUID; 21 | 22 | /** 23 | * A custom CommandSender implementation that captures command output 24 | */ 25 | public class CommandOutputCapture implements ConsoleCommandSender { 26 | private final ConsoleCommandSender originalSender; 27 | private final List> outputMessages = new ArrayList<>(); 28 | 29 | public CommandOutputCapture() { 30 | this.originalSender = Bukkit.getConsoleSender(); 31 | } 32 | 33 | @Override 34 | public void sendMessage(String message) { 35 | // Capture the message 36 | HashMap outputMessage = new HashMap<>(); 37 | outputMessage.put("message", message); 38 | String readableTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(new Date()); 39 | outputMessage.put("time", readableTime); 40 | outputMessages.add(outputMessage); 41 | 42 | // Forward to the original sender 43 | originalSender.sendMessage(message); 44 | } 45 | 46 | @Override 47 | public void sendMessage(String[] messages) { 48 | for (String message : messages) { 49 | sendMessage(message); 50 | } 51 | } 52 | 53 | @Override 54 | public void sendMessage(UUID sender, String message) { 55 | HashMap outputMessage = new HashMap<>(); 56 | outputMessage.put("message", message); 57 | outputMessage.put("sender", sender.toString()); 58 | String readableTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(new Date()); 59 | outputMessage.put("time", readableTime); 60 | outputMessages.add(outputMessage); 61 | 62 | originalSender.sendMessage(sender, message); 63 | } 64 | 65 | @Override 66 | public void sendMessage(UUID sender, String[] messages) { 67 | for (String message : messages) { 68 | sendMessage(sender, message); 69 | } 70 | } 71 | 72 | public List> getOutputMessages() { 73 | return outputMessages; 74 | } 75 | 76 | // Delegate all other methods to the original sender 77 | @Override 78 | public Server getServer() { 79 | return originalSender.getServer(); 80 | } 81 | 82 | @Override 83 | public String getName() { 84 | return originalSender.getName(); 85 | } 86 | 87 | @Override 88 | public Spigot spigot() { 89 | return originalSender.spigot(); 90 | } 91 | 92 | @Override 93 | public boolean isConversing() { 94 | return originalSender.isConversing(); 95 | } 96 | 97 | @Override 98 | public void acceptConversationInput(String input) { 99 | originalSender.acceptConversationInput(input); 100 | } 101 | 102 | @Override 103 | public boolean beginConversation(Conversation conversation) { 104 | return originalSender.beginConversation(conversation); 105 | } 106 | 107 | @Override 108 | public void abandonConversation(Conversation conversation) { 109 | originalSender.abandonConversation(conversation); 110 | } 111 | 112 | @Override 113 | public void abandonConversation(Conversation conversation, ConversationAbandonedEvent details) { 114 | originalSender.abandonConversation(conversation, details); 115 | } 116 | 117 | @Override 118 | public void sendRawMessage(String message) { 119 | sendMessage(message); 120 | } 121 | 122 | @Override 123 | public void sendRawMessage(UUID sender, String message) { 124 | sendMessage(sender, message); 125 | } 126 | 127 | @Override 128 | public boolean isPermissionSet(String name) { 129 | return originalSender.isPermissionSet(name); 130 | } 131 | 132 | @Override 133 | public boolean isPermissionSet(Permission perm) { 134 | return originalSender.isPermissionSet(perm); 135 | } 136 | 137 | @Override 138 | public boolean hasPermission(String name) { 139 | return originalSender.hasPermission(name); 140 | } 141 | 142 | @Override 143 | public boolean hasPermission(Permission perm) { 144 | return originalSender.hasPermission(perm); 145 | } 146 | 147 | @Override 148 | public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) { 149 | return originalSender.addAttachment(plugin, name, value); 150 | } 151 | 152 | @Override 153 | public PermissionAttachment addAttachment(Plugin plugin) { 154 | return originalSender.addAttachment(plugin); 155 | } 156 | 157 | @Override 158 | public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) { 159 | return originalSender.addAttachment(plugin, name, value, ticks); 160 | } 161 | 162 | @Override 163 | public PermissionAttachment addAttachment(Plugin plugin, int ticks) { 164 | return originalSender.addAttachment(plugin, ticks); 165 | } 166 | 167 | @Override 168 | public void removeAttachment(PermissionAttachment attachment) { 169 | originalSender.removeAttachment(attachment); 170 | } 171 | 172 | @Override 173 | public void recalculatePermissions() { 174 | originalSender.recalculatePermissions(); 175 | } 176 | 177 | @Override 178 | public Set getEffectivePermissions() { 179 | return originalSender.getEffectivePermissions(); 180 | } 181 | 182 | @Override 183 | public boolean isOp() { 184 | return originalSender.isOp(); 185 | } 186 | 187 | @Override 188 | public void setOp(boolean value) { 189 | originalSender.setOp(value); 190 | } 191 | } -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/handlers/LogHandler.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.handlers; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.ArrayList; 5 | import java.util.HashMap; 6 | import java.util.List; 7 | import java.util.logging.Handler; 8 | import java.util.logging.LogRecord; 9 | 10 | public final class LogHandler extends Handler { 11 | private final List> log = new ArrayList<>(); 12 | 13 | @Override 14 | public void publish(final LogRecord record) { 15 | HashMap logRecord = new HashMap<>(); 16 | logRecord.put("level", record.getLevel().getName()); 17 | logRecord.put("message", record.getMessage()); 18 | 19 | String readableTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(record.getMillis()); 20 | logRecord.put("time", readableTime); 21 | log.add(logRecord); 22 | } 23 | 24 | @Override 25 | public void flush() { 26 | 27 | } 28 | 29 | @Override 30 | public void close() throws SecurityException { 31 | 32 | } 33 | 34 | public List> getLog() { 35 | return log; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/listeners/ChatListener.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.listeners; 2 | 3 | import org.bukkit.event.EventHandler; 4 | import org.bukkit.event.Listener; 5 | 6 | import java.text.SimpleDateFormat; 7 | import java.util.*; 8 | 9 | public final class ChatListener implements Listener { 10 | private final List> messages = new ArrayList<>(); 11 | 12 | @EventHandler 13 | public void onPlayerChat(final org.bukkit.event.player.AsyncPlayerChatEvent event) { 14 | HashMap message = new HashMap<>(); 15 | message.put("player", event.getPlayer().getName()); 16 | message.put("message", event.getMessage()); 17 | 18 | String readableTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(new Date()); 19 | message.put("time", readableTime); 20 | messages.add(message); 21 | } 22 | 23 | public List> getMessages() { 24 | return messages; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/listeners/PlayerLoginListener.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.listeners; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import org.bukkit.event.EventHandler; 5 | import org.bukkit.event.Listener; 6 | import org.bukkit.event.player.PlayerLoginEvent; 7 | 8 | public final class PlayerLoginListener implements Listener { 9 | @EventHandler 10 | public void onPlayerLogin(final PlayerLoginEvent event) { 11 | if (MinecraftServerAPI.isBlockNewConnections()) { 12 | event.disallow(PlayerLoginEvent.Result.KICK_OTHER, MinecraftServerAPI.getBlockNewConnectionsMessage()); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/utils/Helper.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.utils; 2 | 3 | import com.google.gson.JsonObject; 4 | import com.google.gson.JsonParser; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.net.URI; 9 | import java.net.http.HttpRequest; 10 | import java.net.http.HttpResponse; 11 | import java.nio.file.Files; 12 | import java.util.UUID; 13 | 14 | public final class Helper { 15 | 16 | private Helper() { 17 | throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); 18 | } 19 | 20 | public static UUID usernameToUUID(final String username) { 21 | HttpRequest request = HttpRequest.newBuilder() 22 | .uri(URI.create("https://api.mojang.com/users/profiles/minecraft/" + username)) 23 | .build(); 24 | HttpResponse response; 25 | 26 | UUID playerUUID; 27 | 28 | try { 29 | response = java.net.http.HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); 30 | JsonObject jsonObject = JsonParser.parseString(response.body()).getAsJsonObject(); 31 | playerUUID = UUID.fromString(jsonObject.get("id").getAsString().replaceAll("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})", "$1-$2-$3-$4-$5")); 32 | } catch (InterruptedException e) { 33 | Logger.error("Request was interrupted: " + e.getMessage()); 34 | Thread.currentThread().interrupt(); 35 | return null; 36 | } catch (IOException e) { 37 | Logger.error("Failed to convert username to UUID: " + username + " - " + e.getMessage()); 38 | return null; 39 | } catch (Exception e) { 40 | Logger.error("Unexpected error occurred: " + e.getMessage()); 41 | return null; 42 | } 43 | 44 | return playerUUID; 45 | } 46 | 47 | public static double calculateTPS() { 48 | final int ticksSize = 600; 49 | final double maxTps = 20.0; 50 | 51 | long[] ticks = new long[ticksSize]; 52 | int tickCount = 0; 53 | 54 | ticks[tickCount % ticksSize] = System.currentTimeMillis(); 55 | tickCount++; 56 | 57 | if (tickCount < 100) { 58 | return maxTps; 59 | } 60 | int target = (tickCount - 1 - 100) % ticksSize; 61 | long elapsed = System.currentTimeMillis() - ticks[target]; 62 | 63 | return 100 / (elapsed / 1000.0); 64 | } 65 | 66 | public static void deleteDirectory(final File directory) throws IOException { 67 | if (directory.isDirectory()) { 68 | for (File file : directory.listFiles()) { 69 | if (file.isDirectory()) { 70 | deleteDirectory(file); 71 | } else { 72 | Files.deleteIfExists(file.toPath()); 73 | } 74 | } 75 | Files.deleteIfExists(directory.toPath()); 76 | } 77 | } 78 | 79 | public static String formatSize(final long size) { 80 | String[] units = new String[] {"B", "KB", "MB", "GB", "TB"}; 81 | int unitIndex = 0; 82 | double sizeD = size; 83 | 84 | while (sizeD >= 1024 && unitIndex < units.length - 1) { 85 | sizeD /= 1024; 86 | unitIndex++; 87 | } 88 | 89 | return String.format("%.2f %s", sizeD, units[unitIndex]); 90 | } 91 | 92 | public static String dateConverter(final long timestamp) { 93 | return new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(new java.util.Date(timestamp)); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/utils/Logger.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.utils; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import org.bukkit.Bukkit; 5 | 6 | import java.util.logging.Level; 7 | 8 | public final class Logger { 9 | 10 | private Logger() { 11 | throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); 12 | } 13 | 14 | private static final String PREFIX = "[MinecraftServerAPI] "; 15 | 16 | public static void info(final String message) { 17 | Bukkit.getLogger().log(java.util.logging.Level.INFO, PREFIX + message); 18 | } 19 | 20 | public static void warning(final String message) { 21 | Bukkit.getLogger().log(java.util.logging.Level.WARNING, PREFIX + message); 22 | } 23 | 24 | public static void error(final String message) { 25 | Bukkit.getLogger().log(java.util.logging.Level.SEVERE, PREFIX + message); 26 | } 27 | 28 | public static void debug(final String message) { 29 | boolean debugMode = MinecraftServerAPI.config.getBoolean("debug", false); 30 | 31 | if (debugMode) { 32 | Bukkit.getLogger().log(Level.INFO, "[DEBUG] " + PREFIX + message); 33 | } 34 | } 35 | 36 | public static java.util.logging.Logger getLogger() { 37 | return Bukkit.getLogger(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/utils/RouteDefinition.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.utils; 2 | 3 | import fi.iki.elonen.NanoHTTPD; 4 | 5 | import java.util.Map; 6 | import java.util.function.Function; 7 | 8 | public final class RouteDefinition { 9 | private final String routePattern; 10 | private final NanoHTTPD.Method httpMethod; 11 | private final Function, NanoHTTPD.Response> handler; 12 | 13 | public RouteDefinition(final NanoHTTPD.Method method, final String pattern, final Function, NanoHTTPD.Response> routeHandler) { 14 | this.routePattern = pattern; 15 | this.httpMethod = method; 16 | this.handler = routeHandler; 17 | } 18 | 19 | public String getRoutePattern() { 20 | return routePattern; 21 | } 22 | 23 | public NanoHTTPD.Method getHttpMethod() { 24 | return httpMethod; 25 | } 26 | 27 | public Function, NanoHTTPD.Response> getHandler() { 28 | return handler; 29 | } 30 | 31 | public boolean matches(final String uri, final NanoHTTPD.Method method, final Map params) { 32 | if (!this.httpMethod.equals(method)) { 33 | return false; 34 | } 35 | 36 | String[] patternParts = routePattern.split("/"); 37 | String[] uriParts = uri.split("/"); 38 | 39 | if (patternParts.length != uriParts.length) { 40 | return false; 41 | } 42 | 43 | for (int i = 0; i < patternParts.length; i++) { 44 | String patternPart = patternParts[i]; 45 | String uriPart = uriParts[i]; 46 | 47 | if (patternPart.startsWith("{") && patternPart.endsWith("}")) { 48 | String paramName = patternPart.substring(1, patternPart.length() - 1); // Entferne die geschweiften Klammern 49 | params.put(paramName, uriPart); 50 | } else if (!patternPart.equals(uriPart)) { 51 | return false; 52 | } 53 | } 54 | 55 | return true; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/RegisterWebHooks.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.utils.Logger; 5 | import com.shweit.serverapi.webhooks.block.*; 6 | import com.shweit.serverapi.webhooks.enchantment.EnchantItem; 7 | import com.shweit.serverapi.webhooks.entity.*; 8 | import com.shweit.serverapi.webhooks.inventory.Brew; 9 | import com.shweit.serverapi.webhooks.inventory.CraftItem; 10 | import com.shweit.serverapi.webhooks.inventory.FurnaceBurn; 11 | import com.shweit.serverapi.webhooks.inventory.FurnaceSmelt; 12 | import com.shweit.serverapi.webhooks.player.*; 13 | import com.shweit.serverapi.webhooks.server.PluginDisable; 14 | import com.shweit.serverapi.webhooks.server.PluginEnable; 15 | import com.shweit.serverapi.webhooks.server.ServerStart; 16 | import com.shweit.serverapi.webhooks.weather.LightningStrike; 17 | import com.shweit.serverapi.webhooks.weather.ThunderChange; 18 | import com.shweit.serverapi.webhooks.weather.WeatherChange; 19 | import com.shweit.serverapi.webhooks.world.WorldLoad; 20 | import com.shweit.serverapi.webhooks.world.WorldSave; 21 | import com.shweit.serverapi.webhooks.world.WorldUnload; 22 | import org.json.JSONObject; 23 | 24 | import java.net.URI; 25 | import java.net.http.HttpClient; 26 | import java.net.http.HttpRequest; 27 | import java.net.http.HttpResponse; 28 | import java.util.List; 29 | import java.util.concurrent.CompletableFuture; 30 | 31 | public final class RegisterWebHooks { 32 | private static List urls; 33 | private static final HttpClient HTTP_CLIENT = HttpClient.newHttpClient(); 34 | 35 | public void registerWebHooks() { 36 | 37 | urls = MinecraftServerAPI.config.getStringList("webhooks.urls"); 38 | 39 | if (urls.isEmpty()) { 40 | Logger.warning("No WebHook URL's found in config.yml"); 41 | } 42 | 43 | // Register all webhooks 44 | new ServerStart().register(); 45 | Logger.debug("Registered server_start WebHook"); 46 | 47 | // ServerStop is not registered here, because it is triggered when the plugin gets disabled 48 | Logger.debug("Registered server_stop WebHook"); 49 | 50 | new PluginDisable().register(); 51 | Logger.debug("Registered plugin_disable WebHook"); 52 | 53 | new PluginEnable().register(); 54 | Logger.debug("Registered plugin_enable WebHook"); 55 | 56 | new BlockBreak().register(); 57 | Logger.debug("Registered block_break WebHook"); 58 | 59 | new BlockPlace().register(); 60 | Logger.debug("Registered block_place WebHook"); 61 | 62 | new BlockBurn().register(); 63 | Logger.debug("Registered block_burn WebHook"); 64 | 65 | new BlockRedstone().register(); 66 | Logger.debug("Registered block_redstone WebHook"); 67 | 68 | new NotePlay().register(); 69 | Logger.debug("Registered note_play WebHook"); 70 | 71 | new SignChange().register(); 72 | Logger.debug("Registered sign_change WebHook"); 73 | 74 | new EnchantItem().register(); 75 | Logger.debug("Registered enchant_item WebHook"); 76 | 77 | new CreeperPower().register(); 78 | Logger.debug("Registered creeper_power WebHook"); 79 | 80 | new CreatureSpawn().register(); 81 | Logger.debug("Registered creature_spawn WebHook"); 82 | 83 | new EntityDeath().register(); 84 | Logger.debug("Registered entity_death WebHook"); 85 | 86 | new EntityExplode().register(); 87 | Logger.debug("Registered entity_explode WebHook"); 88 | 89 | new EntityShootBow().register(); 90 | Logger.debug("Registered entity_shot_bow WebHook"); 91 | 92 | new EntityTame().register(); 93 | Logger.debug("Registered entity_tame WebHook"); 94 | 95 | new ExplosionPrime().register(); 96 | Logger.debug("Registered explosion_prime WebHook"); 97 | 98 | new PlayerDeath().register(); 99 | Logger.debug("Registered player_death WebHook"); 100 | 101 | new Brew().register(); 102 | Logger.debug("Registered brew WebHook"); 103 | 104 | new CraftItem().register(); 105 | Logger.debug("Registered craft_item WebHook"); 106 | 107 | new FurnaceBurn().register(); 108 | Logger.debug("Registered furnace_burn WebHook"); 109 | 110 | new FurnaceSmelt().register(); 111 | Logger.debug("Registered furnace_smelt WebHook"); 112 | 113 | new PlayerChat().register(); 114 | Logger.debug("Registered player_chat WebHook"); 115 | 116 | new PlayerLogin().register(); 117 | Logger.debug("Registered player_login WebHook"); 118 | 119 | new PlayerCommand().register(); 120 | Logger.debug("Registered player_command WebHook"); 121 | 122 | new PlayerGamemodeChange().register(); 123 | Logger.debug("Registered player_gamemode_change WebHook"); 124 | 125 | new PlayerItemBreak().register(); 126 | Logger.debug("Registered player_item_break WebHook"); 127 | 128 | new PlayerKick().register(); 129 | Logger.debug("Registered player_kick WebHook"); 130 | 131 | new PlayerQuit().register(); 132 | Logger.debug("Registered player_quit WebHook"); 133 | 134 | new PlayerRespawn().register(); 135 | Logger.debug("Registered player_respawn WebHook"); 136 | 137 | new LightningStrike().register(); 138 | Logger.debug("Registered lightning_strike WebHook"); 139 | 140 | new WeatherChange().register(); 141 | Logger.debug("Registered weather_change WebHook"); 142 | 143 | new ThunderChange().register(); 144 | Logger.debug("Registered thunder_change WebHook"); 145 | 146 | new WorldLoad().register(); 147 | Logger.debug("Registered world_load WebHook"); 148 | 149 | new WorldSave().register(); 150 | Logger.debug("Registered world_save WebHook"); 151 | 152 | new WorldUnload().register(); 153 | Logger.debug("Registered world_unload WebHook"); 154 | } 155 | 156 | public static void sendToAllUrls(final JSONObject jsonObject) { 157 | if (urls == null || urls.isEmpty()) { 158 | Logger.warning("Keine WebHook-URLs in der config.yml gefunden"); 159 | return; 160 | } 161 | 162 | for (String url : urls) { 163 | sendWebHook(url, jsonObject); 164 | } 165 | } 166 | 167 | private static void sendWebHook(final String url, final JSONObject jsonObject) { 168 | try { 169 | HttpRequest request = HttpRequest.newBuilder() 170 | .uri(URI.create(url)) 171 | .header("Content-Type", "application/json") 172 | .POST(HttpRequest.BodyPublishers.ofString(jsonObject.toString())) 173 | .build(); 174 | 175 | CompletableFuture> response = HTTP_CLIENT.sendAsync(request, HttpResponse.BodyHandlers.ofString()); 176 | 177 | response.thenAccept(httpResponse -> { 178 | if (httpResponse.statusCode() == 200) { 179 | Logger.debug("WebHook '" + jsonObject.get("event") + "' erfolgreich an " + url + "gesendet"); 180 | } else { 181 | Logger.warning("Fehler beim Senden des WebHooks '" + jsonObject.get("event") + "' an " + url + ". Antwortcode: " + httpResponse.statusCode()); 182 | } 183 | }).exceptionally(e -> { 184 | Logger.error("Fehler beim Senden des WebHooks " + jsonObject.get("event") + " an " + url + ": " + e.getMessage()); 185 | return null; 186 | }); 187 | 188 | } catch (Exception e) { 189 | Logger.error("Fehler beim Senden des WebHooks " + jsonObject.get("event") + " an " + url + ": " + e.getMessage()); 190 | } 191 | } 192 | 193 | public static boolean doActivateWebhook(final String eventName) { 194 | String eventPath = "webhooks." + eventName; 195 | 196 | return MinecraftServerAPI.config.getBoolean(eventPath, true); 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/WebHook.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks; 2 | 3 | public interface WebHook { 4 | void register(); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/WebHookEnum.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks; 2 | 3 | import java.util.List; 4 | import java.util.stream.Stream; 5 | 6 | public enum WebHookEnum { 7 | SERVER_START("server_start", "Triggered when the server starts"), 8 | SERVER_STOP("server_stop", "Triggered when the server stops"), 9 | PLUGIN_DISABLE("plugin_disable", "Triggered when a plugin is disabled"), 10 | PLUGIN_ENABLE("plugin_enable", "Triggered when a plugin is enabled"), 11 | BLOCK_BREAK("block_break", "Triggered when a block is broken"), 12 | BLOCK_PLACE("block_place", "Triggered when a block is placed"), 13 | BLOCK_BURN("block_burn", "Triggered when a block is burned"), 14 | BLOCK_REDSTONE("block_redstone", "Triggered when a block is powered by redstone or a redstone current changes"), 15 | NOTE_PLAY("note_play", "Triggered when a note block plays a note"), 16 | SIGN_CHANGE("sign_change", "Triggered when a sign is changed"), 17 | ENCHANT_ITEM("enchant_item", "Triggered when an item is enchanted"), 18 | CREEPER_POWER("creeper_power", "Triggered when a Creeper is hit by lightning and becomes supercharged"), 19 | CREATURE_SPAWN("creature_spawn", "Triggered when a creature spawns"), 20 | ENTITY_DEATH("entity_death", "Triggered when an entity dies"), 21 | ENTITY_EXPLODE("entity_explode", "Triggered when an entity explodes"), 22 | ENTITY_SHOOT_BOW("entity_shoot_bow", "Triggered when an entity shoots a bow"), 23 | ENTITY_TAME("entity_tame", "Triggered when an entity is tamed"), 24 | EXPLOSION_PRIME("explosion_prime", "Triggered when an explosion is primed"), 25 | PLAYER_DEATH("player_death", "Triggered when a player dies"), 26 | BREW("brew", "Triggered when a potion is brewed"), 27 | CRAFT_ITEM("craft_item", "Triggered when an item is crafted"), 28 | FURNACE_BURN("furnace_burn", "Triggered when a furnace burns an item as fuel"), 29 | FURNACE_SMELT("furnace_smelt", "Triggered when a furnace smelts an item"), 30 | PLAYER_CHAT("player_chat", "Triggered when a player sends a chat message"), 31 | PLAYER_LOGIN("player_login", "Triggered when a player logs in"), 32 | PLAYER_COMMAND("player_command", "Triggered when a player executes a command"), 33 | PLAYER_GAMEMODE_CHANGE("player_gamemode_change", "Triggered when a player changes their gamemode"), 34 | PLAYER_ITEM_BREAK("player_item_break", "Triggered when a player's item breaks"), 35 | PLAYER_JOIN("player_join", "Triggered when a player joins the server"), 36 | PLAYER_KICK("player_kick", "Triggered when a player is kicked from the server"), 37 | PLAYER_QUIT("player_quit", "Triggered when a player quits the server"), 38 | PLAYER_RESPAWN("player_respawn", "Triggered when a player respawns"), 39 | LIGHTNING_STRIKE("lightning_strike", "Triggered when lightning strikes"), 40 | WEATHER_CHANGE("weather_change", "Triggered when the weather changes"), 41 | THUNDER_CHANGE("thunder_change", "Triggered when the thunder changes"), 42 | WORLD_LOAD("world_load", "Triggered when a world is loaded"), 43 | WORLD_SAVE("world_save", "Triggered when a world is saved"), 44 | WORLD_UNLOAD("world_unload", "Triggered when a world is unloaded"); 45 | 46 | public final String label; 47 | public final String description; 48 | 49 | WebHookEnum(final String enumLabel, final String enumDescription) { 50 | this.label = enumLabel; 51 | this.description = enumDescription; 52 | } 53 | 54 | public String getLabel() { 55 | return label; 56 | } 57 | 58 | public String getDescription() { 59 | return description; 60 | } 61 | 62 | public static boolean isValid(final String webhookName) { 63 | for (WebHookEnum hook : values()) { 64 | if (hook.label.equalsIgnoreCase(webhookName)) { 65 | return true; 66 | } 67 | } 68 | return false; 69 | } 70 | 71 | public static String getValidHooks() { 72 | StringBuilder hooks = new StringBuilder(); 73 | for (WebHookEnum hook : values()) { 74 | if (hooks.length() > 0) { 75 | hooks.append(", "); 76 | } 77 | hooks.append(hook.label.toLowerCase()); 78 | } 79 | return hooks.toString(); 80 | } 81 | 82 | public static List getValidHookList() { 83 | return Stream.of(values()).map(hook -> hook.label.toLowerCase()).toList(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/block/BlockBreak.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.block; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.block.BlockBreakEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class BlockBreak implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.BLOCK_BREAK.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onBlockBreak(final BlockBreakEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("player", event.getPlayer().getName()); 29 | jsonObject.put("block", event.getBlock().getType().name()); 30 | jsonObject.put("location", event.getBlock().getLocation().toString()); 31 | 32 | RegisterWebHooks.sendToAllUrls(jsonObject); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/block/BlockBurn.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.block; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.block.BlockBurnEvent; 10 | import org.json.JSONObject; 11 | 12 | import java.util.Objects; 13 | 14 | public final class BlockBurn implements WebHook, Listener { 15 | 16 | private final String eventName = WebHookEnum.BLOCK_BURN.label; 17 | 18 | @Override 19 | public void register() { 20 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 21 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 22 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 23 | } 24 | } 25 | 26 | @EventHandler 27 | public void onBlockBurn(final BlockBurnEvent event) { 28 | JSONObject jsonObject = new JSONObject(); 29 | jsonObject.put("event", eventName); 30 | jsonObject.put("block", event.getBlock().getType().name()); 31 | jsonObject.put("location", event.getBlock().getLocation().toString()); 32 | jsonObject.put("ignitingBlock", Objects.requireNonNull(event.getIgnitingBlock()).getType().name()); 33 | 34 | RegisterWebHooks.sendToAllUrls(jsonObject); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/block/BlockPlace.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.block; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.block.BlockPlaceEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class BlockPlace implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.BLOCK_PLACE.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onBlockPlace(final BlockPlaceEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("player", event.getPlayer().getName()); 29 | jsonObject.put("block", event.getBlock().getType().name()); 30 | jsonObject.put("location", event.getBlock().getLocation().toString()); 31 | jsonObject.put("placedAgainst", event.getBlockAgainst().getType().name()); 32 | jsonObject.put("hand", event.getHand().name()); 33 | 34 | RegisterWebHooks.sendToAllUrls(jsonObject); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/block/BlockRedstone.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.block; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.block.BlockRedstoneEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class BlockRedstone implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.BLOCK_REDSTONE.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onBlockRedstone(final BlockRedstoneEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("block", event.getBlock().getType().name()); 29 | jsonObject.put("location", event.getBlock().getLocation().toString()); 30 | jsonObject.put("oldCurrent", event.getOldCurrent()); 31 | jsonObject.put("newCurrent", event.getNewCurrent()); 32 | 33 | RegisterWebHooks.sendToAllUrls(jsonObject); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/block/NotePlay.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.block; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.block.NotePlayEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class NotePlay implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.NOTE_PLAY.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onNotePlay(final NotePlayEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("instrument", event.getInstrument().name()); 29 | jsonObject.put("tone", event.getNote().getTone().name()); 30 | jsonObject.put("octave", event.getNote().getOctave()); 31 | jsonObject.put("pitch", event.getNote().getPitch()); 32 | jsonObject.put("location", event.getBlock().getLocation().toString()); 33 | 34 | RegisterWebHooks.sendToAllUrls(jsonObject); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/block/SignChange.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.block; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.block.SignChangeEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class SignChange implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.SIGN_CHANGE.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onSignChange(final SignChangeEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("block", event.getBlock().getType().name()); 29 | jsonObject.put("location", event.getBlock().getLocation().toString()); 30 | jsonObject.put("line1", event.getLine(0)); 31 | jsonObject.put("line2", event.getLine(1)); 32 | jsonObject.put("line3", event.getLine(2)); 33 | jsonObject.put("line4", event.getLine(3)); 34 | jsonObject.put("player", event.getPlayer().getName()); 35 | jsonObject.put("side", event.getSide().name()); 36 | 37 | RegisterWebHooks.sendToAllUrls(jsonObject); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/enchantment/EnchantItem.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.enchantment; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.enchantment.EnchantItemEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class EnchantItem implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.ENCHANT_ITEM.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onEnchantItem(final EnchantItemEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("item", event.getItem().getType().name()); 29 | jsonObject.put("player", event.getEnchanter().getName()); 30 | jsonObject.put("enchantments", event.getEnchantsToAdd().toString()); 31 | jsonObject.put("location", event.getEnchantBlock().getLocation().toString()); 32 | jsonObject.put("expLevelCost", event.getExpLevelCost()); 33 | jsonObject.put("levelHint", event.getLevelHint()); 34 | 35 | RegisterWebHooks.sendToAllUrls(jsonObject); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/entity/CreatureSpawn.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.entity; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import org.bukkit.event.EventHandler; 7 | import org.bukkit.event.Listener; 8 | import org.bukkit.event.entity.CreatureSpawnEvent; 9 | import org.json.JSONObject; 10 | 11 | public final class CreatureSpawn implements WebHook, Listener { 12 | 13 | private final String eventName = "creature_spawn"; 14 | 15 | @Override 16 | public void register() { 17 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 18 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 19 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 20 | } 21 | } 22 | 23 | @EventHandler 24 | public void onCreatureSpawn(final CreatureSpawnEvent event) { 25 | JSONObject jsonObject = new JSONObject(); 26 | jsonObject.put("event", eventName); 27 | jsonObject.put("entity", event.getEntity().getType().name()); 28 | jsonObject.put("location", event.getEntity().getLocation().toString()); 29 | jsonObject.put("spawnReason", event.getSpawnReason().name()); 30 | 31 | RegisterWebHooks.sendToAllUrls(jsonObject); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/entity/CreeperPower.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.entity; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.entity.CreeperPowerEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class CreeperPower implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.CREEPER_POWER.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onCreeperPower(final CreeperPowerEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("entity", event.getEntity().getType().name()); 29 | jsonObject.put("location", event.getEntity().getLocation().toString()); 30 | jsonObject.put("cause", event.getCause().name()); 31 | 32 | if (event.getLightning().getCausingPlayer() != null) { 33 | jsonObject.put("power", event.getLightning().getCausingPlayer().getName()); 34 | } 35 | 36 | RegisterWebHooks.sendToAllUrls(jsonObject); 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/entity/EntityDeath.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.entity; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.entity.EntityDeathEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class EntityDeath implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.ENTITY_DEATH.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onEntityDeath(final EntityDeathEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("entity", event.getEntity().getType().name()); 29 | jsonObject.put("location", event.getEntity().getLocation().toString()); 30 | jsonObject.put("drops", event.getDrops().toString()); 31 | jsonObject.put("xp", event.getDroppedExp()); 32 | 33 | if (event.getEntity().getKiller() != null) { 34 | jsonObject.put("killedBy", event.getEntity().getKiller().getName()); 35 | } else { 36 | jsonObject.put("killedBy", "null"); 37 | } 38 | 39 | if (event.getEntity().getLastDamageCause() != null) { 40 | jsonObject.put("cause", event.getEntity().getLastDamageCause().getCause().name()); 41 | } 42 | 43 | RegisterWebHooks.sendToAllUrls(jsonObject); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/entity/EntityExplode.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.entity; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.entity.EntityExplodeEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class EntityExplode implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.ENTITY_EXPLODE.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onEntityExplode(final EntityExplodeEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("entity", event.getEntity().getType().name()); 29 | jsonObject.put("location", event.getEntity().getLocation().toString()); 30 | jsonObject.put("yields", event.getYield()); 31 | jsonObject.put("blockList", event.blockList().toString()); 32 | jsonObject.put("explosionResult", event.getExplosionResult().name()); 33 | 34 | RegisterWebHooks.sendToAllUrls(jsonObject); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/entity/EntityShootBow.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.entity; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import org.bukkit.event.EventHandler; 7 | import org.bukkit.event.Listener; 8 | import org.bukkit.event.entity.EntityShootBowEvent; 9 | import org.json.JSONObject; 10 | import com.shweit.serverapi.webhooks.WebHookEnum; 11 | 12 | public final class EntityShootBow implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.ENTITY_SHOOT_BOW.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onEntityShotBow(final EntityShootBowEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("entity", event.getEntity().getType().name()); 29 | jsonObject.put("location", event.getEntity().getLocation().toString()); 30 | jsonObject.put("projectile", event.getProjectile().getType().name()); 31 | jsonObject.put("force", event.getForce()); 32 | 33 | RegisterWebHooks.sendToAllUrls(jsonObject); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/entity/EntityTame.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.entity; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.entity.EntityTameEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class EntityTame implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.ENTITY_TAME.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onEntityTame(final EntityTameEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("entity", event.getEntity().getType().name()); 29 | jsonObject.put("location", event.getEntity().getLocation().toString()); 30 | jsonObject.put("owner", event.getOwner().getName()); 31 | 32 | RegisterWebHooks.sendToAllUrls(jsonObject); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/entity/ExplosionPrime.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.entity; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import org.bukkit.event.EventHandler; 7 | import org.bukkit.event.Listener; 8 | import org.bukkit.event.entity.EntityExplodeEvent; 9 | import org.json.JSONObject; 10 | import com.shweit.serverapi.webhooks.WebHookEnum; 11 | 12 | public final class ExplosionPrime implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.EXPLOSION_PRIME.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onExplosionPrime(final EntityExplodeEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("entity", event.getEntity().getType().name()); 29 | jsonObject.put("location", event.getEntity().getLocation().toString()); 30 | jsonObject.put("radius", event.getYield()); 31 | 32 | RegisterWebHooks.sendToAllUrls(jsonObject); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/entity/PlayerDeath.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.entity; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.entity.PlayerDeathEvent; 9 | import org.json.JSONObject; 10 | import org.bukkit.event.Listener; 11 | 12 | public final class PlayerDeath implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.PLAYER_DEATH.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onPlayerDeath(final PlayerDeathEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("player", event.getEntity().getName()); 29 | jsonObject.put("location", event.getEntity().getLocation().toString()); 30 | jsonObject.put("cause", event.getDeathMessage()); 31 | 32 | RegisterWebHooks.sendToAllUrls(jsonObject); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/inventory/Brew.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.inventory; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.inventory.BrewEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class Brew implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.BREW.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onBrew(final BrewEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("fuelLevel", event.getFuelLevel()); 29 | jsonObject.put("location", event.getBlock().getLocation().toString()); 30 | 31 | if (event.getContents().getIngredient() != null) { 32 | jsonObject.put("ingredient", event.getContents().getIngredient().getType().name()); 33 | } 34 | RegisterWebHooks.sendToAllUrls(jsonObject); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/inventory/CraftItem.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.inventory; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.inventory.CraftItemEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class CraftItem implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.CRAFT_ITEM.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onCraftItem(final CraftItemEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("item", event.getRecipe().getResult().getType().name()); 29 | jsonObject.put("location", event.getWhoClicked().getLocation().toString()); 30 | jsonObject.put("recipe", event.getRecipe().toString()); 31 | 32 | if (event.getInventory().getResult() != null) { 33 | jsonObject.put("result", event.getInventory().getResult().getType().name()); 34 | } 35 | 36 | RegisterWebHooks.sendToAllUrls(jsonObject); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/inventory/FurnaceBurn.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.inventory; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.inventory.FurnaceBurnEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class FurnaceBurn implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.FURNACE_BURN.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onFurnaceBurn(final FurnaceBurnEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("location", event.getBlock().getLocation().toString()); 29 | jsonObject.put("burnTime", event.getBurnTime()); 30 | jsonObject.put("fuel", event.getFuel().getType().name()); 31 | 32 | RegisterWebHooks.sendToAllUrls(jsonObject); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/inventory/FurnaceSmelt.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.inventory; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.inventory.FurnaceSmeltEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class FurnaceSmelt implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.FURNACE_SMELT.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onFurnaceSmelt(final FurnaceSmeltEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("location", event.getBlock().getLocation().toString()); 29 | jsonObject.put("result", event.getResult().getType().name()); 30 | jsonObject.put("source", event.getSource().getType().name()); 31 | 32 | RegisterWebHooks.sendToAllUrls(jsonObject); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/player/PlayerChat.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.player; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.player.AsyncPlayerChatEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class PlayerChat implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.PLAYER_CHAT.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onPlayerChat(final AsyncPlayerChatEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("player", event.getPlayer().getName()); 29 | jsonObject.put("message", event.getMessage()); 30 | jsonObject.put("location", event.getPlayer().getLocation().toString()); 31 | 32 | RegisterWebHooks.sendToAllUrls(jsonObject); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/player/PlayerCommand.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.player; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.player.PlayerCommandPreprocessEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class PlayerCommand implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.PLAYER_COMMAND.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onPlayerCommand(final PlayerCommandPreprocessEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("player", event.getPlayer().getName()); 29 | jsonObject.put("command", event.getMessage()); 30 | jsonObject.put("location", event.getPlayer().getLocation().toString()); 31 | 32 | if (event.getPlayer().getAddress() != null) { 33 | jsonObject.put("ip", event.getPlayer().getAddress().getAddress().getHostAddress()); 34 | } 35 | 36 | RegisterWebHooks.sendToAllUrls(jsonObject); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/player/PlayerGamemodeChange.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.player; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.player.PlayerGameModeChangeEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class PlayerGamemodeChange implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.PLAYER_GAMEMODE_CHANGE.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onPlayerGamemodeChange(final PlayerGameModeChangeEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("player", event.getPlayer().getName()); 29 | jsonObject.put("location", event.getPlayer().getLocation().toString()); 30 | jsonObject.put("gamemode", event.getNewGameMode().name()); 31 | 32 | RegisterWebHooks.sendToAllUrls(jsonObject); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/player/PlayerItemBreak.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.player; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.player.PlayerItemBreakEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class PlayerItemBreak implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.PLAYER_ITEM_BREAK.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onPlayerItemBreak(final PlayerItemBreakEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("player", event.getPlayer().getName()); 29 | jsonObject.put("location", event.getPlayer().getLocation().toString()); 30 | jsonObject.put("item", event.getBrokenItem().getType().name()); 31 | 32 | RegisterWebHooks.sendToAllUrls(jsonObject); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/player/PlayerKick.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.player; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.player.PlayerKickEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class PlayerKick implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.PLAYER_KICK.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onPlayerKick(final PlayerKickEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("player", event.getPlayer().getName()); 29 | jsonObject.put("location", event.getPlayer().getLocation().toString()); 30 | jsonObject.put("reason", event.getReason()); 31 | 32 | if (event.getPlayer().getAddress() != null) { 33 | jsonObject.put("ip", event.getPlayer().getAddress().getAddress().getHostAddress()); 34 | } 35 | 36 | RegisterWebHooks.sendToAllUrls(jsonObject); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/player/PlayerLogin.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.player; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.player.PlayerLoginEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class PlayerLogin implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.PLAYER_LOGIN.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onPlayerLogin(final PlayerLoginEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("player", event.getPlayer().getName()); 29 | jsonObject.put("location", event.getPlayer().getLocation().toString()); 30 | jsonObject.put("ip", event.getAddress().getHostAddress()); 31 | 32 | RegisterWebHooks.sendToAllUrls(jsonObject); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/player/PlayerQuit.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.player; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.player.PlayerQuitEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class PlayerQuit implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.PLAYER_QUIT.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onPlayerQuit(final PlayerQuitEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("player", event.getPlayer().getName()); 29 | jsonObject.put("location", event.getPlayer().getLocation().toString()); 30 | jsonObject.put("quitMessage", event.getQuitMessage()); 31 | 32 | RegisterWebHooks.sendToAllUrls(jsonObject); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/player/PlayerRespawn.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.player; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.player.PlayerRespawnEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class PlayerRespawn implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.PLAYER_RESPAWN.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onPlayerRespawn(final PlayerRespawnEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("player", event.getPlayer().getName()); 29 | jsonObject.put("location", event.getPlayer().getLocation().toString()); 30 | jsonObject.put("respawnLocation", event.getRespawnLocation().toString()); 31 | jsonObject.put("isBedSpawn", event.isBedSpawn()); 32 | jsonObject.put("isAnchorSpawn", event.isAnchorSpawn()); 33 | jsonObject.put("respawnReason", event.getRespawnReason().name()); 34 | 35 | RegisterWebHooks.sendToAllUrls(jsonObject); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/server/PluginDisable.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.server; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.server.PluginDisableEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class PluginDisable implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.PLUGIN_DISABLE.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onPluginDisable(final PluginDisableEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("plugin_name", event.getPlugin().getName()); 29 | jsonObject.put("plugin_version", event.getPlugin().getDescription().getVersion()); 30 | jsonObject.put("plugin_author", event.getPlugin().getDescription().getAuthors().get(0)); 31 | jsonObject.put("plugin_description", event.getPlugin().getDescription().getDescription()); 32 | 33 | RegisterWebHooks.sendToAllUrls(jsonObject); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/server/PluginEnable.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.server; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.server.PluginEnableEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class PluginEnable implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.PLUGIN_ENABLE.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onPluginEnable(final PluginEnableEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("plugin_name", event.getPlugin().getName()); 29 | jsonObject.put("plugin_version", event.getPlugin().getDescription().getVersion()); 30 | jsonObject.put("plugin_author", event.getPlugin().getDescription().getAuthors().get(0)); 31 | jsonObject.put("plugin_description", event.getPlugin().getDescription().getDescription()); 32 | 33 | RegisterWebHooks.sendToAllUrls(jsonObject); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/server/ServerStart.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.server; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.server.ServerLoadEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class ServerStart implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.SERVER_START.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onServerLoad(final ServerLoadEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | 29 | String message; 30 | if (event.getType() == ServerLoadEvent.LoadType.STARTUP) { 31 | message = "Server has started"; 32 | } else { 33 | message = "Server has reloaded"; 34 | } 35 | 36 | jsonObject.put("message", message); 37 | jsonObject.put("load_type", event.getType().name()); 38 | 39 | RegisterWebHooks.sendToAllUrls(jsonObject); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/server/ServerStop.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.server; 2 | 3 | import com.shweit.serverapi.webhooks.WebHook; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHookEnum; 6 | import org.json.JSONObject; 7 | 8 | public final class ServerStop implements WebHook { 9 | 10 | private final String eventName = WebHookEnum.SERVER_STOP.label; 11 | 12 | @Override 13 | public void register() { 14 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 15 | JSONObject jsonObject = new JSONObject(); 16 | jsonObject.put("event", eventName); 17 | jsonObject.put("message", "Server has stopped"); 18 | jsonObject.put("note", "This event is triggered when the plugin gets disabled, that means the server could still be runnig."); 19 | 20 | RegisterWebHooks.sendToAllUrls(jsonObject); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/weather/LightningStrike.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.weather; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.weather.LightningStrikeEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class LightningStrike implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.LIGHTNING_STRIKE.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onLightningStrike(final LightningStrikeEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("location", event.getLightning().getLocation().toString()); 29 | jsonObject.put("cause", event.getCause().name()); 30 | 31 | RegisterWebHooks.sendToAllUrls(jsonObject); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/weather/ThunderChange.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.weather; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.weather.ThunderChangeEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class ThunderChange implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.THUNDER_CHANGE.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onThunderChange(final ThunderChangeEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("world", event.getWorld().getName()); 29 | jsonObject.put("thunder", event.toThunderState()); 30 | 31 | RegisterWebHooks.sendToAllUrls(jsonObject); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/weather/WeatherChange.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.weather; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.weather.WeatherChangeEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class WeatherChange implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.WEATHER_CHANGE.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onWeatherChange(final WeatherChangeEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("world", event.getWorld().getName()); 29 | jsonObject.put("rain", event.toWeatherState()); 30 | 31 | RegisterWebHooks.sendToAllUrls(jsonObject); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/world/WorldLoad.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.world; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.world.WorldLoadEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class WorldLoad implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.WORLD_LOAD.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onWorldLoad(final WorldLoadEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("world", event.getWorld().getName()); 29 | 30 | RegisterWebHooks.sendToAllUrls(jsonObject); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/world/WorldSave.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.world; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.world.WorldSaveEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class WorldSave implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.WORLD_SAVE.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onWorldSave(final WorldSaveEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("world", event.getWorld().getName()); 29 | 30 | RegisterWebHooks.sendToAllUrls(jsonObject); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/shweit/serverapi/webhooks/world/WorldUnload.java: -------------------------------------------------------------------------------- 1 | package com.shweit.serverapi.webhooks.world; 2 | 3 | import com.shweit.serverapi.MinecraftServerAPI; 4 | import com.shweit.serverapi.webhooks.RegisterWebHooks; 5 | import com.shweit.serverapi.webhooks.WebHook; 6 | import com.shweit.serverapi.webhooks.WebHookEnum; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.world.WorldUnloadEvent; 10 | import org.json.JSONObject; 11 | 12 | public final class WorldUnload implements WebHook, Listener { 13 | 14 | private final String eventName = WebHookEnum.WORLD_UNLOAD.label; 15 | 16 | @Override 17 | public void register() { 18 | if (RegisterWebHooks.doActivateWebhook(eventName)) { 19 | MinecraftServerAPI plugin = MinecraftServerAPI.getInstance(); 20 | plugin.getServer().getPluginManager().registerEvents(this, plugin); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onWorldUnload(final WorldUnloadEvent event) { 26 | JSONObject jsonObject = new JSONObject(); 27 | jsonObject.put("event", eventName); 28 | jsonObject.put("world", event.getWorld().getName()); 29 | 30 | RegisterWebHooks.sendToAllUrls(jsonObject); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/maven/archetype.xml: -------------------------------------------------------------------------------- 1 | 2 | MinecraftServerAPI 3 | 4 | src/main/java/App.java 5 | 6 | 7 | src/test/java/AppTest.java 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/main/resources/archetype-resources/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | $org.example 5 | $MinecraftServerAPI 6 | $1.0-SNAPSHOT 7 | 8 | 9 | junit 10 | junit 11 | 3.8.1 12 | test 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main/resources/archetype-resources/src/main/java/App.java: -------------------------------------------------------------------------------- 1 | package $org.example; 2 | 3 | /** 4 | * Hello world! 5 | * 6 | */ 7 | public class App 8 | { 9 | public static void main( String[] args ) 10 | { 11 | System.out.println( "Hello World!" ); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/resources/archetype-resources/src/test/java/AppTest.java: -------------------------------------------------------------------------------- 1 | package $org.example; 2 | 3 | import junit.framework.Test; 4 | import junit.framework.TestCase; 5 | import junit.framework.TestSuite; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | extends TestCase 12 | { 13 | /** 14 | * Create the test case 15 | * 16 | * @param testName name of the test case 17 | */ 18 | public AppTest( String testName ) 19 | { 20 | super( testName ); 21 | } 22 | 23 | /** 24 | * @return the suite of tests being tested 25 | */ 26 | public static Test suite() 27 | { 28 | return new TestSuite( AppTest.class ); 29 | } 30 | 31 | /** 32 | * Rigourous Test :-) 33 | */ 34 | public void testApp() 35 | { 36 | assertTrue( true ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/resources/config.yml: -------------------------------------------------------------------------------- 1 | # This is the configuration file for the MinecraftServerAPI-Plugin. 2 | 3 | # The port the API should listen on. 4 | port: 7000 5 | 6 | # Enable swagger documentation for the API endpoints 7 | swagger: true 8 | 9 | # If you want to enable Authentication, set this to true. 10 | # It is not recommended to disable this. If you do, everyone can access the API. 11 | authentication: 12 | enabled: true 13 | key: "CHANGE_ME" 14 | 15 | # If you want to enable the debug mode, set this to true. 16 | # This will print more information to the console. 17 | debug: false 18 | 19 | # Here you can turn on/off the different Webhooks. 20 | # If you want to disable a Webhook, set it to false. 21 | webhooks: 22 | 23 | # You can set a list of URLs which should be called when the Webhook is triggered. 24 | # You can set multiple URLs here. 25 | urls: 26 | - "https://example.com/webhook1" 27 | - "https://example.com/webhook2" 28 | 29 | # Here is a list of all available Webhooks. 30 | # You can enable or disable them here. 31 | # Or via the command /webhooks 32 | server_start: true 33 | server_stop: true 34 | plugin_disable: true 35 | plugin_enable: true 36 | block_break: false # This is disabled by default, because it can spam your Webhook-URLs. 37 | block_place: false # This is disabled by default, because it can spam your Webhook-URLs. 38 | block_burn: false # This is disabled by default, because it can spam your Webhook-URLs. 39 | block_redstone: false # This is disabled by default, because it can spam your Webhook-URLs. 40 | note_play: true 41 | sign_change: true 42 | enchant_item: true 43 | creeper_power: true 44 | creature_spawn: false # This is disabled by default, because it can spam your Webhook-URLs. 45 | entity_death: false # This is disabled by default, because it can spam your Webhook-URLs. 46 | entity_explode: true 47 | entity_shoot_bow: true 48 | entity_tame: true 49 | explosion_prime: true 50 | player_death: true 51 | brew: true 52 | craft_item: false # This is disabled by default, because it can spam your Webhook-URLs. 53 | furnace_burn: true # This is disabled by default, because it can spam your Webhook-URLs. 54 | furnace_smelt: true # This is disabled by default, because it can spam your Webhook-URLs. 55 | player_chat: false # This is disabled by default, because it delays the delivery of the message to the server. 56 | player_login: true 57 | player_command: false # This is disabled by default, because it delays the delivery of the command to the server. 58 | player_gamemode_change: true 59 | player_item_break: true 60 | player_join: true 61 | player_kick: true 62 | player_quit: true 63 | player_respawn: true 64 | lightning_strike: true 65 | weather_change: true 66 | thunder_change: true 67 | world_load: true 68 | world_save: true 69 | world_unload: true 70 | 71 | # Here you can list an extra set of Files or Directories which should be saved by the Backup-System. 72 | # Following directories and files are already saved by default: ["world", "world_nether", "world_the_end", "plugins", "config", "server.properties", "banned-ips.json", "banned-players.json", "ops.json", "whitelist.json"] 73 | # e.g.: ["plugins/MyPlugin/config.yml", "plugins/MyPlugin/data/"] 74 | backup_files: [] -------------------------------------------------------------------------------- /src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: MinecraftServerAPI 2 | version: 1.21.x 3 | description: Provides RESTful APIs and WebHooks for managing and automating your Minecraft server. 4 | website: https://github.com/Shweit/MinecraftServerAPI 5 | author: Shweit 6 | contributors: 7 | - Shweit 8 | - Flix-29 9 | api-version: 1.20 10 | softdepend: 11 | - Maintenance 12 | 13 | main: com.shweit.serverapi.MinecraftServerAPI 14 | 15 | commands: 16 | webhooks: 17 | description: Command to manage the Webhooks. 18 | usage: /webhooks [args] 19 | permission: mcapi.webhooks 20 | aliases: 21 | - wh 22 | 23 | mcapi: 24 | description: Main command for the MinecraftServerAPI. 25 | usage: /mcapi [args] 26 | permission: mcapi 27 | -------------------------------------------------------------------------------- /src/main/resources/swagger/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shweit/MinecraftServerAPI/d36ba797787e303adf44196cb264617eb970787c/src/main/resources/swagger/favicon-16x16.png -------------------------------------------------------------------------------- /src/main/resources/swagger/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shweit/MinecraftServerAPI/d36ba797787e303adf44196cb264617eb970787c/src/main/resources/swagger/favicon-32x32.png -------------------------------------------------------------------------------- /src/main/resources/swagger/index.css: -------------------------------------------------------------------------------- 1 | html { 2 | box-sizing: border-box; 3 | overflow-y: scroll; 4 | } 5 | 6 | *, 7 | *:before, 8 | *:after { 9 | box-sizing: inherit; 10 | } 11 | 12 | body { 13 | margin: 0 !important; 14 | background: #fafafa; 15 | } 16 | 17 | .download-url-wrapper { 18 | display: none !important; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/resources/swagger/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Swagger UI 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/main/resources/swagger/oauth2-redirect.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Swagger UI: OAuth2 Redirect 5 | 6 | 7 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /src/main/resources/swagger/swagger-initializer.js: -------------------------------------------------------------------------------- 1 | // Custom Plugin to add a search bar and filter endpoints with additional options and improved styling 2 | const SearchPlugin = () => { 3 | return { 4 | // Inserting the search bar after initialising Swagger-UI 5 | afterLoad: function(system) { 6 | // Wait for the DOM to load and then add the search field 7 | const observer = new MutationObserver(() => { 8 | const container = document.querySelector("#swagger-ui > section > div.swagger-ui > div:nth-child(2) > div:nth-child(4)"); 9 | 10 | if (container && !document.getElementById('endpoint-search')) { 11 | // Creating the search field and filter options 12 | const searchBar = document.createElement("div"); 13 | searchBar.id = "search-container"; 14 | searchBar.style.display = "flex"; // Use flexbox for better alignment 15 | searchBar.style.alignItems = "center"; // Center align items vertically 16 | searchBar.style.marginBottom = "20px"; 17 | 18 | const searchInput = document.createElement("input"); 19 | searchInput.type = "text"; 20 | searchInput.id = "endpoint-search"; 21 | searchInput.placeholder = "Search Endpoints..."; 22 | searchInput.style.flex = "1"; 23 | searchInput.style.padding = "8px"; 24 | searchInput.onkeydown = filterEndpoints; 25 | searchInput.onkeyup = filterEndpoints; 26 | 27 | // Create case sensitivity toggle (button) 28 | const caseSensitiveButton = document.createElement("button"); 29 | caseSensitiveButton.id = "case-sensitive"; 30 | caseSensitiveButton.style.marginLeft = "10px"; 31 | caseSensitiveButton.style.padding = "8px"; 32 | caseSensitiveButton.style.border = "1px solid #ccc"; 33 | caseSensitiveButton.style.backgroundColor = "#f5f5f5"; 34 | caseSensitiveButton.style.cursor = "pointer"; 35 | caseSensitiveButton.innerHTML = ""; // Icon for case sensitivity 36 | caseSensitiveButton.title = "Toggle case sensitivity"; // Tooltip text 37 | caseSensitiveButton.onclick = toggleCaseSensitive; 38 | 39 | // Create description search toggle (button) 40 | const searchByDescriptionButton = document.createElement("button"); 41 | searchByDescriptionButton.id = "search-description"; 42 | searchByDescriptionButton.style.marginLeft = "10px"; 43 | searchByDescriptionButton.style.padding = "8px"; 44 | searchByDescriptionButton.style.border = "1px solid #ccc"; 45 | searchByDescriptionButton.style.backgroundColor = "#f5f5f5"; 46 | searchByDescriptionButton.style.cursor = "pointer"; 47 | searchByDescriptionButton.innerHTML = ""; // Icon for searching in descriptions 48 | searchByDescriptionButton.title = "Toggle search in descriptions"; // Tooltip text 49 | searchByDescriptionButton.onclick = toggleSearchDescription; 50 | 51 | searchBar.appendChild(searchInput); 52 | searchBar.appendChild(caseSensitiveButton); 53 | searchBar.appendChild(searchByDescriptionButton); 54 | 55 | // Inserting the search field into the DOM 56 | container.prepend(searchBar); 57 | 58 | // Stops the observer when the search field has been successfully added 59 | observer.disconnect(); 60 | } 61 | }); 62 | 63 | // Start the observer to track changes in the DOM 64 | observer.observe(document.body, { childList: true, subtree: true }); 65 | } 66 | }; 67 | }; 68 | 69 | // Toggle case sensitivity 70 | function toggleCaseSensitive() { 71 | const caseSensitiveButton = document.getElementById('case-sensitive'); 72 | caseSensitiveButton.classList.toggle('active'); 73 | caseSensitiveButton.style.backgroundColor = caseSensitiveButton.classList.contains('active') ? '#007bff' : '#f5f5f5'; 74 | caseSensitiveButton.style.color = caseSensitiveButton.classList.contains('active') ? '#fff' : '#000'; 75 | filterEndpoints(); 76 | } 77 | 78 | // Toggle search in descriptions 79 | function toggleSearchDescription() { 80 | const searchByDescriptionButton = document.getElementById('search-description'); 81 | searchByDescriptionButton.classList.toggle('active'); 82 | searchByDescriptionButton.style.backgroundColor = searchByDescriptionButton.classList.contains('active') ? '#007bff' : '#f5f5f5'; 83 | searchByDescriptionButton.style.color = searchByDescriptionButton.classList.contains('active') ? '#fff' : '#000'; 84 | filterEndpoints(); 85 | } 86 | 87 | // Function to filter the endpoints based on the search query and selected options 88 | function filterEndpoints() { 89 | const input = document.getElementById('endpoint-search').value; 90 | const caseSensitive = document.getElementById('case-sensitive').classList.contains('active'); 91 | const searchInDescription = document.getElementById('search-description').classList.contains('active'); 92 | 93 | const operations = document.querySelectorAll('.opblock'); 94 | 95 | operations.forEach((operation) => { 96 | const summary = operation.querySelector('.opblock-summary-description'); 97 | const endpoint = operation.querySelector('.opblock-summary-path a'); 98 | let textToSearch = endpoint.textContent; 99 | 100 | if (searchInDescription) { 101 | textToSearch += " " + summary.textContent; 102 | } 103 | 104 | if (!caseSensitive) { 105 | textToSearch = textToSearch.toLowerCase(); 106 | } 107 | 108 | const searchValue = caseSensitive ? input : input.toLowerCase(); 109 | 110 | if (textToSearch.includes(searchValue)) { 111 | operation.style.display = ''; 112 | } else { 113 | operation.style.display = 'none'; 114 | } 115 | }); 116 | } 117 | 118 | const EndpointInformationPlugin = (endpointElementId, htmlText) => { 119 | return { 120 | afterLoad: function(system) { 121 | const observer = new MutationObserver(() => { 122 | const container = document.getElementById(endpointElementId); 123 | 124 | if (container && !document.getElementById('maintenance-info')) { 125 | // Create a maintenance information div 126 | const maintenanceInfo = document.createElement("div"); 127 | maintenanceInfo.id = "maintenance-info"; 128 | maintenanceInfo.style.fontSize = "12px"; 129 | maintenanceInfo.style.color = "#555"; 130 | maintenanceInfo.style.textAlign = "left"; 131 | maintenanceInfo.style.marginTop = "8px"; // Add margin to position it below the header 132 | maintenanceInfo.style.width = "100%"; // Ensure it takes full width 133 | 134 | const infoText = document.createElement("p"); 135 | infoText.style.margin = "0"; 136 | infoText.innerHTML = htmlText; 137 | 138 | maintenanceInfo.appendChild(infoText); 139 | 140 | // Insert the maintenance information right after the first child of the header 141 | const headerTitle = container.querySelector('span'); 142 | headerTitle.parentNode.insertBefore(maintenanceInfo, headerTitle.nextSibling); 143 | 144 | observer.disconnect(); 145 | } 146 | }); 147 | 148 | observer.observe(document.body, { childList: true, subtree: true }); 149 | } 150 | }; 151 | } 152 | 153 | window.onload = function() { 154 | window.ui = SwaggerUIBundle({ 155 | url: "/api-docs", 156 | dom_id: '#swagger-ui', 157 | deepLinking: true, 158 | presets: [ 159 | SwaggerUIBundle.presets.apis, 160 | SwaggerUIStandalonePreset 161 | ], 162 | plugins: [ 163 | SwaggerUIBundle.plugins.DownloadUrl, 164 | SearchPlugin, 165 | EndpointInformationPlugin("operations-tag-Maintenance", "These API Endpoints depend on the Maintenance plugin. If you don't have the plugin installed, you won't be able to access these endpoints. You can install it here.") 166 | ], 167 | layout: "StandaloneLayout", 168 | }); 169 | }; 170 | -------------------------------------------------------------------------------- /src/test/java/ApiTestHelper.java: -------------------------------------------------------------------------------- 1 | import org.json.JSONObject; 2 | import org.junit.jupiter.api.AfterAll; 3 | import org.junit.jupiter.api.BeforeAll; 4 | import org.junit.jupiter.api.TestInstance; 5 | import org.testcontainers.containers.DockerComposeContainer; 6 | 7 | import java.io.File; 8 | import java.io.IOException; 9 | import java.net.HttpURLConnection; 10 | import java.net.URL; 11 | import java.util.Scanner; 12 | import java.util.logging.Logger; 13 | 14 | import org.apache.commons.io.FileUtils; 15 | 16 | @TestInstance(TestInstance.Lifecycle.PER_CLASS) 17 | public abstract class ApiTestHelper { 18 | 19 | protected static final DockerComposeContainer compose = SharedDockerComposeContainer.getInstance(); 20 | public static final String BASE_URL = "http://localhost:7001"; 21 | 22 | public static String getBaseUrl() { 23 | return BASE_URL; 24 | } 25 | 26 | @BeforeAll 27 | public void setUp() { 28 | buildPluginWithMaven(); 29 | copyPluginToDockerContainer(); 30 | reloadMinecraftServer(); 31 | } 32 | 33 | @AfterAll 34 | public void tearDown() { 35 | // Reset the Minecraft server to its original state 36 | try { 37 | File pluginFile = new File("src/test/resources/server-data/server.properties"); 38 | File destDir_1 = new File("src/test/resources/minecraft-test-server/"); 39 | FileUtils.copyFileToDirectory(pluginFile, destDir_1); 40 | 41 | File whitelistFile = new File("src/test/resources/server-data/whitelist.json"); 42 | File destDir_2 = new File("src/test/resources/minecraft-test-server/"); 43 | FileUtils.copyFileToDirectory(whitelistFile, destDir_2); 44 | 45 | } catch (IOException e) { 46 | throw new RuntimeException("Failed to copy server properties to Docker container directory", e); 47 | } 48 | 49 | try { 50 | org.testcontainers.containers.Container.ExecResult result = compose.getContainerByServiceName("mc_1").get().execInContainer("whitelist", "on"); 51 | } catch (Exception e) { 52 | throw new RuntimeException("Failed to execute Docker command to enable Whitelist", e); 53 | } 54 | } 55 | 56 | private static void buildPluginWithMaven() { 57 | try { 58 | ProcessBuilder processBuilder = new ProcessBuilder("mvn", "clean", "package", "-DskipTests"); 59 | processBuilder.directory(new File(".")); 60 | processBuilder.inheritIO(); 61 | Process process = processBuilder.start(); 62 | int exitCode = process.waitFor(); 63 | if (exitCode != 0) { 64 | throw new RuntimeException("Maven build failed"); 65 | } 66 | } catch (Exception e) { 67 | throw new RuntimeException("Failed to build plugin with Maven", e); 68 | } 69 | } 70 | 71 | private static void copyPluginToDockerContainer() { 72 | try { 73 | // Plugin file 74 | File pluginFile = new File("target/MinecraftServerAPI-1.0.jar"); 75 | File destDir_1 = new File("src/test/resources/minecraft-test-server/plugins"); 76 | FileUtils.copyFileToDirectory(pluginFile, destDir_1); 77 | 78 | // Config file 79 | File configFile = new File("src/test/resources/server-data/config.yml"); 80 | File destDir_2 = new File("src/test/resources/minecraft-test-server/plugins/MinecraftServerAPI"); 81 | FileUtils.copyFileToDirectory(configFile, destDir_2); 82 | 83 | // Citizens plugin 84 | File citizensFile = new File("src/test/resources/server-data/plugins/Citizens-2.0.35-b3535.jar"); 85 | File destDir_3 = new File("src/test/resources/minecraft-test-server/plugins"); 86 | FileUtils.copyFileToDirectory(citizensFile, destDir_3); 87 | 88 | // Maintenance plugin 89 | File maintenanceFile = new File("src/test/resources/server-data/plugins/Maintenance-4.2.1.jar"); 90 | File destDir_4 = new File("src/test/resources/minecraft-test-server/plugins"); 91 | FileUtils.copyFileToDirectory(maintenanceFile, destDir_4); 92 | 93 | // server.properties file 94 | File serverPropertiesFile = new File("src/test/resources/server-data/server.properties"); 95 | File destDir_5 = new File("src/test/resources/minecraft-test-server/"); 96 | FileUtils.copyFileToDirectory(serverPropertiesFile, destDir_5); 97 | 98 | //whitelist.json file 99 | File whitelistFile = new File("src/test/resources/server-data/whitelist.json"); 100 | File destDir_6 = new File("src/test/resources/minecraft-test-server/"); 101 | FileUtils.copyFileToDirectory(whitelistFile, destDir_6); 102 | } catch (IOException e) { 103 | throw new RuntimeException("Failed to copy plugin to Docker container directory", e); 104 | } 105 | 106 | try { 107 | org.testcontainers.containers.Container.ExecResult result = compose.getContainerByServiceName("mc_1").get().execInContainer("whitelist", "on"); 108 | } catch (Exception e) { 109 | throw new RuntimeException("Failed to execute Docker command to enable Whitelist", e); 110 | } 111 | } 112 | 113 | private static void reloadMinecraftServer() { 114 | try { 115 | org.testcontainers.containers.Container.ExecResult result = compose.getContainerByServiceName("mc_1").get().execInContainer("rcon-cli", "reload confirm"); 116 | int exitCode = result.getExitCode(); 117 | if (exitCode != 0) { 118 | throw new RuntimeException("Failed to reload Minecraft server using Docker exec"); 119 | } 120 | } catch (Exception e) { 121 | throw new RuntimeException("Failed to execute Docker command to reload Minecraft server", e); 122 | } 123 | 124 | // Wait for the Minecraft Server to reload 125 | try { 126 | boolean isReady = false; 127 | int attempts = 0; 128 | 129 | Logger logger = Logger.getLogger("org.testcontainers"); 130 | 131 | while (!isReady && attempts < 30) { // max 30 attempts * 1 second = 30 seconds 132 | Thread.sleep(1000); 133 | try { 134 | URL url = new URL(getBaseUrl() + "/v1/ping"); 135 | HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 136 | conn.setRequestMethod("GET"); 137 | conn.setRequestProperty("Authorization", "TestKey"); 138 | conn.setRequestProperty("accept", "*/*"); 139 | conn.connect(); 140 | 141 | int responseCode = conn.getResponseCode(); 142 | if (responseCode == 200) { 143 | isReady = true; 144 | } 145 | 146 | conn.disconnect(); // Verbindung schließen 147 | 148 | } catch (Exception e) { 149 | logger.warning("Exception during server check: " + e.getMessage()); 150 | // Continue to retry while the server is still starting 151 | } 152 | 153 | attempts++; 154 | } 155 | 156 | if (!isReady) { 157 | throw new RuntimeException("Minecraft server did not reload successfully"); 158 | } 159 | } catch (InterruptedException e) { 160 | Thread.currentThread().interrupt(); 161 | throw new RuntimeException("Interrupted while waiting for Minecraft server to reload", e); 162 | } 163 | } 164 | 165 | public static HttpURLConnection sendRequest(String endpoint, String method) throws IOException { 166 | URL url = new URL(getBaseUrl() + endpoint); 167 | HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 168 | conn.setRequestMethod(method); 169 | conn.setRequestProperty("Authorization", "TestKey"); 170 | return conn; 171 | } 172 | 173 | public static String readResponse(HttpURLConnection conn) throws IOException { 174 | try (Scanner scanner = new Scanner(conn.getInputStream())) { 175 | scanner.useDelimiter("\\A"); 176 | return scanner.hasNext() ? scanner.next() : ""; 177 | } 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /src/test/java/PlayerAPITest.java: -------------------------------------------------------------------------------- 1 | import org.json.JSONObject; 2 | import org.junit.Ignore; 3 | import org.junit.jupiter.api.Disabled; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import java.io.IOException; 7 | import java.net.HttpURLConnection; 8 | import java.net.URL; 9 | 10 | import static org.junit.jupiter.api.Assertions.*; 11 | 12 | public class PlayerAPITest extends ApiTestHelper { 13 | 14 | @Test 15 | public void testPlayersEndpoint() throws IOException { 16 | HttpURLConnection conn = sendRequest("/v1/players", "GET"); 17 | String response = ApiTestHelper.readResponse(conn); 18 | 19 | assertEquals(200, conn.getResponseCode()); 20 | assertNotNull(response); 21 | 22 | JSONObject jsonResponse = new JSONObject(response); 23 | 24 | assertTrue(jsonResponse.has("onlinePlayers")); 25 | assertEquals(0, jsonResponse.getJSONArray("onlinePlayers").length()); 26 | } 27 | 28 | @Test 29 | @Disabled 30 | public void testPlayerEndpoint() throws IOException { 31 | HttpURLConnection conn = sendRequest("/v1/player/Shweit", "GET"); 32 | assertEquals(404, conn.getResponseCode()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/ServerAPITest.java: -------------------------------------------------------------------------------- 1 | import io.swagger.v3.core.util.Json; 2 | import org.json.JSONObject; 3 | import org.junit.jupiter.api.DisplayName; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import java.io.IOException; 7 | import java.net.HttpURLConnection; 8 | 9 | import static org.junit.jupiter.api.Assertions.assertEquals; 10 | import static org.junit.jupiter.api.Assertions.assertTrue; 11 | 12 | public class ServerAPITest extends ApiTestHelper { 13 | @Test 14 | @DisplayName("Test the GET /v1/ping endpoint") 15 | public void testPingEndpoint() throws IOException { 16 | HttpURLConnection conn = sendRequest("/v1/ping", "GET"); 17 | assertEquals(200, conn.getResponseCode()); 18 | 19 | String response = ApiTestHelper.readResponse(conn); 20 | assertEquals("pong", response); 21 | } 22 | 23 | @Test 24 | @DisplayName("Test the GET /v1/server endpoint") 25 | public void testServerEndpoint() throws IOException { 26 | HttpURLConnection conn = sendRequest("/v1/server", "GET"); 27 | assertEquals(200, conn.getResponseCode()); 28 | 29 | String response = ApiTestHelper.readResponse(conn); 30 | JSONObject jsonResponse = new JSONObject(response); 31 | 32 | assertEquals("A Minecraft Server", jsonResponse.getString("motd")); 33 | assertEquals("minecraft:normal", jsonResponse.getString("worldType")); 34 | assertEquals(20, jsonResponse.getInt("maxPlayers")); 35 | assertEquals("SURVIVAL", jsonResponse.getString("defaultGameMode")); 36 | } 37 | 38 | @Test 39 | @DisplayName("Test the GET /v1/server/health endpoint") 40 | public void testServerHealthEndpoint() throws IOException { 41 | HttpURLConnection conn = sendRequest("/v1/server/health", "GET"); 42 | assertEquals(200, conn.getResponseCode()); 43 | 44 | String response = ApiTestHelper.readResponse(conn); 45 | JSONObject jsonResponse = new JSONObject(response); 46 | 47 | assertTrue(jsonResponse.has("usedMemory")); 48 | assertTrue(jsonResponse.has("availableProcessors")); 49 | assertTrue(jsonResponse.has("threadCount")); 50 | assertTrue(jsonResponse.has("uptime")); 51 | assertTrue(jsonResponse.has("tps")); 52 | } 53 | 54 | @Test 55 | @DisplayName("Test the GET /v1/server/tps endpoint") 56 | public void testServerTPSEndpoint() throws IOException { 57 | HttpURLConnection conn = sendRequest("/v1/server/tps", "GET"); 58 | assertEquals(200, conn.getResponseCode()); 59 | 60 | String response = ApiTestHelper.readResponse(conn); 61 | JSONObject jsonResponse = new JSONObject(response); 62 | 63 | assertTrue(jsonResponse.has("tps")); 64 | } 65 | 66 | @Test 67 | @DisplayName("Test the GET /v1/server/uptime endpoint") 68 | public void testServerUptimeEndpoint() throws IOException { 69 | HttpURLConnection conn = sendRequest("/v1/server/uptime", "GET"); 70 | assertEquals(200, conn.getResponseCode()); 71 | 72 | String response = ApiTestHelper.readResponse(conn); 73 | JSONObject jsonResponse = new JSONObject(response); 74 | 75 | assertTrue(jsonResponse.has("uptime")); 76 | } 77 | 78 | @Test 79 | @DisplayName("Test the GET /v1/server/properties endpoint") 80 | public void testServerPropertiesEndpoint() throws IOException { 81 | HttpURLConnection conn = sendRequest("/v1/server/properties", "GET"); 82 | assertEquals(200, conn.getResponseCode()); 83 | 84 | String response = ApiTestHelper.readResponse(conn); 85 | JSONObject jsonResponse = new JSONObject(response); 86 | 87 | assertEquals("survival", jsonResponse.getString("gamemode")); 88 | assertEquals("A Minecraft Server", jsonResponse.getString("motd")); 89 | assertEquals("25565", jsonResponse.getString("server-port")); 90 | } 91 | 92 | @Test 93 | @DisplayName("Test the POST /v1/server/properties endpoint") 94 | public void testUpdateServerPropertiesEndpoint() throws IOException { 95 | HttpURLConnection conn = sendRequest("/v1/server/properties?key=motd&value=Test", "POST"); 96 | assertEquals(200, conn.getResponseCode()); 97 | 98 | String response = ApiTestHelper.readResponse(conn); 99 | JSONObject jsonResponse = new JSONObject(response); 100 | 101 | assertEquals("Property updated successfully.", jsonResponse.getString("message")); 102 | 103 | // Check if the property was updated 104 | conn = sendRequest("/v1/server/properties", "GET"); 105 | assertEquals(200, conn.getResponseCode()); 106 | 107 | response = ApiTestHelper.readResponse(conn); 108 | jsonResponse = new JSONObject(response); 109 | 110 | assertEquals("Test", jsonResponse.getString("motd")); 111 | } 112 | 113 | @Test 114 | @DisplayName("Test the POST /v1/server/exec endpoint") 115 | public void testServerExecEndpoint() throws IOException { 116 | HttpURLConnection conn = sendRequest("/v1/server/exec?command=help", "POST"); 117 | assertEquals(200, conn.getResponseCode()); 118 | 119 | String response = ApiTestHelper.readResponse(conn); 120 | JSONObject jsonResponse = new JSONObject(response); 121 | 122 | assertTrue(jsonResponse.getBoolean("success")); 123 | } 124 | 125 | @Test 126 | @DisplayName("Test the POST /v1/server/reload endpoint") 127 | public void testServerReloadEndpoint() throws IOException { 128 | HttpURLConnection conn = sendRequest("/v1/server/reload", "POST"); 129 | assertEquals(200, conn.getResponseCode()); 130 | } 131 | 132 | @Test 133 | @DisplayName("Test the POST /v1/server/broadcast endpoint") 134 | public void testServerBroadcastEndpoint() throws IOException { 135 | HttpURLConnection conn = sendRequest("/v1/server/broadcast?message=Test", "POST"); 136 | assertEquals(200, conn.getResponseCode()); 137 | } 138 | 139 | @Test 140 | @DisplayName("Test the GET /v1/server/chat endpoint") 141 | public void testServerChatEndpoint() throws IOException { 142 | HttpURLConnection conn = sendRequest("/v1/server/chat", "GET"); 143 | assertEquals(200, conn.getResponseCode()); 144 | } 145 | 146 | @Test 147 | @DisplayName("Test the GET /v1/server/log endpoint") 148 | public void testServerLogEndpoint() throws IOException { 149 | HttpURLConnection conn = sendRequest("/v1/server/log", "GET"); 150 | assertEquals(200, conn.getResponseCode()); 151 | 152 | String response = ApiTestHelper.readResponse(conn); 153 | JSONObject jsonResponse = new JSONObject(response); 154 | 155 | assertTrue(jsonResponse.has("log")); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/test/java/SharedDockerComposeContainer.java: -------------------------------------------------------------------------------- 1 | import org.testcontainers.containers.DockerComposeContainer; 2 | 3 | import java.io.File; 4 | 5 | public class SharedDockerComposeContainer { 6 | 7 | private static DockerComposeContainer instance; 8 | 9 | private SharedDockerComposeContainer() { 10 | // Private constructor to prevent instantiation 11 | } 12 | 13 | public static DockerComposeContainer getInstance() { 14 | if (instance == null) { 15 | instance = new DockerComposeContainer<>(new File("src/test/resources/docker-compose.yml")) 16 | .withExposedService("mc_1", 25565) 17 | .withExposedService("mc_1", 7001); 18 | instance.start(); 19 | } 20 | return instance; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/WhitelistAPITest.java: -------------------------------------------------------------------------------- 1 | import org.junit.Ignore; 2 | import org.junit.jupiter.api.*; 3 | 4 | import java.io.IOException; 5 | import java.net.HttpURLConnection; 6 | 7 | public class WhitelistAPITest extends ApiTestHelper { 8 | 9 | @Test 10 | @DisplayName("Test the GET /v1/whitelist endpoint") 11 | @Disabled 12 | public void testWhitelistEndpoint() throws IOException { 13 | HttpURLConnection conn = sendRequest("/v1/whitelist", "GET"); 14 | Assertions.assertEquals(200, conn.getResponseCode()); 15 | } 16 | 17 | @Test 18 | @DisplayName("Test the POST /v1/whitelist endpoint") 19 | public void testWhitelistAddEndpoint() throws IOException { 20 | HttpURLConnection conn = sendRequest("/v1/whitelist?username=Shweit", "POST"); 21 | Assertions.assertEquals(200, conn.getResponseCode()); 22 | } 23 | 24 | @Test 25 | @DisplayName("Test the DELETE /v1/whitelist endpoint") 26 | public void testWhitelistRemoveEndpoint() throws IOException { 27 | HttpURLConnection conn = sendRequest("/v1/whitelist?username=Shweit", "DELETE"); 28 | Assertions.assertEquals(200, conn.getResponseCode()); 29 | } 30 | 31 | @Test 32 | @DisplayName("Test the POST /v1/whitelist/deactivate endpoint") 33 | public void testDeactivateWhitelist() throws IOException { 34 | HttpURLConnection conn = sendRequest("/v1/whitelist/deactivate", "POST"); 35 | Assertions.assertEquals(200, conn.getResponseCode()); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/test/resources/config.yml: -------------------------------------------------------------------------------- 1 | # This is the configuration file for the MinecraftServerAPI-Plugin. 2 | 3 | # The port the API should listen on. 4 | port: 7001 5 | 6 | # If you want to enable Authentication, set this to true. 7 | # It is not recommended to disable this. If you do, everyone can access the API. 8 | authentication: 9 | enabled: true 10 | key: "TestKey" 11 | 12 | # If you want to enable the debug mode, set this to true. 13 | # This will print more information to the console. 14 | debug: true 15 | 16 | # Here you can turn on/off the different Webhooks. 17 | # If you want to disable a Webhook, set it to false. 18 | webhooks: 19 | player_location: true 20 | player_join: true 21 | player_leave: true 22 | player_death: true 23 | server_start: true 24 | server_stop: true 25 | server_chat: true 26 | 27 | # Here you can list an extra set of Files or Directories which should be saved by the Backup-System. 28 | # Following directories and files are already saved by default: ["world", "world_nether", "world_the_end", "plugins", "config.yml", "server.properties"] 29 | # e.g.: ["plugins/MyPlugin/config.yml", "plugins/MyPlugin/data/"] 30 | backup_files: [] -------------------------------------------------------------------------------- /src/test/resources/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | 3 | services: 4 | mc: 5 | image: itzg/minecraft-server 6 | tty: true 7 | stdin_open: true 8 | ports: 9 | - "25565:25565" 10 | - "7001:7001" 11 | environment: 12 | EULA: "TRUE" 13 | VERSION: "1.21" 14 | TYPE: "PAPER" 15 | volumes: 16 | - ./minecraft-test-server:/data 17 | -------------------------------------------------------------------------------- /src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/test/resources/server-data/config.yml: -------------------------------------------------------------------------------- 1 | # This is the configuration file for the MinecraftServerAPI-Plugin. 2 | 3 | # The port the API should listen on. 4 | port: 7001 5 | 6 | # If you want to enable Authentication, set this to true. 7 | # It is not recommended to disable this. If you do, everyone can access the API. 8 | authentication: 9 | enabled: true 10 | key: "TestKey" 11 | 12 | # If you want to enable the debug mode, set this to true. 13 | # This will print more information to the console. 14 | debug: true 15 | 16 | # Here you can turn on/off the different Webhooks. 17 | # If you want to disable a Webhook, set it to false. 18 | webhooks: 19 | player_location: true 20 | player_join: true 21 | player_leave: true 22 | player_death: true 23 | server_start: true 24 | server_stop: true 25 | server_chat: true 26 | 27 | # Here you can list an extra set of Files or Directories which should be saved by the Backup-System. 28 | # Following directories and files are already saved by default: ["world", "world_nether", "world_the_end", "plugins", "config.yml", "server.properties"] 29 | # e.g.: ["plugins/MyPlugin/config.yml", "plugins/MyPlugin/data/"] 30 | backup_files: [] -------------------------------------------------------------------------------- /src/test/resources/server-data/plugins/Citizens-2.0.35-b3535.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shweit/MinecraftServerAPI/d36ba797787e303adf44196cb264617eb970787c/src/test/resources/server-data/plugins/Citizens-2.0.35-b3535.jar -------------------------------------------------------------------------------- /src/test/resources/server-data/plugins/Maintenance-4.2.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shweit/MinecraftServerAPI/d36ba797787e303adf44196cb264617eb970787c/src/test/resources/server-data/plugins/Maintenance-4.2.1.jar -------------------------------------------------------------------------------- /src/test/resources/server-data/server.properties: -------------------------------------------------------------------------------- 1 | #Minecraft server properties 2 | #Thu Aug 29 13:32:46 UTC 2024 3 | accepts-transfers=false 4 | allow-flight=false 5 | allow-nether=true 6 | broadcast-console-to-ops=true 7 | broadcast-rcon-to-ops=true 8 | bug-report-link= 9 | debug=false 10 | difficulty=easy 11 | enable-command-block=false 12 | enable-jmx-monitoring=false 13 | enable-query=false 14 | enable-rcon=true 15 | enable-status=true 16 | enforce-secure-profile=true 17 | enforce-whitelist=false 18 | entity-broadcast-range-percentage=100 19 | force-gamemode=false 20 | function-permission-level=2 21 | gamemode=survival 22 | generate-structures=true 23 | generator-settings={} 24 | hardcore=false 25 | hide-online-players=false 26 | initial-disabled-packs= 27 | initial-enabled-packs=vanilla 28 | level-name=world 29 | level-seed= 30 | level-type=minecraft\:normal 31 | log-ips=true 32 | max-chained-neighbor-updates=1000000 33 | max-players=20 34 | max-tick-time=60000 35 | max-world-size=29999984 36 | motd=A Minecraft Server 37 | network-compression-threshold=256 38 | online-mode=true 39 | op-permission-level=4 40 | player-idle-timeout=0 41 | prevent-proxy-connections=false 42 | pvp=true 43 | query.port=25565 44 | rate-limit=0 45 | rcon.password=f45d958cdb470ae28697dded 46 | rcon.port=25575 47 | region-file-compression=deflate 48 | require-resource-pack=false 49 | resource-pack= 50 | resource-pack-id= 51 | resource-pack-prompt= 52 | resource-pack-sha1= 53 | server-ip= 54 | server-port=25565 55 | simulation-distance=10 56 | spawn-animals=true 57 | spawn-monsters=true 58 | spawn-npcs=true 59 | spawn-protection=16 60 | sync-chunk-writes=true 61 | text-filtering-config= 62 | use-native-transport=true 63 | view-distance=10 64 | white-list=false 65 | -------------------------------------------------------------------------------- /src/test/resources/server-data/whitelist.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "uuid": "4f82e47c-7d4d-4607-9b19-29e3e23946a9", 4 | "name": "Shweit" 5 | } 6 | ] -------------------------------------------------------------------------------- /webhooks.md: -------------------------------------------------------------------------------- 1 | # MinecraftServerAPI WebHooks 2 | 3 | ## Overview 4 | MinecraftServerAPI allows you to configure various WebHooks that are triggered by specific events on your Minecraft server. These WebHooks can be used to send notifications or execute specific actions when events occur in the game. 5 | 6 | Below is a list of all possible WebHooks supported by MinecraftServerAPI, along with their default activation status. 7 | 8 | ## WebHooks List 9 | 10 | | WebHook | Description | Default Status | 11 | |------------------------|----------------------------------------------------------------------------------|----------------| 12 | | `server_start` | Triggered when the server starts. | Enabled | 13 | | `server_stop` | Triggered when the server stops. | Enabled | 14 | | `plugin_disable` | Triggered when a plugin is disabled. | Enabled | 15 | | `plugin_enable` | Triggered when a plugin is enabled. | Enabled | 16 | | `block_break` | Triggered when a block is broken. | Disabled | 17 | | `block_place` | Triggered when a block is placed. | Disabled | 18 | | `block_burn` | Triggered when a block burns. | Disabled | 19 | | `block_redstone` | Triggered when a redstone event occurs. | Disabled | 20 | | `note_play` | Triggered when a note block is played. | Enabled | 21 | | `sign_change` | Triggered when a sign is changed. | Enabled | 22 | | `enchant_item` | Triggered when an item is enchanted. | Enabled | 23 | | `creeper_power` | Triggered when a creeper is struck by lightning and becomes charged. | Enabled | 24 | | `creature_spawn` | Triggered when a creature spawns. | Disabled | 25 | | `entity_death` | Triggered when an entity dies. | Disabled | 26 | | `entity_explode` | Triggered when an entity explodes. | Enabled | 27 | | `entity_shoot_bow` | Triggered when an entity shoots a bow. | Enabled | 28 | | `entity_tame` | Triggered when an entity is tamed. | Enabled | 29 | | `explosion_prime` | Triggered when an explosion is primed. | Enabled | 30 | | `player_death` | Triggered when a player dies. | Enabled | 31 | | `brew` | Triggered when a brewing event occurs. | Enabled | 32 | | `craft_item` | Triggered when an item is crafted. | Disabled | 33 | | `furnace_burn` | Triggered when a furnace starts burning. | Disabled | 34 | | `furnace_smelt` | Triggered when a furnace smelts an item. | Disabled | 35 | | `player_chat` | Triggered when a player sends a chat message. | Disabled | 36 | | `player_login` | Triggered when a player logs in. | Enabled | 37 | | `player_command` | Triggered when a player issues a command. | Disabled | 38 | | `player_gamemode_change` | Triggered when a player's game mode changes. | Enabled | 39 | | `player_item_break` | Triggered when a player breaks an item. | Enabled | 40 | | `player_join` | Triggered when a player joins the server. | Enabled | 41 | | `player_kick` | Triggered when a player is kicked from the server. | Enabled | 42 | | `player_quit` | Triggered when a player quits the server. | Enabled | 43 | | `player_respawn` | Triggered when a player respawns. | Enabled | 44 | | `lightning_strike` | Triggered when a lightning strike occurs. | Enabled | 45 | | `weather_change` | Triggered when the weather changes. | Enabled | 46 | | `thunder_change` | Triggered when thunder starts or stops. | Enabled | 47 | | `world_load` | Triggered when a world is loaded. | Enabled | 48 | | `world_save` | Triggered when a world is saved. | Enabled | 49 | | `world_unload` | Triggered when a world is unloaded. | Enabled | 50 | 51 | ## Configuration 52 | You can enable or disable these WebHooks by modifying the `config.yml` file located in the `plugins/MinecraftServerAPI` directory. Each WebHook can be toggled individually, allowing you to control which events trigger notifications. 53 | 54 | For more details on configuring WebHooks, please refer to the [main README](README.md). 55 | 56 | --------------------------------------------------------------------------------