├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ └── config.yml ├── release.yml └── workflows │ ├── publish-artifacts.yml │ └── wiki.yml ├── .gitignore ├── LICENSE ├── README.md ├── SECURITY.md ├── bungeecord ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── andre601 │ │ └── oneversionremake │ │ └── bungeecord │ │ ├── BungeeCore.java │ │ ├── commands │ │ ├── BungeeSender.java │ │ └── CmdOneVersionRemake.java │ │ ├── listener │ │ ├── BungeeLoginListener.java │ │ └── BungeePingListener.java │ │ └── logging │ │ └── BungeeLogger.java │ └── resources │ └── bungee.yml ├── core ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── andre601 │ │ └── oneversionremake │ │ └── core │ │ ├── CommandPermissions.java │ │ ├── OneVersionRemake.java │ │ ├── Parser.java │ │ ├── commands │ │ └── CommandHandler.java │ │ ├── files │ │ └── ConfigHandler.java │ │ ├── interfaces │ │ ├── CmdSender.java │ │ ├── PluginCore.java │ │ └── ProxyLogger.java │ │ └── proxy │ │ ├── ProtocolVersionResolver.java │ │ ├── ProxyPlatform.java │ │ └── VersionsFile.java │ └── resources │ ├── config.yml │ └── core.properties ├── docs ├── assets │ ├── css │ │ └── custom.css │ ├── img │ │ └── favicon.png │ └── js │ │ └── version-table-gen.js ├── config.md ├── index.md └── protocols.md ├── mkdocs.yml ├── pom.xml ├── renovate.json ├── requirements.txt ├── velocity ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── andre601 │ │ └── oneversionremake │ │ └── velocity │ │ ├── VelocityCore.java │ │ ├── commands │ │ ├── CmdOneVersionRemake.java │ │ └── VelocitySender.java │ │ ├── listener │ │ ├── VelocityLoginListener.java │ │ └── VelocityPingListener.java │ │ └── logging │ │ └── VelocityLogger.java │ └── resources │ └── velocity-plugin.json └── versions.json /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: Found a Bug in OneVersionRemake? Use this template to report it! 3 | labels: 4 | - "Type: Bug" 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: |- 9 | Thank you for taking your time and opening a Bug Report. 10 | In order for me to process this Bug Report as fast and efficently as possible do I ask you to read the form carefully and provide any requested information. 11 | Required fields are marked with an asterisk symbol (`*`) 12 | 13 | Also, always make sure to use the latest Release from [Spigot](https://www.spigotmc.org/resources/71727/) or the latest [development build](https://ci.codemc.io/job/Andre601/job/OneVersionRemake/) to make sure that your issue isn't already fixed. 14 | - type: checkboxes 15 | attributes: 16 | label: Confirmation 17 | description: "Please make sure to have followed the following checks." 18 | options: 19 | - label: "My issue isn't already found on the Issue tracker." 20 | required: true 21 | - label: "I use the latest release or development build of the plugin." 22 | required: true 23 | - type: dropdown 24 | attributes: 25 | label: "Platform" 26 | description: |- 27 | What platform (Proxy) do you use? 28 | Please mention the platform when you select "Other". 29 | multiple: false 30 | options: 31 | - "BungeeCord" 32 | - "Waterfall" 33 | - "Flamecord" 34 | - "Travertine" 35 | - "Velocity v3.x" 36 | - "Other" 37 | validations: 38 | required: true 39 | - type: input 40 | attributes: 41 | label: "Other Proxy platform (Optional)" 42 | description: "Provide the name of the proxy you use, if you selected 'Other' in the previous section." 43 | - type: textarea 44 | attributes: 45 | label: "What happens?" 46 | description: "What bug are you encountering? Try to explain it as detailed as possible." 47 | placeholder: "OneVersionRemake does this when I do that..." 48 | validations: 49 | required: true 50 | - type: textarea 51 | attributes: 52 | label: "Expected Behaviour" 53 | description: "What behaviour did you expect from OneVersionRemake?" 54 | placeholder: "OneVersionRemake should actually do..." 55 | validations: 56 | required: true 57 | - type: textarea 58 | attributes: 59 | label: "How to Reproduce" 60 | description: "List the steps on how to reproduce this Bug." 61 | placeholder: |- 62 | 1. Do this 63 | 2. ... 64 | 3. Profit! 65 | validations: 66 | required: true 67 | - type: textarea 68 | attributes: 69 | label: "Config.yml" 70 | description: |- 71 | Please provide the content of the config.yml you currently use. 72 | The text field automatically formats the content as code. 73 | render: yaml 74 | validations: 75 | required: true 76 | - type: input 77 | id: "console" 78 | attributes: 79 | label: "Console Log" 80 | description: |- 81 | Get the latest content of your `latest.log` file an upload it to https://paste.helpch.at 82 | Take the generated URL and paste it into this field. 83 | placeholder: "https://paste.helpch.at/latest.log" 84 | validations: 85 | required: true 86 | - type: input 87 | id: "error" 88 | attributes: 89 | label: "Errors" 90 | description: |- 91 | Upload any errors you find to https://paste.helpch.at and post the link in the field below. 92 | placeholder: "https://paste.helpch.at/error.log" 93 | - type: textarea 94 | attributes: 95 | label: "Additional Info" 96 | description: "Add any extra info you think is nessesary for this Bug report." 97 | placeholder: "Put any extra info you like into this field..." 98 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Support 4 | url: https://discord.gg/6dazXp6 5 | about: "The Discord is a go-to place for getting fast support. Head over to the #oneversionremake channel for support." 6 | - name: Wiki 7 | url: https://github.com/Andre601/OneVersionRemake/wiki 8 | about: "The Wiki contains helpful information about the configuration and other things." 9 | - name: Hastebin 10 | url: https://paste.helpch.at 11 | about: Use this Hastebin-site for sharing errors and configuration files. 12 | - name: Update Wiki 13 | url: https://github.com/PlaceholderAPI/PlaceholderAPI/pulls 14 | about: Please make a Pull request towards the "wiki" folder to update the wiki. 15 | - name: Feedback 16 | url: https://github.com/Andre601/OneVersionRemake/discussions 17 | about: "Share your feedback on the Discussions page of this Repository." 18 | -------------------------------------------------------------------------------- /.github/release.yml: -------------------------------------------------------------------------------- 1 | changelog: 2 | exclude: 3 | labels: 4 | - 'Target: Documentation' 5 | - 'Target: GitHub Action' 6 | categories: 7 | - title: '💥 Breaking' 8 | labels: 9 | - 'Type: Breaking' 10 | - title: '🚀 Features' 11 | labels: 12 | - 'Type: Enhancement' 13 | - title: '🐛 Bug Fixes' 14 | labels: 15 | - 'Type: Bug' 16 | - title: '🧰 Maintenance' 17 | labels: 18 | - 'Type: Update (Dependency)' 19 | -------------------------------------------------------------------------------- /.github/workflows/publish-artifacts.yml: -------------------------------------------------------------------------------- 1 | name: Build Jar 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | build: 9 | strategy: 10 | matrix: 11 | include: 12 | - platforms: | 13 | bungeecord 14 | waterfall 15 | directory: bungeecord 16 | name: BungeeCord, Waterfall 17 | - platforms: velocity 18 | directory: velocity 19 | name: Velocity 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: actions/checkout@v4 23 | - name: Set up JDK 1.11 24 | uses: actions/setup-java@v4 25 | with: 26 | distribution: 'temurin' 27 | java-version: '11' 28 | - name: Build jar 29 | run: mvn clean install 30 | - name: Obtain version from Release 31 | id: release-version 32 | run: | 33 | version=$(echo ${{ github.event.release.tag_name }} | cut -d'v' -f2) 34 | echo "::set-output name=version::$version" 35 | - name: Upload ${{ matrix.name }} file to Modrinth and GitHub 36 | uses: Kir-Antipov/mc-publish@v3.3 37 | with: 38 | name: v${{ steps.release-version.outputs.version }} - ${{ matrix.name }} 39 | version: v${{ steps.release-version.outputs.version }} 40 | version-type: release 41 | files: ${{ matrix.directory }}/target/OneVersionRemake-*.jar 42 | files-secondary: "" 43 | loaders: ${{ matrix.platforms }} 44 | game-version-filter: releases 45 | game-versions: '>=1.8.8' 46 | modrinth-id: EONKUmG1 47 | modrinth-token: ${{ secrets.MODRINTH_TOKEN }} 48 | github-token: ${{ secrets.GITHUB_TOKEN }} 49 | -------------------------------------------------------------------------------- /.github/workflows/wiki.yml: -------------------------------------------------------------------------------- 1 | name: Publish wiki 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - master 8 | paths: 9 | - '.github/workflows/wiki.yml' 10 | - 'docs/**' 11 | - 'mkdocs.yml' 12 | - 'requirements.txt' 13 | 14 | permissions: 15 | actions: read 16 | contents: read 17 | pages: write 18 | id-token: write 19 | 20 | concurrency: 21 | group: github-pages 22 | cancel-in-progress: false 23 | 24 | jobs: 25 | buildSite: 26 | runs-on: ubuntu-latest 27 | environment: 28 | name: github-pages 29 | url: ${{ steps.deployment.outputs.page_url }} 30 | steps: 31 | - name: Checkout Repository 32 | uses: actions/checkout@v4 33 | with: 34 | fetch-depth: 0 35 | - name: Setup Python 3.x 36 | uses: actions/setup-python@v5 37 | with: 38 | python-version: 3.x 39 | - name: Update Pip and install dependencies 40 | run: | 41 | python -m pip install -U pip 42 | pip install -r requirements.txt 43 | - name: Build Site 44 | run: mkdocs build 45 | - name: Configure GitHub Pages 46 | uses: actions/configure-pages@v5 47 | - name: Upload Pages Artifact 48 | uses: actions/upload-pages-artifact@v3 49 | with: 50 | path: 'site/' 51 | - name: Deploy to GitHub Pages 52 | uses: actions/deploy-pages@v4 53 | id: deployment -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | # Mobile Tools for Java (J2ME) 3 | .mtj.tmp/ 4 | # Package Files # 5 | *.jar 6 | *.war 7 | *.ear 8 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 9 | hs_err_pid* 10 | ## eclipse 11 | /eclipse 12 | /.settings 13 | /.metadata 14 | /.classpath 15 | /.project 16 | /bin 17 | ## intellij 18 | /out 19 | /.idea 20 | /*.iml 21 | /*.ipr 22 | /*.iws 23 | /atlassian-ide-plugin.xml 24 | */dependency-reduced-pom.xml 25 | */velocity*.iml 26 | */core.iml 27 | */bungeecord.iml 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Andre_601 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [oneversion]: https://github.com/johnnywoof/OneVersion 2 | [wiki]: https://github.com/Andre601/OneVersionRemake/wiki 3 | [releases]: https://github.com/Andre601/OneVersionRemake/releases 4 | 5 | 6 | OneVersionRemake 7 | 8 | 9 | # OneVersionRemake 10 | 11 | OneVersionRemake is a plugin for Velocity and BungeeCord based on the original concept from [OneVersion] but with a lot of changes and improved code. 12 | 13 | ## Changes from the original 14 | 15 | OneVersionRemake has a few specifici differences that make it better than the original: 16 | 17 | - **Improved Code** 18 | The Code has been improved. The plugin no longer has everything in a single class and instead has things split up for better readability and understanding. 19 | Additionally are commonly used parts shared between the different plugin variants to reduce duplicate code. 20 | - **Better configuration** 21 | The configuration received a general overhaul. 22 | Not only is Configurate used for better config handling, but new features and settings have been added for you to use. No longer is a weird placeholder needed to add a line-break. 23 | - **Placeholders to display MC Versions** 24 | OneVersionRemake uses a JSON file containing known MC protocols and their versions. 25 | This allows you to use placeholders such as `{version}` and `{clientVersion}` in messages to display the Network's supported version and the client's used version respectively. 26 | The JSON file is automatically updated on proxy restarts (Can be disabled) and you can modify it to change the text displayed or add your own MC versions. 27 | - **Allow the versions you want** 28 | The configuration is very simple to understand. Just add the version protocols you want to allow on your network, reload OneVersionRemake and enjoy. 29 | The [Wiki] has a page listing all supported version protocols. 30 | 31 | ## Downloads 32 | 33 | modrinth 34 | 35 | 36 | spigot 37 | 38 | 39 | codemc 40 | 41 | 42 | ## Build it yourself 43 | 44 | You can build your own version of OneVersionRemake from this source. 45 | 46 | ### Requirements 47 | 48 | You need: 49 | 50 | - Java (Obviously) 51 | - Maven 52 | - Git-based terminal (i.e. Git-scm for windows) 53 | 54 | ### Clone the repository 55 | 56 | To clone the repository, first choose where you want to store the folder and open your terminal in there (For windows will you need to use Git Bash). 57 | Next, run the following command: 58 | 59 | ```bash 60 | git clone https://github.com/Andre601/OneVersionRemake 61 | ``` 62 | 63 | After everything has been cloned, head over to the now generated `OneVersionRemake` folder by using `cd OneVersionRemake` in your terminal. 64 | 65 | ### Build the jars 66 | 67 | Now you can build the jar files. Just execute `mvn clean install` and the jars should be build within a few minutes (Depends on your download speed). 68 | Afterwards can you obtain the final jar from either `bungeecord/target/` or `velocity/target/`. 69 | 70 | Note: Make sure to use the jar file either labeled `OneVersionRemake-BungeeCord-.jar` or `OneVersionRemake-Velocity-.jar`. Do not use jars containing `original` in their name! 71 | 72 | ## Contribute 73 | 74 | Contributions towards OneVersionRemake are always welcome when it helps improving the plugin in one way or another. 75 | 76 | ### Modules 77 | 78 | The project is split into 4 different modules which all have their own purpose. 79 | 80 | #### `core` 81 | 82 | The `core` module contains all code that is used on either version of OneVersionRemake (That is platform-agnostic). 83 | 84 | Your primary goal when adding new stuff to OneVersionRemake should be to make the code as platform-independand as possible. This helps to reduce duplicate code. So whenever possible, add new code to this module first and only to the other ones when it can't be avoided. 85 | 86 | #### `bungeecord` 87 | 88 | This module contains all the code used on BungeeCord and that can't be put into the core module itself. 89 | 90 | When adding new BungeeCord features to OneVersionRemake, make sure that it also supports popular forks such as Waterfall, Flamecord, etc. 91 | 92 | #### `velocity` 93 | 94 | This module contains code used for making the Velocity version of OneVersionRemake. 95 | The currently used major API version of Velocity is v3 and the old v1 API is not supported anymore, so please avoid adding v1 support here. 96 | 97 | ## Links 98 | 99 | ghpages 100 | 101 | 102 | discord 103 | 104 | 105 | revolt 106 | 107 | 108 | mastodon 109 | 110 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | ### Plugin 6 | 7 | We only support the **very latest release** of OneVersionRemake. 8 | Using any older version will get your support request ignored. 9 | 10 | ### Platforms 11 | 12 | As of writing this (29th of April 2022) are only the following platforms officially supported: 13 | 14 | | Platform | Supported Version | 15 | |---------------|--------------------------------------| 16 | | BungeeCord | Any 1.18.x builds | 17 | | Waterfall[^1] | Any 1.18.x builds | 18 | | FlameCord[^2] | Any 1.18.x builds | 19 | | Velocity | 3.1.2-SNAPSHOT (Build 116) and newer | 20 | 21 | ## Reporting a Vulnerability 22 | 23 | Please report any vulnerability on our Discord server in the `#oneversionremake` channel. 24 | Do not use the issues section for reporting vulnerabilities to avoid exploitation. 25 | 26 | [^1]: Other BungeeCord forks may also work, but aren't supported by us. 27 | [^2]: FlameCord has not been tested by us, and we do not guarantee a 100% compatability with it. 28 | -------------------------------------------------------------------------------- /bungeecord/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 23 | 4.0.0 24 | 25 | bungeecord 26 | jar 27 | ${plugin.version} 28 | 29 | 30 | parent 31 | com.andre601.oneversionremake 32 | parent 33 | 34 | 35 | 36 | 37 | sonatype-oss 38 | https://oss.sonatype.org/content/repositories/snapshots/ 39 | 40 | 41 | 42 | 43 | 44 | com.andre601.oneversionremake 45 | core 46 | ${project.version} 47 | compile 48 | 49 | 50 | net.md-5 51 | bungeecord-api 52 | 1.21-R0.2 53 | jar 54 | provided 55 | 56 | 57 | net.md-5 58 | bungeecord-api 59 | 1.21-R0.2 60 | javadoc 61 | provided 62 | 63 | 64 | net.kyori 65 | adventure-platform-bungeecord 66 | 4.4.0 67 | 68 | 69 | net.kyori 70 | adventure-api 71 | 4.21.0 72 | 73 | 74 | org.spongepowered 75 | configurate-yaml 76 | 4.2.0 77 | 78 | 79 | org.bstats 80 | bstats-bungeecord 81 | 3.1.0 82 | compile 83 | 84 | 85 | 86 | 87 | OneVersionRemake-BungeeCord-${project.version} 88 | 89 | 90 | true 91 | ${project.basedir}/src/main/resources 92 | 93 | 94 | 95 | 96 | org.apache.maven.plugins 97 | maven-compiler-plugin 98 | 3.14.0 99 | 100 | 101 | org.apache.maven.plugins 102 | maven-shade-plugin 103 | 3.6.0 104 | 105 | true 106 | 107 | 108 | org.spongepowered.configurate 109 | com.andre601.oneversionremake.bungeecord.dependencies.configurate 110 | 111 | 112 | org.bstats 113 | com.andre601.oneversionremake.bungeecord.dependencies.bstats 114 | 115 | 116 | net.kyori 117 | com.andre601.oneversionremake.bungeecord.dependencies.adventure 118 | 119 | 120 | 121 | 122 | *:* 123 | 124 | META-INF/*.SF 125 | META-INF/*.RSA 126 | META-INF/versions/16/ 127 | 128 | 129 | 130 | 131 | 132 | 133 | package 134 | 135 | shade 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /bungeecord/src/main/java/com/andre601/oneversionremake/bungeecord/BungeeCore.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2021 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.bungeecord; 20 | 21 | import com.andre601.oneversionremake.bungeecord.commands.CmdOneVersionRemake; 22 | import com.andre601.oneversionremake.bungeecord.listener.BungeeLoginListener; 23 | import com.andre601.oneversionremake.bungeecord.listener.BungeePingListener; 24 | import com.andre601.oneversionremake.bungeecord.logging.BungeeLogger; 25 | import com.andre601.oneversionremake.core.OneVersionRemake; 26 | import com.andre601.oneversionremake.core.Parser; 27 | import com.andre601.oneversionremake.core.commands.CommandHandler; 28 | import com.andre601.oneversionremake.core.proxy.ProtocolVersionResolver; 29 | import com.andre601.oneversionremake.core.proxy.ProxyPlatform; 30 | import com.andre601.oneversionremake.core.files.ConfigHandler; 31 | import com.andre601.oneversionremake.core.interfaces.PluginCore; 32 | import com.andre601.oneversionremake.core.interfaces.ProxyLogger; 33 | import net.md_5.bungee.api.ServerPing; 34 | import net.md_5.bungee.api.plugin.Plugin; 35 | import org.bstats.bungeecord.Metrics; 36 | import org.bstats.charts.DrilldownPie; 37 | import org.bstats.charts.SimplePie; 38 | 39 | import java.nio.file.Path; 40 | import java.util.List; 41 | import java.util.Locale; 42 | 43 | public class BungeeCore extends Plugin implements PluginCore{ 44 | 45 | private OneVersionRemake core; 46 | private final ProxyLogger logger = new BungeeLogger(getLogger()); 47 | 48 | @Override 49 | public void onEnable(){ 50 | this.core = new OneVersionRemake(this); 51 | } 52 | 53 | // PluginCore stuff 54 | 55 | @Override 56 | public void loadCommands(){ 57 | getProxy().getPluginManager().registerCommand(this, new CmdOneVersionRemake(this)); 58 | } 59 | 60 | @Override 61 | public void loadEventListeners(){ 62 | new BungeeLoginListener(this); 63 | new BungeePingListener(this); 64 | } 65 | 66 | @Override 67 | public void loadMetrics(){ 68 | Metrics metrics = new Metrics(this, 10340); 69 | 70 | metrics.addCustomChart(new DrilldownPie("allowed_protocols", () -> core.getPieMap())); 71 | metrics.addCustomChart(new SimplePie("proxy_type", () -> getProxyPlatform().getName())); 72 | } 73 | 74 | @Override 75 | public Path getPath(){ 76 | return getDataFolder().toPath(); 77 | } 78 | 79 | @Override 80 | public ProxyPlatform getProxyPlatform(){ 81 | switch(getProxy().getName().toLowerCase(Locale.ROOT)){ 82 | case "flamecord": 83 | return ProxyPlatform.FLAMECORD; 84 | 85 | case "travertine": 86 | return ProxyPlatform.TRAVERTINE; 87 | 88 | case "waterfall": 89 | return ProxyPlatform.WATERFALL; 90 | 91 | case "bungeecord": 92 | default: 93 | return ProxyPlatform.BUNGEECORD; 94 | } 95 | } 96 | 97 | @Override 98 | public ProxyLogger getProxyLogger(){ 99 | return logger; 100 | } 101 | 102 | @Override 103 | public ConfigHandler getConfigHandler(){ 104 | return core.getConfigHandler(); 105 | } 106 | 107 | @Override 108 | public ProtocolVersionResolver getProtocolVersionResolver(){ 109 | return core.getProtocolVersionResolver(); 110 | } 111 | 112 | @Override 113 | public CommandHandler getCommandHandler(){ 114 | return core.getCommandHandler(); 115 | } 116 | 117 | @Override 118 | public Parser getComponentParser(){ 119 | return core.getComponentParser(); 120 | } 121 | 122 | @Override 123 | public String getVersion(){ 124 | return core.getVersion(); 125 | } 126 | 127 | @Override 128 | public String getProxyVersion(){ 129 | String[] version = getProxy().getVersion().split(":"); 130 | if(version.length <= 0) 131 | return "UNKNOWN"; 132 | 133 | if(version.length == 1) 134 | return version[0]; 135 | 136 | return String.format("%s (Build #%s)", version[2], version[4]); 137 | } 138 | 139 | public ServerPing.PlayerInfo[] getPlayers(List lines, List serverProtocols, int userProtocol, boolean majorOnly, boolean blacklist){ 140 | return core.getPlayers(ServerPing.PlayerInfo.class, lines, serverProtocols, userProtocol, majorOnly, blacklist) 141 | .toArray(new ServerPing.PlayerInfo[0]); 142 | } 143 | 144 | public OneVersionRemake getCore(){ 145 | return core; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /bungeecord/src/main/java/com/andre601/oneversionremake/bungeecord/commands/BungeeSender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2021 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.bungeecord.commands; 20 | 21 | import com.andre601.oneversionremake.core.CommandPermissions; 22 | import com.andre601.oneversionremake.core.OneVersionRemake; 23 | import com.andre601.oneversionremake.core.interfaces.CmdSender; 24 | import net.kyori.adventure.platform.bungeecord.BungeeAudiences; 25 | import net.kyori.adventure.text.format.NamedTextColor; 26 | import net.md_5.bungee.api.CommandSender; 27 | 28 | public class BungeeSender implements CmdSender{ 29 | 30 | private final OneVersionRemake core; 31 | private final CommandSender sender; 32 | private final BungeeAudiences bungeeAudiences; 33 | 34 | public BungeeSender(OneVersionRemake core, CommandSender sender, BungeeAudiences bungeeAudiences){ 35 | this.core = core; 36 | this.sender = sender; 37 | this.bungeeAudiences = bungeeAudiences; 38 | } 39 | 40 | @Override 41 | public boolean hasPermission(String permission){ 42 | return sender.hasPermission(permission) || sender.hasPermission(CommandPermissions.ADMIN); 43 | } 44 | 45 | @Override 46 | public void sendMsg(){ 47 | sendMsg(""); 48 | } 49 | 50 | @Override 51 | public void sendMsg(String msg, Object... args){ 52 | sendMsg(NamedTextColor.WHITE, msg, args); 53 | } 54 | 55 | @Override 56 | public void sendMsg(NamedTextColor color, String msg, Object... args){ 57 | bungeeAudiences.sender(sender).sendMessage( 58 | core.getComponentParser().toComponent(String.format(msg, args)).color(color) 59 | ); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /bungeecord/src/main/java/com/andre601/oneversionremake/bungeecord/commands/CmdOneVersionRemake.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2021 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.bungeecord.commands; 20 | 21 | import com.andre601.oneversionremake.bungeecord.BungeeCore; 22 | import com.andre601.oneversionremake.core.CommandPermissions; 23 | import net.kyori.adventure.platform.bungeecord.BungeeAudiences; 24 | import net.md_5.bungee.api.CommandSender; 25 | import net.md_5.bungee.api.plugin.Command; 26 | 27 | public class CmdOneVersionRemake extends Command{ 28 | 29 | private final BungeeCore plugin; 30 | private final BungeeAudiences bungeeAudiences; 31 | 32 | public CmdOneVersionRemake(BungeeCore plugin){ 33 | super("oneversionremake", CommandPermissions.ADMIN, "ovr"); 34 | this.plugin = plugin; 35 | this.bungeeAudiences = BungeeAudiences.create(plugin); 36 | } 37 | 38 | @Override 39 | public void execute(CommandSender commandSender, String[] args){ 40 | BungeeSender sender = new BungeeSender(plugin.getCore(), commandSender, bungeeAudiences); 41 | 42 | plugin.getCommandHandler().handle(sender, args); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /bungeecord/src/main/java/com/andre601/oneversionremake/bungeecord/listener/BungeeLoginListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2021 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.bungeecord.listener; 20 | 21 | import com.andre601.oneversionremake.bungeecord.BungeeCore; 22 | import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer; 23 | import net.md_5.bungee.api.event.PreLoginEvent; 24 | import net.md_5.bungee.api.plugin.Listener; 25 | import net.md_5.bungee.event.EventHandler; 26 | import net.md_5.bungee.event.EventPriority; 27 | 28 | import java.util.Collections; 29 | import java.util.List; 30 | 31 | public class BungeeLoginListener implements Listener{ 32 | 33 | private final BungeeCore plugin; 34 | 35 | public BungeeLoginListener(BungeeCore plugin){ 36 | this.plugin = plugin; 37 | plugin.getProxy().getPluginManager().registerListener(plugin, this); 38 | } 39 | 40 | @EventHandler(priority = EventPriority.LOWEST) 41 | public void onLogin(PreLoginEvent event){ 42 | List serverProtocols = plugin.getConfigHandler().getIntList("Protocol", "Versions"); 43 | List kickMessage = plugin.getConfigHandler().getStringList(false, "Messages", "Kick"); 44 | 45 | boolean majorOnly = plugin.getConfigHandler().getBoolean(false, "Protocol", "MajorOnly"); 46 | boolean blacklist = plugin.getConfigHandler().getBoolean(false, "Protocol", "Blacklist"); 47 | 48 | int userProtocol = event.getConnection().getVersion(); 49 | if(serverProtocols.isEmpty()) 50 | return; 51 | 52 | if((blacklist && serverProtocols.contains(userProtocol)) || (!blacklist && !serverProtocols.contains(userProtocol))){ 53 | if(kickMessage.isEmpty()) 54 | kickMessage = Collections.singletonList("This Server is running MC {version}! Please change your client version."); 55 | 56 | event.setCancelReason(BungeeComponentSerializer.get().serialize( 57 | plugin.getComponentParser().toComponent(kickMessage, serverProtocols, userProtocol, majorOnly, blacklist) 58 | )); 59 | event.setCancelled(true); 60 | 61 | if(plugin.getConfigHandler().getBoolean(true, "Protocol", "LogDenial")){ 62 | plugin.getProxyLogger().infoFormat( 63 | "Denied login for Player %s with MC version %s (Protocol version: %d)", 64 | event.getConnection().getName(), 65 | plugin.getProtocolVersionResolver().getVersions().getFriendlyName(userProtocol), 66 | userProtocol 67 | ); 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /bungeecord/src/main/java/com/andre601/oneversionremake/bungeecord/listener/BungeePingListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2021 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.bungeecord.listener; 20 | 21 | import com.andre601.oneversionremake.bungeecord.BungeeCore; 22 | import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer; 23 | import net.md_5.bungee.api.ServerPing; 24 | import net.md_5.bungee.api.chat.TextComponent; 25 | import net.md_5.bungee.api.event.ProxyPingEvent; 26 | import net.md_5.bungee.api.plugin.Listener; 27 | import net.md_5.bungee.event.EventHandler; 28 | import net.md_5.bungee.event.EventPriority; 29 | 30 | import java.util.Comparator; 31 | import java.util.List; 32 | 33 | public class BungeePingListener implements Listener{ 34 | 35 | private final BungeeCore plugin; 36 | 37 | public BungeePingListener(BungeeCore plugin){ 38 | this.plugin = plugin; 39 | plugin.getProxy().getPluginManager().registerListener(plugin, this); 40 | } 41 | 42 | @EventHandler(priority = EventPriority.LOWEST) 43 | public void onProxyPing(ProxyPingEvent event){ 44 | ServerPing ping = event.getResponse(); 45 | ServerPing.Protocol protocol = ping.getVersion(); 46 | if(protocol == null) 47 | return; 48 | 49 | int userProtocol = protocol.getProtocol(); 50 | 51 | List serverProtocols = plugin.getConfigHandler().getIntList("Protocol", "Versions"); 52 | List hoverMessage = plugin.getConfigHandler().getStringList(false, "Messages", "Hover"); 53 | 54 | if(serverProtocols.isEmpty()) 55 | return; 56 | 57 | serverProtocols.sort(Comparator.reverseOrder()); 58 | 59 | boolean majorOnly = plugin.getConfigHandler().getBoolean(false, "Protocol", "MajorOnly"); 60 | boolean blacklist = plugin.getConfigHandler().getBoolean(false, "Protocol", "Blacklist"); 61 | 62 | String playerCount = plugin.getConfigHandler().getString("", "Messages", "PlayerCount"); 63 | List motd = plugin.getConfigHandler().getStringList(true, "Messages", "Motd"); 64 | 65 | if((blacklist && serverProtocols.contains(userProtocol)) || (!blacklist && !serverProtocols.contains(userProtocol))){ 66 | if(!hoverMessage.isEmpty()){ 67 | ServerPing.PlayerInfo[] players = plugin.getPlayers(hoverMessage, serverProtocols, userProtocol, majorOnly, blacklist); 68 | if(players != null) 69 | ping.getPlayers().setSample(players); 70 | } 71 | 72 | if(!playerCount.isEmpty()) 73 | protocol.setName(plugin.getComponentParser().toString(playerCount, serverProtocols, userProtocol, majorOnly, blacklist)); 74 | 75 | if(!motd.isEmpty()){ 76 | TextComponent component = new TextComponent(BungeeComponentSerializer.get().serialize( 77 | plugin.getComponentParser().toComponent(motd, serverProtocols, userProtocol, majorOnly, blacklist) 78 | )); 79 | 80 | ping.setDescriptionComponent(component); 81 | } 82 | 83 | ping.setFavicon(ping.getFaviconObject()); 84 | 85 | protocol.setProtocol(-1); 86 | 87 | ping.setVersion(protocol); 88 | event.setResponse(ping); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /bungeecord/src/main/java/com/andre601/oneversionremake/bungeecord/logging/BungeeLogger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2021 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.bungeecord.logging; 20 | 21 | import com.andre601.oneversionremake.core.interfaces.ProxyLogger; 22 | 23 | import java.util.logging.Level; 24 | import java.util.logging.Logger; 25 | 26 | public class BungeeLogger implements ProxyLogger{ 27 | 28 | private final Logger logger; 29 | 30 | public BungeeLogger(Logger logger){ 31 | this.logger = logger; 32 | } 33 | 34 | @Override 35 | public void info(String msg){ 36 | logger.log(Level.INFO, msg); 37 | } 38 | 39 | @Override 40 | public void infoFormat(String msg, Object... args){ 41 | info(String.format(msg, args)); 42 | } 43 | 44 | @Override 45 | public void warn(String msg){ 46 | logger.log(Level.WARNING, msg); 47 | } 48 | 49 | @Override 50 | public void warnFormat(String msg, Object... args){ 51 | warn(String.format(msg, args)); 52 | } 53 | 54 | @Override 55 | public void warn(String msg, Throwable throwable){ 56 | logger.log(Level.WARNING, msg, throwable); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /bungeecord/src/main/resources/bungee.yml: -------------------------------------------------------------------------------- 1 | name: OneVersionRemake 2 | author: Andre_601 3 | version: ${project.version} 4 | description: ${project.description} 5 | 6 | main: com.andre601.oneversionremake.bungeecord.BungeeCore 7 | 8 | # 9 | # Permission stuff 10 | # 11 | permissions: 12 | oneversionremake.admin: 13 | default: op 14 | description: 'Gives access to all commands of OneVersionRemake' 15 | children: 16 | oneversionremake.command.*: true 17 | oneversionremake.command.*: 18 | default: op 19 | description: 'Gives access to all commands of OneVersionRemake' 20 | children: 21 | oneversionremake.command.help: true 22 | oneversionremake.command.reload: true 23 | oneversionremake.command.help: 24 | default: op 25 | description: 'Gives access to /ovr help' 26 | oneversionremake.command.reload: 27 | default: op 28 | description: 'Gives access to /ovr reload' -------------------------------------------------------------------------------- /core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 23 | 4.0.0 24 | 25 | core 26 | jar 27 | ${plugin.version} 28 | 29 | 30 | com.andre601.oneversionremake 31 | parent 32 | parent 33 | 34 | 35 | 36 | 37 | sonatype 38 | https://oss.sonatype.org/content/repositories/snapshots 39 | 40 | 41 | 42 | 43 | 44 | com.google.code.gson 45 | gson 46 | 2.13.1 47 | compile 48 | 49 | 50 | org.spongepowered 51 | configurate-yaml 52 | 4.2.0 53 | 54 | 55 | net.kyori 56 | adventure-api 57 | 4.21.0 58 | provided 59 | 60 | 61 | net.kyori 62 | adventure-text-minimessage 63 | 4.21.0 64 | compile 65 | 66 | 67 | net.kyori 68 | adventure-text-serializer-legacy 69 | 4.21.0 70 | provided 71 | 72 | 73 | com.squareup.okhttp3 74 | okhttp 75 | 4.12.0 76 | 77 | 78 | 79 | 80 | 81 | 82 | true 83 | ${project.basedir}/src/main/resources 84 | 85 | 86 | 87 | 88 | org.apache.maven.plugins 89 | maven-jar-plugin 90 | 3.4.2 91 | 92 | OneVersionRemake-Core-${project.version} 93 | 94 | 95 | true 96 | true 97 | 98 | 99 | 100 | 101 | 102 | org.apache.maven.plugins 103 | maven-compiler-plugin 104 | 3.14.0 105 | 106 | 107 | org.apache.maven.plugins 108 | maven-shade-plugin 109 | 3.6.0 110 | 111 | true 112 | 113 | 114 | org.spongepowered.configurate 115 | com.andre601.oneversionremake.core.dependencies.configurate 116 | 117 | 118 | net.kyori 119 | com.andre601.oneversionremake.core.dependencies.adventure 120 | 121 | 122 | okhttp3 123 | com.andre601.oneversionremake.core.dependencies.okhttp 124 | 125 | 126 | 127 | 128 | *:* 129 | 130 | META-INF/*.SF 131 | META-INF/*.RSA 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /core/src/main/java/com/andre601/oneversionremake/core/CommandPermissions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2021 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.core; 20 | 21 | public class CommandPermissions{ 22 | 23 | private final static String BASE = "oneversionremake."; 24 | private final static String COMMAND_BASE = BASE + "command."; 25 | 26 | // oneversionremake.admin 27 | public final static String ADMIN = BASE + "admin"; 28 | 29 | // oneversionremake.command.help 30 | public static final String COMMAND_HELP = COMMAND_BASE + "help"; 31 | // oneversionremake.command.reload 32 | public static final String COMMAND_RELOAD = COMMAND_BASE + "reload"; 33 | // oneversionremake.command.refresh 34 | public static final String COMMAND_REFRESH = COMMAND_BASE + "refresh"; 35 | } 36 | -------------------------------------------------------------------------------- /core/src/main/java/com/andre601/oneversionremake/core/OneVersionRemake.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2021 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.core; 20 | 21 | import com.andre601.oneversionremake.core.commands.CommandHandler; 22 | import com.andre601.oneversionremake.core.files.ConfigHandler; 23 | import com.andre601.oneversionremake.core.interfaces.PluginCore; 24 | import com.andre601.oneversionremake.core.interfaces.ProxyLogger; 25 | import com.andre601.oneversionremake.core.proxy.ProtocolVersionResolver; 26 | import com.andre601.oneversionremake.core.proxy.VersionsFile; 27 | 28 | import java.io.IOException; 29 | import java.io.InputStream; 30 | import java.lang.reflect.Constructor; 31 | import java.lang.reflect.InvocationTargetException; 32 | import java.util.*; 33 | 34 | public class OneVersionRemake{ 35 | 36 | public static final String DEF_VERSIONS_URL = "https://www.andre601.ch/oneversionremake/protocol_versions.json"; 37 | 38 | private final PluginCore pluginCore; 39 | private final ConfigHandler configHandler; 40 | private final CommandHandler commandHandler; 41 | private final ProtocolVersionResolver protocolVersionResolver; 42 | private final Parser parser; 43 | 44 | private String version; 45 | 46 | public OneVersionRemake(PluginCore pluginCore){ 47 | this.pluginCore = pluginCore; 48 | this.configHandler = new ConfigHandler(this, pluginCore.getPath()); 49 | this.commandHandler = new CommandHandler(this); 50 | this.protocolVersionResolver = new ProtocolVersionResolver(this, pluginCore.getPath()); 51 | this.parser = new Parser(this); 52 | 53 | load(); 54 | } 55 | 56 | public ProxyLogger getProxyLogger(){ 57 | return pluginCore.getProxyLogger(); 58 | } 59 | 60 | public String getVersion(){ 61 | return version; 62 | } 63 | 64 | public ConfigHandler getConfigHandler(){ 65 | return configHandler; 66 | } 67 | 68 | public boolean reloadConfig(){ 69 | return configHandler.reload(); 70 | } 71 | 72 | public CommandHandler getCommandHandler(){ 73 | return commandHandler; 74 | } 75 | 76 | public ProtocolVersionResolver getProtocolVersionResolver(){ 77 | return protocolVersionResolver; 78 | } 79 | 80 | public Parser getComponentParser(){ 81 | return parser; 82 | } 83 | 84 | public Map> getPieMap(){ 85 | Map> map = new HashMap<>(); 86 | 87 | List versions = getConfigHandler().getIntList("Protocol", "Versions"); 88 | if(versions.isEmpty()){ 89 | String unknown = getProtocolVersionResolver().getVersions().getFriendlyName(0); 90 | 91 | Map entry = new HashMap<>(); 92 | 93 | entry.put(unknown, 1); 94 | map.put("other", entry); 95 | 96 | return map; 97 | } 98 | 99 | for(int version : versions){ 100 | String major = getProtocolVersionResolver().getVersions().getMajor(version); 101 | String name = getProtocolVersionResolver().getVersions().getFriendlyName(version); 102 | 103 | Map entry = new HashMap<>(); 104 | entry.put(name, 1); 105 | 106 | if(major.equalsIgnoreCase("?")){ 107 | map.put("other", entry); 108 | }else{ 109 | map.put(major, entry); 110 | } 111 | } 112 | 113 | return map; 114 | } 115 | 116 | public List getPlayers(Class clazz, List lines, List serverProtocols, int userProtocol, boolean majorOnly, boolean blacklist){ 117 | try{ 118 | final List players = new ArrayList<>(lines.size()); 119 | final Constructor constructor = clazz.getDeclaredConstructor(String.class, UUID.class); 120 | constructor.setAccessible(true); 121 | 122 | for(String line : lines){ 123 | players.add(constructor.newInstance( 124 | getComponentParser().toString(line, serverProtocols, userProtocol, majorOnly, blacklist), UUID.randomUUID() 125 | )); 126 | } 127 | 128 | return players; 129 | }catch(NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException ex){ 130 | return null; 131 | } 132 | } 133 | 134 | private void load(){ 135 | loadVersion(); 136 | printBanner(); 137 | 138 | if(getConfigHandler().loadConfig()){ 139 | getProxyLogger().info("Loaded config.yml!"); 140 | }else{ 141 | getProxyLogger().warn("Couldn't load config.yml! Check above lines for errors and warnings."); 142 | return; 143 | } 144 | 145 | String url = getConfigHandler().getString(DEF_VERSIONS_URL, "Settings", "VersionsUrl"); 146 | 147 | if(getProtocolVersionResolver().isFileMissing()){ 148 | getProxyLogger().info("Creating versions.json..."); 149 | getProtocolVersionResolver().createFile(url).whenComplete((versions, throwable) -> { 150 | if(handleErrors(versions, throwable)) 151 | return; 152 | 153 | getProxyLogger().info("Successfully created versions.json!"); 154 | enable(); 155 | }); 156 | }else 157 | if(getConfigHandler().getBoolean(true, "Settings", "UpdateVersions")){ 158 | getProxyLogger().info("Checking for updated versions.json..."); 159 | getProtocolVersionResolver().updateFile(url).whenComplete((versions, throwable) -> { 160 | if(handleErrors(versions, throwable)) 161 | return; 162 | 163 | getProxyLogger().info("Update-check complete!"); 164 | enable(); 165 | }); 166 | }else{ 167 | getProxyLogger().info("Loading versions.json..."); 168 | getProtocolVersionResolver().loadFile().whenComplete(((versions, throwable) -> { 169 | if(handleErrors(versions, throwable)) 170 | return; 171 | 172 | getProxyLogger().info("Loaded versions.json!"); 173 | enable(); 174 | })); 175 | } 176 | } 177 | 178 | private void enable(){ 179 | List protocols = configHandler.getIntList("Protocol", "Versions"); 180 | boolean versionsSet; 181 | if(protocols.isEmpty()){ 182 | printWarning(); 183 | 184 | versionsSet = false; 185 | }else{ 186 | getProxyLogger().info("Loaded the following Protocol Version(s):"); 187 | getProxyLogger().info(getProtocolVersionResolver().getVersions().getFriendlyNames(protocols, false, false)); 188 | 189 | versionsSet = true; 190 | } 191 | 192 | getProxyLogger().info("Loading command /ovr..."); 193 | pluginCore.loadCommands(); 194 | getProxyLogger().info("Command loaded!"); 195 | 196 | getProxyLogger().info("Loading Event Listeners..."); 197 | pluginCore.loadEventListeners(); 198 | getProxyLogger().info("Event Listeners loaded!"); 199 | 200 | getProxyLogger().info("Loading Metrics..."); 201 | if(versionsSet){ 202 | pluginCore.loadMetrics(); 203 | getProxyLogger().info("Metrics loaded!"); 204 | }else{ 205 | getProxyLogger().info("No Protocol Versions set. Skipping Metrics initialization..."); 206 | } 207 | 208 | getProxyLogger().info("OneVersionRemake ready!"); 209 | } 210 | 211 | private void printBanner(){ 212 | getProxyLogger().info(""); 213 | getProxyLogger().info(" ____ _ ______"); 214 | getProxyLogger().info(" / __ \\ | / / __ \\"); 215 | getProxyLogger().info(" / / / / | / / /_/ /"); 216 | getProxyLogger().info("/ /_/ /| |/ / _, _/"); 217 | getProxyLogger().info("\\____/ |___/_/ |_|"); 218 | getProxyLogger().info(""); 219 | getProxyLogger().infoFormat("OneVersionRemake v%s", getVersion()); 220 | getProxyLogger().infoFormat("Platform: %s v%s", pluginCore.getProxyPlatform().getName(), pluginCore.getProxyVersion()); 221 | getProxyLogger().info(""); 222 | } 223 | 224 | private void printWarning(){ 225 | getProxyLogger().warn("================================================================================"); 226 | getProxyLogger().warn("WARNING!"); 227 | getProxyLogger().warn("The config option 'Versions' doesn't contain any protocol numbers!"); 228 | getProxyLogger().warn("Please edit the config to include valid protocol numbers or OneVersionRemake"); 229 | getProxyLogger().warn("won't work as expected."); 230 | getProxyLogger().warn(""); 231 | getProxyLogger().warn("You may find a list of supported protocol versions here:"); 232 | getProxyLogger().warn("https://github.com/Andre601/OneVersionRemake/wiki/Supported-Protocols"); 233 | getProxyLogger().warn(""); 234 | getProxyLogger().warn("OneVersionRemake won't handle joining Players to prevent any possible issues."); 235 | getProxyLogger().warn("================================================================================"); 236 | } 237 | 238 | private void loadVersion(){ 239 | try(InputStream is = getClass().getResourceAsStream("/core.properties")){ 240 | Properties properties = new Properties(); 241 | 242 | properties.load(is); 243 | 244 | version = properties.getProperty("version"); 245 | }catch(IOException ex){ 246 | version = "UNKNOWN"; 247 | } 248 | } 249 | 250 | private boolean handleErrors(VersionsFile versionsFile, Throwable throwable){ 251 | if(throwable != null || versionsFile == null){ 252 | if(throwable != null){ 253 | getProxyLogger().warn("Encountered an Exception while handling versions.json"); 254 | getProxyLogger().warnFormat("Error Message: %s", throwable.getMessage()); 255 | }else{ 256 | getProxyLogger().warn("Handling of versions.json was non-successful!"); 257 | getProxyLogger().warn("Please check previous entries for any errors."); 258 | } 259 | return true; 260 | } 261 | 262 | return false; 263 | } 264 | } 265 | -------------------------------------------------------------------------------- /core/src/main/java/com/andre601/oneversionremake/core/Parser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2021 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.core; 20 | 21 | import net.kyori.adventure.text.Component; 22 | import net.kyori.adventure.text.minimessage.MiniMessage; 23 | import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; 24 | 25 | import java.util.List; 26 | 27 | public class Parser{ 28 | 29 | private final OneVersionRemake core; 30 | 31 | public Parser(OneVersionRemake core){ 32 | this.core = core; 33 | } 34 | 35 | public Component toComponent(List lines, List serverProtocols, int userProtocol, boolean majorOnly, boolean blacklist){ 36 | return toComponent(parse(String.join("\n", lines), serverProtocols, userProtocol, majorOnly, blacklist)); 37 | } 38 | 39 | public Component toComponent(String text){ 40 | return MiniMessage.miniMessage().deserialize(text); 41 | } 42 | 43 | public String toString(String text, List serverProtocols, int userProtocol, boolean majorOnly, boolean blacklist){ 44 | Component component = MiniMessage.miniMessage() 45 | .deserialize(parse(text, serverProtocols, userProtocol, majorOnly, blacklist)); 46 | return LegacyComponentSerializer.legacySection().serialize(component); 47 | } 48 | 49 | private String parse(String text, List serverProtocols, int userProtocol, boolean majorOnly, boolean blacklist){ 50 | return text.replace("{version}", core.getProtocolVersionResolver().getVersions().getFriendlyNames(serverProtocols, majorOnly, blacklist)) 51 | .replace("{userVersion}", core.getProtocolVersionResolver().getVersions().getFriendlyName(userProtocol)); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /core/src/main/java/com/andre601/oneversionremake/core/commands/CommandHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2021 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.core.commands; 20 | 21 | import com.andre601.oneversionremake.core.CommandPermissions; 22 | import com.andre601.oneversionremake.core.OneVersionRemake; 23 | import com.andre601.oneversionremake.core.interfaces.CmdSender; 24 | import net.kyori.adventure.text.format.NamedTextColor; 25 | 26 | import java.util.List; 27 | 28 | public class CommandHandler{ 29 | 30 | public final OneVersionRemake core; 31 | 32 | public CommandHandler(OneVersionRemake core){ 33 | this.core = core; 34 | } 35 | 36 | public void handle(CmdSender sender, String[] args){ 37 | if(args.length == 0 || args[0].equalsIgnoreCase("help")){ 38 | if(!sender.hasPermission(CommandPermissions.COMMAND_HELP)){ 39 | sender.sendMsg(NamedTextColor.RED, "Insufficient permissions!"); 40 | return; 41 | } 42 | 43 | sender.sendMsg("OneVersionRemake v%s", core.getVersion()); 44 | sender.sendMsg(); 45 | sender.sendMsg(NamedTextColor.AQUA, "/ovr help"); 46 | sender.sendMsg(NamedTextColor.GRAY, "Shows this Command list."); 47 | sender.sendMsg(); 48 | sender.sendMsg(NamedTextColor.AQUA, "/ovr reload"); 49 | sender.sendMsg(NamedTextColor.GRAY, "Reloads the configuration file."); 50 | sender.sendMsg(); 51 | sender.sendMsg(NamedTextColor.AQUA, "/ovr refresh"); 52 | sender.sendMsg(NamedTextColor.GRAY, "Updates the versions.json file."); 53 | }else 54 | if(args[0].equalsIgnoreCase("reload")){ 55 | if(!sender.hasPermission(CommandPermissions.COMMAND_RELOAD)){ 56 | sender.sendMsg(NamedTextColor.RED, "Insufficient permissions!"); 57 | return; 58 | } 59 | 60 | sender.sendMsg(NamedTextColor.GRAY, "Reloading config.yml..."); 61 | 62 | if(core.reloadConfig()){ 63 | List protocols = core.getConfigHandler().getIntList("Protocol", "Versions"); 64 | 65 | sender.sendMsg(NamedTextColor.AQUA, "Loaded following Minecraft version(s):"); 66 | if(protocols.isEmpty()){ 67 | sender.sendMsg(NamedTextColor.RED, "None"); 68 | }else{ 69 | sender.sendMsg(NamedTextColor.GRAY, core.getProtocolVersionResolver().getVersions().getFriendlyNames(protocols, false, false)); 70 | } 71 | 72 | sender.sendMsg(); 73 | sender.sendMsg(NamedTextColor.GREEN, "Reload successful!"); 74 | }else{ 75 | sender.sendMsg(NamedTextColor.RED, "There was an issue while reloading the configuration file!"); 76 | sender.sendMsg(NamedTextColor.RED, "Please check the Console of the Proxy for any errors and warnings."); 77 | } 78 | }else 79 | if(args[0].equalsIgnoreCase("refresh")){ 80 | if(!sender.hasPermission(CommandPermissions.COMMAND_REFRESH)){ 81 | sender.sendMsg(NamedTextColor.RED, "Insufficient permissions!"); 82 | return; 83 | } 84 | 85 | sender.sendMsg(NamedTextColor.GRAY, "Updating versions.json..."); 86 | 87 | core.getProtocolVersionResolver() 88 | .updateFile(core.getConfigHandler().getString(OneVersionRemake.DEF_VERSIONS_URL, "Settings", "VersionsUrl")) 89 | .whenComplete((versions, throwable) -> { 90 | if(versions == null || throwable != null){ 91 | if(throwable != null){ 92 | sender.sendMsg(NamedTextColor.RED, "Encountered an Exception while performing the update."); 93 | }else{ 94 | sender.sendMsg(NamedTextColor.RED, "Update was not successful! Check console for any errors!"); 95 | } 96 | 97 | return; 98 | } 99 | 100 | sender.sendMsg(NamedTextColor.GREEN, "Successfully updated versions.json!"); 101 | }); 102 | }else{ 103 | sender.sendMsg(NamedTextColor.RED, "Unknown argument \"%s\".", args[0]); 104 | sender.sendMsg(NamedTextColor.RED, "Run \"/ovr help\" for all commands."); 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /core/src/main/java/com/andre601/oneversionremake/core/files/ConfigHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2021 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.core.files; 20 | 21 | import com.andre601.oneversionremake.core.OneVersionRemake; 22 | import com.andre601.oneversionremake.core.interfaces.ProxyLogger; 23 | import org.spongepowered.configurate.ConfigurationNode; 24 | import org.spongepowered.configurate.serialize.SerializationException; 25 | import org.spongepowered.configurate.yaml.YamlConfigurationLoader; 26 | 27 | import java.io.File; 28 | import java.io.IOException; 29 | import java.io.InputStream; 30 | import java.nio.file.Files; 31 | import java.nio.file.Path; 32 | import java.util.ArrayList; 33 | import java.util.Collections; 34 | import java.util.List; 35 | 36 | public class ConfigHandler{ 37 | 38 | private final OneVersionRemake core; 39 | private final ProxyLogger logger; 40 | 41 | private final File config; 42 | private final File path; 43 | 44 | private ConfigurationNode node = null; 45 | 46 | public ConfigHandler(OneVersionRemake core, Path path){ 47 | this.core = core; 48 | logger = core.getProxyLogger(); 49 | 50 | this.config = new File(path.toFile(), "config.yml"); 51 | this.path = path.toFile(); 52 | } 53 | 54 | public boolean loadConfig(){ 55 | if(!path.isDirectory() && !path.mkdirs()){ 56 | logger.warn("Could not create folder for plugin!"); 57 | return false; 58 | } 59 | 60 | if(!config.exists()){ 61 | try(InputStream is = core.getClass().getResourceAsStream("/config.yml")){ 62 | if(is == null){ 63 | logger.warn("Unable to create config file! InputStream was null."); 64 | return false; 65 | } 66 | 67 | Files.copy(is, config.toPath()); 68 | }catch(IOException ex){ 69 | logger.warn("Unable to create config file!", ex); 70 | return false; 71 | } 72 | } 73 | 74 | YamlConfigurationLoader loader = YamlConfigurationLoader.builder() 75 | .file(config) 76 | .build(); 77 | 78 | try{ 79 | node = loader.load(); 80 | }catch(IOException ex){ 81 | logger.warn("There was an issue while attempting to load the config.", ex); 82 | return false; 83 | } 84 | 85 | return true; 86 | } 87 | 88 | public boolean reload(){ 89 | YamlConfigurationLoader loader = YamlConfigurationLoader.builder() 90 | .file(config) 91 | .build(); 92 | 93 | try{ 94 | node = loader.load(); 95 | return true; 96 | }catch(IOException ex){ 97 | logger.warn("There was an issue while attempting to reload the config", ex); 98 | return false; 99 | } 100 | } 101 | 102 | public boolean getBoolean(boolean def, Object... path){ 103 | return fromPath(path).getBoolean(def); 104 | } 105 | 106 | public String getString(String def, Object... path){ 107 | return fromPath(path).getString(def); 108 | } 109 | 110 | public List getIntList(Object... path){ 111 | try{ 112 | return fromPath(path).getList(Integer.class); 113 | }catch(SerializationException ex){ 114 | return new ArrayList<>(); 115 | } 116 | } 117 | 118 | public List getStringList(boolean trim, Object... path){ 119 | List list; 120 | try{ 121 | list = fromPath(path).getList(String.class); 122 | }catch(SerializationException ex){ 123 | return Collections.emptyList(); 124 | } 125 | 126 | if(list == null) 127 | return Collections.emptyList(); 128 | 129 | return (trim && list.size() > 2) ? list.subList(0, 2) : list; 130 | } 131 | 132 | private ConfigurationNode fromPath(Object... path){ 133 | return node.node(path); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /core/src/main/java/com/andre601/oneversionremake/core/interfaces/CmdSender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2021 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.core.interfaces; 20 | 21 | import net.kyori.adventure.text.format.NamedTextColor; 22 | 23 | public interface CmdSender{ 24 | 25 | @SuppressWarnings("BooleanMethodIsAlwaysInverted") 26 | boolean hasPermission(String permission); 27 | 28 | void sendMsg(); 29 | 30 | void sendMsg(String msg, Object... args); 31 | 32 | void sendMsg(NamedTextColor color, String msg, Object... args); 33 | } 34 | -------------------------------------------------------------------------------- /core/src/main/java/com/andre601/oneversionremake/core/interfaces/PluginCore.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2021 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.core.interfaces; 20 | 21 | import com.andre601.oneversionremake.core.Parser; 22 | import com.andre601.oneversionremake.core.commands.CommandHandler; 23 | import com.andre601.oneversionremake.core.proxy.ProtocolVersionResolver; 24 | import com.andre601.oneversionremake.core.proxy.ProxyPlatform; 25 | import com.andre601.oneversionremake.core.files.ConfigHandler; 26 | 27 | import java.nio.file.Path; 28 | 29 | public interface PluginCore{ 30 | 31 | void loadCommands(); 32 | 33 | void loadEventListeners(); 34 | 35 | void loadMetrics(); 36 | 37 | Path getPath(); 38 | 39 | ProxyPlatform getProxyPlatform(); 40 | 41 | ProxyLogger getProxyLogger(); 42 | 43 | ConfigHandler getConfigHandler(); 44 | 45 | ProtocolVersionResolver getProtocolVersionResolver(); 46 | 47 | CommandHandler getCommandHandler(); 48 | 49 | Parser getComponentParser(); 50 | 51 | String getVersion(); 52 | 53 | String getProxyVersion(); 54 | } 55 | -------------------------------------------------------------------------------- /core/src/main/java/com/andre601/oneversionremake/core/interfaces/ProxyLogger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2021 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.core.interfaces; 20 | 21 | public interface ProxyLogger{ 22 | 23 | void info(String msg); 24 | 25 | void infoFormat(String msg, Object... args); 26 | 27 | void warn(String msg); 28 | 29 | void warnFormat(String msg, Object... args); 30 | 31 | void warn(String msg, Throwable throwable); 32 | } 33 | -------------------------------------------------------------------------------- /core/src/main/java/com/andre601/oneversionremake/core/proxy/ProtocolVersionResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2021 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.core.proxy; 20 | 21 | import com.andre601.oneversionremake.core.OneVersionRemake; 22 | import com.andre601.oneversionremake.core.interfaces.ProxyLogger; 23 | import com.google.gson.Gson; 24 | import com.google.gson.JsonSyntaxException; 25 | import okhttp3.OkHttpClient; 26 | import okhttp3.Request; 27 | import okhttp3.Response; 28 | import okhttp3.ResponseBody; 29 | 30 | import java.io.*; 31 | import java.nio.charset.StandardCharsets; 32 | import java.nio.file.Files; 33 | import java.nio.file.Path; 34 | import java.util.List; 35 | import java.util.concurrent.CompletableFuture; 36 | 37 | public class ProtocolVersionResolver{ 38 | private final OkHttpClient CLIENT = new OkHttpClient(); 39 | private final Gson gson = new Gson(); 40 | 41 | private final ProxyLogger logger; 42 | 43 | private final Path file; 44 | 45 | private VersionsFile versions = null; 46 | 47 | public ProtocolVersionResolver(OneVersionRemake core, Path path){ 48 | this.logger = core.getProxyLogger(); 49 | 50 | this.file = path.resolve("versions.json"); 51 | } 52 | 53 | public VersionsFile getVersions(){ 54 | return versions; 55 | } 56 | 57 | public boolean isFileMissing(){ 58 | return !file.toFile().exists(); 59 | } 60 | 61 | public CompletableFuture createFile(String url){ 62 | return CompletableFuture.supplyAsync(() -> (copyAndUpdate(getSiteJson(url)))); 63 | } 64 | 65 | public CompletableFuture updateFile(String url){ 66 | return CompletableFuture.supplyAsync(() -> { 67 | String json = getSiteJson(url); 68 | if(json == null) 69 | return null; 70 | 71 | try{ 72 | VersionsFile currentVersions = getVersionsFile(Files.readAllLines(file)); 73 | VersionsFile newVersions = getVersionsFile(json); 74 | 75 | if(currentVersions == null || newVersions == null){ 76 | logger.warn("Error while getting current and new versions info."); 77 | logger.warnFormat("Current null? %b; New null? %b", currentVersions == null, newVersions == null); 78 | return null; 79 | } 80 | 81 | // User is using old versions.json URL 82 | if(newVersions.getFileVersion() == -1){ 83 | logger.warn("Remote JSON file does not have a 'file_version' property set!"); 84 | logger.warn("Make sure the URL points to an updated versions file."); 85 | logger.warnFormat("New URL: %s", OneVersionRemake.DEF_VERSIONS_URL); 86 | 87 | return null; 88 | } 89 | 90 | if(currentVersions.getFileVersion() < newVersions.getFileVersion()){ 91 | logger.info("Current versions.json is outdated. Updating..."); 92 | return copyAndUpdate(json); 93 | }else{ 94 | logger.info("Current versions.json is up-to-date!"); 95 | return (versions = currentVersions); 96 | } 97 | }catch(IOException ex){ 98 | logger.warn("Encountered IOException while reading versions.json file.", ex); 99 | return null; 100 | } 101 | }); 102 | } 103 | 104 | public CompletableFuture loadFile(){ 105 | return CompletableFuture.supplyAsync(() -> { 106 | try{ 107 | return (versions = getVersionsFile(Files.readAllLines(file))); 108 | }catch(IOException ex){ 109 | logger.warn("Encountered IOException while trying to load versions.json"); 110 | return null; 111 | } 112 | }); 113 | } 114 | 115 | private VersionsFile copyAndUpdate(String json){ 116 | if(json == null) 117 | return null; 118 | 119 | try{ 120 | FileWriter fileWriter = new FileWriter(file.toFile(), StandardCharsets.UTF_8, false); 121 | BufferedWriter writer = new BufferedWriter(fileWriter); 122 | 123 | writer.write(json); 124 | writer.close(); 125 | 126 | return (versions = getVersionsFile(json)); 127 | }catch(IOException ex){ 128 | logger.warn("Encountered IOException while saving the versions.json file.", ex); 129 | return null; 130 | } 131 | } 132 | 133 | private VersionsFile getVersionsFile(List lines){ 134 | return getVersionsFile(String.join("", lines)); 135 | } 136 | 137 | private VersionsFile getVersionsFile(String json){ 138 | try{ 139 | return gson.fromJson(json, VersionsFile.class); 140 | }catch(JsonSyntaxException ex){ 141 | logger.warn("Encountered JsonSyntaxException while parsing JSON.", ex); 142 | return null; 143 | } 144 | } 145 | 146 | private String getSiteJson(String url){ 147 | Request request = new Request.Builder() 148 | .url(url) 149 | .addHeader("User-Agent", "OneVersionRemake") 150 | .build(); 151 | 152 | try(Response response = CLIENT.newCall(request).execute()){ 153 | if(!response.isSuccessful()){ 154 | logger.warnFormat("Received non-successful response code from %s. Further details below.", url); 155 | 156 | switch(response.code()){ 157 | case 404: 158 | logger.warn("404: Unknown Site. Make sure the URL is valid."); 159 | break; 160 | 161 | case 429: 162 | logger.warn("429: Encountered rate limit. Please delay any future requests."); 163 | break; 164 | 165 | case 500: 166 | logger.warn("500: Site couldn't process request and encountered an 'Internal Server Error'. Try again later?"); 167 | break; 168 | 169 | default: 170 | logger.warnFormat("%d: %s", response.code(), response.message()); 171 | break; 172 | } 173 | 174 | return null; 175 | } 176 | 177 | ResponseBody body = response.body(); 178 | if(body == null){ 179 | logger.warn("Received null response body."); 180 | return null; 181 | } 182 | 183 | String json = body.string(); 184 | if(json.isEmpty()){ 185 | logger.warn("Received empty response body."); 186 | return null; 187 | } 188 | 189 | return json; 190 | }catch(IOException ex){ 191 | logger.warn("Encountered IOException!", ex); 192 | return null; 193 | } 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /core/src/main/java/com/andre601/oneversionremake/core/proxy/ProxyPlatform.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2021 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.core.proxy; 20 | 21 | public enum ProxyPlatform{ 22 | 23 | // BungeeCord and forks 24 | BUNGEECORD ("BungeeCord"), 25 | FLAMECORD ("FlameCord"), 26 | TRAVERTINE ("Travertine"), 27 | WATERFALL ("Waterfall"), 28 | 29 | // Velocity 30 | VELOCITY ("Velocity"); 31 | 32 | private final String name; 33 | 34 | ProxyPlatform(String name){ 35 | this.name = name; 36 | } 37 | 38 | public String getName(){ 39 | return name; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /core/src/main/java/com/andre601/oneversionremake/core/proxy/VersionsFile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2022 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.core.proxy; 20 | 21 | import com.google.gson.annotations.SerializedName; 22 | 23 | import java.util.Arrays; 24 | import java.util.Comparator; 25 | import java.util.List; 26 | import java.util.stream.Collectors; 27 | import java.util.stream.Stream; 28 | 29 | public class VersionsFile{ 30 | 31 | @SerializedName("file_version") 32 | private int fileVersion = -1; 33 | @SerializedName("protocols") 34 | private ProtocolInfo[] protocolInfos = new ProtocolInfo[0]; 35 | 36 | public int getFileVersion(){ 37 | return fileVersion; 38 | } 39 | 40 | public String getFriendlyNames(List protocols, boolean majorOnly, boolean blacklist){ 41 | Stream stream; 42 | 43 | if(blacklist){ 44 | stream = Arrays.stream(protocolInfos) 45 | .map(ProtocolInfo::getProtocol) 46 | .filter(protocol -> !protocols.contains(protocol)) 47 | .sorted(Comparator.reverseOrder()); 48 | }else{ 49 | stream = protocols.stream() 50 | .sorted(Comparator.reverseOrder()); 51 | } 52 | 53 | if(majorOnly){ 54 | return stream.map(this::getMajor) 55 | .distinct() 56 | .collect(Collectors.joining(", ")); 57 | } 58 | 59 | return stream.map(this::getFriendlyName) 60 | .collect(Collectors.joining(", ")); 61 | } 62 | 63 | public String getFriendlyName(int protocol){ 64 | ProtocolInfo protocolInfo = getProtocolInfo(protocol); 65 | if(protocolInfo == null) 66 | return "?"; 67 | 68 | return protocolInfo.getName(); 69 | } 70 | 71 | public String getMajor(int protocol){ 72 | ProtocolInfo protocolInfo = getProtocolInfo(protocol); 73 | if(protocolInfo == null) 74 | return "?"; 75 | 76 | return protocolInfo.getMajor(); 77 | } 78 | 79 | private ProtocolInfo getProtocolInfo(int protocol){ 80 | for(ProtocolInfo protocolInfo : protocolInfos){ 81 | if(protocolInfo.getProtocol() == protocol) 82 | return protocolInfo; 83 | } 84 | 85 | return null; 86 | } 87 | 88 | @SuppressWarnings({"FieldCanBeLocal", "FieldMayBeFinal"}) 89 | private static class ProtocolInfo{ 90 | private int protocol = 0; 91 | private String major = "UNKNOWN"; 92 | private String name = "UNKNOWN"; 93 | 94 | public int getProtocol(){ 95 | return protocol; 96 | } 97 | 98 | public String getMajor(){ 99 | return major; 100 | } 101 | 102 | public String getName(){ 103 | return name; 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /core/src/main/resources/config.yml: -------------------------------------------------------------------------------- 1 | ################################################################################# 2 | # +---------------------------------------------------------------------------+ # 3 | # | ____ _ ______ | # 4 | # | / __ \ | / / __ \ OneVersionRemake | # 5 | # | / / / / | / / /_/ / by Andre_601 | # 6 | # | / /_/ /| |/ / _, _/ | # 7 | # | \____/ |___/_/ |_| | # 8 | # | | # 9 | # | GitHub: https://github.com/Andre601/OneVersionRemake | # 10 | # | Spigot: https://spigotmc.org/resources/71727/ | # 11 | # | Wiki: https://ovr.andre601.ch | # 12 | # | | # 13 | # +---------------------------------------------------------------------------+ # 14 | ################################################################################# 15 | # 16 | # Created with Version ${project.version} 17 | # 18 | # +----------------------------------------------------------------------------+ 19 | # | Main Settings | 20 | # | | 21 | # | Main Settings for the plugin. | 22 | # | | 23 | # | https://ovr.andre601.ch/config#settings | 24 | # +----------------------------------------------------------------------------+ 25 | Settings: 26 | # +--------------------------------------------------------------------------+ 27 | # | Whether OneVersionRemake should download the latest versions.json on | 28 | # | Proxy (re)start. | 29 | # | | 30 | # | https://ovr.andre601.ch/config#updateversions | 31 | # +--------------------------------------------------------------------------+ 32 | UpdateVersions: true 33 | # +--------------------------------------------------------------------------+ 34 | # | URL pointing to the file that contains the different Protocols OVR | 35 | # | should use. | 36 | # | | 37 | # | https://ovr.andre601.ch/config#versionsurl | 38 | # +--------------------------------------------------------------------------+ 39 | VersionsUrl: 'https://andre601.ch/oneversionremake/protocol_versions.json' 40 | 41 | # +----------------------------------------------------------------------------+ 42 | # | Protocol Settings | 43 | # | | 44 | # | Protocol Settings for the plugin. | 45 | # | | 46 | # | https://ovr.andre601.ch/config#protocol | 47 | # +----------------------------------------------------------------------------+ 48 | Protocol: 49 | # +--------------------------------------------------------------------------+ 50 | # | The Protocol Versions that should be allowed to join the network. | 51 | # | | 52 | # | https://ovr.andre601.ch/config#versions | 53 | # +--------------------------------------------------------------------------+ 54 | Versions: [] 55 | 56 | # +--------------------------------------------------------------------------+ 57 | # | Should OneVersionRemake log denied Logins in the console? | 58 | # | | 59 | # | https://ovr.andre601.ch/config#logdenial | 60 | # +--------------------------------------------------------------------------+ 61 | LogDenial: true 62 | 63 | # +--------------------------------------------------------------------------+ 64 | # | Should the {version} placeholder only show major MC versions? | 65 | # | | 66 | # | https://ovr.andre601.ch/config#majoronly | 67 | # +--------------------------------------------------------------------------+ 68 | MajorOnly: false 69 | # +--------------------------------------------------------------------------+ 70 | # | Should the list of protocols be treated as a Blacklist? | 71 | # | If set to true, only protocol versions NOT in the list will be allowed. | 72 | # | | 73 | # | https://ovr.andre601.ch/config#blacklist | 74 | # +--------------------------------------------------------------------------+ 75 | Blacklist: false 76 | 77 | # +----------------------------------------------------------------------------+ 78 | # | Messages | 79 | # | | 80 | # | This section contains all the messages that you can configure. | 81 | # | | 82 | # | https://ovr.andre601.ch/config#messages | 83 | # +----------------------------------------------------------------------------+ 84 | Messages: 85 | # +--------------------------------------------------------------------------+ 86 | # | Message to display instead of the Player count (/) next to | 87 | # | the ping icon. | 88 | # | | 89 | # | https://ovr.andre601.ch/config#playercount | 90 | # +--------------------------------------------------------------------------+ 91 | PlayerCount: 'Minecraft {version}' 92 | 93 | # +--------------------------------------------------------------------------+ 94 | # | Reason to display, when the player gets kicked for using a unsupported | 95 | # | Minecraft Version. | 96 | # | | 97 | # | https://ovr.andre601.ch/config#kick | 98 | # +--------------------------------------------------------------------------+ 99 | Kick: 100 | - 'You are using an unsupported version of Minecraft ({userVersion})!' 101 | - 'This server supports the following Versions:' 102 | - '{version}' 103 | - '' 104 | - 'Please change your Version and try again.' 105 | 106 | # +--------------------------------------------------------------------------+ 107 | # | Message to show when the player hovers over the player count with his | 108 | # | cursor. | 109 | # | | 110 | # | https://ovr.andre601.ch/config#hover | 111 | # +--------------------------------------------------------------------------+ 112 | Hover: 113 | - 'You are using an unsupported version of Minecraft ({userVersion})!' 114 | - 'Please change your version to {version}.' 115 | 116 | # +--------------------------------------------------------------------------+ 117 | # | Message to display in the MOTD of the server. | 118 | # | | 119 | # | https://ovr.andre601.ch/config#motd | 120 | # +--------------------------------------------------------------------------+ 121 | Motd: 122 | - 'Unsupported Minecraft Version {userVersion}' 123 | - 'Please use {version}.' 124 | -------------------------------------------------------------------------------- /core/src/main/resources/core.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020 Andre601 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | # documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | # and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | # 9 | # The above copyright notice and this permission notice shall be included in all copies or substantial 10 | # portions of the Software. 11 | # 12 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | # 18 | 19 | version=${project.version} -------------------------------------------------------------------------------- /docs/assets/css/custom.css: -------------------------------------------------------------------------------- 1 | .md-header__button.md-logo img, .md-header__button.md-logo svg { 2 | height: 3rem; 3 | } -------------------------------------------------------------------------------- /docs/assets/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Andre601/OneVersionRemake/a0e462b20803564c75dea1be6613fc173e3fa5ae/docs/assets/img/favicon.png -------------------------------------------------------------------------------- /docs/assets/js/version-table-gen.js: -------------------------------------------------------------------------------- 1 | document$.subscribe(async () => { 2 | const url = `https://api.allorigins.win/raw?url=${encodeURIComponent('https://andre601.ch/oneversionremake/protocol_versions.json')}`; 3 | 4 | const versions_table = document.querySelector('[data-md-component="versions-table"]'); 5 | 6 | const headerText = ['Protocol', 'Version', 'Major']; 7 | 8 | function createTable(data) { 9 | const table = document.createElement("table"); 10 | const tableHead = document.createElement("thead"); 11 | const tableBody = document.createElement("tbody"); 12 | 13 | if(tableHead === null || tableBody === null) 14 | return; 15 | 16 | const headRow = document.createElement("tr"); 17 | for(let i = 0; i < 3; i++) { 18 | const cell = document.createElement("th"); 19 | const text = document.createTextNode(`${headerText[`${i}`]}`); 20 | 21 | cell.appendChild(text); 22 | headRow.appendChild(cell); 23 | } 24 | 25 | tableHead.appendChild(headRow); 26 | 27 | console.log(data.protocols) 28 | 29 | for(i in data.protocols){ 30 | const value = data.protocols[i]; 31 | const row = document.createElement("tr"); 32 | 33 | const protocol = document.createElement("td"); 34 | const protocolText = document.createTextNode(value.protocol) 35 | 36 | const version = document.createElement("td"); 37 | const versionText = document.createTextNode(value.name) 38 | 39 | const major = document.createElement("td"); 40 | const majorText = document.createTextNode(value.major) 41 | 42 | protocol.appendChild(protocolText); 43 | version.appendChild(versionText); 44 | major.appendChild(majorText); 45 | 46 | row.appendChild(protocol); 47 | row.appendChild(version); 48 | row.appendChild(major); 49 | 50 | tableBody.appendChild(row); 51 | } 52 | 53 | table.appendChild(tableHead); 54 | table.appendChild(tableBody); 55 | 56 | versions_table.appendChild(table); 57 | } 58 | 59 | async function fetchData() { 60 | const data = await fetch(`${url}`).then(_ => _.json()); 61 | 62 | __md_set("__versions_data", data, sessionStorage); 63 | createTable(data); 64 | } 65 | 66 | if(document.querySelector('[data-md-component="versions-table"]')) { 67 | const cached = __md_get("__versions_data", sessionStorage); 68 | if(cached != null) { 69 | createTable(cached); 70 | } else { 71 | fetchData(); 72 | } 73 | } 74 | }) -------------------------------------------------------------------------------- /docs/config.md: -------------------------------------------------------------------------------- 1 | # Config.yml 2 | 3 | OneVersionRemake's `config.yml` offers various options to configure. This page explains them in detail. 4 | 5 | ## Contents 6 | 7 | - [Settings](#settings) 8 | - [UpdateVersions](#updateversions) 9 | - [VersionsUrl](#versionsurl) 10 | - [Protocol](#protocol) 11 | - [Versions](#versions) 12 | - [LogDenial](#logdenial) 13 | - [MajorOnly](#majoronly) 14 | - [Blacklist](#blacklist) 15 | - [Messages](#messages) 16 | - [Supported Formatting](#supported-formatting) 17 | - [Available Placeholders](#available-placeholders) 18 | - [PlayerCount](#playercount) 19 | - [Kick](#kick) 20 | - [Hover](#hover) 21 | - [Motd](#motd) 22 | 23 | ## Settings 24 | 25 | Main settings of the plugin that don't fit any of the other sections. 26 | 27 | ### UpdateVersions 28 | 29 | /// info | 30 | **Type:** `Boolean` 31 | **Default:** 32 | ```yaml 33 | Settings: 34 | UpdateVersions: true 35 | ``` 36 | /// 37 | 38 | Wether OneVersionRemake should update the versions file when enabling itself. 39 | Only updates should there be a newer version at the source. 40 | 41 | ### VersionsUrl 42 | 43 | /// info | 44 | **Type:** `String` 45 | **Default:** 46 | ```yaml 47 | Settings: 48 | VersionsUrl: 'https://www.andre601.ch/oneversionremake/protocol_versions.json' 49 | ``` 50 | /// 51 | 52 | The URL OneVersionRemake should use to check for an updated file. 53 | Should you change the URL, make sure the new URL follows these requirements: 54 | 55 | - Content-type returned is `application/json` 56 | - The returned Content is a valid JSON file 57 | - [[Since v3.11.0](https://github.com/Andre601/OneVersionRemake/releases/tag/v3.11.0)] The file contains a `file_version` Number option and a `protocols` Array. 58 | 59 | ## Protocol 60 | 61 | Protocol-related options can be found here. This also includes the option to set what Client versions should (not) join your Server. 62 | 63 | ### Versions 64 | 65 | /// info | 66 | **Type:** `List[Integer]` 67 | **Default:** 68 | ```yaml 69 | Protocol: 70 | Versions: [] 71 | ``` 72 | /// 73 | 74 | /// note 75 | You need to use protocol versions and not the MC version. 76 | As an example, to support all 1.21 versions (State: 15th of february 2025) will you need to use the values `767`, `768` and `769`. 77 | 78 | A full list of all available Protocol Versions can be found at https://minecraft.wiki/w/Protocol_version#Java_Edition 79 | 80 | Be aware that only a selected number of versions may be translatable into readable MC versions by the plugin. Please see the [Supported Protocols](protocols.md) page for more. 81 | /// 82 | 83 | Sets the list of allowed client versions that can join the Server. 84 | Should [Blacklist](#blacklist) be enabled will the list be treated as Client versions that should not join your Server. 85 | 86 | ### LogDenial 87 | 88 | /// info | 89 | **Type:** `Boolean` 90 | **Default:** 91 | ```yaml 92 | Protocol: 93 | LogDenial: true 94 | ``` 95 | /// 96 | 97 | Wether OneVersionRemake should log denied joins for players with unsupported Protocol Versions. 98 | 99 | When enabled will the plugin post the following message for every denied Player: 100 | ``` 101 | [OneVersionRemake] Denied login for Player {player} with MC version {version} (Protocol version {protocol}) 102 | ``` 103 | 104 | ### MajorOnly 105 | 106 | /// info | 107 | **Type:** `Boolean` 108 | **Default:** 109 | ```yaml 110 | Protocol: 111 | MajorOnly: false 112 | ``` 113 | /// 114 | 115 | Wether OneVersionRemake should only display the major version for a set of protocols in the `{version}` placeholder. 116 | 117 | /// details | Example 118 | type: example 119 | 120 | //// tab | MajorOnly enabled 121 | **Setup:** 122 | ```yaml 123 | Protocol: 124 | Versions: 125 | - 477 126 | - 480 127 | - 485 128 | - 490 129 | - 498 130 | - 573 131 | - 575 132 | - 578 133 | - 735 134 | - 736 135 | - 751 136 | - 753 137 | - 754 138 | MajorOnly: true 139 | ``` 140 | 141 | **`{version}` Output:** 142 | ``` 143 | 1.14.x, 1.15.x, 1.16.x 144 | ``` 145 | //// 146 | 147 | //// tab | MajorOnly disabled 148 | **Setup:** 149 | ```yaml 150 | Protocol: 151 | Versions: 152 | - 477 153 | - 480 154 | - 485 155 | - 490 156 | - 498 157 | - 573 158 | - 575 159 | - 578 160 | - 735 161 | - 736 162 | - 751 163 | - 753 164 | - 754 165 | MajorOnly: false 166 | ``` 167 | 168 | **`{version}` Output:** 169 | ``` 170 | 1.14, 1.14.2, 1.14.3, 1.14.4, 1.15, 1.15.1, 1.15.2, 1.16, 1.16.1, 1.16.2, 1.16.3, 1.16.5 171 | ``` 172 | //// 173 | /// 174 | 175 | ### Blacklist 176 | 177 | /// info | 178 | **Type:** `Boolean` 179 | **Default:** 180 | ```yaml 181 | Protocol: 182 | Blacklist: false 183 | ``` 184 | /// 185 | 186 | Wether the Provided Protocol List should be treated as a Blacklist. 187 | When enabled will OneVersionRemake deny access to your Server should the Player use any of the versions set. 188 | 189 | ## Messages 190 | 191 | The Messages section contains all the options for customizing the different texts displayed to a player with a denied version. 192 | 193 | ### Supported Formatting 194 | 195 | Please note that OneVersionRemake uses `MiniMessage` for formatting, meaning that instead of color and formatting codes such as `&1` and `&l` would you use `` and `` respectively. 196 | This choice was made deliberately, as MiniMessage allows a much more complex formatting without sacrificing readability in the process (See the ugly aproach of making gradients with color codes). 197 | 198 | As a final note, be aware that the following options **cannot** be used, no matter where they are used: 199 | 200 | - Click actions (``). They won't perform anything on click. 201 | - Custom Fonts (``). May work if the client already has the resource pack loaded. 202 | - Hover text (``). Won't display anything on hover. 203 | - Text insertion (``). Won't do anything on click. 204 | 205 | ### Available Placeholders 206 | 207 | OneVersionRemake provides the following Placeholders: 208 | 209 | | Placeholder | Description | 210 | |-----------------|----------------------------------------------------------------------------------------------------------------------------| 211 | | `{version}` | Gets converted to a comma-separated list of MC versions based on the [protocol versions](#versions) you set. | 212 | | | Should [MajorOnly](#majoronly) be true will only the major versions be listed. | 213 | | `{userVersion}` | Displays the Player's MC version. Should the player use a version not in OVR's Version JSON file, will `???` be displayed. | 214 | 215 | ### PlayerCount 216 | 217 | /// info | 218 | **Type:** `String` 219 | **Default:** 220 | ```yaml 221 | Messages: 222 | PlayerCount: 'Minecraft {version}' 223 | ``` 224 | **Supported formatting:** 225 | 226 | - Basic colors (``, ``, etc.) 227 | - Formatting 228 | /// 229 | 230 | Modifies the text that usually displays the online and total number of players for the server. 231 | Set this to an empty String (`#!yaml PlayerCount: ''`) to not modify the Player count. 232 | 233 | You can also set it to just a color/formatting code (i.e. `#!yaml PlayerCount: ''`) to hide the player count. 234 | 235 | ### Kick 236 | 237 | /// info | 238 | **Type:** `List[String]` 239 | **Default:** 240 | ```yaml 241 | Messages: 242 | Kick: 243 | - 'You are using an unsupported version of Minecraft ({userVersion})!' 244 | - 'This server supports the following Version(s):' 245 | - '{version}' 246 | - '' 247 | - 'Please change your Minecraft Version and try again.' 248 | ``` 249 | **Supported formatting:** 250 | 251 | - Hex Colors (`<#rrggbb>`, includes ``) 252 | - Basic colors (``, ``, etc.) 253 | - Formatting (``, ``, etc.) 254 | /// 255 | 256 | Sets the Message to display when OneVersionRemake kicks the player (Denies the join). 257 | 258 | Note that this option can **not** be disabled and will default to the following kick message when removed or set empty: 259 | ``` 260 | This Server is running MC {version}! Please change your client version. 261 | ``` 262 | 263 | ### Hover 264 | 265 | /// info | 266 | **Type:** `List[String]` 267 | **Default:** 268 | ```yaml 269 | Messages: 270 | Hover: 271 | - 'You are using an unsupported version of Minecraft ({userVersion})!' 272 | - 'Please change your version to {version}.' 273 | ``` 274 | **Supported formatting:** 275 | 276 | - Basic colors (``, ``, etc.) 277 | - Formatting (``, ``, etc.) 278 | /// 279 | 280 | This sets the text that is displayed when the player hovers over the Player count, which usually displays players online on the server. 281 | Set this to an empty List (`#!yaml Hover: []`) to not alter the Hover. 282 | 283 | ### Motd 284 | 285 | /// info | 286 | **Type:** `List[String]` 287 | **Default:** 288 | ```yaml 289 | Messages: 290 | Motd: 291 | - 'Unsupported Minecraft Version {userVersion}' 292 | - 'Please use {version}.' 293 | ``` 294 | **Supported formatting:** 295 | 296 | - Hex Colors (`<#rrggbb>`, includes ``) 297 | - Basic colors (``, ``, etc.) 298 | - Formatting (``, ``, etc.) 299 | /// 300 | 301 | Sets the text to display in the Server's MOTD. 302 | Only the first two lines are considered and every additional one will be ignored. 303 | 304 | Set to an empty List (`#!yaml Motd: []`) to not modify the MOTD. 305 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # Welcome to the OneVersionRemake Wiki 2 | 3 | OneVersionRemake is a plugin that allows you to allow/block specific Minecraft versions from joining your servers, displaying a custom MOTD, player count, hover text and kick message. 4 | 5 | ## Pages 6 | 7 |
8 | 9 | - ## [Config.yml](config.md) 10 | 11 | ---- 12 | 13 | Page covering the different options available in the config.yml of OneVersionRemake 14 | 15 | - ## [Supported Protocols](protocols.md) 16 | 17 | ---- 18 | 19 | A list of supported Protocol Versions that OneVersionRemake can translate into readable MC versions. 20 | 21 |
-------------------------------------------------------------------------------- /docs/protocols.md: -------------------------------------------------------------------------------- 1 | # Supported Protocols 2 | 3 | Due to BungeeCord not offering a way to convert a player's protocol version into a readable MC version, does OneVersionRemake have its own system in place to do so. 4 | This system is used to replace `{version}` and `{userVersion}` with readable MC versions. Former will display a comma-separated list of the configured Protocol Versions while the later will display the Player's MC version. 5 | 6 | To achieve this feature does OneVersionRemake pull from a JSON file which contains the necessary info. The source may differ depending on the version used: 7 | 8 | - `v3.11.0` and newer: https://andre601.ch/oneversionremake/protocol_versions.json ([Source](https://codeberg.org/Andre601/website/src/branch/main/docs/oneversionremake/protocol_versions.json)) 9 | - `v3.9.0` through `v3.10.0`: https://andre601.ch/oneversionremake/versions.json ([Source](https://codeberg.org/Andre601/website/src/branch/main/docs/oneversionremake/versions.json)) 10 | - `v3.8.2` and older: https://raw.githubusercontent.com/Andre601/OneVersionRemake/master/versions.json ([Source](https://github.com/Andre601/OneVersionRemake/blob/master/versions.json)) 11 | 12 | You are free to customize the file to your liking by adding or removing entries from it and you can even [change the source URL to pull from](config.md#versionsurl), just keep the structure of the file in mind. 13 | 14 | /// note 15 | Any protocol version not listed in the JSON file will be displayed as `?` 16 | /// 17 | 18 | ## Versions 19 | 20 | Below is a table of supported Protocol Versions which will be translated into their respective MC version or Major MC Version for the `{version}` and `{userVersion}` placeholder. 21 | 22 | /// note 23 | The table is automatically created using the latest [`protocol_versions.json` file](https://andre601.ch/oneversionremake/protocol_versions.json) as source. 24 | If you're unable to see the Table, make sure you allow Javascript or otherwise check the above link for the JSON file. 25 | /// 26 | 27 |
28 |
29 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: 'OneVersionRemake' 2 | site_description: 'Wiki of the Plugin OneVersionRemake' 3 | site_author: 'Andre_601' 4 | site_url: 'https://ovr.andre601.ch' 5 | 6 | copyright: | 7 | Plugin and Wiki licensed under MIT License. 8 | 9 | docs_dir: 'docs/' 10 | 11 | repo_name: 'OneVersionRemake' 12 | repo_url: 'https://github.com/Andre601/OneVersionRemake' 13 | 14 | theme: 15 | name: 'material' 16 | favicon: 'assets/img/favicon.png' 17 | logo: 'assets/img/favicon.png' 18 | icon: 19 | admonition: 20 | note: octicons/pencil-16 21 | abstract: octicons/checklist-16 22 | info: octicons/info-16 23 | tip: octicons/squirrel-16 24 | success: octicons/check-16 25 | question: octicons/question-16 26 | warning: octicons/alert-16 27 | failure: octicons/x-circle-16 28 | danger: octicons/zap-16 29 | bug: octicons/bug-16 30 | example: octicons/beaker-16 31 | quote: octicons/comment-16 32 | palette: 33 | scheme: 'slate' 34 | primary: 'red' 35 | features: 36 | - navigation.tabs 37 | - navigation.tabs.sticky 38 | 39 | extra: 40 | social: 41 | - icon: 'simple/github' 42 | link: 'https://github.com/Andre601/OneVersionRemake' 43 | - icon: 'simple/modrinth' 44 | link: 'https://modrinth.com/plugin/oneversionremake' 45 | 46 | extra_css: 47 | - 'assets/css/custom.css' 48 | 49 | extra_javascript: 50 | - 'assets/js/version-table-gen.js' 51 | 52 | nav: 53 | - Home: index.md 54 | - Config.yml: config.md 55 | - Supported Protocols: protocols.md 56 | 57 | markdown_extensions: 58 | - md_in_html 59 | - toc: 60 | permalink: true 61 | - pymdownx.highlight 62 | - pymdownx.inlinehilite 63 | - pymdownx.superfences 64 | - pymdownx.magiclink 65 | - pymdownx.blocks.admonition: 66 | types: 67 | - note 68 | - abstract 69 | - info 70 | - tip 71 | - success 72 | - question 73 | - warning 74 | - failure 75 | - danger 76 | - bug 77 | - example 78 | - quote 79 | - pymdownx.blocks.details: 80 | - pymdownx.blocks.tab: 81 | alternate_style: true -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.andre601.oneversionremake 8 | parent 9 | pom 10 | parent 11 | 12 | 13 | UTF-8 14 | 15 | 3.12.0 16 | Only allow specific client versions on your Network. 17 | 18 | 11 19 | 11 20 | 21 | 22 | 23 | core 24 | bungeecord 25 | velocity 26 | 27 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:recommended", 5 | "group:allNonMajor" 6 | ], 7 | "labels": ["Type: Update (Dependency)"], 8 | "packageRules": [ 9 | { 10 | "description": "Apply label for GitHub Actions", 11 | "matchFileNames": [ 12 | ".github/workflows/publish-artifacts.yml", 13 | ".github/workflows/wiki.yml" 14 | ], 15 | "addLabels": ["Target: GitHub Actions"] 16 | }, 17 | { 18 | "description": "Apply label for BungeeCord", 19 | "matchFileNames": ["bungeecord/pom.xml"], 20 | "addLabels": ["Target: BungeeCord"] 21 | }, 22 | { 23 | "description": "Apply label for Core", 24 | "matchFileNames": ["core/pom.xml"], 25 | "addLabels": ["Target: Core"] 26 | }, 27 | { 28 | "description": "Apply label for Velocity", 29 | "matchFileNames": ["velocity/pom.xml"], 30 | "addLabels": ["Target: Velocity"] 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | mkdocs-material==9.6.14 -------------------------------------------------------------------------------- /velocity/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 23 | 4.0.0 24 | 25 | velocity 26 | jar 27 | ${plugin.version} 28 | ${plugin.description} 29 | 30 | 31 | parent 32 | com.andre601.oneversionremake 33 | parent 34 | 35 | 36 | 37 | 38 | velocity 39 | https://repo.papermc.io/repository/maven-public/ 40 | 41 | 42 | sonatype 43 | https://oss.sonatype.org/content/repositories/snapshots/ 44 | 45 | 46 | 47 | 48 | 49 | com.andre601.oneversionremake 50 | core 51 | ${project.version} 52 | compile 53 | 54 | 55 | com.velocitypowered 56 | velocity-api 57 | 3.1.2-SNAPSHOT 58 | provided 59 | 60 | 61 | org.bstats 62 | bstats-velocity 63 | 3.1.0 64 | compile 65 | 66 | 67 | org.spongepowered 68 | configurate-yaml 69 | 4.2.0 70 | 71 | 72 | 73 | 74 | OneVersionRemake-Velocity-${project.version} 75 | 76 | 77 | true 78 | ${project.basedir}/src/main/resources 79 | 80 | 81 | 82 | 83 | org.apache.maven.plugins 84 | maven-compiler-plugin 85 | 3.14.0 86 | 87 | 88 | org.apache.maven.plugins 89 | maven-shade-plugin 90 | 3.6.0 91 | 92 | true 93 | 94 | 95 | org.spongepowered.configurate 96 | com.andre601.oneversionremake.velocity.dependencies.configurate 97 | 98 | 99 | org.bstats 100 | com.andre601.oneversionremake.velocity.dependencies.bstats 101 | 102 | 103 | 104 | 105 | *:* 106 | 107 | META-INF/*.SF 108 | META-INF/*.RSA 109 | META-INF/versions/16/ 110 | 111 | 112 | 113 | 114 | 115 | 116 | package 117 | 118 | shade 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /velocity/src/main/java/com/andre601/oneversionremake/velocity/VelocityCore.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2021 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.velocity; 20 | 21 | import com.andre601.oneversionremake.core.OneVersionRemake; 22 | import com.andre601.oneversionremake.core.Parser; 23 | import com.andre601.oneversionremake.core.commands.CommandHandler; 24 | import com.andre601.oneversionremake.core.proxy.ProtocolVersionResolver; 25 | import com.andre601.oneversionremake.core.proxy.ProxyPlatform; 26 | import com.andre601.oneversionremake.core.files.ConfigHandler; 27 | import com.andre601.oneversionremake.core.interfaces.PluginCore; 28 | import com.andre601.oneversionremake.core.interfaces.ProxyLogger; 29 | import com.andre601.oneversionremake.velocity.commands.CmdOneVersionRemake; 30 | import com.andre601.oneversionremake.velocity.listener.VelocityLoginListener; 31 | import com.andre601.oneversionremake.velocity.listener.VelocityPingListener; 32 | import com.andre601.oneversionremake.velocity.logging.VelocityLogger; 33 | import com.google.inject.Inject; 34 | import com.velocitypowered.api.command.CommandMeta; 35 | import com.velocitypowered.api.event.Subscribe; 36 | import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; 37 | import com.velocitypowered.api.plugin.annotation.DataDirectory; 38 | import com.velocitypowered.api.proxy.ProxyServer; 39 | import com.velocitypowered.api.proxy.server.ServerPing; 40 | import org.bstats.charts.DrilldownPie; 41 | import org.bstats.velocity.Metrics; 42 | import org.slf4j.LoggerFactory; 43 | 44 | import java.nio.file.Path; 45 | import java.util.List; 46 | 47 | public class VelocityCore implements PluginCore{ 48 | 49 | private final ProxyLogger logger; 50 | private final ProxyServer proxy; 51 | private final Path path; 52 | 53 | private final Metrics.Factory factory; 54 | 55 | private OneVersionRemake core; 56 | 57 | @Inject 58 | public VelocityCore(ProxyServer proxy, @DataDirectory Path path, Metrics.Factory factory){ 59 | this.logger = new VelocityLogger(LoggerFactory.getLogger("OneVersionRemake")); 60 | 61 | this.proxy = proxy; 62 | this.path = path; 63 | this.factory = factory; 64 | } 65 | 66 | @Subscribe 67 | public void initialize(ProxyInitializeEvent event){ 68 | this.core = new OneVersionRemake(this); 69 | } 70 | 71 | // PluginCore stuff 72 | 73 | @Override 74 | public void loadCommands(){ 75 | CommandMeta commandMeta = getProxy().getCommandManager() 76 | .metaBuilder("oneversionremake") 77 | .aliases("ovr") 78 | .build(); 79 | 80 | getProxy().getCommandManager().register(commandMeta, new CmdOneVersionRemake(this)); 81 | } 82 | 83 | @Override 84 | public void loadEventListeners(){ 85 | new VelocityLoginListener(this); 86 | new VelocityPingListener(this); 87 | } 88 | 89 | @Override 90 | public void loadMetrics(){ 91 | Metrics metrics = factory.make(this, 10341); 92 | 93 | metrics.addCustomChart(new DrilldownPie("allowed_protocols", () -> core.getPieMap())); 94 | 95 | } 96 | 97 | @Override 98 | public Path getPath(){ 99 | return path; 100 | } 101 | 102 | @Override 103 | public ProxyPlatform getProxyPlatform(){ 104 | return ProxyPlatform.VELOCITY; 105 | } 106 | 107 | @Override 108 | public ProxyLogger getProxyLogger(){ 109 | return logger; 110 | } 111 | 112 | @Override 113 | public ConfigHandler getConfigHandler(){ 114 | return core.getConfigHandler(); 115 | } 116 | 117 | @Override 118 | public ProtocolVersionResolver getProtocolVersionResolver(){ 119 | return core.getProtocolVersionResolver(); 120 | } 121 | 122 | @Override 123 | public CommandHandler getCommandHandler(){ 124 | return core.getCommandHandler(); 125 | } 126 | 127 | @Override 128 | public Parser getComponentParser(){ 129 | return core.getComponentParser(); 130 | } 131 | 132 | @Override 133 | public String getVersion(){ 134 | return core.getVersion(); 135 | } 136 | 137 | @Override 138 | public String getProxyVersion(){ 139 | return getProxy().getVersion().getVersion(); 140 | } 141 | 142 | public ProxyServer getProxy(){ 143 | return proxy; 144 | } 145 | 146 | public ServerPing.SamplePlayer[] getPlayers(List lines, List serverProtocols, int userProtocol, boolean majorOnly, boolean blacklist){ 147 | return core.getPlayers(ServerPing.SamplePlayer.class, lines, serverProtocols, userProtocol, majorOnly, blacklist) 148 | .toArray(new ServerPing.SamplePlayer[0]); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /velocity/src/main/java/com/andre601/oneversionremake/velocity/commands/CmdOneVersionRemake.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2021 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.velocity.commands; 20 | 21 | import com.andre601.oneversionremake.velocity.VelocityCore; 22 | import com.velocitypowered.api.command.SimpleCommand; 23 | 24 | public class CmdOneVersionRemake implements SimpleCommand{ 25 | 26 | private final VelocityCore plugin; 27 | 28 | public CmdOneVersionRemake(VelocityCore plugin){ 29 | this.plugin = plugin; 30 | } 31 | 32 | @Override 33 | public void execute(Invocation invocation){ 34 | VelocitySender sender = new VelocitySender(invocation.source()); 35 | String[] args = invocation.arguments(); 36 | 37 | plugin.getCommandHandler().handle(sender, args); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /velocity/src/main/java/com/andre601/oneversionremake/velocity/commands/VelocitySender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2021 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.velocity.commands; 20 | 21 | import com.andre601.oneversionremake.core.CommandPermissions; 22 | import com.andre601.oneversionremake.core.interfaces.CmdSender; 23 | import com.velocitypowered.api.command.CommandSource; 24 | import net.kyori.adventure.text.Component; 25 | import net.kyori.adventure.text.format.NamedTextColor; 26 | 27 | public class VelocitySender implements CmdSender{ 28 | 29 | private final CommandSource sender; 30 | 31 | public VelocitySender(CommandSource sender){ 32 | this.sender = sender; 33 | } 34 | 35 | @Override 36 | public boolean hasPermission(String permission){ 37 | return sender.hasPermission(permission) || sender.hasPermission(CommandPermissions.ADMIN); 38 | } 39 | 40 | @Override 41 | public void sendMsg(){ 42 | sendMsg(""); 43 | } 44 | 45 | @Override 46 | public void sendMsg(String msg, Object... args){ 47 | sendMsg(NamedTextColor.WHITE, msg, args); 48 | } 49 | 50 | @Override 51 | public void sendMsg(NamedTextColor color, String msg, Object... args){ 52 | sender.sendMessage(Component.text(String.format(msg, args)).color(color)); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /velocity/src/main/java/com/andre601/oneversionremake/velocity/listener/VelocityLoginListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2021 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.velocity.listener; 20 | 21 | import com.andre601.oneversionremake.velocity.VelocityCore; 22 | import com.velocitypowered.api.event.PostOrder; 23 | import com.velocitypowered.api.event.Subscribe; 24 | import com.velocitypowered.api.event.connection.PreLoginEvent; 25 | 26 | import java.util.Collections; 27 | import java.util.List; 28 | 29 | public class VelocityLoginListener{ 30 | 31 | private final VelocityCore plugin; 32 | 33 | public VelocityLoginListener(VelocityCore plugin){ 34 | this.plugin = plugin; 35 | plugin.getProxy().getEventManager().register(plugin, this); 36 | } 37 | 38 | @Subscribe(order = PostOrder.FIRST) 39 | public void onPreLogin(PreLoginEvent event){ 40 | List serverProtocols = plugin.getConfigHandler().getIntList("Protocol", "Versions"); 41 | List kickMessage = plugin.getConfigHandler().getStringList(false, "Messages", "Kick"); 42 | 43 | boolean majorOnly = plugin.getConfigHandler().getBoolean(false, "Protocol", "MajorOnly"); 44 | boolean blacklist = plugin.getConfigHandler().getBoolean(false, "Protocol", "Blacklist"); 45 | 46 | int userProtocol = event.getConnection().getProtocolVersion().getProtocol(); 47 | if(serverProtocols.isEmpty()) 48 | return; 49 | 50 | if((blacklist && serverProtocols.contains(userProtocol)) || (!blacklist && !serverProtocols.contains(userProtocol))){ 51 | if(kickMessage.isEmpty()) 52 | kickMessage = Collections.singletonList("&cThis Server is running MC {version}! Please change your client version."); 53 | 54 | PreLoginEvent.PreLoginComponentResult result = PreLoginEvent.PreLoginComponentResult 55 | .denied(plugin.getComponentParser().toComponent(kickMessage, serverProtocols, userProtocol, majorOnly, blacklist)); 56 | 57 | event.setResult(result); 58 | 59 | if(plugin.getConfigHandler().getBoolean(true, "Protocol", "LogDenial")){ 60 | plugin.getProxyLogger().infoFormat( 61 | "Denied login for Player %s with MC version %s (Protocol version: %d)", 62 | event.getUsername(), 63 | plugin.getProtocolVersionResolver().getVersions().getFriendlyName(userProtocol), 64 | userProtocol 65 | ); 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /velocity/src/main/java/com/andre601/oneversionremake/velocity/listener/VelocityPingListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2021 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.velocity.listener; 20 | 21 | import com.andre601.oneversionremake.velocity.VelocityCore; 22 | import com.velocitypowered.api.event.PostOrder; 23 | import com.velocitypowered.api.event.Subscribe; 24 | import com.velocitypowered.api.event.proxy.ProxyPingEvent; 25 | import com.velocitypowered.api.proxy.server.ServerPing; 26 | 27 | import java.util.Comparator; 28 | import java.util.List; 29 | 30 | public class VelocityPingListener{ 31 | 32 | private final VelocityCore plugin; 33 | 34 | public VelocityPingListener(VelocityCore plugin){ 35 | this.plugin = plugin; 36 | plugin.getProxy().getEventManager().register(plugin, this); 37 | } 38 | 39 | @Subscribe(order = PostOrder.FIRST) 40 | public void onProxyPing(ProxyPingEvent event){ 41 | ServerPing ping = event.getPing(); 42 | ServerPing.Version protocolVersion = ping.getVersion(); 43 | if(protocolVersion == null) 44 | return; 45 | 46 | int userProtocol = protocolVersion.getProtocol(); 47 | 48 | List serverProtocols = plugin.getConfigHandler().getIntList("Protocol", "Versions"); 49 | 50 | if(serverProtocols.isEmpty()) 51 | return; 52 | 53 | serverProtocols.sort(Comparator.reverseOrder()); 54 | 55 | boolean majorOnly = plugin.getConfigHandler().getBoolean(false, "Protocol", "MajorOnly"); 56 | boolean blacklist = plugin.getConfigHandler().getBoolean(false, "Protocol", "Blacklist"); 57 | 58 | String playerCount = plugin.getConfigHandler().getString("", "Messages", "PlayerCount"); 59 | List motd = plugin.getConfigHandler().getStringList(true, "Messages", "Motd"); 60 | List hoverMessage = plugin.getConfigHandler().getStringList(false, "Messages", "Hover"); 61 | 62 | if((blacklist && serverProtocols.contains(userProtocol)) || (!blacklist && !serverProtocols.contains(userProtocol))){ 63 | ServerPing.Builder builder = ping.asBuilder(); 64 | 65 | if(!hoverMessage.isEmpty()){ 66 | ServerPing.SamplePlayer[] players = plugin.getPlayers(hoverMessage, serverProtocols, userProtocol, majorOnly, blacklist); 67 | if(players != null) 68 | builder.samplePlayers(players); 69 | } 70 | 71 | if(!playerCount.isEmpty()){ 72 | playerCount = plugin.getComponentParser().toString(playerCount, serverProtocols, userProtocol, majorOnly, blacklist); 73 | 74 | builder.version(new ServerPing.Version(-1, playerCount)); 75 | } 76 | 77 | if(!motd.isEmpty()){ 78 | builder.description(plugin.getComponentParser().toComponent(motd, serverProtocols, userProtocol, majorOnly, blacklist)); 79 | } 80 | 81 | event.setPing(builder.build()); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /velocity/src/main/java/com/andre601/oneversionremake/velocity/logging/VelocityLogger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2021 Andre601 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 7 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial 10 | * portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 16 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | package com.andre601.oneversionremake.velocity.logging; 20 | 21 | import com.andre601.oneversionremake.core.interfaces.ProxyLogger; 22 | import org.slf4j.Logger; 23 | 24 | public class VelocityLogger implements ProxyLogger{ 25 | 26 | private final Logger logger; 27 | 28 | public VelocityLogger(Logger logger){ 29 | this.logger = logger; 30 | } 31 | 32 | @Override 33 | public void info(String msg){ 34 | logger.info(msg); 35 | } 36 | 37 | @Override 38 | public void infoFormat(String msg, Object... args){ 39 | info(String.format(msg, args)); 40 | } 41 | 42 | @Override 43 | public void warn(String msg){ 44 | logger.warn(msg); 45 | } 46 | 47 | @Override 48 | public void warnFormat(String msg, Object... args){ 49 | warn(String.format(msg, args)); 50 | } 51 | 52 | @Override 53 | public void warn(String msg, Throwable throwable){ 54 | logger.warn(msg, throwable); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /velocity/src/main/resources/velocity-plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "oneversionremake", 3 | "name": "OneVersionRemake", 4 | "version": "${project.version}", 5 | "description": "${project.description}", 6 | "authors": [ 7 | "Andre_601" 8 | ], 9 | "main": "com.andre601.oneversionremake.velocity.VelocityCore" 10 | } 11 | -------------------------------------------------------------------------------- /versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "note": [ 3 | "This file is no longer updated and used by the latest OneVersionRemake version.", 4 | "The latest version can be found at https://codeberg.org/Andre601/website under", 5 | "/docs/oneversionremake/protocol_versions.json", 6 | "", 7 | "This file will no longer receive updates." 8 | ], 9 | "759": { 10 | "name": "1.19", 11 | "major": "1.19.x" 12 | }, 13 | "758": { 14 | "name": "1.18.2", 15 | "major": "1.18.x" 16 | }, 17 | "757": { 18 | "name": "1.18.1", 19 | "major": "1.18.x" 20 | }, 21 | "756": { 22 | "name": "1.17.1", 23 | "major": "1.17.x" 24 | }, 25 | "755": { 26 | "name": "1.17", 27 | "major": "1.17.x" 28 | }, 29 | "754": { 30 | "name": "1.16.5", 31 | "major": "1.16.x" 32 | }, 33 | "753": { 34 | "name": "1.16.3", 35 | "major": "1.16.x" 36 | }, 37 | "751": { 38 | "name": "1.16.2", 39 | "major": "1.16.x" 40 | }, 41 | "736": { 42 | "name": "1.16.1", 43 | "major": "1.16.x" 44 | }, 45 | "735": { 46 | "name": "1.16", 47 | "major": "1.16.x" 48 | }, 49 | "578": { 50 | "name": "1.15.2", 51 | "major": "1.15.x" 52 | }, 53 | "575": { 54 | "name": "1.15.1", 55 | "major": "1.15.x" 56 | }, 57 | "573": { 58 | "name": "1.15", 59 | "major": "1.15.x" 60 | }, 61 | "498": { 62 | "name": "1.14.4", 63 | "major": "1.14.x" 64 | }, 65 | "490": { 66 | "name": "1.14.3", 67 | "major": "1.14.x" 68 | }, 69 | "485": { 70 | "name": "1.14.2", 71 | "major": "1.14.x" 72 | }, 73 | "480": { 74 | "name": "1.14.1", 75 | "major": "1.14.x" 76 | }, 77 | "477": { 78 | "name": "1.14", 79 | "major": "1.14.x" 80 | }, 81 | "404": { 82 | "name": "1.13.2", 83 | "major": "1.13.x" 84 | }, 85 | "401": { 86 | "name": "1.13.1", 87 | "major": "1.13.x" 88 | }, 89 | "393": { 90 | "name": "1.13", 91 | "major": "1.13.x" 92 | }, 93 | "340": { 94 | "name": "1.12.2", 95 | "major": "1.12.x" 96 | }, 97 | "338": { 98 | "name": "1.12.1", 99 | "major": "1.12.x" 100 | }, 101 | "335": { 102 | "name": "1.12", 103 | "major": "1.12.x" 104 | }, 105 | "316": { 106 | "name": "1.11.2", 107 | "major": "1.11.x" 108 | }, 109 | "315": { 110 | "name": "1.11", 111 | "major": "1.11.x" 112 | }, 113 | "210": { 114 | "name": "1.10.2", 115 | "major": "1.10.x" 116 | }, 117 | "110": { 118 | "name": "1.9.4", 119 | "major": "1.9.x" 120 | }, 121 | "109": { 122 | "name": "1.9.2", 123 | "major": "1.9.x" 124 | }, 125 | "108": { 126 | "name": "1.9.1", 127 | "major": "1.9.x" 128 | }, 129 | "107": { 130 | "name": "1.9", 131 | "major": "1.9.x" 132 | }, 133 | "47": { 134 | "name": "1.8.4", 135 | "major": "1.8.x" 136 | } 137 | } 138 | --------------------------------------------------------------------------------