├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── build └── pom.xml ├── bukkit ├── pom.xml └── src │ └── main │ ├── java │ └── net │ │ └── labymod │ │ └── serverapi │ │ └── bukkit │ │ ├── BukkitLabyModConfig.java │ │ ├── LabyModPlugin.java │ │ ├── event │ │ ├── LabyModPlayerJoinEvent.java │ │ ├── MessageReceiveEvent.java │ │ ├── MessageSendEvent.java │ │ └── PermissionsSendEvent.java │ │ ├── listener │ │ └── PlayerJoinListener.java │ │ └── utils │ │ └── PacketUtils.java │ └── resources │ └── plugin.yml ├── bungeecord ├── pom.xml └── src │ └── main │ ├── java │ └── net │ │ └── labymod │ │ └── serverapi │ │ └── bungee │ │ ├── BungeecordLabyModConfig.java │ │ ├── LabyModPlugin.java │ │ ├── event │ │ ├── LabyModPlayerJoinEvent.java │ │ ├── MessageReceiveEvent.java │ │ ├── MessageSendEvent.java │ │ └── PermissionsSendEvent.java │ │ └── listener │ │ ├── PlayerJoinListener.java │ │ └── PluginMessageListener.java │ └── resources │ └── bungee.yml ├── common ├── pom.xml └── src │ └── main │ └── java │ └── net │ └── labymod │ └── serverapi │ ├── Addon.java │ ├── LabyModAPI.java │ ├── LabyModConfig.java │ └── Permission.java └── pom.xml /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | | Q | A 2 | | ---------------- | ----- 3 | | Bug report? | yes/no 4 | | Feature request? | yes/no 5 | | BC Break report? | yes/no 6 | | RFC? | yes/no 7 | 8 | 13 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | | Q | A 2 | | ------------- | --- 3 | | Bug fix? | yes/no 4 | | New feature? | yes/no 5 | | BC breaks? | no 6 | | Deprecations? | yes/no 7 | | Fixed tickets | #... 8 | 9 | 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .idea/ 3 | target/ 4 | dependency-reduced-pom.xml 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Server-API 2 | 3 | ## Bug Reports & Feature Requests 4 | 5 | * [Open an issue](https://github.com/labymod/labymod-server-api/issues) here on GitHub. 6 | If you can, **please provide a fix and create a pull request (PR) instead**; this will automatically create an issue for you. 7 | * Please be patient as not all items will be tested immediately - remember, LabyMod is developed by normal people like you. They have to work or go to school and LabyMod is only a product of their leisure time 8 | * Occasionally we'll close issues if they appear stale or are too vague - please don't take this personally! 9 | Please feel free to re-open issues we've closed if there's something we've missed and they still need to be addressed. 10 | 11 | ## Contributing Pull Requests 12 | PR's are even better than issues. 13 | We gladly accept community pull requests. 14 | There are a few necessary steps before we can accept a pull request: 15 | 16 | * [Open an issue](https://github.com/labymod/labymod-server-api/issues) describing the problem that you are looking to solve in 17 | your PR (if one is not already open), and your approach to solving it (no necessary for bug fixes - only feature contributions). 18 | * [Sign the CLA](https://cla-assistant.io/labymod/labymod-server-api) - see also below. 19 | * [Send a pull request](https://help.github.com/articles/using-pull-requests/) from your fork’s branch to our `master` branch. 20 | 21 | ## Contributor License Agreement 22 | The following terms are used throughout this agreement: 23 | 24 | * **You** - the person or legal entity including its affiliates asked to accept this agreement. An affiliate is any 25 | entity that controls or is controlled by the legal entity, or is under common control with it. 26 | 27 | * **Project** - is an umbrella term that refers to any and all LabyMod open source projects. 28 | 29 | * **Contribution** - any type of work that is submitted to a Project, including any modifications or additions to 30 | existing work. 31 | 32 | * **Submitted** - conveyed to a Project via a pull request, commit, issue, or any form of electronic, written, or 33 | verbal communication with LabyMod, contributors or maintainers. 34 | 35 | #### 1. Grant of Copyright License. 36 | Subject to the terms and conditions of this agreement, You grant to the Projects’ maintainers, contributors, users and 37 | to LabyMod a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, 38 | prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your contributions and such 39 | derivative works. Except for this license, You reserve all rights, title, and interest in your contributions. 40 | 41 | #### 2. Grant of Patent License. 42 | Subject to the terms and conditions of this agreement, You grant to the Projects’ maintainers, contributors, users and 43 | to LabyMod a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) 44 | patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer your contributions, where 45 | such license applies only to those patent claims licensable by you that are necessarily infringed by your contribution 46 | or by combination of your contribution with the project to which this contribution was submitted. 47 | 48 | If any entity institutes patent litigation - including cross-claim or counterclaim in a lawsuit - against You alleging 49 | that your contribution or any project it was submitted to constitutes or is responsible for direct or contributory 50 | patent infringement, then any patent licenses granted to that entity under this agreement shall terminate as of the 51 | date such litigation is filed. 52 | 53 | #### 3. Source of Contribution. 54 | Your contribution is either your original creation, based upon previous work that, to the best of your knowledge, is 55 | covered under an appropriate open source license and you have the right under that license to submit that work with 56 | modifications, whether created in whole or in part by you, or you have clearly identified the source of the contribution 57 | and any license or other restriction (like related patents, trademarks, and license agreements) of which you are 58 | personally aware. 59 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 LabyMedia GmbH 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LabyMod Server API 2 | [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/LabyMod/labymod-server-api/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/LabyMod/labymod-server-api/?branch=master) 3 | [![Discord](https://img.shields.io/discord/412724944112320513.svg)](https://labymod.net/dc/dev) 4 | [![CLA assistant](https://cla-assistant.io/readme/badge/LabyMod/labymod-server-api)](https://cla-assistant.io/LabyMod/labymod-server-api) 5 | 6 | Our new Server API allows you to communicate between the LabyMod client and the server by using simple JSON messages. It also allows you to enable or disable LabyMod features. 7 | If you want to find out how our API works, visit https://docs.labymod.net/pages/server/introduction/ 8 | -------------------------------------------------------------------------------- /build/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | serverapi 7 | net.labymod 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | net.labymod.serverapi 13 | build 14 | 15 | 16 | 17 | 18 | org.apache.maven.plugins 19 | maven-shade-plugin 20 | 2.4.3 21 | 22 | 23 | package 24 | 25 | shade 26 | 27 | 28 | 29 | 30 | 31 | 32 | net.labymod.serverapi:common 33 | net.labymod.serverapi:bukkit 34 | net.labymod.serverapi:bungeecord 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | net.labymod.serverapi 46 | bukkit 47 | 1.0-SNAPSHOT 48 | 49 | 50 | 51 | 52 | net.labymod.serverapi 53 | bungeecord 54 | 1.0-SNAPSHOT 55 | 56 | 57 | 58 | 59 | net.labymod.serverapi 60 | common 61 | 1.0-SNAPSHOT 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /bukkit/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | serverapi 9 | net.labymod 10 | 1.0-SNAPSHOT 11 | 12 | 13 | net.labymod.serverapi 14 | bukkit 15 | 1.0-SNAPSHOT 16 | 17 | 18 | 19 | 20 | org.spigotmc 21 | spigot-api 22 | 1.8.8-R0.1-SNAPSHOT 23 | provided 24 | 25 | 26 | 27 | 28 | org.bukkit 29 | bukkit 30 | 1.8.8-R0.1-SNAPSHOT 31 | provided 32 | 33 | 34 | 35 | 36 | net.labymod.serverapi 37 | common 38 | 1.0-SNAPSHOT 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /bukkit/src/main/java/net/labymod/serverapi/bukkit/BukkitLabyModConfig.java: -------------------------------------------------------------------------------- 1 | package net.labymod.serverapi.bukkit; 2 | 3 | import net.labymod.serverapi.LabyModConfig; 4 | import org.bukkit.configuration.file.FileConfiguration; 5 | import org.bukkit.configuration.file.YamlConfiguration; 6 | 7 | import java.io.File; 8 | import java.io.IOException; 9 | 10 | /** 11 | * Class created by qlow | Jan 12 | */ 13 | public class BukkitLabyModConfig extends LabyModConfig { 14 | 15 | private FileConfiguration fileConfiguration; 16 | 17 | public BukkitLabyModConfig( File file ) { 18 | super( file ); 19 | 20 | // Creating the file if it doesn't exist 21 | if ( !file.exists() ) 22 | try { 23 | file.createNewFile(); 24 | } catch ( IOException e ) { 25 | e.printStackTrace(); 26 | } 27 | 28 | // Loading the config 29 | this.fileConfiguration = YamlConfiguration.loadConfiguration( file ); 30 | 31 | // Initializing the config 32 | init( file ); 33 | } 34 | 35 | @Override 36 | public void init( File file ) { 37 | // Applying options to the config 38 | fileConfiguration.options().copyDefaults( true ); 39 | 40 | // Adding the defaults 41 | addDefaults(); 42 | 43 | // Saving the config after adding the defaults 44 | saveConfig(); 45 | 46 | // Loading the values 47 | loadValues(); 48 | } 49 | 50 | @Override 51 | public Object getValue( String key ) { 52 | return fileConfiguration.get( key ); 53 | } 54 | 55 | @Override 56 | public void addDefault( String key, Object value ) { 57 | fileConfiguration.addDefault( key, value ); 58 | } 59 | 60 | @Override 61 | public void saveConfig() { 62 | try { 63 | fileConfiguration.save( file ); 64 | } catch ( IOException e ) { 65 | e.printStackTrace(); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /bukkit/src/main/java/net/labymod/serverapi/bukkit/LabyModPlugin.java: -------------------------------------------------------------------------------- 1 | package net.labymod.serverapi.bukkit; 2 | 3 | import com.google.gson.JsonElement; 4 | import com.google.gson.JsonObject; 5 | import com.google.gson.JsonParseException; 6 | import com.google.gson.JsonParser; 7 | import io.netty.buffer.ByteBuf; 8 | import io.netty.buffer.Unpooled; 9 | import lombok.Getter; 10 | import net.labymod.serverapi.Addon; 11 | import net.labymod.serverapi.LabyModAPI; 12 | import net.labymod.serverapi.LabyModConfig; 13 | import net.labymod.serverapi.Permission; 14 | import net.labymod.serverapi.bukkit.event.LabyModPlayerJoinEvent; 15 | import net.labymod.serverapi.bukkit.event.MessageReceiveEvent; 16 | import net.labymod.serverapi.bukkit.event.MessageSendEvent; 17 | import net.labymod.serverapi.bukkit.event.PermissionsSendEvent; 18 | import net.labymod.serverapi.bukkit.listener.PlayerJoinListener; 19 | import net.labymod.serverapi.bukkit.utils.PacketUtils; 20 | import org.bukkit.Bukkit; 21 | import org.bukkit.entity.Player; 22 | import org.bukkit.plugin.java.JavaPlugin; 23 | import org.bukkit.plugin.messaging.PluginMessageListener; 24 | 25 | import java.io.File; 26 | import java.util.ArrayList; 27 | import java.util.HashMap; 28 | import java.util.Map; 29 | 30 | /** 31 | * Class created by qlow | Jan 32 | */ 33 | public class LabyModPlugin extends JavaPlugin { 34 | 35 | @Getter 36 | private static LabyModPlugin instance; 37 | 38 | private static final JsonParser JSON_PARSER = new JsonParser(); 39 | 40 | @Getter 41 | private LabyModConfig labyModConfig; 42 | 43 | @Getter 44 | private LabyModAPI api = new LabyModAPI(); 45 | 46 | @Getter 47 | private PacketUtils packetUtils; 48 | 49 | @Override 50 | public void onEnable() { 51 | instance = this; 52 | 53 | // Initializing packet utils 54 | this.packetUtils = new PacketUtils(); 55 | 56 | // Creating the data folder 57 | if ( !getDataFolder().exists() ) 58 | getDataFolder().mkdir(); 59 | 60 | // Initializing the config 61 | this.labyModConfig = new BukkitLabyModConfig( new File( getDataFolder(), "config.yml" ) ); 62 | 63 | // Registering the listeners 64 | Bukkit.getPluginManager().registerEvents( new PlayerJoinListener(), this ); 65 | 66 | // The LABYMOD plugin channel is higly deprecated and shouldn't be used - we just listen to it to retrieve old labymod clients. 67 | // Registering the incoming plugin messages listeners 68 | getServer().getMessenger().registerIncomingPluginChannel( this, "LABYMOD", new PluginMessageListener() { 69 | @Override 70 | public void onPluginMessageReceived( String channel, final Player player, byte[] bytes ) { 71 | // Converting the byte array into a byte buffer 72 | ByteBuf buf = Unpooled.wrappedBuffer( bytes ); 73 | 74 | try { 75 | // Reading the version from the buffer 76 | final String version = api.readString( buf, Short.MAX_VALUE ); 77 | 78 | // Calling the event synchronously 79 | Bukkit.getScheduler().runTask( LabyModPlugin.this, new Runnable() { 80 | @Override 81 | public void run() { 82 | // Checking whether the player is still online 83 | if ( !player.isOnline() ) 84 | return; 85 | 86 | // Calling the LabyModPlayerJoinEvent 87 | Bukkit.getPluginManager().callEvent( new LabyModPlayerJoinEvent( player, version, false, 0, new ArrayList() ) ); 88 | } 89 | } ); 90 | } catch ( RuntimeException ex ) { 91 | } 92 | } 93 | } ); 94 | 95 | getServer().getMessenger().registerIncomingPluginChannel( this, "LMC", new PluginMessageListener() { 96 | @Override 97 | public void onPluginMessageReceived( String channel, final Player player, byte[] bytes ) { 98 | // Converting the byte array into a byte buffer 99 | ByteBuf buf = Unpooled.wrappedBuffer( bytes ); 100 | 101 | try { 102 | // Reading the message key 103 | final String messageKey = api.readString( buf, Short.MAX_VALUE ); 104 | final String messageContents = api.readString( buf, Short.MAX_VALUE ); 105 | final JsonElement jsonMessage = JSON_PARSER.parse( messageContents ); 106 | 107 | // Calling the event synchronously 108 | Bukkit.getScheduler().runTask( LabyModPlugin.this, new Runnable() { 109 | @Override 110 | public void run() { 111 | // Checking whether the player is still online 112 | if ( !player.isOnline() ) 113 | return; 114 | 115 | // Listening to the INFO (join) message 116 | if ( messageKey.equals( "INFO" ) && jsonMessage.isJsonObject() ) { 117 | JsonObject jsonObject = jsonMessage.getAsJsonObject(); 118 | String version = jsonObject.has( "version" ) 119 | && jsonObject.get( "version" ).isJsonPrimitive() 120 | && jsonObject.get( "version" ).getAsJsonPrimitive().isString() ? jsonObject.get( "version" ).getAsString() : "Unknown"; 121 | 122 | boolean chunkCachingEnabled = false; 123 | int chunkCachingVersion = 0; 124 | 125 | if ( jsonObject.has( "ccp" ) && jsonObject.get( "ccp" ).isJsonObject() ) { 126 | JsonObject chunkCachingObject = jsonObject.get( "ccp" ).getAsJsonObject(); 127 | 128 | if ( chunkCachingObject.has( "enabled" ) ) 129 | chunkCachingEnabled = chunkCachingObject.get( "enabled" ).getAsBoolean(); 130 | 131 | if ( chunkCachingObject.has( "version" ) ) 132 | chunkCachingVersion = chunkCachingObject.get( "version" ).getAsInt(); 133 | } 134 | 135 | Bukkit.getPluginManager().callEvent( new LabyModPlayerJoinEvent( player, version, 136 | chunkCachingEnabled, chunkCachingVersion, Addon.getAddons( jsonObject ) ) ); 137 | return; 138 | } 139 | 140 | // Calling the MessageReceiveEvent 141 | Bukkit.getPluginManager().callEvent( new MessageReceiveEvent( player, messageKey, jsonMessage ) ); 142 | } 143 | } ); 144 | } catch ( RuntimeException ignored ) { 145 | } 146 | } 147 | } ); 148 | } 149 | 150 | @Override 151 | public void onDisable() { 152 | // Unregistering the plugin-message listeners 153 | getServer().getMessenger().unregisterIncomingPluginChannel( this, "LABYMOD" ); 154 | getServer().getMessenger().unregisterIncomingPluginChannel( this, "LMC" ); 155 | } 156 | 157 | /** 158 | * Sends the modified permissions to the given player 159 | * 160 | * @param player the player the permissions should be sent to 161 | */ 162 | public void sendPermissions( Player player ) { 163 | Map modifiedPermissions = new HashMap<>( labyModConfig.getPermissions() ); 164 | 165 | // Calling the Bukkit event 166 | PermissionsSendEvent sendEvent = new PermissionsSendEvent( player, modifiedPermissions, false ); 167 | Bukkit.getPluginManager().callEvent( sendEvent ); 168 | 169 | // Sending the packet 170 | if ( !sendEvent.isCancelled() && sendEvent.getPermissions().size() > 0 ) 171 | packetUtils.sendPacket( player, packetUtils.getPluginMessagePacket( "LMC", api.getBytesToSend( modifiedPermissions ) ) ); 172 | } 173 | 174 | /** 175 | * Sends a JSON server-message to the player 176 | * 177 | * @param player the player the message should be sent to 178 | * @param messageKey the message's key 179 | * @param messageContents the message's contents 180 | */ 181 | public void sendServerMessage( Player player, String messageKey, JsonElement messageContents ) { 182 | messageContents = cloneJson( messageContents ); 183 | 184 | // Calling the Bukkit event 185 | MessageSendEvent sendEvent = new MessageSendEvent( player, messageKey, messageContents, false ); 186 | Bukkit.getPluginManager().callEvent( sendEvent ); 187 | 188 | // Sending the packet 189 | if ( !sendEvent.isCancelled() ) 190 | packetUtils.sendPacket( player, packetUtils.getPluginMessagePacket( "LMC", api.getBytesToSend( messageKey, messageContents.toString() ) ) ); 191 | } 192 | 193 | /** 194 | * Clones a JsonElement 195 | * 196 | * @param cloneElement the element that should be cloned 197 | * @return the cloned element 198 | */ 199 | public JsonElement cloneJson( JsonElement cloneElement ) { 200 | try { 201 | return JSON_PARSER.parse( cloneElement.toString() ); 202 | } catch ( JsonParseException ex ) { 203 | ex.printStackTrace(); 204 | return null; 205 | } 206 | } 207 | 208 | } 209 | -------------------------------------------------------------------------------- /bukkit/src/main/java/net/labymod/serverapi/bukkit/event/LabyModPlayerJoinEvent.java: -------------------------------------------------------------------------------- 1 | package net.labymod.serverapi.bukkit.event; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import net.labymod.serverapi.Addon; 6 | import org.bukkit.entity.Player; 7 | import org.bukkit.event.Event; 8 | import org.bukkit.event.HandlerList; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * Class created by qlow | Jan 14 | */ 15 | @AllArgsConstructor 16 | @Getter 17 | public class LabyModPlayerJoinEvent extends Event { 18 | 19 | @Getter 20 | private final static HandlerList handlerList = new HandlerList(); 21 | 22 | private Player player; 23 | private String modVersion; 24 | private boolean chunkCachingEnabled; 25 | private int chunkCachingVersion; 26 | private List addons; 27 | 28 | @Override 29 | public HandlerList getHandlers() { 30 | return handlerList; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /bukkit/src/main/java/net/labymod/serverapi/bukkit/event/MessageReceiveEvent.java: -------------------------------------------------------------------------------- 1 | package net.labymod.serverapi.bukkit.event; 2 | 3 | import com.google.gson.JsonElement; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Getter; 6 | import org.bukkit.entity.Player; 7 | import org.bukkit.event.Event; 8 | import org.bukkit.event.HandlerList; 9 | 10 | /** 11 | * Class created by qlow | Jan 12 | */ 13 | @AllArgsConstructor 14 | @Getter 15 | public class MessageReceiveEvent extends Event { 16 | 17 | @Getter 18 | private final static HandlerList handlerList = new HandlerList(); 19 | 20 | private Player player; 21 | private String messageKey; 22 | private JsonElement jsonElement; 23 | 24 | @Override 25 | public HandlerList getHandlers() { 26 | return handlerList; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /bukkit/src/main/java/net/labymod/serverapi/bukkit/event/MessageSendEvent.java: -------------------------------------------------------------------------------- 1 | package net.labymod.serverapi.bukkit.event; 2 | 3 | import com.google.gson.JsonElement; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import org.bukkit.entity.Player; 8 | import org.bukkit.event.Cancellable; 9 | import org.bukkit.event.Event; 10 | import org.bukkit.event.HandlerList; 11 | 12 | /** 13 | * Class created by qlow | Jan 14 | */ 15 | @AllArgsConstructor 16 | @Getter 17 | public class MessageSendEvent extends Event implements Cancellable { 18 | 19 | @Getter 20 | private final static HandlerList handlerList = new HandlerList(); 21 | 22 | private Player player; 23 | private String messageKey; 24 | private JsonElement jsonElement; 25 | @Setter 26 | private boolean cancelled; 27 | 28 | @Override 29 | public HandlerList getHandlers() { 30 | return handlerList; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /bukkit/src/main/java/net/labymod/serverapi/bukkit/event/PermissionsSendEvent.java: -------------------------------------------------------------------------------- 1 | package net.labymod.serverapi.bukkit.event; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import net.labymod.serverapi.Permission; 7 | import org.bukkit.entity.Player; 8 | import org.bukkit.event.Cancellable; 9 | import org.bukkit.event.Event; 10 | import org.bukkit.event.HandlerList; 11 | 12 | import java.util.EnumMap; 13 | import java.util.Map; 14 | 15 | /** 16 | * Class created by qlow | Jan 17 | */ 18 | @AllArgsConstructor 19 | @Getter 20 | public class PermissionsSendEvent extends Event implements Cancellable { 21 | 22 | @Getter 23 | private final static HandlerList handlerList = new HandlerList(); 24 | 25 | private Player player; 26 | private Map permissions = new EnumMap<>( Permission.class ); 27 | @Setter 28 | private boolean cancelled; 29 | 30 | @Override 31 | public HandlerList getHandlers() { 32 | return handlerList; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /bukkit/src/main/java/net/labymod/serverapi/bukkit/listener/PlayerJoinListener.java: -------------------------------------------------------------------------------- 1 | package net.labymod.serverapi.bukkit.listener; 2 | 3 | import net.labymod.serverapi.bukkit.LabyModPlugin; 4 | import org.bukkit.entity.Player; 5 | import org.bukkit.event.EventHandler; 6 | import org.bukkit.event.Listener; 7 | import org.bukkit.event.player.PlayerJoinEvent; 8 | 9 | /** 10 | * Class created by qlow | Jan 11 | */ 12 | public class PlayerJoinListener implements Listener { 13 | 14 | @EventHandler 15 | public void onJoin( PlayerJoinEvent event ) { 16 | Player player = event.getPlayer(); 17 | 18 | // Sending the permissions 19 | LabyModPlugin.getInstance().sendPermissions( player ); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /bukkit/src/main/java/net/labymod/serverapi/bukkit/utils/PacketUtils.java: -------------------------------------------------------------------------------- 1 | package net.labymod.serverapi.bukkit.utils; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.buffer.Unpooled; 5 | import lombok.Getter; 6 | import net.labymod.serverapi.bukkit.LabyModPlugin; 7 | import org.bukkit.Bukkit; 8 | import org.bukkit.entity.Player; 9 | 10 | import java.lang.reflect.Constructor; 11 | import java.lang.reflect.Field; 12 | import java.lang.reflect.InvocationTargetException; 13 | import java.lang.reflect.Method; 14 | 15 | /** 16 | * Class created by qlow | Jan 17 | */ 18 | public class PacketUtils { 19 | 20 | private String version; 21 | 22 | private Class packetClass; 23 | 24 | private Class packetPlayOutCustomPayloadClass; 25 | private Constructor customPayloadConstructor; 26 | private boolean customPayloadHasBytes; 27 | 28 | private Class packetDataSerializerClass; 29 | private Constructor packetDataSerializerConstructor; 30 | 31 | private Method getHandleMethod; 32 | private Field playerConnectionField; 33 | @Getter 34 | private Field networkManagerField; 35 | 36 | public PacketUtils() { 37 | this.version = Bukkit.getServer().getClass().getPackage().getName().replace( ".", "," ).split( "," )[3]; 38 | 39 | try { 40 | this.packetClass = getNmsClass( "Packet" ); 41 | this.packetPlayOutCustomPayloadClass = getNmsClass( "PacketPlayOutCustomPayload" ); 42 | this.networkManagerField = getNmsClass( "PlayerConnection" ).getDeclaredField( "networkManager" ); 43 | } catch ( ClassNotFoundException | NoSuchFieldException e ) { 44 | e.printStackTrace(); 45 | } 46 | 47 | if ( this.packetPlayOutCustomPayloadClass != null ) { 48 | for ( Constructor constructors : packetPlayOutCustomPayloadClass.getDeclaredConstructors() ) { 49 | if ( constructors.getParameterTypes().length == 2 && constructors.getParameterTypes()[1] == byte[].class ) { 50 | customPayloadHasBytes = true; 51 | customPayloadConstructor = constructors; 52 | } else if ( constructors.getParameterTypes().length == 2 && constructors.getParameterTypes()[1].getSimpleName().equals( "PacketDataSerializer" ) ) { 53 | customPayloadConstructor = constructors; 54 | } 55 | } 56 | 57 | if ( !customPayloadHasBytes ) { 58 | try { 59 | packetDataSerializerClass = getNmsClass( "PacketDataSerializer" ); 60 | packetDataSerializerConstructor = packetDataSerializerClass.getDeclaredConstructor( ByteBuf.class ); 61 | } catch ( Exception ex ) { 62 | ex.printStackTrace(); 63 | LabyModPlugin.getInstance().getLogger().severe( "Couldn't find a valid constructor for PacketPlayOutCustomPayload. Disabling the plugin." ); 64 | Bukkit.getPluginManager().disablePlugin( LabyModPlugin.getInstance() ); 65 | } 66 | } 67 | } 68 | } 69 | 70 | /** 71 | * Gets the player's nms-handle 72 | * 73 | * @param player the bukkit-player 74 | * @return the nms-handle 75 | */ 76 | public Object getPlayerHandle( Player player ) { 77 | try { 78 | if ( getHandleMethod == null ) 79 | getHandleMethod = player.getClass().getMethod( "getHandle" ); 80 | 81 | // Getting the player's nms-handle 82 | return getHandleMethod.invoke( player ); 83 | } catch ( Exception ex ) { 84 | ex.printStackTrace(); 85 | } 86 | 87 | return null; 88 | } 89 | 90 | /** 91 | * Gets the player's connection 92 | * 93 | * @param nmsPlayer the player's nms-handle 94 | * @return the player-connection 95 | */ 96 | public Object getPlayerConnection( Object nmsPlayer ) { 97 | try { 98 | if ( playerConnectionField == null ) 99 | playerConnectionField = nmsPlayer.getClass().getField( "playerConnection" ); 100 | 101 | // Getting the player's connection 102 | return playerConnectionField.get( nmsPlayer ); 103 | } catch ( IllegalAccessException | NoSuchFieldException e ) { 104 | e.printStackTrace(); 105 | } 106 | 107 | return null; 108 | } 109 | 110 | /** 111 | * Sends a packet to the given player 112 | * 113 | * @param player the player the packet should be sent to 114 | * @param packet the packet that should be sent to the player 115 | */ 116 | public void sendPacket( Player player, Object packet ) { 117 | try { 118 | // Getting the player's nms-handle 119 | Object nmsPlayer = getPlayerHandle( player ); 120 | 121 | // Getting the player's connection 122 | Object playerConnection = getPlayerConnection( nmsPlayer ); 123 | 124 | // Sending the packet 125 | playerConnection.getClass().getMethod( "sendPacket", packetClass ).invoke( playerConnection, packet ); 126 | } catch ( Exception ex ) { 127 | ex.printStackTrace(); 128 | } 129 | } 130 | 131 | /** 132 | * Gets a constructed plugin message packet 133 | * 134 | * @param channel the channel-name 135 | * @param bytes the bytes that should be sent with the packet 136 | * @return a plugin-message packet 137 | */ 138 | public Object getPluginMessagePacket( String channel, byte[] bytes ) { 139 | try { 140 | return customPayloadConstructor.newInstance( channel, customPayloadHasBytes ? bytes : packetDataSerializerConstructor.newInstance( Unpooled.wrappedBuffer( bytes ) ) ); 141 | } catch ( NullPointerException | InstantiationException | IllegalAccessException | InvocationTargetException e ) { 142 | LabyModPlugin.getInstance().getLogger().severe( "Couldn't construct a custom-payload packet (Channel: " + channel + "):" ); 143 | e.printStackTrace(); 144 | } 145 | 146 | return null; 147 | } 148 | 149 | /** 150 | * Gets a nms-class 151 | * 152 | * @param nmsClassName the nms-class name 153 | * @return the multi-version compatible name of the class including the package 154 | * @throws ClassNotFoundException if the class wasn't found 155 | */ 156 | public Class getNmsClass( String nmsClassName ) throws ClassNotFoundException { 157 | return Class.forName( "net.minecraft.server." + version + "." + nmsClassName ); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /bukkit/src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: LabyModAPI 2 | author: LabyMedia 3 | version: 1.1 4 | main: net.labymod.serverapi.bukkit.LabyModPlugin -------------------------------------------------------------------------------- /bungeecord/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | serverapi 7 | net.labymod 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | net.labymod.serverapi 13 | bungeecord 14 | 15 | 16 | 17 | bungeecord-repo 18 | https://oss.sonatype.org/content/repositories/snapshots 19 | 20 | 21 | 22 | 23 | 24 | 25 | net.md-5 26 | bungeecord-api 27 | 1.12-SNAPSHOT 28 | jar 29 | provided 30 | 31 | 32 | 33 | 34 | net.md-5 35 | bungeecord-api 36 | 1.12-SNAPSHOT 37 | javadoc 38 | provided 39 | 40 | 41 | 42 | 43 | net.labymod.serverapi 44 | common 45 | 1.0-SNAPSHOT 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /bungeecord/src/main/java/net/labymod/serverapi/bungee/BungeecordLabyModConfig.java: -------------------------------------------------------------------------------- 1 | package net.labymod.serverapi.bungee; 2 | 3 | import net.labymod.serverapi.LabyModConfig; 4 | import net.md_5.bungee.config.Configuration; 5 | import net.md_5.bungee.config.ConfigurationProvider; 6 | import net.md_5.bungee.config.YamlConfiguration; 7 | 8 | import java.io.File; 9 | import java.io.IOException; 10 | 11 | /** 12 | * Class created by qlow | Jan 13 | */ 14 | public class BungeecordLabyModConfig extends LabyModConfig { 15 | 16 | private Configuration configuration; 17 | 18 | public BungeecordLabyModConfig( File file ) { 19 | super( file ); 20 | 21 | // Creating the file if it doesn't exist 22 | if ( !file.exists() ) 23 | try { 24 | file.createNewFile(); 25 | } catch ( IOException e ) { 26 | e.printStackTrace(); 27 | } 28 | 29 | // Initializing the config 30 | init( file ); 31 | } 32 | 33 | @Override 34 | public void init( File file ) { 35 | // Loading the config 36 | try { 37 | this.configuration = ConfigurationProvider.getProvider( YamlConfiguration.class ).load( file ); 38 | } catch ( IOException e ) { 39 | e.printStackTrace(); 40 | } 41 | 42 | // Adding the defaults 43 | addDefaults(); 44 | 45 | // Saving the config after adding the defaults 46 | saveConfig(); 47 | 48 | // Loading the values 49 | loadValues(); 50 | } 51 | 52 | @Override 53 | public Object getValue( String key ) { 54 | return configuration.get( key ); 55 | } 56 | 57 | @Override 58 | public void addDefault( String key, Object value ) { 59 | if ( !configuration.contains( key ) ) 60 | configuration.set( key, value ); 61 | } 62 | 63 | @Override 64 | public void saveConfig() { 65 | try { 66 | ConfigurationProvider.getProvider( YamlConfiguration.class ).save( configuration, file ); 67 | } catch ( IOException e ) { 68 | e.printStackTrace(); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /bungeecord/src/main/java/net/labymod/serverapi/bungee/LabyModPlugin.java: -------------------------------------------------------------------------------- 1 | package net.labymod.serverapi.bungee; 2 | 3 | import com.google.gson.JsonElement; 4 | import com.google.gson.JsonParseException; 5 | import com.google.gson.JsonParser; 6 | import lombok.Getter; 7 | import net.labymod.serverapi.LabyModAPI; 8 | import net.labymod.serverapi.LabyModConfig; 9 | import net.labymod.serverapi.Permission; 10 | import net.labymod.serverapi.bungee.event.MessageSendEvent; 11 | import net.labymod.serverapi.bungee.event.PermissionsSendEvent; 12 | import net.labymod.serverapi.bungee.listener.PlayerJoinListener; 13 | import net.labymod.serverapi.bungee.listener.PluginMessageListener; 14 | import net.md_5.bungee.api.connection.ProxiedPlayer; 15 | import net.md_5.bungee.api.plugin.Plugin; 16 | import net.md_5.bungee.protocol.packet.PluginMessage; 17 | 18 | import java.io.File; 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | 22 | /** 23 | * Class created by qlow | Jan 24 | */ 25 | public class LabyModPlugin extends Plugin { 26 | 27 | @Getter 28 | private static LabyModPlugin instance; 29 | 30 | private static final JsonParser JSON_PARSER = new JsonParser(); 31 | 32 | @Getter 33 | private LabyModConfig labyModConfig; 34 | 35 | @Getter 36 | private LabyModAPI api = new LabyModAPI(); 37 | 38 | @Override 39 | public void onEnable() { 40 | instance = this; 41 | 42 | // Creating the data folder 43 | if ( !getDataFolder().exists() ) 44 | getDataFolder().mkdir(); 45 | 46 | // Initializing the config 47 | this.labyModConfig = new BungeecordLabyModConfig( new File( getDataFolder(), "config.yml" ) ); 48 | 49 | // Registering the listeners 50 | getProxy().getPluginManager().registerListener( this, new PlayerJoinListener() ); 51 | getProxy().getPluginManager().registerListener( this, new PluginMessageListener() ); 52 | } 53 | 54 | /** 55 | * Sends the modified permissions to the given player 56 | * 57 | * @param player the player the permissions should be sent to 58 | */ 59 | public void sendPermissions( ProxiedPlayer player ) { 60 | Map modifiedPermissions = new HashMap<>( labyModConfig.getPermissions() ); 61 | 62 | // Calling the Bukkit event 63 | PermissionsSendEvent sendEvent = new PermissionsSendEvent( player, modifiedPermissions, false ); 64 | getProxy().getPluginManager().callEvent( sendEvent ); 65 | 66 | // Sending the packet 67 | if ( !sendEvent.isCancelled() ) 68 | player.unsafe().sendPacket( new PluginMessage( "LMC", api.getBytesToSend( modifiedPermissions ), false ) ); 69 | } 70 | 71 | /** 72 | * Sends a JSON server-message to the player 73 | * 74 | * @param player the player the message should be sent to 75 | * @param messageKey the message's key 76 | * @param messageContents the message's contents 77 | */ 78 | public void sendServerMessage( ProxiedPlayer player, String messageKey, JsonElement messageContents ) { 79 | messageContents = cloneJson( messageContents ); 80 | 81 | // Calling the Bukkit event 82 | MessageSendEvent sendEvent = new MessageSendEvent( player, messageKey, messageContents, false ); 83 | getProxy().getPluginManager().callEvent( sendEvent ); 84 | 85 | // Sending the packet 86 | if ( !sendEvent.isCancelled() ) 87 | player.unsafe().sendPacket( new PluginMessage( "LMC", api.getBytesToSend( messageKey, messageContents.toString() ), false ) ); 88 | } 89 | 90 | /** 91 | * Clones a JsonElement 92 | * 93 | * @param cloneElement the element that should be cloned 94 | * @return the cloned element 95 | */ 96 | public JsonElement cloneJson( JsonElement cloneElement ) { 97 | try { 98 | return JSON_PARSER.parse( cloneElement.toString() ); 99 | } catch ( JsonParseException ex ) { 100 | ex.printStackTrace(); 101 | return null; 102 | } 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /bungeecord/src/main/java/net/labymod/serverapi/bungee/event/LabyModPlayerJoinEvent.java: -------------------------------------------------------------------------------- 1 | package net.labymod.serverapi.bungee.event; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import net.labymod.serverapi.Addon; 7 | import net.md_5.bungee.api.connection.ProxiedPlayer; 8 | import net.md_5.bungee.api.plugin.Event; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * Class created by qlow | Jan 14 | */ 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @Getter 18 | public class LabyModPlayerJoinEvent extends Event { 19 | 20 | private ProxiedPlayer player; 21 | private String modVersion; 22 | private boolean chunkCachingEnabled; 23 | private int chunkCachingVersion; 24 | private List addons; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /bungeecord/src/main/java/net/labymod/serverapi/bungee/event/MessageReceiveEvent.java: -------------------------------------------------------------------------------- 1 | package net.labymod.serverapi.bungee.event; 2 | 3 | import com.google.gson.JsonElement; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Getter; 6 | import lombok.NoArgsConstructor; 7 | import net.md_5.bungee.api.connection.ProxiedPlayer; 8 | import net.md_5.bungee.api.plugin.Event; 9 | 10 | /** 11 | * Class created by qlow | Jan 12 | */ 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | @Getter 16 | public class MessageReceiveEvent extends Event { 17 | 18 | private ProxiedPlayer player; 19 | private String messageKey; 20 | private JsonElement jsonElement; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /bungeecord/src/main/java/net/labymod/serverapi/bungee/event/MessageSendEvent.java: -------------------------------------------------------------------------------- 1 | package net.labymod.serverapi.bungee.event; 2 | 3 | import com.google.gson.JsonElement; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Getter; 6 | import lombok.NoArgsConstructor; 7 | import lombok.Setter; 8 | import net.md_5.bungee.api.connection.ProxiedPlayer; 9 | import net.md_5.bungee.api.plugin.Event; 10 | 11 | /** 12 | * Class created by qlow | Jan 13 | */ 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | @Getter 17 | public class MessageSendEvent extends Event { 18 | 19 | private ProxiedPlayer player; 20 | private String messageKey; 21 | private JsonElement jsonElement; 22 | @Setter 23 | private boolean cancelled; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /bungeecord/src/main/java/net/labymod/serverapi/bungee/event/PermissionsSendEvent.java: -------------------------------------------------------------------------------- 1 | package net.labymod.serverapi.bungee.event; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | import net.labymod.serverapi.Permission; 8 | import net.md_5.bungee.api.connection.ProxiedPlayer; 9 | import net.md_5.bungee.api.plugin.Cancellable; 10 | import net.md_5.bungee.api.plugin.Event; 11 | 12 | import java.util.EnumMap; 13 | import java.util.Map; 14 | 15 | /** 16 | * Class created by qlow | Jan 17 | */ 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Getter 21 | public class PermissionsSendEvent extends Event implements Cancellable { 22 | 23 | private ProxiedPlayer player; 24 | private Map permissions = new EnumMap<>( Permission.class ); 25 | @Setter 26 | private boolean cancelled; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /bungeecord/src/main/java/net/labymod/serverapi/bungee/listener/PlayerJoinListener.java: -------------------------------------------------------------------------------- 1 | package net.labymod.serverapi.bungee.listener; 2 | 3 | import net.labymod.serverapi.bungee.LabyModPlugin; 4 | import net.md_5.bungee.api.event.PostLoginEvent; 5 | import net.md_5.bungee.api.plugin.Listener; 6 | import net.md_5.bungee.event.EventHandler; 7 | 8 | /** 9 | * Class created by qlow | Jan 10 | */ 11 | public class PlayerJoinListener implements Listener { 12 | 13 | @EventHandler 14 | public void onJoin( PostLoginEvent event ) { 15 | // Sending the permissions 16 | LabyModPlugin.getInstance().sendPermissions( event.getPlayer() ); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /bungeecord/src/main/java/net/labymod/serverapi/bungee/listener/PluginMessageListener.java: -------------------------------------------------------------------------------- 1 | package net.labymod.serverapi.bungee.listener; 2 | 3 | import com.google.gson.JsonElement; 4 | import com.google.gson.JsonObject; 5 | import com.google.gson.JsonParser; 6 | import io.netty.buffer.ByteBuf; 7 | import io.netty.buffer.Unpooled; 8 | import lombok.Getter; 9 | import net.labymod.serverapi.Addon; 10 | import net.labymod.serverapi.bungee.LabyModPlugin; 11 | import net.labymod.serverapi.bungee.event.LabyModPlayerJoinEvent; 12 | import net.labymod.serverapi.bungee.event.MessageReceiveEvent; 13 | import net.md_5.bungee.api.ProxyServer; 14 | import net.md_5.bungee.api.connection.ProxiedPlayer; 15 | import net.md_5.bungee.api.event.PluginMessageEvent; 16 | import net.md_5.bungee.api.plugin.Listener; 17 | import net.md_5.bungee.event.EventHandler; 18 | 19 | import java.util.ArrayList; 20 | import java.util.concurrent.TimeUnit; 21 | 22 | /** 23 | * Class created by qlow | Jan 24 | */ 25 | public class PluginMessageListener implements Listener { 26 | 27 | @Getter 28 | private final static JsonParser jsonParser = new JsonParser(); 29 | 30 | @EventHandler 31 | public void onPluginMessage( PluginMessageEvent event ) { 32 | if ( !(event.getSender() instanceof ProxiedPlayer) ) 33 | return; 34 | 35 | final ProxiedPlayer player = ( ProxiedPlayer ) event.getSender(); 36 | 37 | // The LABYMOD plugin channel is higly deprecated and shouldn't be used - we just listen to it to retrieve old labymod clients. 38 | if ( event.getTag().equals( "LABYMOD" ) ) { 39 | // Converting the byte array into a byte buffer 40 | ByteBuf buf = Unpooled.wrappedBuffer( event.getData() ); 41 | 42 | try { 43 | // Reading the version from the buffer 44 | final String version = LabyModPlugin.getInstance().getApi().readString( buf, Short.MAX_VALUE ); 45 | 46 | // Calling the event synchronously 47 | ProxyServer.getInstance().getScheduler().schedule( LabyModPlugin.getInstance(), new Runnable() { 48 | @Override 49 | public void run() { 50 | // Calling the LabyModPlayerJoinEvent 51 | ProxyServer.getInstance().getPluginManager().callEvent( new LabyModPlayerJoinEvent( player, version, false, 0, new ArrayList() ) ); 52 | } 53 | }, 0L, TimeUnit.SECONDS ); 54 | } catch ( RuntimeException ex ) { 55 | ex.printStackTrace(); 56 | } 57 | } 58 | 59 | if ( event.getTag().equals( "LMC" ) ) { 60 | // Converting the byte array into a byte buffer 61 | ByteBuf buf = Unpooled.wrappedBuffer( event.getData() ); 62 | 63 | try { 64 | // Reading the message key 65 | final String messageKey = LabyModPlugin.getInstance().getApi().readString( buf, Short.MAX_VALUE ); 66 | final String messageContents = LabyModPlugin.getInstance().getApi().readString( buf, Short.MAX_VALUE ); 67 | final JsonElement jsonMessage = jsonParser.parse( messageContents ); 68 | 69 | // Calling the event synchronously 70 | ProxyServer.getInstance().getScheduler().schedule( LabyModPlugin.getInstance(), new Runnable() { 71 | @Override 72 | public void run() { 73 | // Listening to the INFO (join) message 74 | if ( messageKey.equals( "INFO" ) && jsonMessage.isJsonObject() ) { 75 | JsonObject jsonObject = jsonMessage.getAsJsonObject(); 76 | String version = jsonObject.has( "version" ) 77 | && jsonObject.get( "version" ).isJsonPrimitive() 78 | && jsonObject.get( "version" ).getAsJsonPrimitive().isString() ? jsonObject.get( "version" ).getAsString() : "Unknown"; 79 | 80 | boolean chunkCachingEnabled = false; 81 | int chunkCachingVersion = 0; 82 | 83 | if ( jsonObject.has( "ccp" ) && jsonObject.get( "ccp" ).isJsonObject() ) { 84 | JsonObject chunkCachingObject = jsonObject.get( "ccp" ).getAsJsonObject(); 85 | 86 | if ( chunkCachingObject.has( "enabled" ) ) 87 | chunkCachingEnabled = chunkCachingObject.get( "enabled" ).getAsBoolean(); 88 | 89 | if ( chunkCachingObject.has( "version" ) ) 90 | chunkCachingVersion = chunkCachingObject.get( "version" ).getAsInt(); 91 | } 92 | 93 | ProxyServer.getInstance().getPluginManager().callEvent( new LabyModPlayerJoinEvent( player, version, 94 | chunkCachingEnabled, chunkCachingVersion, Addon.getAddons( jsonObject ) ) ); 95 | return; 96 | } 97 | 98 | // Calling the LabyModPlayerJoinEvent 99 | ProxyServer.getInstance().getPluginManager().callEvent( new MessageReceiveEvent( player, messageKey, jsonMessage ) ); 100 | } 101 | }, 0L, TimeUnit.SECONDS ); 102 | } catch ( RuntimeException ex ) { 103 | ex.printStackTrace(); 104 | } 105 | } 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /bungeecord/src/main/resources/bungee.yml: -------------------------------------------------------------------------------- 1 | name: LabyModAPI 2 | author: LabyMedia 3 | version: 1.1 4 | main: net.labymod.serverapi.bungee.LabyModPlugin -------------------------------------------------------------------------------- /common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | serverapi 9 | net.labymod 10 | 1.0-SNAPSHOT 11 | 12 | 13 | net.labymod.serverapi 14 | common 15 | 1.0-SNAPSHOT 16 | 17 | 18 | 19 | 20 | io.netty 21 | netty-all 22 | 4.1.42.Final 23 | 24 | 25 | 26 | 27 | com.google.code.gson 28 | gson 29 | 2.2.4 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /common/src/main/java/net/labymod/serverapi/Addon.java: -------------------------------------------------------------------------------- 1 | package net.labymod.serverapi; 2 | 3 | import com.google.gson.JsonElement; 4 | import com.google.gson.JsonObject; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Getter; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.UUID; 11 | 12 | /** 13 | * An Addon represents a player's addon 14 | * The addons are being sent when a user joins the server 15 | * You can retrieve them by using LabyModPlayerJoinEvent#getAddons() 16 | * 17 | * @author Jan 18 | */ 19 | @AllArgsConstructor 20 | @Getter 21 | public class Addon { 22 | 23 | private UUID uuid; 24 | private String name; 25 | 26 | /** 27 | * Parses the addons from the INFO plugin message 28 | * 29 | * @param jsonObject the json object of the message 30 | * @return a list containing the message's addons 31 | */ 32 | public static List getAddons( JsonObject jsonObject ) { 33 | if ( !jsonObject.has( "addons" ) || !jsonObject.get( "addons" ).isJsonArray() ) 34 | return new ArrayList<>(); 35 | 36 | List addons = new ArrayList<>(); 37 | 38 | for ( JsonElement arrayElement : jsonObject.get( "addons" ).getAsJsonArray() ) { 39 | if ( !arrayElement.isJsonObject() ) 40 | continue; 41 | 42 | JsonObject arrayObject = arrayElement.getAsJsonObject(); 43 | 44 | if ( !arrayObject.has( "uuid" ) || !arrayObject.get( "uuid" ).isJsonPrimitive() || !arrayObject.get( "uuid" ).getAsJsonPrimitive().isString() 45 | || !arrayObject.has( "name" ) || !arrayObject.get( "name" ).isJsonPrimitive() || !arrayObject.get( "name" ).getAsJsonPrimitive().isString() ) 46 | continue; 47 | 48 | UUID uuid = null; 49 | 50 | try { 51 | uuid = UUID.fromString( arrayObject.get( "uuid" ).getAsString() ); 52 | } catch ( IllegalArgumentException ex ) { 53 | continue; 54 | } 55 | 56 | addons.add( new Addon( uuid, arrayObject.get( "name" ).getAsString() ) ); 57 | } 58 | 59 | return addons; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /common/src/main/java/net/labymod/serverapi/LabyModAPI.java: -------------------------------------------------------------------------------- 1 | package net.labymod.serverapi; 2 | 3 | import com.google.gson.JsonObject; 4 | import io.netty.buffer.ByteBuf; 5 | import io.netty.buffer.Unpooled; 6 | import io.netty.handler.codec.DecoderException; 7 | import io.netty.handler.codec.EncoderException; 8 | 9 | import java.nio.charset.Charset; 10 | import java.util.Map; 11 | 12 | /** 13 | * Class created by qlow | Jan 14 | */ 15 | public class LabyModAPI { 16 | 17 | /** 18 | * Gets the bytes we should send to a player to update the permissions 19 | * 20 | * @param permissions a map containing the permissions 21 | * @return the byte array that should be the payload 22 | */ 23 | public byte[] getBytesToSend( Map permissions ) { 24 | // Creating a json object we will put the permissions in 25 | JsonObject object = new JsonObject(); 26 | 27 | // Adding the permissions to the json object 28 | for ( Map.Entry permissionEntry : permissions.entrySet() ) { 29 | object.addProperty( permissionEntry.getKey().name(), permissionEntry.getValue() ); 30 | } 31 | 32 | // Returning the byte array 33 | return getBytesToSend( "PERMISSIONS", object.toString() ); 34 | } 35 | 36 | /** 37 | * Gets the bytes that are required to send the given message 38 | * 39 | * @param messageKey the message's key 40 | * @param messageContents the message's contents 41 | * @return the byte array that should be the payload 42 | */ 43 | public byte[] getBytesToSend( String messageKey, String messageContents ) { 44 | // Getting an empty buffer 45 | ByteBuf byteBuf = Unpooled.buffer(); 46 | 47 | // Writing the message-key to the buffer 48 | writeString( byteBuf, messageKey ); 49 | 50 | // Writing the contents to the buffer 51 | writeString( byteBuf, messageContents ); 52 | 53 | // Copying the buffer's bytes to the byte array 54 | byte[] bytes = new byte[byteBuf.readableBytes()]; 55 | byteBuf.readBytes( bytes ); 56 | 57 | // Returning the byte array 58 | return bytes; 59 | } 60 | 61 | /** 62 | * Writes a varint to the given byte buffer 63 | * 64 | * @param buf the byte buffer the int should be written to 65 | * @param input the int that should be written to the buffer 66 | */ 67 | private void writeVarIntToBuffer( ByteBuf buf, int input ) { 68 | while ( (input & -128) != 0 ) { 69 | buf.writeByte( input & 127 | 128 ); 70 | input >>>= 7; 71 | } 72 | 73 | buf.writeByte( input ); 74 | } 75 | 76 | /** 77 | * Writes a string to the given byte buffer 78 | * 79 | * @param buf the byte buffer the string should be written to 80 | * @param string the string that should be written to the buffer 81 | */ 82 | private void writeString( ByteBuf buf, String string ) { 83 | byte[] abyte = string.getBytes( Charset.forName( "UTF-8" ) ); 84 | 85 | if ( abyte.length > Short.MAX_VALUE ) { 86 | throw new EncoderException( "String too big (was " + string.length() + " bytes encoded, max " + Short.MAX_VALUE + ")" ); 87 | } else { 88 | writeVarIntToBuffer( buf, abyte.length ); 89 | buf.writeBytes( abyte ); 90 | } 91 | } 92 | 93 | /** 94 | * Reads a varint from the given byte buffer 95 | * 96 | * @param buf the byte buffer the varint should be read from 97 | * @return the int read 98 | */ 99 | public int readVarIntFromBuffer( ByteBuf buf ) { 100 | int i = 0; 101 | int j = 0; 102 | 103 | byte b0; 104 | do { 105 | b0 = buf.readByte(); 106 | i |= (b0 & 127) << j++ * 7; 107 | if ( j > 5 ) { 108 | throw new RuntimeException( "VarInt too big" ); 109 | } 110 | } while ( (b0 & 128) == 128 ); 111 | 112 | return i; 113 | } 114 | 115 | /** 116 | * Reads a string from the given byte buffer 117 | * 118 | * @param buf the byte buffer the string should be read from 119 | * @param maxLength the string's max-length 120 | * @return the string read 121 | */ 122 | public String readString( ByteBuf buf, int maxLength ) { 123 | int i = this.readVarIntFromBuffer( buf ); 124 | 125 | if ( i > maxLength * 4 ) { 126 | throw new DecoderException( "The received encoded string buffer length is longer than maximum allowed (" + i + " > " + maxLength * 4 + ")" ); 127 | } else if ( i < 0 ) { 128 | throw new DecoderException( "The received encoded string buffer length is less than zero! Weird string!" ); 129 | } else { 130 | byte[] bytes = new byte[i]; 131 | buf.readBytes( bytes ); 132 | 133 | String s = new String( bytes, Charset.forName( "UTF-8" ) ); 134 | if ( s.length() > maxLength ) { 135 | throw new DecoderException( "The received string length is longer than maximum allowed (" + i + " > " + maxLength + ")" ); 136 | } else { 137 | return s; 138 | } 139 | } 140 | } 141 | 142 | } 143 | -------------------------------------------------------------------------------- /common/src/main/java/net/labymod/serverapi/LabyModConfig.java: -------------------------------------------------------------------------------- 1 | package net.labymod.serverapi; 2 | 3 | import lombok.Getter; 4 | 5 | import java.io.File; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | /** 10 | * Class created by qlow | Jan 11 | */ 12 | public abstract class LabyModConfig { 13 | 14 | protected File file; 15 | 16 | @Getter 17 | private Map permissions = new HashMap<>(); 18 | 19 | public LabyModConfig( File file ) { 20 | this.file = file; 21 | } 22 | 23 | /** 24 | * Called once to initialize the config 25 | * 26 | * @param file the config-file 27 | */ 28 | public abstract void init( File file ); 29 | 30 | /** 31 | * Gets a key's value 32 | * 33 | * @param key the key the value should be resolved from 34 | * @return the value according to this key or null if there is no value according to this key 35 | */ 36 | public abstract Object getValue( String key ); 37 | 38 | /** 39 | * Adds a default to the config 40 | * 41 | * @param key the key 42 | * @param value the default value 43 | */ 44 | public abstract void addDefault( String key, Object value ); 45 | 46 | /** 47 | * Saves the config 48 | */ 49 | public abstract void saveConfig(); 50 | 51 | /** 52 | * Adds the config's defaults 53 | */ 54 | public void addDefaults() { 55 | // Iterating through all permissions 56 | for ( Permission permission : Permission.values() ) { 57 | // Putting the default value in 58 | addDefault( "permissions." + permission.name(), permission.isDefaultEnabled() ); 59 | } 60 | } 61 | 62 | /** 63 | * Loads the config values after adding the defaults 64 | */ 65 | public void loadValues() { 66 | // Iterating through all permissions 67 | for ( Permission permission : Permission.values() ) { 68 | Object value = getValue( "permissions." + permission.name() ); 69 | 70 | // Checking whether there is a value according to this permission 71 | if ( value != null && value instanceof Boolean ) { 72 | // Checking whether the permission value was modified 73 | permissions.put( permission, ( Boolean ) value ); 74 | } else { 75 | permissions.put( permission, permission.isDefaultEnabled() ); 76 | } 77 | } 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /common/src/main/java/net/labymod/serverapi/Permission.java: -------------------------------------------------------------------------------- 1 | package net.labymod.serverapi; 2 | 3 | /** 4 | * Class created by qlow | Jan 5 | */ 6 | public enum Permission { 7 | 8 | // Permissions that are disabled by default 9 | IMPROVED_LAVA( "Improved Lava", false ), 10 | CROSSHAIR_SYNC( "Crosshair sync", false ), 11 | REFILL_FIX( "Refill fix", false ), 12 | 13 | // GUI permissions 14 | GUI_ALL( "LabyMod GUI", true ), 15 | GUI_POTION_EFFECTS( "Potion Effects", true ), 16 | GUI_ARMOR_HUD( "Armor HUD", true ), 17 | GUI_ITEM_HUD( "Item HUD", true ), 18 | 19 | // Permissions that are enabled by default 20 | BLOCKBUILD( "Blockbuild", true ), 21 | TAGS( "Tags", true ), 22 | CHAT( "Chat features", true ), 23 | ANIMATIONS( "Animations", true ), 24 | SATURATION_BAR( "Saturation bar", true ); 25 | 26 | private String displayName; 27 | private boolean defaultEnabled; 28 | 29 | /** 30 | * @param displayName the permission's display-name 31 | * @param defaultEnabled whether or not this permission is enabled/activated by default 32 | */ 33 | Permission( String displayName, boolean defaultEnabled ) { 34 | this.displayName = displayName; 35 | this.defaultEnabled = defaultEnabled; 36 | } 37 | 38 | public String getDisplayName() { 39 | return displayName; 40 | } 41 | 42 | public boolean isDefaultEnabled() { 43 | return defaultEnabled; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | net.labymod 8 | serverapi 9 | pom 10 | 1.0-SNAPSHOT 11 | 12 | common 13 | bukkit 14 | bungeecord 15 | build 16 | 17 | 18 | 19 | 20 | spigot-repo 21 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/ 22 | 23 | 24 | 25 | 26 | 27 | 28 | org.projectlombok 29 | lombok 30 | 1.18.6 31 | provided 32 | 33 | 34 | 35 | 36 | 37 | 38 | org.apache.maven.plugins 39 | maven-compiler-plugin 40 | 3.6.1 41 | 42 | 1.7 43 | 1.7 44 | 45 | 46 | 47 | 48 | 49 | --------------------------------------------------------------------------------